├── .github ├── dependabot.yml └── workflows │ └── deploy copy.yml ├── .gitignore ├── .npmrc ├── .prettierignore ├── .prettierrc ├── .yarnrc ├── LICENSE ├── README.md ├── lerna-debug.log ├── lerna.json ├── package.json ├── packages ├── @finetwork:ui-sections │ ├── .gitignore │ ├── .yarnrc │ ├── package.json │ ├── src │ │ ├── index.ts │ │ ├── sections │ │ │ ├── PriceCard │ │ │ │ ├── index.tsx │ │ │ │ └── styled.ts │ │ │ └── PriceCardHorizontal │ │ │ │ ├── index.tsx │ │ │ │ └── styled.ts │ │ └── stitches.config.ts │ └── tsconfig.json ├── @finetwork:ui │ ├── .gitignore │ ├── .yarnrc │ ├── package.json │ ├── src │ │ ├── animations.ts │ │ ├── components │ │ │ ├── Accordion │ │ │ │ ├── index.tsx │ │ │ │ ├── styled.ts │ │ │ │ └── types.ts │ │ │ ├── Button │ │ │ │ ├── index.tsx │ │ │ │ ├── styled.ts │ │ │ │ └── types.ts │ │ │ ├── Card │ │ │ │ ├── index.tsx │ │ │ │ ├── styled.ts │ │ │ │ └── types.ts │ │ │ ├── Checkbox │ │ │ │ ├── index.tsx │ │ │ │ ├── styled.ts │ │ │ │ └── types.ts │ │ │ ├── Dialog │ │ │ │ ├── index.tsx │ │ │ │ ├── styled.ts │ │ │ │ ├── types.ts │ │ │ │ └── utils.ts │ │ │ ├── DropdownMenu │ │ │ │ ├── index.tsx │ │ │ │ ├── styled.ts │ │ │ │ └── types.ts │ │ │ ├── Input │ │ │ │ ├── index.tsx │ │ │ │ ├── styled.ts │ │ │ │ └── types.ts │ │ │ ├── Link │ │ │ │ ├── index.tsx │ │ │ │ ├── styled.ts │ │ │ │ └── types.ts │ │ │ ├── Loading │ │ │ │ ├── index.tsx │ │ │ │ ├── styled.ts │ │ │ │ └── types.ts │ │ │ ├── Radio │ │ │ │ ├── index.tsx │ │ │ │ ├── styled.ts │ │ │ │ └── types.ts │ │ │ ├── Select │ │ │ │ ├── index.tsx │ │ │ │ ├── options.tsx │ │ │ │ ├── styled.ts │ │ │ │ └── types.ts │ │ │ ├── Separator │ │ │ │ ├── index.tsx │ │ │ │ ├── styled.ts │ │ │ │ └── types.ts │ │ │ ├── Skeleton │ │ │ │ ├── index.tsx │ │ │ │ ├── styled.ts │ │ │ │ └── types.ts │ │ │ ├── Switch │ │ │ │ ├── index.tsx │ │ │ │ ├── styled.ts │ │ │ │ └── types.ts │ │ │ ├── Tabs │ │ │ │ ├── context.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── styled.ts │ │ │ │ └── types.ts │ │ │ ├── Tag │ │ │ │ ├── index.tsx │ │ │ │ ├── styled.ts │ │ │ │ └── types.ts │ │ │ ├── Textarea │ │ │ │ ├── index.tsx │ │ │ │ ├── styled.ts │ │ │ │ └── types.ts │ │ │ ├── Theme │ │ │ │ ├── ThemeContext.tsx │ │ │ │ ├── ThemeProvider.tsx │ │ │ │ ├── hook.ts │ │ │ │ ├── index.ts │ │ │ │ ├── initial-theme.ts │ │ │ │ └── types.ts │ │ │ ├── Toast │ │ │ │ ├── index.tsx │ │ │ │ ├── styled.ts │ │ │ │ └── types.ts │ │ │ ├── Tooltip │ │ │ │ ├── index.tsx │ │ │ │ ├── styled.ts │ │ │ │ └── types.ts │ │ │ ├── Typography │ │ │ │ ├── index.tsx │ │ │ │ ├── styled.ts │ │ │ │ └── types.ts │ │ │ └── icons │ │ │ │ ├── ArrowRightIcon.tsx │ │ │ │ ├── CheckIcon.tsx │ │ │ │ ├── ChevronDownIcon.tsx │ │ │ │ ├── CloseIcon.tsx │ │ │ │ ├── Cross1Icon.tsx │ │ │ │ ├── DividerHorizontalIcon.tsx │ │ │ │ ├── EnvelopeClosedIcon.tsx │ │ │ │ ├── ErrorIcon.tsx │ │ │ │ ├── EyeClosedIcon.tsx │ │ │ │ ├── EyeOpenIcon.tsx │ │ │ │ ├── HamburgerIcon.tsx │ │ │ │ ├── Loupe.tsx │ │ │ │ ├── Pencil2Icon.tsx │ │ │ │ ├── PersonIcon.tsx │ │ │ │ ├── RocketIcon.tsx │ │ │ │ ├── SunIcon.tsx │ │ │ │ └── index.ts │ │ ├── hooks │ │ │ ├── useControllScroll.ts │ │ │ └── useWindowSize.ts │ │ ├── index.ts │ │ ├── stitches.config.ts │ │ ├── types │ │ │ ├── boolean-string.ts │ │ │ ├── enhancer.ts │ │ │ ├── fonts.ts │ │ │ ├── index.ts │ │ │ ├── kind.ts │ │ │ ├── orientation.ts │ │ │ ├── placement.ts │ │ │ └── size.ts │ │ └── utils.tsx │ └── tsconfig.json └── website │ ├── next-env.d.ts │ ├── next.config.js │ ├── package.json │ ├── pages │ ├── _app.jsx │ ├── _document.js │ ├── components │ │ ├── accordion.mdx │ │ ├── button.mdx │ │ ├── card.mdx │ │ ├── checkbox.mdx │ │ ├── dialog.mdx │ │ ├── dropdown-menu.mdx │ │ ├── input.mdx │ │ ├── link.mdx │ │ ├── radio.mdx │ │ ├── select.mdx │ │ ├── separator.mdx │ │ ├── skeleton.mdx │ │ ├── switch.mdx │ │ ├── tabs.mdx │ │ ├── tag.mdx │ │ ├── textarea.mdx │ │ ├── toast.mdx │ │ ├── tooltip.mdx │ │ └── typography.mdx │ ├── getting-started.mdx │ ├── index.mdx │ └── sections │ │ ├── price-card-horizontal.mdx │ │ └── price-card.mdx │ ├── playgrounds │ ├── ToastPlayground.tsx │ └── index.ts │ ├── public │ ├── favicon.ico │ ├── finetwork.png │ └── fonts │ │ ├── Druk-Text-Wide.otf │ │ ├── Druk.eot │ │ ├── Druk.woff │ │ ├── Druk.woff2 │ │ ├── DrukText-Bold.otf │ │ └── DrukText-Medium.otf │ ├── styles.ts │ ├── styles │ ├── globals.css │ └── stitches.config.ts │ ├── themes.ts │ └── tsconfig.json ├── scripts ├── build.sh ├── deploy.sh ├── esbuild.config.js └── generate-package.js ├── tsconfig.json └── yarn.lock /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "npm" 9 | directory: "/" 10 | schedule: 11 | interval: "weekly" 12 | - package-ecosystem: "npm" 13 | directory: "/packages/@finetwork:ui" 14 | schedule: 15 | interval: "weekly" 16 | - package-ecosystem: "npm" 17 | directory: "/packages/website" 18 | schedule: 19 | interval: "weekly" 20 | -------------------------------------------------------------------------------- /.github/workflows/deploy copy.yml: -------------------------------------------------------------------------------- 1 | name: Node.js Package 2 | on: 3 | workflow_dispatch: 4 | inputs: 5 | typeLibrary: 6 | description: 'Which library do you want to deploy ? (ui/sections)' 7 | required: true 8 | default: 'ui' 9 | 10 | jobs: 11 | build-publish: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v2 15 | - uses: actions/setup-node@v2 16 | with: 17 | node-version: '12.x' 18 | registry-url: 'https://registry.npmjs.org' 19 | - run: yarn 20 | - run: yarn build-${{ github.event.inputs.typeLibrary }}-library 21 | - run: yarn publish-${{ github.event.inputs.typeLibrary }}-library $NODE_AUTH_TOKEN 22 | env: 23 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /lib/dist 5 | /lib/node_modules 6 | /packages/**/dist 7 | /packages/**/node_modules 8 | /packages/**/.next 9 | /node_modules 10 | /.pnp 11 | .pnp.js 12 | 13 | sidebar.json 14 | 15 | # testing 16 | /coverage 17 | 18 | # next.js 19 | /.next/ 20 | /out/ 21 | 22 | # production 23 | /build 24 | 25 | # misc 26 | .DS_Store 27 | .env* 28 | 29 | ### IntelliJ IDEA ### 30 | .idea 31 | *.iws 32 | *.iml 33 | *.ipr 34 | out/ 35 | 36 | # debug 37 | npm-debug.log* 38 | yarn-debug.log* 39 | yarn-error.log* 40 | 41 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | //registry.npmjs.org/:_authToken=token 2 | always-auth=true 3 | registry=https://registry.npmjs.org/ 4 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .next 3 | public -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "singleQuote": true, 4 | "tabWidth": 2, 5 | "useTabs": false, 6 | "printWidth": 80 7 | } 8 | -------------------------------------------------------------------------------- /.yarnrc: -------------------------------------------------------------------------------- 1 | registry "https://registry.npmjs.org/" -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Finetwork Open Source 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Finetwork UI

2 | 3 |
4 | 5 | [React](https://reactjs.org/) components library, initially for Finetwork projects. 6 | Built on top of Radix-UI primitive components as base components in order to have accessible components, and Stitches for styling. 7 | 8 | [![license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/finetwork-os/ui/blob/master/LICENSE) 9 | [![npm downloads](https://img.shields.io/npm/dt/@finetwork/ui.svg)](https://www.npmjs.com/package/@finetwork/ui) 10 | 11 |
12 | 13 | ## Installation 14 | 15 | ```sh 16 | // with npm 17 | npm install @finetwork/ui react 18 | 19 | // with yarn 20 | yarn add @finetwork/ui react 21 | ``` 22 | 23 | ## Documentation 24 | 25 | Check out our [documentation website](https://finetwork-ui.vercel.app/). 26 | -------------------------------------------------------------------------------- /lerna-debug.log: -------------------------------------------------------------------------------- 1 | 0 silly argv { 2 | 0 silly argv _: [ 'add' ], 3 | 0 silly argv dev: true, 4 | 0 silly argv D: true, 5 | 0 silly argv scope: '@finetwork/ui-sections', 6 | 0 silly argv globs: [], 7 | 0 silly argv lernaVersion: '4.0.0', 8 | 0 silly argv '$0': 'node_modules/.bin/lerna', 9 | 0 silly argv pkg: 'typescript@4.8.4' 10 | 0 silly argv } 11 | 1 notice cli v4.0.0 12 | 2 verbose rootPath /home/smolto/Escritorio/proyectos/ui 13 | 3 notice filter including "@finetwork/ui-sections" 14 | 4 info filter [ '@finetwork/ui-sections' ] 15 | 5 error TypeError: Invalid comparator: latest 16 | 5 error at Comparator.parse (/home/smolto/Escritorio/proyectos/ui/node_modules/semver/classes/comparator.js:37:13) 17 | 5 error at new Comparator (/home/smolto/Escritorio/proyectos/ui/node_modules/semver/classes/comparator.js:21:10) 18 | 5 error at /home/smolto/Escritorio/proyectos/ui/node_modules/semver/classes/range.js:121:20 19 | 5 error at Array.map () 20 | 5 error at Range.parseRange (/home/smolto/Escritorio/proyectos/ui/node_modules/semver/classes/range.js:121:8) 21 | 5 error at /home/smolto/Escritorio/proyectos/ui/node_modules/semver/classes/range.js:34:26 22 | 5 error at Array.map () 23 | 5 error at new Range (/home/smolto/Escritorio/proyectos/ui/node_modules/semver/classes/range.js:34:8) 24 | 5 error at Object.intersects (/home/smolto/Escritorio/proyectos/ui/node_modules/semver/ranges/intersects.js:3:8) 25 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": ["packages/*"], 3 | "version": "1.0.0", 4 | "npmClient": "yarn", 5 | "useWorkspaces": true 6 | } 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "workspaces": [ 3 | "packages/*" 4 | ], 5 | "name": "@finetwork/ui-root", 6 | "private": true, 7 | "npmClient": "yarn", 8 | "useWorkspaces": true, 9 | "repository": "https://github.com/finetwork-os/ui", 10 | "scripts": { 11 | "postinstall": "node_modules/.bin/lerna bootstrap", 12 | "dev": "node_modules/.bin/lerna exec --scope=website yarn dev", 13 | "build-website": "node_modules/.bin/lerna exec --scope=website yarn build", 14 | "start-website": "node_modules/.bin/lerna exec --scope=website yarn start", 15 | "build-ui-library": "node_modules/.bin/lerna exec --scope=@finetwork/ui yarn build", 16 | "publish-ui-library": "node_modules/.bin/lerna exec --scope=@finetwork/ui yarn publish-library", 17 | "build-sections-library": "node_modules/.bin/lerna exec --scope=@finetwork/ui-sections yarn build", 18 | "publish-sections-library": "node_modules/.bin/lerna exec --scope=@finetwork/ui-sections yarn publish-library" 19 | }, 20 | "devDependencies": { 21 | "lerna": "^4.0.0", 22 | "prettier": "^2.2.1", 23 | "typescript": "4.8.4" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /packages/@finetwork:ui-sections/.gitignore: -------------------------------------------------------------------------------- 1 | .npmrc -------------------------------------------------------------------------------- /packages/@finetwork:ui-sections/.yarnrc: -------------------------------------------------------------------------------- 1 | registry "https://registry.npmjs.org/" -------------------------------------------------------------------------------- /packages/@finetwork:ui-sections/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@finetwork/ui-sections", 3 | "version": "0.2.0", 4 | "source": "src/index.ts", 5 | "typings": "src/index.ts", 6 | "main": "src/index.ts", 7 | "license": "MIT", 8 | "scripts": { 9 | "build": "yarn build-ui && sh ../../scripts/build.sh", 10 | "build-ui": "cd .. && cd .. && yarn build-ui-library", 11 | "build-types": "./node_modules/.bin/tsc", 12 | "build-lib": "node ../../scripts/esbuild.config.js", 13 | "publish-library": "sh ../../scripts/deploy.sh" 14 | }, 15 | "dependencies": { 16 | "@radix-ui/colors": "^0.1.8", 17 | "@stitches/react": "^1.2.7" 18 | }, 19 | "devDependencies": { 20 | "@types/react": "^17.0.3", 21 | "@types/react-is": "^17.0.0", 22 | "esbuild": "^0.13.12", 23 | "esbuild-node-externals": "^1.3.0", 24 | "npm-run-all": "^4.1.5", 25 | "react": ">=17.0.0", 26 | "react-is": "^17.0.2", 27 | "rimraf": "^3.0.2", 28 | "tslib": "^2.2.0", 29 | "typescript": "4.8.4" 30 | }, 31 | "peerDependencies": { 32 | "@finetwork/ui": "1.0.0", 33 | "react": ">=17.0.0" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /packages/@finetwork:ui-sections/src/index.ts: -------------------------------------------------------------------------------- 1 | export { PriceCard } from './sections/PriceCard' 2 | export { PriceCardHorizontal } from './sections/PriceCardHorizontal' 3 | -------------------------------------------------------------------------------- /packages/@finetwork:ui-sections/src/sections/PriceCard/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | import { 4 | Bullet, 5 | BulletIcon, 6 | BulletText, 7 | ContainerBullets, 8 | Description, 9 | Price, 10 | PriceContainer, 11 | PriceDescription, 12 | PriceTabletContainer, 13 | StyledButton, 14 | StyledCard, 15 | StyledCardBody, 16 | StyledCardFooter, 17 | StyledCardHeader, 18 | StyledCheckIcon, 19 | StyledTag, 20 | TagText, 21 | Title, 22 | } from './styled' 23 | 24 | import { KINDS, Paragraph6, KIND, Card, TagProps } from '@finetwork/ui' 25 | 26 | type PriceCardProps = React.ComponentProps & { 27 | tagOptions?: { 28 | text?: string 29 | props?: TagProps 30 | } 31 | kind?: KINDS 32 | title: string 33 | price: string 34 | priceDescription?: string[] 35 | description?: string 36 | bullets?: { 37 | text: string 38 | icon?: React.ReactNode 39 | }[] 40 | footerLink?: { 41 | href: string 42 | label: string 43 | LinkComponent: React.FC 44 | } 45 | actionButton: { 46 | text: string 47 | onClick: React.MouseEventHandler 48 | } 49 | } 50 | 51 | export const PriceCard: React.FC = ({ 52 | tagOptions, 53 | kind = KIND.primary, 54 | title, 55 | price, 56 | priceDescription, 57 | description, 58 | bullets, 59 | footerLink, 60 | actionButton, 61 | hoverAnimation, 62 | ...props 63 | }) => { 64 | return ( 65 | 71 | {tagOptions && ( 72 | 73 | 74 | {tagOptions.text} 75 | 76 | 77 | )} 78 | 79 | 80 | {title} 81 | 82 | 83 | {price && ( 84 | 85 | {price} 86 | 87 | )} 88 | {priceDescription && ( 89 | 90 | {priceDescription[0]} 91 | {priceDescription[1]} 92 | 93 | )} 94 | 95 | {description && {description}} 96 | {bullets && ( 97 | 98 | {bullets.map(({ icon, text }, index) => ( 99 | 100 | {icon ? icon : } 101 | {text} 102 | 103 | ))} 104 | 105 | )} 106 | 107 | 108 | 109 | {price && ( 110 | 111 | {price} 112 | 113 | )} 114 | {priceDescription && ( 115 | 116 | {priceDescription[0]} 117 | {priceDescription[1]} 118 | 119 | )} 120 | 121 | 122 | {actionButton.text} 123 | 124 | {footerLink && ( 125 | 126 | {footerLink.label} 127 | 128 | )} 129 | 130 | 131 | ) 132 | } 133 | -------------------------------------------------------------------------------- /packages/@finetwork:ui-sections/src/sections/PriceCardHorizontal/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | import { 4 | Bullet, 5 | BulletIcon, 6 | BulletText, 7 | ContainerBullets, 8 | Price, 9 | PriceContainer, 10 | PriceDescription, 11 | StyledCard, 12 | StyledCardBody, 13 | StyledCardFooter, 14 | StyledCardHeader, 15 | StyledCheckIcon, 16 | Title, 17 | } from './styled' 18 | 19 | import { KINDS, Paragraph6, KIND, Card, TagProps } from '@finetwork/ui' 20 | 21 | type PriceCardProps = Omit< 22 | React.ComponentProps & { 23 | kind?: KINDS 24 | title: string 25 | price: string 26 | priceDescription?: string[] 27 | bullets?: { 28 | text: string 29 | icon?: React.ReactNode 30 | }[] 31 | }, 32 | 'hoverAnimation' 33 | > 34 | 35 | export const PriceCardHorizontal: React.FC = ({ 36 | kind = KIND.primary, 37 | title, 38 | price, 39 | priceDescription, 40 | bullets, 41 | ...props 42 | }) => { 43 | return ( 44 | 45 | 46 | 47 | {title} 48 | 49 | {bullets && ( 50 | 51 | {bullets.map(({ icon, text }, index) => ( 52 | 53 | {icon ? icon : } 54 | {text} 55 | 56 | ))} 57 | 58 | )} 59 | 60 | 61 | 62 | {price && ( 63 | 64 | {price} 65 | 66 | )} 67 | {priceDescription && ( 68 | 69 | {priceDescription[0]} 70 | {priceDescription[1]} 71 | 72 | )} 73 | 74 | 75 | 76 | ) 77 | } 78 | -------------------------------------------------------------------------------- /packages/@finetwork:ui-sections/src/sections/PriceCardHorizontal/styled.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Button, 3 | Card, 4 | CardBody, 5 | CardFooter, 6 | CheckIcon, 7 | H3, 8 | H4, 9 | Paragraph4, 10 | Paragraph5, 11 | Paragraph6, 12 | Tag, 13 | } from '@finetwork/ui' 14 | 15 | import { styled } from '../../stitches.config' 16 | 17 | export const PriceContainer = styled('div', { 18 | position: 'relative', 19 | display: 'flex', 20 | alignItems: 'center', 21 | justifyContent: 'center', 22 | '&::before': { 23 | content: '', 24 | position: 'absolute', 25 | backgroundColor: '$secondary', 26 | width: 3, 27 | height: '5rem', 28 | left: '-1rem', 29 | top: '-1rem', 30 | }, 31 | variants: { 32 | kind: { 33 | primary: { 34 | '&::before': { 35 | backgroundColor: '$primary', 36 | }, 37 | }, 38 | secondary: { 39 | '&::before': { 40 | backgroundColor: '$secondary', 41 | }, 42 | }, 43 | tertiary: { 44 | '&::before': { 45 | backgroundColor: '$tertiary', 46 | }, 47 | }, 48 | }, 49 | }, 50 | defaultVariants: { 51 | kind: 'primary', 52 | }, 53 | }) 54 | 55 | export const StyledTag = styled(Tag, { 56 | position: 'absolute', 57 | top: 0, 58 | left: 0, 59 | width: '100%', 60 | textAlign: 'center', 61 | }) 62 | 63 | export const TagText = styled(Paragraph4, { 64 | color: 'inherit', 65 | textAlign: 'inherit', 66 | }) 67 | 68 | export const StyledCard = styled(Card, { 69 | position: 'relative', 70 | display: 'grid', 71 | alignItems: 'center', 72 | gridTemplateColumns: '1fr auto', 73 | cursor: 'pointer', 74 | }) 75 | 76 | export const StyledCardHeader = styled('div', { 77 | display: 'flex', 78 | }) 79 | 80 | export const StyledCardBody = styled(CardBody, { 81 | display: 'flex', 82 | flexDirection: 'column', 83 | }) 84 | 85 | export const StyledCardFooter = styled(CardFooter, { 86 | display: 'flex', 87 | alignItems: 'center', 88 | height: '100%', 89 | }) 90 | 91 | export const Title = styled(H4, { 92 | textAlign: 'center', 93 | }) 94 | 95 | export const PriceDescription = styled('div', { 96 | display: 'grid', 97 | gap: '.1rem', 98 | marginLeft: '.5rem', 99 | }) 100 | 101 | export const Price = styled(H3, {}) 102 | 103 | export const ContainerBullets = styled('ul', { 104 | display: 'flex', 105 | flexDirection: 'column', 106 | width: '100%', 107 | }) 108 | export const Bullet = styled('li', { 109 | listStyle: 'none', 110 | display: 'flex', 111 | alignItems: 'center', 112 | '&:not(:first-child)': { 113 | marginTop: '.5rem', 114 | }, 115 | }) 116 | export const BulletText = styled(Paragraph6, { 117 | marginLeft: '.5rem', 118 | }) 119 | export const BulletIcon = styled('span', {}) 120 | export const StyledCheckIcon = styled(CheckIcon, { 121 | variants: { 122 | kind: { 123 | primary: { 124 | color: '$primary', 125 | }, 126 | secondary: { 127 | color: '$secondary', 128 | }, 129 | tertiary: { 130 | color: '$tertiary', 131 | }, 132 | }, 133 | }, 134 | defaultVariants: { 135 | kind: 'primary', 136 | }, 137 | }) 138 | export const StyledButton = styled(Button, { 139 | marginBottom: '1rem', 140 | }) 141 | -------------------------------------------------------------------------------- /packages/@finetwork:ui-sections/src/stitches.config.ts: -------------------------------------------------------------------------------- 1 | import { createStitches } from '@stitches/react' 2 | 3 | export const { styled, keyframes } = createStitches({ 4 | media: { 5 | mobile: '(min-width: 360px)', 6 | tablet: '(min-width: 480px)', 7 | tabletXl: '(min-width: 768px)', 8 | desktop: '(min-width: 1024px)', 9 | 'desktop-xl': '(min-width: 1280px)', 10 | }, 11 | }) 12 | -------------------------------------------------------------------------------- /packages/@finetwork:ui-sections/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "emitDeclarationOnly": true, 5 | "declaration": true, 6 | "composite": true, 7 | "outDir": "dist" 8 | }, 9 | "references": [ 10 | { 11 | "path": "../@finetwork:ui/tsconfig.json" 12 | } 13 | ], 14 | "include": ["src/**/*.ts", "src/**/*.tsx"], 15 | "exclude": ["node_modules"] 16 | } 17 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/.gitignore: -------------------------------------------------------------------------------- 1 | .npmrc -------------------------------------------------------------------------------- /packages/@finetwork:ui/.yarnrc: -------------------------------------------------------------------------------- 1 | registry "https://registry.npmjs.org/" -------------------------------------------------------------------------------- /packages/@finetwork:ui/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@finetwork/ui", 3 | "version": "1.3.23", 4 | "source": "src/index.ts", 5 | "typings": "src/index.ts", 6 | "main": "src/index.ts", 7 | "license": "MIT", 8 | "scripts": { 9 | "build": "sh ../../scripts/build.sh", 10 | "build-types": "./node_modules/.bin/tsc", 11 | "build-lib": "node ../../scripts/esbuild.config.js", 12 | "publish-library": "sh ../../scripts/deploy.sh" 13 | }, 14 | "dependencies": { 15 | "@radix-ui/colors": "^0.1.8", 16 | "@radix-ui/react-accordion": "^0.1.5", 17 | "@radix-ui/react-dropdown-menu": "^0.1.4", 18 | "@radix-ui/react-id": "^0.1.4", 19 | "@radix-ui/react-label": "^0.1.4", 20 | "@radix-ui/react-menu": "^0.1.4", 21 | "@radix-ui/react-polymorphic": "^0.0.14", 22 | "@radix-ui/react-popover": "^0.1.4", 23 | "@radix-ui/react-toast": "^0.1.1", 24 | "@radix-ui/react-tooltip": "^0.1.6", 25 | "@stitches/react": "1.2.8", 26 | "downshift": "^6.1.7", 27 | "match-sorter": "^6.3.1", 28 | "polished": "4.2.2" 29 | }, 30 | "devDependencies": { 31 | "@types/react": "^17.0.3", 32 | "@types/react-is": "^17.0.0", 33 | "compose-function": "^3.0.3", 34 | "esbuild": "^0.13.12", 35 | "esbuild-node-externals": "^1.3.0", 36 | "npm-run-all": "^4.1.5", 37 | "react": ">=17.0.0", 38 | "react-is": "^17.0.2", 39 | "rimraf": "^3.0.2", 40 | "tslib": "^2.2.0", 41 | "typescript": "4.8.4" 42 | }, 43 | "peerDependencies": { 44 | "react": ">=17.0.0" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Accordion/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | import { 4 | AccordionComponent, 5 | AccordionContentComponent, 6 | AccordionTriggerComponent, 7 | } from './types' 8 | import { 9 | StyledAccordion, 10 | StyledChevron, 11 | StyledContent, 12 | StyledContentText, 13 | StyledHeader, 14 | StyledItem, 15 | StyledTrigger, 16 | } from './styled' 17 | 18 | export const Accordion: AccordionComponent = ({ children, ...props }) => ( 19 | 20 | {children} 21 | 22 | ) 23 | export const AccordionTrigger: AccordionTriggerComponent = React.forwardRef( 24 | ({ children, withIcon = true, ...props }, forwardedRef) => ( 25 | 26 | 27 | {children} 28 | {withIcon && } 29 | 30 | 31 | ) 32 | ) 33 | export const AccordionContent: AccordionContentComponent = React.forwardRef( 34 | ({ children, ...props }, forwardedRef) => ( 35 | 36 | 37 | {children} 38 | 39 | 40 | ) 41 | ) 42 | export const AccordionItem = StyledItem 43 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Accordion/styled.ts: -------------------------------------------------------------------------------- 1 | import { Content, Header, Item, Root, Trigger } from '@radix-ui/react-accordion' 2 | import { 3 | fadeIn, 4 | fadeOut, 5 | slideDownAccordion, 6 | slideUpAccordion, 7 | } from '../../animations' 8 | 9 | import { StyledComponent } from '@stitches/react/types/styled-component' 10 | import { styled } from '../../stitches.config' 11 | import { ChevronDownIcon } from '../icons' 12 | 13 | export const StyledAccordion = styled(Root, { 14 | variants: { 15 | kind: { 16 | primary: { 17 | svg: { 18 | color: '$primary', 19 | }, 20 | }, 21 | secondary: { 22 | svg: { 23 | color: '$secondary', 24 | }, 25 | }, 26 | tertiary: { 27 | svg: { 28 | color: '$tertiary', 29 | }, 30 | }, 31 | }, 32 | }, 33 | defaultVariants: { 34 | kind: 'primary', 35 | }, 36 | }) 37 | 38 | export const StyledContentText = styled('div', { 39 | paddingBottom: '1.5rem', 40 | paddingRight: '1.2rem', 41 | }) 42 | 43 | export const StyledContent: StyledComponent = styled(Content, { 44 | overflow: 'hidden', 45 | '&[data-state="open"]': { 46 | animation: `${slideDownAccordion} 300ms cubic-bezier(0.87, 0, 0.13, 1), ${fadeIn} 300ms ease`, 47 | }, 48 | '&[data-state="closed"]': { 49 | animation: `${slideUpAccordion} 300ms cubic-bezier(0.87, 0, 0.13, 1), ${fadeOut} 300ms ease`, 50 | }, 51 | }) 52 | 53 | export const StyledItem = styled(Item, { 54 | '&:has(:focus-visible)': { 55 | position: 'relative', 56 | zIndex: 1, 57 | boxShadow: `0 0 0 2px currentColor`, 58 | }, 59 | paddingLeft: '1.2rem', 60 | paddingRight: '1.2rem', 61 | borderBottom: '1px solid #EFF2FC', 62 | }) 63 | 64 | export const StyledHeader = styled(Header, { 65 | all: 'unset', 66 | }) 67 | 68 | export const StyledTrigger: StyledComponent = 69 | styled(Trigger, { 70 | all: 'unset', 71 | boxSizing: 'border-box', 72 | userSelect: 'none', 73 | cursor: 'pointer', 74 | paddingTop: '1.5rem', 75 | paddingBottom: '1.5rem', 76 | display: 'flex', 77 | alignItems: 'center', 78 | justifyContent: 'space-between', 79 | width: '100%', 80 | '&::before': { 81 | boxSizing: 'border-box', 82 | }, 83 | '&::after': { 84 | boxSizing: 'border-box', 85 | }, 86 | svg: { 87 | transition: 'transform 175ms cubic-bezier(0.65, 0, 0.35, 1)', 88 | }, 89 | '&[data-state="open"]': { 90 | svg: { 91 | transform: 'rotate(180deg)', 92 | }, 93 | }, 94 | }) 95 | export const StyledChevron = styled(ChevronDownIcon, { 96 | transition: 'transform 300ms cubic-bezier(0.87, 0, 0.13, 1)', 97 | '[data-state=open] &': { transform: 'rotate(180deg)' }, 98 | }) 99 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Accordion/types.ts: -------------------------------------------------------------------------------- 1 | import { ComponentProps, FC } from 'react' 2 | import { StyledAccordion, StyledContent, StyledTrigger } from './styled' 3 | 4 | import { CSS } from '@stitches/react/types/css-util' 5 | import { ForwardRefComponent } from '@radix-ui/react-polymorphic' 6 | import { KINDS } from '../../types' 7 | 8 | export type AccordionComponent = FC< 9 | ComponentProps & { 10 | kind?: KINDS 11 | } 12 | > 13 | export type AccordionContentComponent = FC> 14 | 15 | type AccordionTriggerCSSProp = { css?: CSS; withIcon?: boolean } 16 | export type AccordionTriggerComponent = ForwardRefComponent< 17 | typeof StyledTrigger, 18 | AccordionTriggerCSSProp 19 | > 20 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Button/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | import { ButtonComponent, ButtonProps } from './types' 4 | import { 5 | ChildrenLoading, 6 | StyledButton, 7 | StyledEndEnhancer, 8 | StyledStartEnhancer, 9 | } from './styled' 10 | 11 | import { Loading } from '../Loading' 12 | import { RenderEnhancer } from '../../utils' 13 | import { SIZE } from '../../types' 14 | 15 | export const Button: ButtonComponent = React.forwardRef( 16 | ( 17 | { 18 | children, 19 | size, 20 | shape, 21 | kind, 22 | isSelected, 23 | isLoading, 24 | loadingProps = {}, 25 | disabled, 26 | startEnhancer, 27 | endEnhancer, 28 | outline, 29 | ...props 30 | }, 31 | ref 32 | ) => { 33 | const sizeLoading = 34 | size === SIZE.large ? 30 : size === SIZE.medium ? 24 : 18 35 | const buttonProps: ButtonProps = { 36 | size, 37 | shape, 38 | kind, 39 | disabled, 40 | isDisabled: disabled, 41 | onClick: !isLoading && !disabled ? props.onClick : undefined, 42 | outline, 43 | ref, 44 | isLoading, 45 | isSelected, 46 | 'aria-disabled': !!disabled, 47 | ...props, 48 | } 49 | return ( 50 | 51 | {isLoading ? ( 52 | <> 53 | {children} 54 | 55 | 56 | ) : ( 57 | <> 58 | {startEnhancer && ( 59 | 60 | 61 | 62 | )} 63 | {children} 64 | {endEnhancer && ( 65 | 66 | 67 | 68 | )} 69 | 70 | )} 71 | 72 | ) 73 | } 74 | ) 75 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Button/types.ts: -------------------------------------------------------------------------------- 1 | import { ComponentProps, FC } from 'react' 2 | import { Enhancer, KINDS, SIZES } from '../../types' 3 | 4 | import { CSS } from '@stitches/react/types/css-util' 5 | import { LoadingProps } from '../Loading/types' 6 | import { StyledButton } from './styled' 7 | 8 | export enum SHAPE { 9 | default = 'default', 10 | pill = 'pill', 11 | round = 'round', 12 | circle = 'circle', 13 | square = 'square', 14 | } 15 | export enum VARIANT { 16 | outline = 'outline', 17 | default = 'default', 18 | } 19 | export type VARIANTS = keyof typeof VARIANT 20 | export type SHAPES = keyof typeof SHAPE 21 | 22 | type ButtonCSSProp = { css?: CSS } 23 | type ButtonOwnProps = ButtonCSSProp & { 24 | size?: SIZES 25 | shape?: SHAPES 26 | outline?: boolean 27 | kind?: KINDS 28 | isLoading?: boolean 29 | isSelected?: boolean 30 | loadingProps?: LoadingProps 31 | startEnhancer?: Enhancer 32 | endEnhancer?: Enhancer 33 | } 34 | 35 | export type ButtonProps = ComponentProps & ButtonOwnProps 36 | export type ButtonComponent = FC 37 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Card/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | import { StyledBody, StyledCard, StyledFooter, StyledHeader } from './styled' 4 | 5 | import { CardProps } from './types' 6 | import { KIND } from '../../types' 7 | 8 | export const CardHeader: React.FC> = 9 | ({ ...props }) => 10 | 11 | export const CardBody: React.FC> = ({ 12 | ...props 13 | }) => 14 | 15 | export const CardFooter: React.FC> = 16 | ({ ...props }) => 17 | 18 | export const Card: React.FC = ({ 19 | hoverAnimation = false, 20 | kind = KIND.primary, 21 | children, 22 | ...props 23 | }) => { 24 | return ( 25 | 31 | {children} 32 | 33 | ) 34 | } 35 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Card/styled.ts: -------------------------------------------------------------------------------- 1 | import { StyledComponent } from '@stitches/react/types/styled-component' 2 | import { styled } from '../../stitches.config' 3 | 4 | const sharedStyles = { 5 | paddingTop: '1rem', 6 | paddingBottom: '1rem', 7 | paddingRight: '1rem', 8 | paddingLeft: '1rem', 9 | width: '100%', 10 | variants: { 11 | font: { 12 | primary: { 13 | fontFamily: '$primary', 14 | }, 15 | secondary: { 16 | fontFamily: '$secondary', 17 | }, 18 | }, 19 | }, 20 | defaultVariants: { 21 | font: 'primary', 22 | }, 23 | } 24 | 25 | export const StyledCardHeader = styled('div', { 26 | ...sharedStyles, 27 | }) 28 | 29 | export const StyledCardBody = styled('div', { 30 | ...sharedStyles, 31 | }) 32 | 33 | export const StyledCardFooter = styled('div', { 34 | ...sharedStyles, 35 | }) 36 | 37 | export const StyledHeader: StyledComponent = styled( 38 | StyledCardHeader, 39 | { 40 | paddingTop: '2rem', 41 | paddingRight: '2rem', 42 | paddingLeft: '2rem', 43 | paddingBottom: '1rem', 44 | } 45 | ) 46 | 47 | export const StyledBody: StyledComponent = styled( 48 | StyledCardBody, 49 | { 50 | paddingTop: '1rem', 51 | paddingBottom: '2rem', 52 | paddingRight: '2rem', 53 | paddingLeft: '2rem', 54 | } 55 | ) 56 | 57 | export const StyledFooter: StyledComponent = styled( 58 | StyledCardFooter, 59 | { 60 | paddingTop: '1.5rem', 61 | paddingBottom: '1.5rem', 62 | paddingRight: '2rem', 63 | paddingLeft: '2rem', 64 | textAlign: 'right', 65 | } 66 | ) 67 | 68 | export const StyledCard = styled('article', { 69 | backgroundColor: '#fff', 70 | color: '#000', 71 | transition: 'all .3s ease', 72 | borderRadius: '5px', 73 | variants: { 74 | kind: { 75 | primary: {}, 76 | secondary: {}, 77 | tertiary: {}, 78 | }, 79 | hoverAnimation: { 80 | true: { 81 | '&:hover': { 82 | transform: 'scale(1.05)', 83 | }, 84 | }, 85 | }, 86 | }, 87 | compoundVariants: [ 88 | { 89 | kind: 'primary', 90 | hoverAnimation: true, 91 | css: { 92 | '&:hover': { 93 | backgroundColor: '$primary', 94 | color: '#fff', 95 | }, 96 | }, 97 | }, 98 | { 99 | kind: 'secondary', 100 | hoverAnimation: true, 101 | css: { 102 | '&:hover': { 103 | backgroundColor: '$secondary', 104 | color: '#fff', 105 | }, 106 | }, 107 | }, 108 | { 109 | kind: 'tertiary', 110 | hoverAnimation: true, 111 | css: { 112 | '&:hover': { 113 | backgroundColor: '$tertiary', 114 | color: '#fff', 115 | }, 116 | }, 117 | }, 118 | ], 119 | }) 120 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Card/types.ts: -------------------------------------------------------------------------------- 1 | import { ComponentProps } from 'react' 2 | import { KINDS } from '../../types' 3 | import { StyledCard } from './styled' 4 | 5 | export type CardProps = ComponentProps & { 6 | hoverAnimation?: boolean 7 | kind?: KINDS 8 | } 9 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Checkbox/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import { 3 | CheckboxContainer, 4 | StyledInput, 5 | StyledInputContainer, 6 | StyledLabel, 7 | } from './styled' 8 | import { CheckboxProps } from './types' 9 | 10 | export const Checkbox = React.forwardRef( 11 | ( 12 | { 13 | kind, 14 | size, 15 | label, 16 | disabled, 17 | value, 18 | name, 19 | checkColor, 20 | checkSize, 21 | textSize, 22 | textColor, 23 | hoverColor, 24 | id, 25 | align = 'center', 26 | borderRadius, 27 | error, 28 | borderColor, 29 | ...props 30 | }, 31 | ref 32 | ) => { 33 | const [customStyle, setCustomStyle] = React.useState({ 34 | input: {}, 35 | label: {}, 36 | hover: {}, 37 | }) 38 | 39 | React.useEffect(() => { 40 | let css = { 41 | input: {}, 42 | label: {}, 43 | hover: {}, 44 | } 45 | 46 | if (hoverColor) { 47 | css = { 48 | ...css, 49 | hover: { 50 | ...css.hover, 51 | '&:hover': { 52 | backgroundColor: `${hoverColor} !important`, 53 | }, 54 | }, 55 | } 56 | } 57 | 58 | if (checkColor) { 59 | css = { 60 | ...css, 61 | input: { 62 | ...css.input, 63 | '&:before': { 64 | boxShadow: `inset 14px 14px ${checkColor}`, 65 | }, 66 | }, 67 | } 68 | } 69 | 70 | if (borderColor) { 71 | css = { 72 | ...css, 73 | input: { 74 | ...css.input, 75 | borderColor: `${borderColor} !important`, 76 | '&:focus': { 77 | outline: `1px solid ${borderColor} !important`, 78 | }, 79 | }, 80 | } 81 | } 82 | 83 | if (textColor) { 84 | css = { 85 | ...css, 86 | label: { 87 | color: textColor, 88 | }, 89 | } 90 | } 91 | 92 | if (textSize) { 93 | css = { 94 | ...css, 95 | label: { 96 | fontSize: textSize, 97 | }, 98 | } 99 | } 100 | 101 | if (borderRadius) { 102 | css = { 103 | ...css, 104 | input: { 105 | ...css.input, 106 | borderRadius: borderRadius, 107 | }, 108 | } 109 | } 110 | 111 | setCustomStyle(css) 112 | }, []) 113 | 114 | return ( 115 | 116 | 122 | 137 | 138 | 139 | {label && ( 140 | 146 | {label} 147 | 148 | )} 149 | 150 | ) 151 | } 152 | ) 153 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Checkbox/types.ts: -------------------------------------------------------------------------------- 1 | import { CSS } from '@stitches/react/types/css-util' 2 | import { ComponentProps, ReactNode } from 'react' 3 | import { KINDS, SIZES } from '../../types' 4 | import { StyledInput } from './styled' 5 | 6 | type CheckboxComponentOwnProps = { 7 | css?: CSS 8 | kind?: KINDS 9 | size?: SIZES 10 | label?: string | number | ReactNode 11 | disabled?: boolean 12 | value?: string | number 13 | name?: string 14 | align?: 'start' | 'center' | 'end' 15 | checkColor?: string 16 | checkSize?: SIZES 17 | textSize?: string 18 | hoverColor?: string 19 | textColor?: string 20 | borderColor?: string 21 | id?: string 22 | borderRadius?: string 23 | error?: boolean 24 | } 25 | export type CheckboxProps = ComponentProps & 26 | CheckboxComponentOwnProps 27 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Dialog/index.tsx: -------------------------------------------------------------------------------- 1 | import { useControllScroll } from '@finetwork:ui/src/hooks/useControllScroll' 2 | import * as React from 'react' 3 | import { DOMEvent } from '../Select/types' 4 | import { 5 | CloseButton, 6 | CloseButtonIcon, 7 | Overlay, 8 | StyledDialog, 9 | StyledDialogTrigger, 10 | } from './styled' 11 | import { DialogProps, DialogTriggerProps } from './types' 12 | import { handleDialogAnimation } from './utils' 13 | 14 | export const DialogTrigger = React.forwardRef< 15 | HTMLButtonElement, 16 | DialogTriggerProps 17 | >(({ children, id, setIsOpen, ...props }, ref) => { 18 | return ( 19 | setIsOpen(true)} {...props}> 20 | {children} 21 | 22 | ) 23 | }) 24 | 25 | export const Dialog = React.forwardRef( 26 | ( 27 | { 28 | children, 29 | id, 30 | overlay = true, 31 | width = 'auto', 32 | borderRadius, 33 | closeButton = true, 34 | closeButtonSize = '15px', 35 | bottomSheet = false, 36 | isOpen, 37 | setIsOpen, 38 | ...props 39 | }, 40 | ref 41 | ) => { 42 | const dialogRef = React.useRef(null) 43 | const overlayRef = React.useRef(null) 44 | 45 | const [customStyle, setCustomStyle] = React.useState({ 46 | dialog: {}, 47 | closeButton: {}, 48 | }) 49 | 50 | function handleOutsideClick(e: DOMEvent) { 51 | if (!dialogRef.current?.contains(e.target)) { 52 | return setIsOpen(false) 53 | } 54 | } 55 | 56 | function handleKeyPress(e) { 57 | if (e.code === 'Escape') { 58 | setIsOpen(false) 59 | } 60 | } 61 | 62 | const { disableScroll, allowScroll, allowScrollInSpecificComponent } = 63 | useControllScroll() 64 | 65 | React.useEffect(() => { 66 | let css = { 67 | dialog: {}, 68 | closeButton: {}, 69 | } 70 | if (borderRadius) { 71 | css = { 72 | ...css, 73 | dialog: { 74 | ...css.dialog, 75 | borderRadius: borderRadius, 76 | }, 77 | } 78 | } 79 | if (closeButtonSize) { 80 | css = { 81 | ...css, 82 | closeButton: { 83 | width: closeButtonSize, 84 | height: closeButtonSize, 85 | }, 86 | } 87 | } 88 | if (width !== 'full' && width !== 'auto') { 89 | css = { 90 | ...css, 91 | dialog: { 92 | ...css.dialog, 93 | width: width, 94 | }, 95 | } 96 | } 97 | setCustomStyle(css) 98 | }, [width, closeButtonSize, borderRadius]) 99 | 100 | React.useEffect(() => { 101 | handleDialogAnimation({ 102 | dialogElement: dialogRef.current, 103 | overlayElement: overlayRef.current, 104 | isOpen: isOpen, 105 | hasBottomSheet: bottomSheet, 106 | hasOverlay: overlay, 107 | width: width, 108 | }) 109 | }, [isOpen, width, bottomSheet]) 110 | 111 | React.useEffect(() => { 112 | if (isOpen) { 113 | dialogRef.current && dialogRef.current.focus() 114 | disableScroll() 115 | allowScrollInSpecificComponent(dialogRef) 116 | document.addEventListener('click', handleOutsideClick, true) 117 | document.addEventListener('keydown', handleKeyPress, true) 118 | } else { 119 | allowScroll() 120 | document.removeEventListener('click', handleOutsideClick, true) 121 | document.removeEventListener('keydown', handleKeyPress, true) 122 | } 123 | 124 | return () => { 125 | allowScroll() 126 | document.removeEventListener('click', handleOutsideClick, true) 127 | document.removeEventListener('keydown', handleKeyPress, true) 128 | } 129 | }, [isOpen]) 130 | 131 | return ( 132 | <> 133 | 134 | 143 | {closeButton && ( 144 | setIsOpen(false)} 149 | > 150 | 151 | 152 | )} 153 | {children} 154 | 155 | 156 | ) 157 | } 158 | ) 159 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Dialog/styled.ts: -------------------------------------------------------------------------------- 1 | import { styled } from '../../stitches.config' 2 | import { Cross1Icon } from '../icons' 3 | 4 | export const StyledDialogTrigger = styled('button', { 5 | padding: '3px', 6 | transition: 'all .5s ease-in-out', 7 | borderRadius: '5px', 8 | '&:focus-visible': { 9 | outline: 'none', 10 | boxShadow: '0 0 0 2px #fff, 0 0 0 4px rgb(95, 10, 255)', 11 | }, 12 | }) 13 | 14 | export const StyledDialog = styled('div', { 15 | display: 'none', 16 | zIndex: '9999', 17 | position: 'fixed', 18 | top: '50%', 19 | left: '50%', 20 | background: '#FFF', 21 | borderRadius: '5px', 22 | boxShadow: '0px 10px 20px 7px rgba(0,0,0,0.1)', 23 | '-webkit-font-smoothing': 'antialiased', 24 | variants: { 25 | bottomSheet: { 26 | true: { 27 | position: 'fixed', 28 | top: 'unset', 29 | left: 0, 30 | right: 0, 31 | bottom: 0, 32 | margin: '0 auto', 33 | transition: 34 | 'opacity 267ms cubic-bezier(0.4, 0, 0.2, 1) 0ms, transform 178ms cubic-bezier(0.4, 0, 0.2, 1) 0ms', 35 | boxShadow: '0 10px 25px rgba(0,0,0,0.1)', 36 | borderRadius: '5px 5px 0 0', 37 | }, 38 | }, 39 | fullSize: { 40 | true: { 41 | transform: 'unset', 42 | bottom: '0', 43 | left: '0', 44 | right: '0', 45 | borderRadius: 0, 46 | }, 47 | }, 48 | }, 49 | }) 50 | 51 | export const CloseButton = styled('button', { 52 | all: 'unset', 53 | zIndex: 10, 54 | marginBottom: '1rem', 55 | fontFamily: 'inherit', 56 | borderRadius: '100%', 57 | display: 'inline-flex', 58 | alignItems: 'center', 59 | justifyContent: 'center', 60 | position: 'absolute', 61 | top: 15, 62 | right: 15, 63 | padding: '0.5rem', 64 | cursor: 'pointer', 65 | transition: 'background-color 0.3s linear', 66 | '&:hover, &:focus': { 67 | borderRadius: '100%', 68 | backgroundColor: 'rgba(0, 0, 0, 0.05)', 69 | }, 70 | }) 71 | 72 | export const CloseButtonIcon = styled(Cross1Icon, { 73 | fontFamily: 'inherit', 74 | borderRadius: '100%', 75 | height: 'inherit', 76 | width: 'inherit', 77 | position: 'relative', 78 | color: 'black', 79 | }) 80 | 81 | export const Overlay = styled('div', { 82 | display: 'none', 83 | height: '100%', 84 | zIndex: 9999, 85 | position: 'fixed', 86 | left: 0, 87 | right: 0, 88 | bottom: 0, 89 | margin: '0 auto', 90 | }) 91 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Dialog/types.ts: -------------------------------------------------------------------------------- 1 | import { ComponentProps } from '@stitches/react' 2 | import { CSS } from '@stitches/react/types/css-util' 3 | import { StyledDialog, StyledDialogTrigger } from './styled' 4 | 5 | type DialogTriggerComponentOwnProps = { 6 | css?: CSS 7 | id?: string 8 | setIsOpen: React.Dispatch> 9 | } 10 | 11 | export type DialogTriggerProps = ComponentProps & 12 | DialogTriggerComponentOwnProps 13 | 14 | type DialogComponentOwnProps = { 15 | css?: CSS 16 | id?: string 17 | overlay?: boolean 18 | width?: 'full' | 'auto' | string 19 | fullSize?: boolean 20 | borderRadius?: string 21 | closeButton?: boolean 22 | closeButtonSize?: string 23 | bottomSheet?: boolean 24 | isOpen: boolean 25 | setIsOpen: React.Dispatch> 26 | } 27 | export type DialogProps = ComponentProps & 28 | DialogComponentOwnProps 29 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Dialog/utils.ts: -------------------------------------------------------------------------------- 1 | import { 2 | animationCloseSelectMobile, 3 | animationSelectMobile, 4 | dialogAnimationClose, 5 | dialogAnimationOpen, 6 | fadeInBackground, 7 | fadeOutBackground, 8 | fullDialogAnimationClose, 9 | fullDialogAnimationOpen, 10 | } from '@finetwork:ui/src/animations' 11 | 12 | type handleDialogProps = { 13 | dialogElement: HTMLElement 14 | overlayElement: HTMLElement 15 | isOpen: boolean 16 | hasBottomSheet: boolean 17 | hasOverlay: boolean 18 | width: string 19 | } 20 | 21 | type elementsDisplayTypes = { 22 | elements: HTMLElement[] 23 | displayValue: 'block' | 'none' 24 | } 25 | 26 | type elementAnimationTypes = { 27 | element: HTMLElement 28 | animationName: { 29 | (): string 30 | name: string 31 | } 32 | animationConfig: string 33 | } 34 | 35 | function setElementsDisplay({ elements, displayValue }: elementsDisplayTypes) { 36 | elements.forEach((element) => { 37 | element.style.display = displayValue 38 | }) 39 | } 40 | 41 | function setElementAnimation({ 42 | element, 43 | animationName, 44 | animationConfig, 45 | }: elementAnimationTypes) { 46 | element.style.animation = `${animationName} ${animationConfig}` 47 | } 48 | 49 | export const handleDialogAnimation = ({ 50 | dialogElement, 51 | overlayElement, 52 | isOpen, 53 | hasBottomSheet, 54 | hasOverlay, 55 | width, 56 | }: handleDialogProps) => { 57 | const displayValue = isOpen ? 'block' : 'none' 58 | const elements = [dialogElement, overlayElement] 59 | 60 | dialogElement.addEventListener('animationend', () => { 61 | setElementsDisplay({ elements, displayValue }) 62 | }) 63 | 64 | if (isOpen) setElementsDisplay({ elements, displayValue }) 65 | 66 | if (!hasBottomSheet && width !== 'full') { 67 | setElementAnimation({ 68 | element: dialogElement, 69 | animationName: isOpen ? dialogAnimationOpen : dialogAnimationClose, 70 | animationConfig: 'linear 0.25s forwards', 71 | }) 72 | } 73 | 74 | if (hasBottomSheet) { 75 | setElementAnimation({ 76 | element: dialogElement, 77 | animationName: isOpen 78 | ? animationSelectMobile 79 | : animationCloseSelectMobile, 80 | animationConfig: 'linear 0.25s forwards', 81 | }) 82 | } 83 | 84 | if (width === 'full') { 85 | setElementAnimation({ 86 | element: dialogElement, 87 | animationName: isOpen 88 | ? fullDialogAnimationOpen 89 | : fullDialogAnimationClose, 90 | animationConfig: '0.3s ease forwards', 91 | }) 92 | } 93 | 94 | if (hasOverlay) { 95 | setElementAnimation({ 96 | element: overlayElement, 97 | animationName: isOpen ? fadeInBackground : fadeOutBackground, 98 | animationConfig: '0.3s forwards', 99 | }) 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/DropdownMenu/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | import { DropdownMenuComponent, DropdownMenuContentComponent } from './types' 4 | import { RadioGroup, Root, Trigger } from '@radix-ui/react-dropdown-menu' 5 | import { 6 | StyledArrow, 7 | StyledCheckboxItem, 8 | StyledContent, 9 | StyledItem, 10 | StyledItemIndicator, 11 | StyledLabel, 12 | StyledRadioItem, 13 | StyledSeparator, 14 | StyledTriggerItem, 15 | } from './styled' 16 | 17 | export const DropdownMenuItem = StyledItem 18 | export const DropdownMenuCheckboxItem = StyledCheckboxItem 19 | export const DropdownMenuRadioItem = StyledRadioItem 20 | export const DropdownMenuItemIndicator = StyledItemIndicator 21 | export const DropdownMenuTriggerItem = StyledTriggerItem 22 | export const DropdownMenuLabel = StyledLabel 23 | export const DropdownMenuSeparator = StyledSeparator 24 | export const DropdownMenuArrow = StyledArrow 25 | export const DropdownMenuRadioGroup = RadioGroup 26 | export const DropdownMenuTrigger = Trigger 27 | export const DropdownMenu: DropdownMenuComponent = ({ children, ...props }) => ( 28 | {children} 29 | ) 30 | export const DropdownMenuContent: DropdownMenuContentComponent = ({ 31 | children, 32 | withArrow, 33 | side = 'top', 34 | ...props 35 | }) => ( 36 | 37 | {children} 38 | {withArrow && } 39 | 40 | ) 41 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/DropdownMenu/styled.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Arrow, 3 | CheckboxItem, 4 | Content, 5 | Item, 6 | ItemIndicator, 7 | Label, 8 | RadioItem, 9 | Separator, 10 | TriggerItem, 11 | } from '@radix-ui/react-dropdown-menu' 12 | import { 13 | slideDownAndFade, 14 | slideLeftAndFade, 15 | slideRightAndFade, 16 | slideUpAndFade, 17 | } from '../../animations' 18 | 19 | import { mauve } from '@radix-ui/colors' 20 | import { styled } from '../../stitches.config' 21 | 22 | export const StyledContent = styled(Content, { 23 | minWidth: 220, 24 | backgroundColor: 'white', 25 | borderRadius: 6, 26 | padding: 5, 27 | boxShadow: 28 | '0px 10px 38px -10px rgba(22, 23, 24, 0.35), 0px 10px 20px -15px rgba(22, 23, 24, 0.2)', 29 | '@media (prefers-reduced-motion: no-preference)': { 30 | animationDuration: '400ms', 31 | animationTimingFunction: 'cubic-bezier(0.16, 1, 0.3, 1)', 32 | willChange: 'transform, opacity', 33 | '&[data-state="open"]': { 34 | '&[data-side="top"]': { animationName: slideDownAndFade }, 35 | '&[data-side="right"]': { animationName: slideLeftAndFade }, 36 | '&[data-side="bottom"]': { animationName: slideUpAndFade }, 37 | '&[data-side="left"]': { animationName: slideRightAndFade }, 38 | }, 39 | }, 40 | }) 41 | 42 | export const itemStyles = { 43 | all: 'unset', 44 | fontSize: 13, 45 | lineHeight: 1, 46 | borderRadius: 3, 47 | display: 'flex', 48 | alignItems: 'center', 49 | height: 25, 50 | padding: '0 5px', 51 | position: 'relative', 52 | paddingLeft: 25, 53 | userSelect: 'none', 54 | color: mauve.mauve12, 55 | cursor: 'pointer', 56 | '&[data-disabled]': { 57 | color: mauve.mauve8, 58 | pointerEvents: 'none', 59 | }, 60 | '&:focus': { 61 | color: mauve.mauve2, 62 | }, 63 | variants: { 64 | kind: { 65 | primary: { 66 | '&:focus': { 67 | backgroundColor: '$primary700', 68 | }, 69 | }, 70 | secondary: { 71 | '&:focus': { 72 | backgroundColor: '$secondary700', 73 | }, 74 | }, 75 | tertiary: { 76 | '&:focus': { 77 | backgroundColor: '$tertiary700', 78 | }, 79 | }, 80 | }, 81 | }, 82 | defaultVariants: { 83 | kind: 'primary', 84 | }, 85 | } 86 | 87 | export const StyledItem = styled(Item, { ...itemStyles }) 88 | export const StyledCheckboxItem = styled(CheckboxItem, { ...itemStyles }) 89 | export const StyledRadioItem = styled(RadioItem, { ...itemStyles }) 90 | export const StyledTriggerItem = styled(TriggerItem) 91 | 92 | export const StyledLabel = styled(Label, { 93 | paddingLeft: 25, 94 | fontSize: 12, 95 | lineHeight: '25px', 96 | color: mauve.mauve11, 97 | }) 98 | 99 | export const StyledSeparator = styled(Separator, { 100 | height: 1, 101 | margin: 5, 102 | variants: { 103 | kind: { 104 | primary: { 105 | backgroundColor: '$primary300', 106 | }, 107 | secondary: { 108 | backgroundColor: '$secondary300', 109 | }, 110 | tertiary: { 111 | backgroundColor: '$tertiary300', 112 | }, 113 | }, 114 | }, 115 | defaultVariants: { 116 | kind: 'primary', 117 | }, 118 | }) 119 | 120 | export const StyledItemIndicator = styled(ItemIndicator, { 121 | position: 'absolute', 122 | left: 0, 123 | width: 25, 124 | display: 'inline-flex', 125 | alignItems: 'center', 126 | justifyContent: 'center', 127 | }) 128 | export const StyledArrow = styled(Arrow, { 129 | fill: 'white', 130 | }) 131 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/DropdownMenu/types.ts: -------------------------------------------------------------------------------- 1 | import { ComponentProps, FC } from 'react' 2 | 3 | import { Root } from '@radix-ui/react-dropdown-menu' 4 | import { StyledContent } from './styled' 5 | 6 | type DropdownMenuContentProps = ComponentProps & { 7 | withArrow?: boolean 8 | } 9 | type DropdownMenuProps = ComponentProps 10 | 11 | export type DropdownMenuContentComponent = FC 12 | export type DropdownMenuComponent = FC 13 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Input/types.ts: -------------------------------------------------------------------------------- 1 | import { ComponentProps, FC, ReactNode, SetStateAction } from 'react' 2 | import { Enhancer, KINDS, SIZES } from '../../types' 3 | import { 4 | StyledContainer, 5 | StyledContainerInput, 6 | StyledEnhancer, 7 | StyledInput, 8 | StyledLabel, 9 | } from './styled' 10 | 11 | export type InputProps = Omit< 12 | Omit, 'startEnhancer'>, 13 | 'size' 14 | > & { 15 | containerProps?: ComponentProps 16 | inputContainerProps?: ComponentProps 17 | size?: SIZES 18 | kind?: KINDS 19 | label?: ReactNode | string 20 | isDisabled?: boolean 21 | startEnhancer?: Enhancer 22 | endEnhancer?: Enhancer 23 | isError?: boolean 24 | errorMessage?: string 25 | info?: ReactNode | string 26 | success?: boolean 27 | handleClear?: () => any 28 | labelProps?: ComponentProps 29 | enhancerProps?: ComponentProps 30 | handleChange?: (value: string) => void 31 | formattedPhoneNumber?: boolean 32 | id?: string 33 | } 34 | 35 | type InputPasswordProps = Omit< 36 | React.ComponentProps, 37 | 'size' 38 | > & { 39 | size?: SIZES 40 | kind?: KINDS 41 | isDisabled?: boolean 42 | handleClear?: () => any 43 | isError: string | number | boolean 44 | } 45 | 46 | export type InputComponent = FC 47 | export type InputPasswordComponent = FC 48 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Link/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | import { StyledEndEnhancer, StyledLink, StyledStartEnhancer } from './styled' 4 | 5 | import { LinkProps } from './types' 6 | import { RenderEnhancer } from '../../utils' 7 | 8 | export const Link = React.forwardRef< 9 | React.ElementRef, 10 | LinkProps 11 | >( 12 | ( 13 | { 14 | children, 15 | kind, 16 | disabled, 17 | size, 18 | textTransform, 19 | startEnhancer, 20 | endEnhancer, 21 | onClick, 22 | animation, 23 | ...props 24 | }, 25 | ref 26 | ) => { 27 | return ( 28 | 41 | {startEnhancer && ( 42 | 43 | 44 | 45 | )} 46 | {children} 47 | {endEnhancer && ( 48 | 49 | 50 | 51 | )} 52 | 53 | ) 54 | } 55 | ) 56 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Link/styled.ts: -------------------------------------------------------------------------------- 1 | import { BooleanString, FONTS, KINDS, SIZES } from '../../types' 2 | 3 | import { Property } from '@stitches/react/types/css' 4 | import { StyledComponent } from '@stitches/react/types/styled-component' 5 | import { styled } from '../../stitches.config' 6 | 7 | export const StyledStartEnhancer = styled('div', { 8 | transition: 'all .3s ease', 9 | marginRight: '0.65em', 10 | right: 0, 11 | position: 'relative', 12 | display: 'flex', 13 | }) 14 | export const StyledEndEnhancer = styled('div', { 15 | transition: 'all .3s ease', 16 | marginLeft: '0.65em', 17 | left: 0, 18 | position: 'relative', 19 | display: 'flex', 20 | }) 21 | 22 | export const StyledLink = styled('a', { 23 | width: 'fit-content', 24 | transition: 'all .3s ease', 25 | textTransform: 'none', 26 | fontWeight: 500, 27 | cursor: 'pointer', 28 | fontFamily: 'inherit', 29 | borderRadius: '2px', 30 | padding: '2px', 31 | variants: { 32 | animation: { 33 | true: {}, 34 | false: {}, 35 | }, 36 | font: { 37 | primary: { 38 | fontFamily: '$primary', 39 | }, 40 | secondary: { 41 | fontFamily: '$secondary', 42 | }, 43 | }, 44 | endEnhancer: { 45 | true: { 46 | display: 'flex', 47 | alignItems: 'center', 48 | flexDirection: 'row', 49 | }, 50 | false: {}, 51 | }, 52 | startEnhancer: { 53 | true: { 54 | display: 'flex', 55 | alignItems: 'center', 56 | flexDirection: 'row', 57 | }, 58 | false: {}, 59 | }, 60 | kind: { 61 | linkText: { 62 | color: '$linkText', 63 | '&:focus': { 64 | color: '$linkText600', 65 | boxShadow: '0 0 0 2px $colors$linkText', 66 | }, 67 | '&:hover': { 68 | color: '$linkText600', 69 | }, 70 | }, 71 | primary: { 72 | color: '$primary', 73 | '&:focus': { 74 | color: '$primary600', 75 | boxShadow: '0 0 0 2px $colors$primary300', 76 | }, 77 | '&:hover': { 78 | color: '$primary600', 79 | }, 80 | }, 81 | secondary: { 82 | color: '$secondary', 83 | '&:focus': { 84 | color: '$secondary600', 85 | boxShadow: '0 0 0 2px $colors$secondary', 86 | }, 87 | '&:hover': { 88 | color: '$secondary600', 89 | }, 90 | }, 91 | tertiary: { 92 | color: '$tertiary', 93 | '&:focus': { 94 | color: '$tertiary600', 95 | boxShadow: '0 0 0 2px $colors$tertiary', 96 | }, 97 | '&:hover': { 98 | color: '$tertiary600', 99 | }, 100 | }, 101 | }, 102 | textTransform: { 103 | capitalize: { 104 | textTransform: 'capitalize', 105 | }, 106 | 'full-size-kana': { 107 | textTransform: 'full-size-kana', 108 | }, 109 | 'full-width': { 110 | textTransform: 'full-width', 111 | }, 112 | lowercase: { 113 | textTransform: 'lowercase', 114 | }, 115 | none: { 116 | textTransform: 'none', 117 | }, 118 | uppercase: { 119 | textTransform: 'uppercase', 120 | }, 121 | }, 122 | size: { 123 | small: { 124 | lineHeight: '17px', 125 | fontSize: '12px', 126 | }, 127 | medium: { 128 | lineHeight: '21px', 129 | fontSize: '16px', 130 | }, 131 | large: { 132 | lineHeight: '25px', 133 | fontSize: '20px', 134 | }, 135 | }, 136 | disabled: { 137 | true: { 138 | color: '$disabled', 139 | pointerEvents: 'none', 140 | }, 141 | false: {}, 142 | }, 143 | }, 144 | compoundVariants: [ 145 | { 146 | endEnhancer: false, 147 | startEnhancer: false, 148 | animation: true, 149 | css: { 150 | '&:hover': { 151 | transform: 'translateY(3px)', 152 | }, 153 | }, 154 | }, 155 | { 156 | endEnhancer: true, 157 | animation: true, 158 | css: { 159 | '&:hover': { 160 | '& > *:last-child': { 161 | left: '.5rem', 162 | }, 163 | }, 164 | }, 165 | }, 166 | { 167 | startEnhancer: true, 168 | animation: true, 169 | css: { 170 | '&:hover': { 171 | '& > *:first-child': { 172 | right: '.5rem', 173 | }, 174 | }, 175 | }, 176 | }, 177 | ], 178 | defaultVariants: { 179 | kind: 'primary', 180 | size: 'medium', 181 | animation: true, 182 | startEnhancer: false, 183 | endEnhancer: false, 184 | textTransform: 'none', 185 | }, 186 | }) 187 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Link/types.ts: -------------------------------------------------------------------------------- 1 | import { CSS } from '../../stitches.config' 2 | import { VariantProps } from '@stitches/react' 3 | import { AnchorHTMLAttributes, ComponentProps } from 'react' 4 | import { Enhancer, SIZES } from '../../types' 5 | 6 | import { StyledLink } from './styled' 7 | 8 | type Props = Omit< 9 | ComponentProps, 10 | 'endEnhancer' | 'startEnhancer' 11 | > & { 12 | href?: string 13 | kind?: string 14 | disabled?: boolean 15 | startEnhancer?: Enhancer 16 | endEnhancer?: Enhancer 17 | size?: SIZES 18 | textTransform?: string 19 | animation?: boolean 20 | as?: any 21 | [key: string]: any 22 | } 23 | type NativeAttrs = Omit, keyof Props> 24 | type LinkVariantsProps = VariantProps 25 | 26 | export type LinkProps = Props & NativeAttrs & LinkVariantsProps & { css?: CSS } 27 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Loading/index.tsx: -------------------------------------------------------------------------------- 1 | import { spin } from '@finetwork:ui/src/animations' 2 | import * as React from 'react' 3 | import { StyledSpinner } from './styled' 4 | import { LoadingComponent } from './types' 5 | 6 | export const Loading: LoadingComponent = ({ 7 | size = 24, 8 | speed = 1, 9 | color = '#fff', 10 | thickness = 2, 11 | }) => { 12 | const [styles, setStyles] = React.useState({}) 13 | 14 | React.useEffect(() => { 15 | let css = {} 16 | 17 | if (size) 18 | css = { 19 | ...css, 20 | width: size, 21 | height: size, 22 | } 23 | 24 | if (speed) { 25 | css = { 26 | ...css, 27 | animation: `${spin} ${speed}s linear infinite`, 28 | } 29 | } 30 | 31 | if (color || thickness) { 32 | css = { 33 | ...css, 34 | border: `${thickness}px solid ${color}`, 35 | borderLeftColor: 'transparent', 36 | } 37 | } 38 | 39 | setStyles(css) 40 | }, []) 41 | return 42 | } 43 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Loading/styled.ts: -------------------------------------------------------------------------------- 1 | import { spin } from '../../animations' 2 | import { styled } from '../../stitches.config' 3 | 4 | export const StyledSpinner = styled('div', { 5 | // border: '2px solid #fff', 6 | animation: `${spin} 1s linear infinite`, 7 | width: '36px', 8 | height: '36px', 9 | borderRadius: '50%', 10 | borderLeftColor: 'transparent', 11 | }) 12 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Loading/types.ts: -------------------------------------------------------------------------------- 1 | import { FC } from 'react' 2 | 3 | export type LoadingProps = { 4 | size?: number 5 | speed?: number 6 | color?: string 7 | thickness?: number 8 | } 9 | export type LoadingComponent = FC 10 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Radio/styled.ts: -------------------------------------------------------------------------------- 1 | import { styled } from '../../stitches.config' 2 | import { Paragraph4, Paragraph5 } from '../Typography' 3 | 4 | export const StyledContainer = styled('div', { 5 | display: 'flex', 6 | flexDirection: 'column', 7 | }) 8 | 9 | export const StyledRadioGroupContainer = styled('div', { 10 | display: 'flex', 11 | variants: { 12 | direction: { 13 | horizontal: { 14 | flexDirection: 'row', 15 | }, 16 | vertical: { 17 | flexDirection: 'column', 18 | }, 19 | }, 20 | }, 21 | defaultVariants: { 22 | direction: 'horizontal', 23 | }, 24 | }) 25 | 26 | export const StyledRadioContainer = styled('div', { 27 | display: 'flex', 28 | alignItems: 'center', 29 | gap: '0.3em', 30 | padding: '0.3rem 0.5rem', 31 | borderRadius: '10px', 32 | cursor: 'pointer', 33 | variants: { 34 | size: { 35 | small: { 36 | fontSize: '20px', 37 | marginLeft: '-12px', 38 | }, 39 | medium: { 40 | fontSize: '25px', 41 | marginLeft: '-12px', 42 | }, 43 | }, 44 | isDisabled: { 45 | true: { 46 | cursor: 'not-allowed', 47 | }, 48 | }, 49 | }, 50 | defaultVariants: { 51 | size: 'medium', 52 | }, 53 | }) 54 | 55 | export const StyledTitle = styled(Paragraph4, { 56 | color: '#333333 !important', 57 | }) 58 | 59 | export const StyledText = styled('label', { 60 | fontSize: '16px', 61 | cursor: 'pointer', 62 | variants: { 63 | size: { 64 | small: { 65 | fontSize: '12px', 66 | }, 67 | medium: { 68 | fontSize: '16px', 69 | }, 70 | }, 71 | isDisabled: { 72 | true: { 73 | color: '$disabled !important', 74 | cursor: 'not-allowed', 75 | }, 76 | }, 77 | }, 78 | defaultVariants: { 79 | size: 'medium', 80 | }, 81 | }) 82 | 83 | export const StyledErrorText = styled(Paragraph5, { 84 | color: '$error !important', 85 | }) 86 | 87 | export const StyledInputContainer = styled('div', { 88 | display: 'table', 89 | alignItems: 'center', 90 | padding: '0.3rem', 91 | borderRadius: '50%', 92 | transition: '100ms background ease-in', 93 | '&:hover': { 94 | backgroundColor: '$colors$secondary200', 95 | }, 96 | variants: { 97 | kind: { 98 | primary: { 99 | '&:hover': { 100 | backgroundColor: '$colors$secondary200', 101 | }, 102 | }, 103 | secondary: { 104 | '&:hover': { 105 | backgroundColor: '$colors$secondary200', 106 | }, 107 | }, 108 | tertiary: { 109 | '&:hover': { 110 | backgroundColor: '$colors$tertiary200', 111 | }, 112 | }, 113 | }, 114 | size: { 115 | small: { 116 | width: '23px', 117 | height: '23px', 118 | }, 119 | medium: { 120 | width: '33px', 121 | height: '33px', 122 | }, 123 | }, 124 | isDisabled: { 125 | true: { 126 | '&:hover': { 127 | cursor: 'not-allowed !important', 128 | backgroundColor: '$disabled100 !important', 129 | }, 130 | }, 131 | }, 132 | }, 133 | defaultVariants: { 134 | kind: 'primary', 135 | size: 'medium', 136 | }, 137 | }) 138 | 139 | export const StyledInput = styled('input', { 140 | '-webkit-apapparance': 'none', 141 | appearance: 'none', 142 | margin: 0, 143 | font: 'inherit', 144 | width: '1.5rem', 145 | height: '1.5rem', 146 | borderRadius: '50%', 147 | display: 'grid', 148 | placeContent: 'center', 149 | transform: 'translateY(0em)', 150 | cursor: 'pointer', 151 | '&:before': { 152 | content: '', 153 | width: '10px', 154 | height: '10px', 155 | borderRadius: '50%', 156 | transition: '115ms transform ease-in-out', 157 | transform: 'scale(0)', 158 | boxShadow: 'inset 14px 14px $colors$primary', 159 | }, 160 | '&:checked': { 161 | '&:before': { 162 | transform: 'scale(1)', 163 | }, 164 | }, 165 | variants: { 166 | size: { 167 | small: { 168 | width: '1.063rem', 169 | height: '1.063rem', 170 | border: '1px solid #000', 171 | '&:before': { 172 | width: '7px', 173 | height: '7px', 174 | }, 175 | }, 176 | medium: { 177 | width: '1.5rem', 178 | height: '1.5rem', 179 | border: '1px solid #000', 180 | '&:before': { 181 | width: '10px', 182 | height: '10px', 183 | }, 184 | }, 185 | }, 186 | kind: { 187 | primary: { 188 | '&:before': { 189 | boxShadow: 'inset 14px 14px $colors$primary', 190 | }, 191 | }, 192 | secondary: { 193 | '&:before': { 194 | boxShadow: 'inset 14px 14px $colors$secondary', 195 | }, 196 | }, 197 | tertiary: { 198 | '&:before': { 199 | boxShadow: 'inset 14px 14px $colors$tertiary', 200 | }, 201 | }, 202 | }, 203 | isDisabled: { 204 | true: { 205 | cursor: 'not-allowed', 206 | border: '1px solid $disabled', 207 | '&:before': { 208 | boxShadow: 'inset 14px 14px $colors$disabled', 209 | }, 210 | }, 211 | }, 212 | }, 213 | defaultVariants: { 214 | size: 'medium', 215 | kind: 'primary', 216 | }, 217 | }) 218 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Radio/types.ts: -------------------------------------------------------------------------------- 1 | import { CSS } from '@stitches/react/types/css-util' 2 | import { ComponentProps, ReactNode } from 'react' 3 | import { Enhancer, KINDS } from '../../types' 4 | import { StyledInput } from './styled' 5 | 6 | export type RadioGroupComponentProps = { 7 | direction?: 'vertical' | 'horizontal' 8 | name?: string 9 | title?: Enhancer 10 | children?: ReactNode 11 | error?: string 12 | optionsGap?: string 13 | } 14 | 15 | type RadioComponentOwnProps = { 16 | css?: CSS 17 | kind?: KINDS 18 | size?: 'small' | 'medium' 19 | fontSize?: string 20 | label?: string | ReactNode 21 | disabled?: boolean 22 | value?: string | number 23 | name?: string 24 | dotColor?: string 25 | dotSize?: string 26 | dotHover?: string 27 | textColor?: string 28 | borderColor?: string 29 | id?: string 30 | checked?: boolean 31 | inputSize?: string 32 | } 33 | export type RadioProps = ComponentProps & 34 | RadioComponentOwnProps 35 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Select/types.ts: -------------------------------------------------------------------------------- 1 | import { CSS } from '@stitches/react/types/css-util' 2 | import * as React from 'react' 3 | import { KINDS } from '../../types' 4 | 5 | export type Value = 6 | | { value: string | number; label: string | number } 7 | | Array<{ value: string | number; label: string | number }> 8 | 9 | export type TypeOption = { 10 | value: string | number 11 | label: string | number 12 | disabled?: boolean 13 | } 14 | 15 | type OptionsWithTitle = { 16 | title: string | number 17 | options: Array 18 | disabled?: boolean 19 | } 20 | 21 | export type TypeOptions = Array | Array 22 | 23 | export interface DOMEvent extends Event { 24 | readonly target: T 25 | } 26 | 27 | type Shared = { 28 | id: string 29 | onChange: React.Dispatch> 30 | kind?: KINDS 31 | withoutCheck?: boolean 32 | scrollbarColor?: string 33 | selectedOptionColor?: string 34 | optionTextColor?: string 35 | value: Value 36 | grouping?: boolean 37 | radio?: boolean 38 | } 39 | 40 | export type SelectProps = { 41 | css?: CSS 42 | width?: string 43 | label?: string | React.ReactNode 44 | disabled?: boolean 45 | name?: string 46 | labelSize?: string 47 | hoverBorderColor?: string | 'none' 48 | labelColor?: string 49 | borderColor?: string | 'none' 50 | borderRadius?: string 51 | checkColor?: string 52 | hoverOptionTextColor?: string 53 | hoverBackgroundOptionColor?: string 54 | error?: string 55 | search?: boolean 56 | optionContainerHeight?: string 57 | optionContainerTitle?: string 58 | options: TypeOptions 59 | notFoundText?: string 60 | searchText?: string 61 | backgroundColor?: string 62 | bottomSheet?: boolean 63 | containerBackgroundColor?: string 64 | optionsBackgroundColor?: string 65 | containerColor?: string 66 | optionsSize?: string 67 | optionsPadding?: string 68 | separator?: string 69 | } & Shared 70 | 71 | export type SelectState = { 72 | isOpen: boolean 73 | searchValue: string 74 | isOverlay: boolean 75 | allPosibleOptions: TypeOptions 76 | } 77 | 78 | export type OptionsProps = { 79 | allPosibleOptions: TypeOptions 80 | optionRef: React.MutableRefObject 81 | setIsOpen: (isOpen: boolean) => void 82 | customStyle: { 83 | select: {} 84 | label: {} 85 | hover: {} 86 | container: {} 87 | optionsContainer: {} 88 | optionsGroup: {} 89 | options: {} 90 | } 91 | isMultiple: boolean 92 | } & Shared 93 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Separator/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import { StyledSeparator } from './styled' 3 | import { SeparatorProps } from './types' 4 | 5 | export const Separator = React.forwardRef( 6 | ( 7 | { 8 | id, 9 | kind, 10 | orientation = 'horizontal', 11 | color, 12 | width, 13 | height, 14 | type = 'solid', 15 | align = 'center', 16 | borderRadius, 17 | borderWidth, 18 | ...props 19 | }, 20 | ref 21 | ) => { 22 | const [customStyle, setCustomStyle] = React.useState({ 23 | hr: {}, 24 | }) 25 | React.useEffect(() => { 26 | let css = { 27 | hr: {}, 28 | } 29 | 30 | if (color) { 31 | css = { 32 | ...css, 33 | hr: { 34 | ...css.hr, 35 | borderColor: `${color} !important`, 36 | }, 37 | } 38 | } 39 | 40 | if (width) { 41 | css = { 42 | ...css, 43 | hr: { 44 | ...css.hr, 45 | width: `${ 46 | orientation === 'horizontal' ? width : height 47 | } !important`, 48 | }, 49 | } 50 | } 51 | 52 | if (height) { 53 | css = { 54 | ...css, 55 | hr: { 56 | ...css.hr, 57 | height: `${ 58 | orientation === 'horizontal' ? height : width 59 | } !important`, 60 | }, 61 | } 62 | } 63 | 64 | if (borderWidth) { 65 | css = { 66 | ...css, 67 | hr: { 68 | ...css.hr, 69 | borderWidth: `${borderWidth}`, 70 | }, 71 | } 72 | } 73 | 74 | if (borderRadius) { 75 | css = { 76 | ...css, 77 | hr: { 78 | ...css.hr, 79 | borderRadius: `${borderRadius} !important`, 80 | }, 81 | } 82 | } 83 | 84 | setCustomStyle(css) 85 | }, []) 86 | return ( 87 | 95 | ) 96 | } 97 | ) 98 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Separator/styled.ts: -------------------------------------------------------------------------------- 1 | import { styled } from '../../stitches.config' 2 | 3 | export const StyledSeparator = styled('hr', { 4 | borderColor: '#ddd', 5 | width: '100%', 6 | variants: { 7 | orientation: { 8 | horizontal: {}, 9 | vertical: { 10 | height: '100%', 11 | width: '1px', 12 | }, 13 | }, 14 | type: { 15 | solid: { 16 | borderStyle: 'solid', 17 | }, 18 | dashed: { 19 | borderStyle: 'dashed', 20 | }, 21 | dotted: { 22 | borderStyle: 'dotted', 23 | }, 24 | }, 25 | kind: { 26 | primary: { 27 | borderColor: '$primary', 28 | }, 29 | secondary: { 30 | borderColor: '$secondary', 31 | }, 32 | tertiary: { 33 | borderColor: '$tertiary', 34 | }, 35 | }, 36 | align: { 37 | start: { 38 | alignSelf: 'start', 39 | }, 40 | center: { 41 | alignSelf: 'center', 42 | }, 43 | end: { 44 | alignSelf: 'end', 45 | }, 46 | }, 47 | }, 48 | }) 49 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Separator/types.ts: -------------------------------------------------------------------------------- 1 | import { CSS } from '@stitches/react/types/css-util' 2 | import { ComponentProps } from 'react' 3 | import { KINDS } from '../../types' 4 | import { StyledSeparator } from './styled' 5 | 6 | type SeparatorComponentOwnProps = { 7 | css?: CSS 8 | id?: string 9 | kind?: KINDS 10 | orientation?: 'horizontal' | 'vertical' 11 | color?: string 12 | width?: string 13 | height?: string 14 | type?: 'solid' | 'dashed' | 'dotted' 15 | align?: 'start' | 'center' | 'end' 16 | borderRadius?: string 17 | borderWidth?: string 18 | } 19 | 20 | export type SeparatorProps = ComponentProps & 21 | SeparatorComponentOwnProps 22 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Skeleton/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | import { 4 | StyledRoot, 5 | StyledElement, 6 | getAnimationColor, 7 | StyledInnerCircle, 8 | StyledOuterCircle, 9 | StyledGroup, 10 | StyledChildrenContainer, 11 | } from './styled' 12 | 13 | import { SkeletonComponent } from './types' 14 | 15 | export const Skeleton: SkeletonComponent = ({ 16 | width, 17 | height, 18 | kind = 'primary', 19 | backgroundColor = 'rgb(238, 238, 238)', 20 | animationColor = 'rgb(246, 246, 246)', 21 | borderRadius = '5px', 22 | children, 23 | chart, 24 | group, 25 | align = 'start', 26 | ...props 27 | }) => { 28 | const [styles, setStyles] = React.useState({ 29 | chart: {}, 30 | }) 31 | 32 | const cssStyles: any = { 33 | width, 34 | height, 35 | backgroundImage: getAnimationColor(kind, backgroundColor, animationColor), 36 | borderRadius: borderRadius, 37 | } 38 | 39 | React.useEffect(() => { 40 | let css = { ...styles } 41 | if (chart) { 42 | css = { 43 | ...css, 44 | chart: { 45 | background: chart?.backgroundInnerCircle 46 | ? chart?.backgroundInnerCircle 47 | : '#fff', 48 | }, 49 | } 50 | } 51 | setStyles(css) 52 | }, [chart]) 53 | 54 | if (group) { 55 | return ( 56 | 62 | {Array(group.repeat) 63 | .fill('') 64 | .map((_, index) => { 65 | if (!chart) { 66 | return ( 67 | 72 | {children} 73 | 74 | ) 75 | } 76 | 77 | return ( 78 | 89 | 93 | 94 | ) 95 | })} 96 | 97 | ) 98 | } 99 | 100 | if (chart) { 101 | return ( 102 | 107 | 113 | {children && ( 114 | 123 | {children} 124 | 125 | )} 126 | 127 | 128 | ) 129 | } 130 | 131 | return ( 132 | 133 | 134 | {children} 135 | 136 | 137 | ) 138 | } 139 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Skeleton/styled.ts: -------------------------------------------------------------------------------- 1 | import { keyframes, styled } from '../../stitches.config' 2 | 3 | export const getAnimationColor = ( 4 | kind: 'primary' | 'secondary', 5 | background: string, 6 | animation: string 7 | ) => { 8 | if (kind === 'secondary') { 9 | background = '$secondary300' 10 | animation = '$secondary200' 11 | } 12 | 13 | return `linear-gradient(135deg, 14 | ${background}, 15 | ${background}, 16 | ${background}, 17 | ${background}, 18 | ${background}, 19 | ${background}, 20 | ${animation}, 21 | ${background}, 22 | ${background}, 23 | ${background}, 24 | ${background}, 25 | ${background}, 26 | ${background})` 27 | } 28 | 29 | const animationStyle = { 30 | animation: `${keyframes({ 31 | '0%': { 32 | backgroundPosition: '100% 50%', 33 | }, 34 | '100%': { 35 | backgroundPosition: '0% 50%', 36 | }, 37 | })}`, 38 | animationTimingFunction: 'linear', 39 | animationDuration: '1.5s', 40 | animationIterationCount: 'infinite', 41 | backgroundSize: '400% 100%', 42 | } 43 | 44 | export const StyledGroup = styled('div', { 45 | display: 'flex', 46 | width: '100%', 47 | variants: { 48 | align: { 49 | start: {}, 50 | center: {}, 51 | end: {}, 52 | }, 53 | direction: { 54 | vertical: {}, 55 | horizontal: {}, 56 | }, 57 | }, 58 | compoundVariants: [ 59 | { 60 | direction: 'vertical', 61 | align: 'start', 62 | css: { 63 | alignItems: 'start', 64 | flexDirection: 'column', 65 | }, 66 | }, 67 | { 68 | direction: 'vertical', 69 | align: 'center', 70 | css: { 71 | alignItems: 'center', 72 | flexDirection: 'column', 73 | }, 74 | }, 75 | { 76 | direction: 'vertical', 77 | align: 'end', 78 | css: { 79 | alignItems: 'end', 80 | flexDirection: 'column', 81 | }, 82 | }, 83 | { 84 | direction: 'horizontal', 85 | align: 'start', 86 | css: { 87 | justifyContent: 'start', 88 | flexDirection: 'row', 89 | }, 90 | }, 91 | { 92 | direction: 'horizontal', 93 | align: 'center', 94 | css: { 95 | justifyContent: 'center', 96 | flexDirection: 'row', 97 | }, 98 | }, 99 | { 100 | direction: 'horizontal', 101 | align: 'end', 102 | css: { 103 | justifyContent: 'end', 104 | flexDirection: 'row', 105 | }, 106 | }, 107 | ], 108 | }) 109 | 110 | export const StyledRoot = styled('div', { 111 | display: 'flex', 112 | width: '100%', 113 | ...animationStyle, 114 | variants: { 115 | align: { 116 | start: { 117 | justifyContent: 'start', 118 | }, 119 | center: { 120 | justifyContent: 'center', 121 | }, 122 | end: { 123 | justifyContent: 'end', 124 | }, 125 | }, 126 | }, 127 | }) 128 | 129 | export const StyledElement = styled('div', { 130 | width: '100%', 131 | height: '100%', 132 | display: 'flex', 133 | ...animationStyle, 134 | variants: { 135 | isChildren: { 136 | true: { 137 | ...animationStyle, 138 | '-webkit-text-fill-color': 'transparent', 139 | '-webkit-background-clip': 'text', 140 | }, 141 | }, 142 | }, 143 | }) 144 | 145 | export const StyledOuterCircle = styled('div', { 146 | borderRadius: '50%', 147 | ...animationStyle, 148 | display: 'flex', 149 | justifyContent: 'center', 150 | alignItems: 'center', 151 | variants: { 152 | size: { 153 | small: { 154 | width: '120px', 155 | height: '120px', 156 | }, 157 | medium: { 158 | width: '140px', 159 | height: '140px', 160 | }, 161 | large: { 162 | width: '153px', 163 | height: '153px', 164 | }, 165 | }, 166 | }, 167 | defaultVariants: { 168 | size: 'medium', 169 | }, 170 | }) 171 | 172 | export const StyledInnerCircle = styled('div', { 173 | borderRadius: '50%', 174 | background: '#fff', 175 | display: 'flex', 176 | variants: { 177 | size: { 178 | small: { 179 | width: '102px', 180 | height: '102px', 181 | }, 182 | medium: { 183 | width: '122px', 184 | height: '122px', 185 | }, 186 | large: { 187 | width: '135px', 188 | height: '135px', 189 | }, 190 | }, 191 | }, 192 | }) 193 | 194 | export const StyledChildrenContainer = styled('div', { 195 | display: 'flex', 196 | justifyContent: 'center', 197 | alignItems: 'center', 198 | width: '100%', 199 | ...animationStyle, 200 | '-webkit-text-fill-color': 'transparent', 201 | '-webkit-background-clip': 'text', 202 | }) 203 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Skeleton/types.ts: -------------------------------------------------------------------------------- 1 | import { SIZES } from '@finetwork:ui/src/types' 2 | import { ComponentProps, FC } from 'react' 3 | import { StyledRoot } from './styled' 4 | 5 | type SkeletonProps = Omit, 'hasRows'> & { 6 | kind?: 'primary' | 'secondary' 7 | width?: number | string 8 | height?: number | string 9 | backgroundColor?: string 10 | animationColor?: string 11 | borderRadius?: string 12 | chart?: { 13 | size?: SIZES 14 | backgroundInnerCircle?: string 15 | } 16 | group?: { 17 | direction: 'vertical' | 'horizontal' 18 | repeat: number 19 | gap: string 20 | } 21 | align?: 'start' | 'center' | 'end' 22 | } 23 | 24 | export type SkeletonComponent = FC 25 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Switch/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import { 3 | StyledEnhancerContainer, 4 | StyledInput, 5 | StyledLoadingContainer, 6 | StyledSlider, 7 | StyledSwitch, 8 | } from './styled' 9 | import { SwitchComponent } from './types' 10 | import { RenderEnhancer } from '@finetwork:ui/src/utils' 11 | import { Loading } from '../Loading' 12 | 13 | export const Switch = React.forwardRef( 14 | ( 15 | { 16 | size = 'medium', 17 | id, 18 | isLoading, 19 | checked, 20 | loadingColor = '#fff', 21 | loadingSpeed = 1, 22 | kind = 'primary', 23 | type, 24 | disabled, 25 | handleChange, 26 | sliderColor, 27 | switchBackgroundColor, 28 | enhancerIcons, 29 | focusOutlineColor, 30 | ...props 31 | }, 32 | ref 33 | ) => { 34 | const [switchStyles, setSwitchStyles] = React.useState({ 35 | slider: {}, 36 | switch: {}, 37 | input: {}, 38 | }) 39 | const [isFirstChecked, setIsFirstChecked] = React.useState(true) 40 | 41 | React.useEffect(() => { 42 | let css = { slider: {}, switch: {}, input: {} } 43 | if (sliderColor) { 44 | css = { 45 | ...css, 46 | slider: { 47 | ...css.slider, 48 | backgroundColor: sliderColor, 49 | }, 50 | } 51 | } 52 | 53 | if (switchBackgroundColor?.checked && switchBackgroundColor?.unchecked) { 54 | css = { 55 | ...css, 56 | switch: { 57 | ...css.switch, 58 | backgroundColor: `${switchBackgroundColor.unchecked} !important`, 59 | }, 60 | input: { 61 | [`&:checked ~ ${StyledSwitch}`]: { 62 | backgroundColor: `${switchBackgroundColor.checked} !important`, 63 | }, 64 | }, 65 | } 66 | } 67 | 68 | if (focusOutlineColor) { 69 | css = { 70 | ...css, 71 | switch: { 72 | ...css.switch, 73 | '&:focus-visible': { 74 | outline: 'none', 75 | boxShadow: `0 0 0 2px #fff, 0 0 0 4px ${focusOutlineColor}`, 76 | }, 77 | }, 78 | } 79 | } 80 | 81 | setSwitchStyles(css) 82 | }, []) 83 | 84 | return ( 85 |
86 | { 98 | if (isFirstChecked) setIsFirstChecked(false) 99 | if (handleChange && !isLoading && !disabled) { 100 | handleChange(e.target.checked) 101 | } 102 | }} 103 | css={{ ...switchStyles.input }} 104 | {...props} 105 | /> 106 | { 115 | if (e.key !== 'Enter') return 116 | if (isFirstChecked) setIsFirstChecked(false) 117 | if (handleChange && !isLoading && !disabled) { 118 | handleChange(!checked) 119 | } 120 | }} 121 | > 122 | {isLoading ? ( 123 | 124 | 129 | 130 | ) : ( 131 | 136 | {enhancerIcons?.checked && checked && ( 137 | 138 | 139 | 140 | )} 141 | 142 | {enhancerIcons?.unchecked && !checked && ( 143 | 144 | 145 | 146 | )} 147 | 148 | )} 149 | 150 |
151 | ) 152 | } 153 | ) 154 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Switch/types.ts: -------------------------------------------------------------------------------- 1 | import { Enhancer, KINDS } from '@finetwork:ui/src/types' 2 | 3 | export type SwitchComponent = { 4 | size?: 'medium' | 'large' 5 | kind?: KINDS 6 | id: string 7 | isLoading?: boolean 8 | checked?: boolean 9 | disabled?: boolean 10 | loadingColor?: string 11 | loadingSpeed?: number 12 | type?: 'standard' | 'success' | 'warning' | 'error' | 'disabled' 13 | handleChange?: (value: boolean) => void 14 | switchBackgroundColor?: { checked: string; unchecked: string } 15 | focusOutlineColor?: string 16 | sliderColor?: string 17 | enhancerIcons?: { checked: Enhancer; unchecked: Enhancer } 18 | } 19 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Tabs/context.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | type Tabs = { 4 | selectedValue?: string 5 | setSelectedValue?: React.Dispatch> 6 | } 7 | 8 | export const TabsContext = React.createContext({}) 9 | 10 | export function TabsProvider({ 11 | defaultValue, 12 | children, 13 | }: { 14 | defaultValue: string 15 | children: React.ReactNode 16 | }) { 17 | const [selectedValue, setSelectedValue] = React.useState(defaultValue) 18 | return ( 19 | 20 | {children} 21 | 22 | ) 23 | } 24 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Tabs/styled.ts: -------------------------------------------------------------------------------- 1 | import { fadeIn, fadeOut } from './../../animations' 2 | import { styled } from '../../stitches.config' 3 | import { Paragraph4 } from '../Typography' 4 | 5 | export const StyledTabs = styled('div', { 6 | display: 'flex', 7 | flexDirection: 'column', 8 | width: '100%', 9 | variants: { 10 | direction: { 11 | horizontal: { 12 | flexDirection: 'column', 13 | }, 14 | vertical: { 15 | flexDirection: 'row', 16 | }, 17 | }, 18 | }, 19 | }) 20 | 21 | export const StyledTabsList = styled('div', { 22 | display: 'flex', 23 | justifyContent: 'space-around', 24 | alignItems: 'center', 25 | variants: { 26 | direction: { 27 | horizontal: { 28 | marginBottom: '1rem', 29 | flexDirection: 'row', 30 | }, 31 | vertical: { 32 | marginRight: '1rem', 33 | flexDirection: 'column', 34 | justifyContent: 'center', 35 | gap: '1rem', 36 | }, 37 | }, 38 | }, 39 | }) 40 | 41 | export const StyledTabsTrigger = styled('div', { 42 | position: 'relative', 43 | display: 'flex', 44 | justifyContent: 'center', 45 | alignItems: 'center', 46 | width: '100%', 47 | transition: 'all 0.5s cubic-bezier(0.4, 0, 0.2, 1) 0ms', 48 | }) 49 | 50 | export const StyledButtonTrigger = styled('button', { 51 | position: 'relative', 52 | display: 'flex', 53 | justifyContent: 'center', 54 | alignItems: 'center', 55 | gap: '0.3rem', 56 | width: '100%', 57 | padding: '0.5rem', 58 | '&::before': { 59 | content: '', 60 | position: 'absolute', 61 | width: '100%', 62 | height: '3px', 63 | bottom: 0, 64 | left: 0, 65 | visibility: 'hidden', 66 | borderRadius: '5px', 67 | transform: 'scaleX(0)', 68 | transition: '.1s ease-in-out', 69 | }, 70 | variants: { 71 | isSelected: { 72 | true: { 73 | '&::before': { 74 | visibility: 'visible', 75 | transform: 'scaleX(1)', 76 | }, 77 | }, 78 | }, 79 | type: { 80 | standard: { 81 | '&::before': { 82 | backgroundColor: '$secondary', 83 | }, 84 | '&:hover': { 85 | cursor: 'pointer', 86 | '& p': { 87 | color: 'rgb(95, 10, 255) !important', 88 | }, 89 | }, 90 | }, 91 | success: { 92 | '&::before': { 93 | backgroundColor: 'rgb(0, 109, 57)', 94 | }, 95 | '&:hover': { 96 | cursor: 'pointer', 97 | '& p': { 98 | color: 'rgb(0, 109, 57) !important', 99 | }, 100 | }, 101 | }, 102 | warning: { 103 | '&::before': { 104 | backgroundColor: '#D0C100', 105 | }, 106 | '&:hover': { 107 | cursor: 'pointer', 108 | '& p': { 109 | color: '#D0C100 !important', 110 | }, 111 | }, 112 | }, 113 | error: { 114 | '&::before': { 115 | backgroundColor: '$error', 116 | }, 117 | '&:hover': { 118 | cursor: 'pointer', 119 | '& p': { 120 | color: '$error !important', 121 | }, 122 | }, 123 | }, 124 | disabled: { 125 | '&::before': { 126 | backgroundColor: '#8E8E8E', 127 | }, 128 | '&:hover': { 129 | cursor: 'not-allowed', 130 | '& p': { 131 | color: '#8E8E8E !important', 132 | }, 133 | }, 134 | }, 135 | }, 136 | }, 137 | }) 138 | 139 | export const StyledTabsContent = styled('div', { 140 | display: 'flex', 141 | justifyContent: 'center', 142 | width: '100%', 143 | variants: { 144 | isShow: { 145 | true: { 146 | display: 'flex', 147 | animation: `${fadeIn} 0.3s ease-in-out`, 148 | }, 149 | false: { 150 | display: 'none', 151 | animation: `${fadeOut} 0.3s ease-in-out`, 152 | }, 153 | }, 154 | }, 155 | }) 156 | 157 | export const StyledParagraph = styled(Paragraph4, { 158 | textAlign: 'center !important', 159 | variants: { 160 | bold: { 161 | true: { 162 | fontWeight: 'bold !important', 163 | }, 164 | }, 165 | type: { 166 | standard: { 167 | color: 'rgb(95, 10, 255)', 168 | }, 169 | success: { 170 | color: 'rgb(0, 109, 57)', 171 | }, 172 | warning: { 173 | color: '#D0C100', 174 | }, 175 | error: { 176 | color: '$error', 177 | }, 178 | disabled: { 179 | color: '#8E8E8E', 180 | }, 181 | }, 182 | }, 183 | }) 184 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Tabs/types.ts: -------------------------------------------------------------------------------- 1 | import { ComponentProps, ReactNode } from 'react' 2 | import { StyledTabs } from './styled' 3 | 4 | export type TabsComponentOwnProps = { 5 | id?: string 6 | defaultValue: string 7 | type?: 'standard' | 'success' | 'warning' | 'error' | 'disabled' 8 | borderRadius?: string 9 | direction?: 'horizontal' | 'vertical' 10 | width?: string 11 | height?: string 12 | } 13 | export type TabsProps = ComponentProps & 14 | TabsComponentOwnProps 15 | 16 | export type TabsListComponentOwnProps = { 17 | direction?: 'horizontal' | 'vertical' 18 | type?: 'standard' | 'success' | 'warning' | 'error' | 'disabled' 19 | justifyContent?: 'start' | 'center' | 'end' | 'space-around' | 'space-between' 20 | borderBottomColor?: string 21 | gap?: string 22 | width?: string 23 | selectedValue?: string 24 | handleChange?: React.Dispatch< 25 | React.SetStateAction 26 | > 27 | } 28 | export type TabsListProps = ComponentProps & 29 | TabsListComponentOwnProps 30 | 31 | export type TabsTriggerComponentOwnProps = { 32 | value: string 33 | type?: 'standard' | 'success' | 'warning' | 'error' | 'disabled' 34 | textColor?: string 35 | textSize?: string 36 | bold?: boolean 37 | disabled?: boolean 38 | width?: string 39 | selectedValue?: string 40 | handleChange?: React.Dispatch< 41 | React.SetStateAction 42 | > 43 | startEnhancer?: ReactNode | string 44 | endEnhancer?: ReactNode | string 45 | } 46 | export type TabsTriggerProps = ComponentProps & 47 | TabsTriggerComponentOwnProps 48 | 49 | export type TabsContentComponentOwnProps = { 50 | value: string 51 | selectedValue?: string 52 | } 53 | export type TabsContentProps = ComponentProps & 54 | TabsContentComponentOwnProps 55 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Tag/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import { RenderEnhancer } from '@finetwork:ui/src/utils' 3 | import { TagProps } from './types' 4 | import { StyledTag, StyledParagraph6 } from './styled' 5 | 6 | export const Tag = React.forwardRef( 7 | ( 8 | { 9 | kind, 10 | textSize, 11 | background, 12 | borderRadius = '5px', 13 | width, 14 | height, 15 | endEnhancer, 16 | startEnhancer, 17 | textColor, 18 | children, 19 | type, 20 | onClick, 21 | bold = false, 22 | ...props 23 | }, 24 | ref 25 | ) => { 26 | const [customStyle, setCustomStyle] = React.useState({ 27 | tag: {}, 28 | text: {}, 29 | }) 30 | React.useEffect(() => { 31 | let css = { 32 | tag: {}, 33 | text: {}, 34 | } 35 | if (background) { 36 | css = { 37 | ...css, 38 | tag: { 39 | ...css.tag, 40 | background: `${background} !important`, 41 | }, 42 | } 43 | } 44 | if (borderRadius) { 45 | css = { 46 | ...css, 47 | tag: { 48 | ...css.tag, 49 | borderRadius: `${borderRadius} !important`, 50 | }, 51 | } 52 | } 53 | if (width) { 54 | css = { 55 | ...css, 56 | tag: { 57 | ...css.tag, 58 | width: `${width} !important`, 59 | }, 60 | } 61 | } 62 | if (height) { 63 | css = { 64 | ...css, 65 | tag: { 66 | ...css.tag, 67 | height: `${height} !important`, 68 | }, 69 | } 70 | } 71 | if (onClick) { 72 | css = { 73 | ...css, 74 | tag: { 75 | ...css.tag, 76 | '&:hover': { 77 | cursor: 'pointer', 78 | }, 79 | }, 80 | } 81 | } 82 | if (textSize) { 83 | css = { 84 | ...css, 85 | text: { 86 | ...css.text, 87 | fontSize: `${textSize} !important`, 88 | }, 89 | } 90 | } 91 | if (textColor) { 92 | css = { 93 | ...css, 94 | text: { 95 | ...css.text, 96 | color: `${textColor} !important`, 97 | }, 98 | } 99 | } 100 | setCustomStyle(css) 101 | }, [background, borderRadius, width, height, onClick, textSize, textColor]) 102 | 103 | return ( 104 | 111 | {startEnhancer && } 112 | 118 | {children} 119 | 120 | {endEnhancer && } 121 | 122 | ) 123 | } 124 | ) 125 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Tag/styled.ts: -------------------------------------------------------------------------------- 1 | import { styled } from '../../stitches.config' 2 | import { Paragraph6 } from '../Typography' 3 | 4 | export const StyledTag = styled('div', { 5 | display: 'flex', 6 | justifyContent: 'center', 7 | alignItems: 'center', 8 | gap: '.3rem', 9 | padding: '5px 10px', 10 | background: '#B4C4F9', 11 | width: 'fit-content', 12 | variants: { 13 | kind: { 14 | primary: { 15 | background: '$primary', 16 | }, 17 | secondary: { 18 | background: '$secondary', 19 | }, 20 | tertiary: { 21 | background: '$tertiary', 22 | }, 23 | }, 24 | type: { 25 | standard: { 26 | background: 'rgb(244, 238, 255) !important', 27 | }, 28 | success: { 29 | background: 'rgb(218, 252, 236) !important', 30 | }, 31 | warning: { 32 | background: '#F7F4CD !important', 33 | }, 34 | error: { 35 | background: '#F7CDCD !important', 36 | }, 37 | disabled: { 38 | background: '#E9E9E9 !important', 39 | }, 40 | }, 41 | }, 42 | }) 43 | 44 | export const StyledParagraph6 = styled(Paragraph6, { 45 | variants: { 46 | bold: { 47 | true: { 48 | fontWeight: 'bold !important', 49 | }, 50 | }, 51 | kind: { 52 | primary: { 53 | color: 'white', 54 | }, 55 | secondary: { 56 | color: 'white', 57 | }, 58 | tertiary: {}, 59 | }, 60 | type: { 61 | standard: { 62 | color: 'rgb(95, 10, 255) !important', 63 | }, 64 | success: { 65 | color: 'rgb(0, 109, 57) !important', 66 | }, 67 | warning: { 68 | color: '#D0C100 !important', 69 | }, 70 | error: { 71 | color: '$error !important', 72 | }, 73 | disabled: { 74 | color: '#8E8E8E !important', 75 | }, 76 | }, 77 | }, 78 | }) 79 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Tag/types.ts: -------------------------------------------------------------------------------- 1 | import { ComponentProps, MouseEventHandler, ReactNode } from 'react' 2 | import { KINDS } from '../../types' 3 | import { StyledTag } from './styled' 4 | 5 | export type TagComponentOwnProps = { 6 | id?: string 7 | kind?: KINDS 8 | textSize?: string 9 | background?: string 10 | width?: string 11 | height?: string 12 | type?: 'standard' | 'success' | 'warning' | 'error' | 'disabled' 13 | borderRadius?: string 14 | textColor?: string 15 | bold?: boolean 16 | startEnhancer?: ReactNode | string 17 | endEnhancer?: ReactNode | string 18 | onClick?: MouseEventHandler & 19 | MouseEventHandler 20 | } 21 | export type TagProps = ComponentProps & TagComponentOwnProps 22 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Textarea/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | import { 4 | StyledContainer, 5 | StyledContainerInput, 6 | StyledEnhancer, 7 | StyledLabel, 8 | StyledMessage, 9 | StyledSuccessIcon, 10 | StyledTextarea, 11 | } from './styled' 12 | 13 | import { RenderEnhancer } from '../../utils' 14 | import { TextareaComponent } from './types' 15 | 16 | export const Textarea: TextareaComponent = React.forwardRef( 17 | ( 18 | { 19 | size, 20 | kind, 21 | label, 22 | rows = 4, 23 | inputContainerProps = {}, 24 | containerProps = {}, 25 | css, 26 | error, 27 | info, 28 | success, 29 | id, 30 | labelProps = {}, 31 | ...props 32 | }, 33 | ref 34 | ) => { 35 | React.useEffect(() => { 36 | if (label && !id) { 37 | console.warn( 38 | 'Input id is undefined, you should put id if you are using label' 39 | ) 40 | } 41 | }, []) 42 | return ( 43 | 44 | {label && ( 45 | 53 | {label} 54 | 55 | )} 56 | 64 | 72 | {success && !error && ( 73 | 74 | } /> 75 | 76 | )} 77 | 78 | {(info || error) && ( 79 | 80 | 81 | 82 | )} 83 | 84 | ) 85 | } 86 | ) 87 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Textarea/types.ts: -------------------------------------------------------------------------------- 1 | import { ComponentProps, FC, ReactNode } from 'react' 2 | import { Enhancer, KINDS, SIZES } from '../../types' 3 | import { 4 | StyledContainer, 5 | StyledContainerInput, 6 | StyledLabel, 7 | StyledTextarea, 8 | } from './styled' 9 | 10 | type TextareaProps = Omit, 'size'> & { 11 | containerProps?: ComponentProps 12 | inputContainerProps?: ComponentProps 13 | size?: SIZES 14 | resize?: boolean 15 | kind?: KINDS 16 | label?: ReactNode | string 17 | isDisabled?: boolean 18 | error?: ReactNode | string 19 | info?: ReactNode | string 20 | success?: boolean 21 | labelProps?: ComponentProps 22 | } 23 | 24 | export type TextareaComponent = FC 25 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Theme/ThemeContext.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | import { initialTheme } from './initial-theme' 4 | 5 | export const ThemeContext = React.createContext({ theme: initialTheme }) 6 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Theme/ThemeProvider.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | import { createTheme, globalStyles } from '../../stitches.config' 4 | import { deepMerge, recalculateColors } from '../../utils' 5 | 6 | import { ThemeContext } from './ThemeContext' 7 | import { initialTheme } from './initial-theme' 8 | import { FiTheme } from './types' 9 | 10 | export const ThemeProvider: React.FC<{ 11 | theme: FiTheme 12 | children?: React.ReactNode 13 | }> = ({ children, theme = initialTheme }) => { 14 | const [computedTheme, fiUiTheme] = React.useMemo(() => { 15 | const mergedTheme = deepMerge(initialTheme, theme) 16 | mergedTheme.colors = recalculateColors(mergedTheme.colors || {}) 17 | return [mergedTheme, createTheme('finetwork-ui', mergedTheme)] 18 | }, [theme, initialTheme]) 19 | React.useEffect(() => { 20 | globalStyles({ 21 | '*': { 22 | outline: 'none', 23 | boxSizing: 'border-box', 24 | }, 25 | })() 26 | if (!document.body.className.includes(fiUiTheme.className)) { 27 | document.body.classList.add(fiUiTheme.toString()) 28 | } 29 | }, [fiUiTheme]) 30 | return ( 31 | 32 | {children} 33 | 34 | ) 35 | } 36 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Theme/hook.ts: -------------------------------------------------------------------------------- 1 | import { ThemeContext } from './ThemeContext' 2 | import { useContext } from 'react' 3 | 4 | export const useTheme = () => { 5 | const context = useContext(ThemeContext) 6 | if (!context) { 7 | throw new Error('useTheme must be used within ThemeProvider') 8 | } 9 | return context 10 | } 11 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Theme/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ThemeContext' 2 | export * from './ThemeProvider' 3 | export * from './hook' 4 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Theme/initial-theme.ts: -------------------------------------------------------------------------------- 1 | import { amber, blue, green, red } from '@radix-ui/colors' 2 | import { FiTheme } from './types' 3 | 4 | export const initialTheme: FiTheme = { 5 | colors: { 6 | linkText: '#5F3DFF', 7 | primary: 'blue', 8 | primaryText: '#000', 9 | primaryButtonText: '#fff', 10 | secondary: '#5F3DFF', 11 | secondaryText: '#fff', 12 | secondaryButtonText: '#fff', 13 | tertiary: '#FA9A1D', 14 | tertiaryText: '#000', 15 | tertiaryButtonText: '#000', 16 | disabled: '#ddd', 17 | error: red.red10, 18 | success: green.green10, 19 | info: blue.blue10, 20 | warning: amber.amber10, 21 | default: 'hsl(206 22% 7% / 35%)', 22 | }, 23 | space: {}, 24 | fonts: { 25 | primary: 'apple-system, sans-serif', 26 | }, 27 | radii: { 28 | round: '50%', 29 | }, 30 | } 31 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Theme/types.ts: -------------------------------------------------------------------------------- 1 | export type Colors = { 2 | primary?: string 3 | primaryText?: string 4 | primaryButtonText?: string 5 | primary100?: string 6 | primary200?: string 7 | primary300?: string 8 | primary400?: string 9 | primary500?: string 10 | primary600?: string 11 | primary700?: string 12 | primary800?: string 13 | primary900?: string 14 | secondary?: string 15 | secondaryText?: string 16 | secondaryButtonText?: string 17 | secondary100?: string 18 | secondary200?: string 19 | secondary300?: string 20 | secondary400?: string 21 | secondary500?: string 22 | secondary600?: string 23 | secondary700?: string 24 | secondary800?: string 25 | secondary900?: string 26 | tertiary?: string 27 | tertiaryText?: string 28 | tertiaryButtonText?: string 29 | tertiary100?: string 30 | tertiary200?: string 31 | tertiary300?: string 32 | tertiary400?: string 33 | tertiary500?: string 34 | tertiary600?: string 35 | tertiary700?: string 36 | tertiary800?: string 37 | tertiary900?: string 38 | linkText?: string 39 | linkText100?: string 40 | linkText200?: string 41 | linkText300?: string 42 | linkText400?: string 43 | linkText500?: string 44 | linkText600?: string 45 | linkText700?: string 46 | linkText800?: string 47 | linkText900?: string 48 | disabled?: string 49 | error?: string 50 | success?: string 51 | info?: string 52 | warning?: string, 53 | default?: string, 54 | } 55 | 56 | export type Fonts = { 57 | primary?: string 58 | secondary?: string 59 | } 60 | 61 | export type FiTheme = { 62 | colors?: Colors 63 | space?: any 64 | fonts?: Fonts 65 | radii?: any 66 | className?: string 67 | selector?: string 68 | toString?: () => string 69 | } 70 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Toast/types.ts: -------------------------------------------------------------------------------- 1 | import type { ToastProviderProps as ToastProviderPrimitiveProps } from '@radix-ui/react-toast' 2 | import { KINDS } from '../../types' 3 | import { StyledToast } from './styled' 4 | 5 | export enum DIRECTION { 6 | 'top-left' = 'top-left', 7 | 'top-right' = 'top-right', 8 | 'top-center' = 'top-center', 9 | 'bottom-left' = 'bottom-left', 10 | 'bottom-right' = 'bottom-right', 11 | 'bottom-center' = 'bottom-center', 12 | } 13 | export type DIRECTIONS = keyof typeof DIRECTION 14 | 15 | export enum TOAST_KIND { 16 | info = 'info', 17 | error = 'error', 18 | success = 'success', 19 | warning = 'warning', 20 | } 21 | export type TOAST_KINDS = keyof typeof TOAST_KIND 22 | 23 | type ToastProps = React.ComponentProps & { 24 | kind?: KINDS | TOAST_KINDS 25 | withProgressBar?: boolean 26 | closeable?: boolean 27 | pauseOnFocusLoss?: boolean 28 | pauseOnHover?: boolean 29 | } 30 | type ToastProviderProps = Omit< 31 | ToastProviderPrimitiveProps, 32 | 'swipeDirection' 33 | > & { 34 | direction?: DIRECTIONS 35 | } 36 | export type ToastComponent = React.FC 37 | export type ToastProviderComponent = React.FC 38 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Tooltip/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | import { Root, Trigger } from '@radix-ui/react-tooltip' 4 | import { StyledContent, StyledTooltipArrow } from './styled' 5 | import { TooltipComponent, TooltipContentComponent } from './types' 6 | 7 | export const Tooltip: TooltipComponent = ({ 8 | children, 9 | delayDuration = 200, 10 | ...props 11 | }) => ( 12 | 13 | {children} 14 | 15 | ) 16 | export const TooltipTrigger = Trigger 17 | export const TooltipContent: TooltipContentComponent = ({ 18 | children, 19 | withArrow = false, 20 | side = 'top', 21 | ...props 22 | }) => ( 23 | 24 | {children} 25 | {withArrow && } 26 | 27 | ) 28 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Tooltip/styled.ts: -------------------------------------------------------------------------------- 1 | import { Arrow, Content } from '@radix-ui/react-tooltip' 2 | import { 3 | slideDownAndFade, 4 | slideLeftAndFade, 5 | slideRightAndFade, 6 | slideUpAndFade, 7 | } from '../../animations' 8 | 9 | import { StyledComponent } from '@stitches/react/types/styled-component' 10 | import { styled } from '../../stitches.config' 11 | 12 | export const StyledContent: StyledComponent = styled(Content, { 13 | borderRadius: 4, 14 | padding: '10px 15px', 15 | fontSize: 15, 16 | lineHeight: 1, 17 | backgroundColor: 'white', 18 | color: '#000', 19 | boxShadow: 20 | 'hsl(206 22% 7% / 35%) 0px 10px 38px -10px, hsl(206 22% 7% / 20%) 0px 10px 20px -15px', 21 | '@media (prefers-reduced-motion: no-preference)': { 22 | animationDuration: '400ms', 23 | animationTimingFunction: 'cubic-bezier(0.16, 1, 0.3, 1)', 24 | willChange: 'transform, opacity', 25 | '&[data-state="delayed-open"]': { 26 | '&[data-side="top"]': { animationName: slideDownAndFade }, 27 | '&[data-side="right"]': { animationName: slideLeftAndFade }, 28 | '&[data-side="bottom"]': { animationName: slideUpAndFade }, 29 | '&[data-side="left"]': { animationName: slideRightAndFade }, 30 | }, 31 | }, 32 | }) 33 | 34 | export const StyledTooltipArrow: StyledComponent = styled(Arrow, { 35 | fill: 'white', 36 | }) 37 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Tooltip/types.ts: -------------------------------------------------------------------------------- 1 | import { ComponentProps, FC } from 'react' 2 | 3 | import { Root } from '@radix-ui/react-tooltip' 4 | import { StyledContent } from './styled' 5 | 6 | type TooltipContentProps = ComponentProps & { 7 | withArrow?: boolean 8 | } 9 | type TooltipProps = ComponentProps 10 | 11 | export type TooltipContentComponent = FC 12 | export type TooltipComponent = FC 13 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Typography/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | import { 4 | StyledH1, 5 | StyledH2, 6 | StyledH3, 7 | StyledH4, 8 | StyledH5, 9 | StyledH6, 10 | StyledHighLight, 11 | StyledParagraph1, 12 | StyledParagraph2, 13 | StyledParagraph3, 14 | StyledParagraph4, 15 | StyledParagraph5, 16 | StyledParagraph6, 17 | } from './styled' 18 | import { TypographyComponent, TypographyImplementationComponent } from './types' 19 | 20 | const Typography: TypographyComponent = React.forwardRef( 21 | ( 22 | { 23 | Component, 24 | children, 25 | isHighLight, 26 | highLightAlign, 27 | align, 28 | kind, 29 | highLightSize, 30 | highLightKind, 31 | ...props 32 | }, 33 | ref 34 | ) => { 35 | return ( 36 | 45 | {children} 46 | {isHighLight && ( 47 | 54 | )} 55 | 56 | ) 57 | } 58 | ) 59 | export const H1: TypographyImplementationComponent = React.forwardRef( 60 | ({ children, ...props }, ref) => { 61 | return ( 62 | 63 | {children} 64 | 65 | ) 66 | } 67 | ) 68 | export const H2: TypographyImplementationComponent = React.forwardRef( 69 | ({ children, ...props }, ref) => { 70 | return ( 71 | 72 | {children} 73 | 74 | ) 75 | } 76 | ) 77 | export const H3: TypographyImplementationComponent = React.forwardRef( 78 | ({ children, ...props }, ref) => { 79 | return ( 80 | 81 | {children} 82 | 83 | ) 84 | } 85 | ) 86 | export const H4: TypographyImplementationComponent = React.forwardRef( 87 | ({ children, ...props }, ref) => { 88 | return ( 89 | 90 | {children} 91 | 92 | ) 93 | } 94 | ) 95 | export const H5: TypographyImplementationComponent = React.forwardRef( 96 | ({ children, ...props }, ref) => { 97 | return ( 98 | 99 | {children} 100 | 101 | ) 102 | } 103 | ) 104 | export const H6: TypographyImplementationComponent = React.forwardRef( 105 | ({ children, ...props }, ref) => { 106 | return ( 107 | 108 | {children} 109 | 110 | ) 111 | } 112 | ) 113 | export const Paragraph1: TypographyImplementationComponent = React.forwardRef( 114 | ({ children, ...props }, ref) => { 115 | return ( 116 | 117 | {children} 118 | 119 | ) 120 | } 121 | ) 122 | export const Paragraph2: TypographyImplementationComponent = React.forwardRef( 123 | ({ children, ...props }, ref) => { 124 | return ( 125 | 126 | {children} 127 | 128 | ) 129 | } 130 | ) 131 | export const Paragraph3: TypographyImplementationComponent = React.forwardRef( 132 | ({ children, ...props }, ref) => { 133 | return ( 134 | 135 | {children} 136 | 137 | ) 138 | } 139 | ) 140 | export const Paragraph4: TypographyImplementationComponent = React.forwardRef( 141 | ({ children, ...props }, ref) => { 142 | return ( 143 | 144 | {children} 145 | 146 | ) 147 | } 148 | ) 149 | export const Paragraph5: TypographyImplementationComponent = React.forwardRef( 150 | ({ children, ...props }, ref) => { 151 | return ( 152 | 153 | {children} 154 | 155 | ) 156 | } 157 | ) 158 | export const Paragraph6: TypographyImplementationComponent = React.forwardRef( 159 | ({ children, ...props }, ref) => { 160 | return ( 161 | 162 | {children} 163 | 164 | ) 165 | } 166 | ) 167 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/Typography/types.ts: -------------------------------------------------------------------------------- 1 | import { ComponentProps, FC } from 'react' 2 | import { FONTS, KINDS, SIZES } from '../../types' 3 | 4 | import { StyledH1 } from './styled' 5 | 6 | export enum HIGHLIGHT_ALIGN { 7 | bottom = 'bottom', 8 | top = 'top', 9 | } 10 | export enum ALIGN { 11 | right = 'right', 12 | center = 'center', 13 | left = 'left', 14 | } 15 | export type HIGHLIGHT_ALIGNS = keyof typeof HIGHLIGHT_ALIGN 16 | export type ALIGNS = keyof typeof ALIGN 17 | 18 | type TypographyProps = ComponentProps & { 19 | kind?: KINDS 20 | isHighLight?: boolean 21 | highLightSize?: SIZES 22 | highLightAlign?: HIGHLIGHT_ALIGNS 23 | align?: ALIGNS 24 | highLightKind?: KINDS 25 | font?: FONTS 26 | } 27 | export type TypographyComponent = FC< 28 | TypographyProps & { 29 | Component: any 30 | isHighLight?: boolean 31 | } 32 | > 33 | export type TypographyImplementationComponent = FC 34 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/icons/ArrowRightIcon.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | export const ArrowRightIcon: React.FC> = ({ 4 | ...props 5 | }) => { 6 | return ( 7 | 15 | 21 | 22 | ) 23 | } 24 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/icons/CheckIcon.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | export const CheckIcon: React.FC> = ({ 4 | ...props 5 | }) => { 6 | return ( 7 | 15 | 21 | 22 | ) 23 | } 24 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/icons/ChevronDownIcon.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | export const ChevronDownIcon: React.FC> = ({ 4 | ...props 5 | }) => { 6 | return ( 7 | 15 | 21 | 22 | ) 23 | } 24 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/icons/CloseIcon.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | export const CloseIcon: React.FC> = ({ 4 | ...props 5 | }) => { 6 | return ( 7 | 8 | 9 | 10 | ) 11 | } -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/icons/Cross1Icon.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | export const Cross1Icon: React.FC> = ({ 4 | ...props 5 | }) => { 6 | return ( 7 | 15 | 21 | 22 | ) 23 | } 24 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/icons/DividerHorizontalIcon.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | export const DividerHorizontalIcon: React.FC> = ({ 4 | ...props 5 | }) => { 6 | return ( 7 | 15 | 21 | 22 | ) 23 | } 24 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/icons/EnvelopeClosedIcon.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | export const EnvelopeClosedIcon: React.FC> = ({ 4 | ...props 5 | }) => { 6 | return ( 7 | 15 | 21 | 22 | ) 23 | } 24 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/icons/ErrorIcon.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | export const ErrorIcon: React.FC> = ({ 4 | ...props 5 | }) => { 6 | return ( 7 | 8 | 9 | 10 | 11 | ) 12 | } -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/icons/EyeOpenIcon.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | export const EyeOpenIcon: React.FC> = ({ 4 | ...props 5 | }) => { 6 | return ( 7 | 15 | 19 | 23 | 24 | ) 25 | } 26 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/icons/HamburgerIcon.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | export const HamburgerIcon: React.FC> = ({ 4 | ...props 5 | }) => { 6 | return ( 7 | 15 | 21 | 22 | ) 23 | } 24 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/icons/Loupe.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | export const Loupe: React.FC> = ({ 4 | ...props 5 | }) => { 6 | return ( 7 | 15 | 19 | 20 | 21 | ) 22 | } 23 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/icons/Pencil2Icon.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | export const Pencil2Icon: React.FC> = ({ 4 | ...props 5 | }) => { 6 | return ( 7 | 15 | 21 | 22 | ) 23 | } 24 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/icons/PersonIcon.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | export const PersonIcon: React.FC> = ({ 4 | ...props 5 | }) => { 6 | return ( 7 | 15 | 21 | 22 | ) 23 | } 24 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/icons/RocketIcon.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | export const RocketIcon: React.FC> = ({ 4 | ...props 5 | }) => { 6 | return ( 7 | 15 | 21 | 22 | ) 23 | } 24 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/icons/SunIcon.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | export const SunIcon: React.FC> = ({ 4 | ...props 5 | }) => { 6 | return ( 7 | 15 | 21 | 22 | ) 23 | } 24 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/components/icons/index.ts: -------------------------------------------------------------------------------- 1 | export * from './CheckIcon' 2 | export * from './ChevronDownIcon' 3 | export * from './Cross1Icon' 4 | export * from './DividerHorizontalIcon' 5 | export * from './EyeClosedIcon' 6 | export * from './EyeOpenIcon' 7 | export * from './Pencil2Icon' 8 | export * from './PersonIcon' 9 | export * from './SunIcon' 10 | export * from './EnvelopeClosedIcon' 11 | export * from './HamburgerIcon' 12 | export * from './RocketIcon' 13 | export * from './ArrowRightIcon' 14 | export * from './Loupe' 15 | export * from './ErrorIcon' 16 | export * from './CloseIcon' 17 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/hooks/useControllScroll.ts: -------------------------------------------------------------------------------- 1 | const KEYS = { 37: 1, 38: 1, 39: 1, 40: 1 } 2 | 3 | export const useControllScroll = () => { 4 | function preventDefault(e) { 5 | e.preventDefault() 6 | e.stopPropagation() 7 | } 8 | 9 | function preventScroll(e) { 10 | e.stopPropagation() 11 | } 12 | 13 | function preventDefaultForScrollKeys(e) { 14 | if (KEYS[e.keyCode]) { 15 | preventDefault(e) 16 | return false 17 | } 18 | } 19 | 20 | var supportsPassive = false 21 | try { 22 | window.addEventListener( 23 | 'test', 24 | null, 25 | Object.defineProperty({}, 'passive', { 26 | get: function () { 27 | supportsPassive = true 28 | }, 29 | }) 30 | ) 31 | } catch (e) {} 32 | 33 | let wheelOpt = supportsPassive ? { passive: false } : false 34 | // var wheelEvent = 35 | // 'onwheel' in document.createElement('div') ? 'wheel' : 'mousewheel' 36 | 37 | const disableScroll = () => { 38 | const scrollTop = window.scrollY || document.documentElement.scrollTop 39 | const scrollLeft = window.scrollX || document.documentElement.scrollLeft 40 | window.onscroll = function () { 41 | window.scrollTo(scrollLeft, scrollTop) 42 | } 43 | window.addEventListener('wheel', preventDefault, wheelOpt) 44 | window.addEventListener('touchmove', preventDefault, wheelOpt) 45 | window.addEventListener('keydown', preventDefaultForScrollKeys, false) 46 | } 47 | const allowScroll = () => { 48 | window.onscroll = function () {} 49 | window.removeEventListener('wheel', preventDefault, false) 50 | window.removeEventListener('touchmove', preventDefault, false) 51 | window.removeEventListener('keydown', preventDefaultForScrollKeys, false) 52 | } 53 | const allowScrollInSpecificComponent = ( 54 | ref: React.MutableRefObject 55 | ) => { 56 | if (ref?.current.clientHeight < ref?.current.scrollHeight) { 57 | ref?.current?.addEventListener('wheel', preventScroll, { 58 | passive: false, 59 | }) 60 | ref?.current?.addEventListener('touchmove', preventScroll, { 61 | passive: false, 62 | }) 63 | ref?.current?.addEventListener( 64 | 'keydown', 65 | preventDefaultForScrollKeys, 66 | false 67 | ) 68 | } 69 | } 70 | 71 | return { 72 | disableScroll, 73 | allowScroll, 74 | allowScrollInSpecificComponent, 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/hooks/useWindowSize.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | type WindowSize = { 4 | width: number 5 | height: number 6 | } 7 | 8 | export const useWindowSize = (): WindowSize => { 9 | const [windowSize, setWindowSize]: [ 10 | WindowSize, 11 | React.Dispatch> 12 | ] = React.useState({ 13 | width: undefined, 14 | height: undefined, 15 | }) 16 | 17 | React.useEffect(() => { 18 | function handleResize() { 19 | setWindowSize({ 20 | width: window.innerWidth, 21 | height: window.innerHeight, 22 | }) 23 | } 24 | 25 | window.addEventListener('resize', handleResize) 26 | handleResize() 27 | return () => window.removeEventListener('resize', handleResize) 28 | }, []) 29 | return windowSize 30 | } 31 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/index.ts: -------------------------------------------------------------------------------- 1 | export { 2 | Accordion, 3 | AccordionContent, 4 | AccordionItem, 5 | AccordionTrigger, 6 | } from './components/Accordion' 7 | export { Checkbox } from './components/Checkbox' 8 | export { Button } from './components/Button' 9 | export { Card, CardBody, CardFooter, CardHeader } from './components/Card' 10 | export { Input } from './components/Input' 11 | export { Link } from './components/Link' 12 | export { Loading } from './components/Loading' 13 | export { Dialog, DialogTrigger } from './components/Dialog' 14 | export { 15 | DropdownMenu, 16 | DropdownMenuTrigger, 17 | DropdownMenuArrow, 18 | DropdownMenuCheckboxItem, 19 | DropdownMenuContent, 20 | DropdownMenuItem, 21 | DropdownMenuItemIndicator, 22 | DropdownMenuLabel, 23 | DropdownMenuRadioGroup, 24 | DropdownMenuRadioItem, 25 | DropdownMenuSeparator, 26 | DropdownMenuTriggerItem, 27 | } from './components/DropdownMenu' 28 | export { Radio, RadioGroup } from './components/Radio' 29 | export { Select } from './components/Select' 30 | export { Separator } from './components/Separator' 31 | export { Skeleton } from './components/Skeleton' 32 | export { Switch } from './components/Switch' 33 | export { Tabs, TabsContent, TabsList, TabsTrigger } from './components/Tabs' 34 | export { Tag } from './components/Tag' 35 | export type { TagProps } from './components/Tag/types' 36 | export { Textarea } from './components/Textarea' 37 | export { ThemeProvider, useTheme } from './components/Theme' 38 | export { 39 | Toast, 40 | ToastAction, 41 | ToastClose, 42 | ToastDescription, 43 | ToastProvider, 44 | ToastTitle, 45 | } from './components/Toast' 46 | export { Tooltip, TooltipContent, TooltipTrigger } from './components/Tooltip' 47 | export { 48 | H1, 49 | H2, 50 | H3, 51 | H4, 52 | H5, 53 | H6, 54 | Paragraph1, 55 | Paragraph2, 56 | Paragraph3, 57 | Paragraph4, 58 | Paragraph5, 59 | Paragraph6, 60 | } from './components/Typography' 61 | export { IdProvider } from '@radix-ui/react-id' 62 | export { getCssText } from './stitches.config' 63 | export * from './types' 64 | export * from './components/icons' 65 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/stitches.config.ts: -------------------------------------------------------------------------------- 1 | import * as Stitches from '@stitches/react' 2 | 3 | const media = { 4 | mobile: '(min-width: 360px)', 5 | tablet: '(min-width: 480px)', 6 | tabletXl: '(min-width: 768px)', 7 | desktop: '(min-width: 1024px)', 8 | 'desktop-xl': '(min-width: 1280px)', 9 | } 10 | 11 | const prefix = 'fi-ui' 12 | 13 | export const { 14 | styled, 15 | css, 16 | theme, 17 | keyframes, 18 | globalCss: globalStyles, 19 | createTheme, 20 | getCssText, 21 | config, 22 | } = Stitches.createStitches({ 23 | media, 24 | }) 25 | 26 | export type CSS = Stitches.CSS 27 | 28 | // export const getCssText = (t: FiTheme = initialTheme) => { 29 | // const mergedTheme = deepMerge(initialTheme, t) 30 | // mergedTheme.colors = recalculateColors(mergedTheme.colors || {}) 31 | // const stitches = createStitches({ 32 | // theme: mergedTheme, 33 | // media, 34 | // }) 35 | // return stitches.getCssText 36 | // } 37 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/types/boolean-string.ts: -------------------------------------------------------------------------------- 1 | export type BooleanString = boolean | 'false' | 'true' 2 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/types/enhancer.ts: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react' 2 | 3 | export type Enhancer = ReactNode | string 4 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/types/fonts.ts: -------------------------------------------------------------------------------- 1 | export enum FONT { 2 | primary = 'primary', 3 | secondary = 'secondary', 4 | tertiary = 'tertiary', 5 | } 6 | 7 | export type FONTS = keyof typeof FONT 8 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from './kind' 2 | export * from './enhancer' 3 | export * from './size' 4 | export * from './orientation' 5 | export * from './placement' 6 | export * from './boolean-string' 7 | export * from './fonts' 8 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/types/kind.ts: -------------------------------------------------------------------------------- 1 | export enum KIND { 2 | primary = 'primary', 3 | secondary = 'secondary', 4 | tertiary = 'tertiary', 5 | } 6 | 7 | export type KINDS = keyof typeof KIND 8 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/types/orientation.ts: -------------------------------------------------------------------------------- 1 | export enum ORIENTATION { 2 | horizontal = 'horizontal', 3 | vertical = 'vertical', 4 | } 5 | 6 | export type ORIENTATIONS = keyof typeof ORIENTATION 7 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/types/placement.ts: -------------------------------------------------------------------------------- 1 | export type Placement = 2 | | 'auto-start' 3 | | 'auto' 4 | | 'auto-end' 5 | | 'top-start' 6 | | 'top' 7 | | 'top-end' 8 | | 'right-start' 9 | | 'right' 10 | | 'right-end' 11 | | 'bottom-end' 12 | | 'bottom' 13 | | 'bottom-start' 14 | | 'left-end' 15 | | 'left' 16 | | 'left-start' 17 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/src/types/size.ts: -------------------------------------------------------------------------------- 1 | export enum SIZE { 2 | small = 'small', 3 | medium = 'medium', 4 | large = 'large', 5 | } 6 | 7 | export const mediaQuery = { 8 | mobile: 360, 9 | tablet: 480, 10 | tabletXl: 768, 11 | desktop: 1024, 12 | desktopXl: 1280, 13 | desktop2Xl: 1600, 14 | } 15 | 16 | export type SIZES = keyof typeof SIZE 17 | 18 | export enum DIALOG_SIZE { 19 | default = 'default', 20 | auto = 'auto', 21 | full = 'full', 22 | } 23 | 24 | export type DIALOG_SIZES = keyof typeof DIALOG_SIZE 25 | -------------------------------------------------------------------------------- /packages/@finetwork:ui/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "emitDeclarationOnly": true, 5 | "composite": true, 6 | "declaration": true, 7 | "outDir": "dist" 8 | }, 9 | "include": ["src/**/*.ts", "src/**/*.tsx"], 10 | "exclude": ["node_modules"] 11 | } 12 | -------------------------------------------------------------------------------- /packages/website/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/basic-features/typescript for more information. 6 | -------------------------------------------------------------------------------- /packages/website/next.config.js: -------------------------------------------------------------------------------- 1 | const compose = require('compose-function') 2 | const { withDokz } = require('dokz/dist/plugin') 3 | const withTM = require('next-transpile-modules')([ 4 | '@finetwork/ui', 5 | '@finetwork/ui-sections', 6 | ]) 7 | 8 | const composed = compose(withDokz, withTM) 9 | 10 | module.exports = composed({ 11 | pageExtensions: ['js', 'jsx', 'md', 'mdx', 'ts', 'tsx'], 12 | }) 13 | -------------------------------------------------------------------------------- /packages/website/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "website", 3 | "version": "0.1.0", 4 | "scripts": { 5 | "dev": "./node_modules/.bin/next dev", 6 | "build": "./node_modules/.bin/next build", 7 | "start": "./node_modules/.bin/next start" 8 | }, 9 | "dependencies": { 10 | "@chakra-ui/react": "latest", 11 | "@emotion/react": "latest", 12 | "@emotion/styled": "latest", 13 | "@finetwork/ui": "1.3.23", 14 | "@finetwork/ui-sections": "0.2.0", 15 | "@stitches/react": "1.2.8", 16 | "dokz": "2.0.7", 17 | "framer-motion": "latest", 18 | "next": "latest", 19 | "next-compose-plugins": "^2.2.1", 20 | "next-transpile-modules": "^8.0.0", 21 | "polished": "4.2.2", 22 | "react": ">=17.0.0", 23 | "react-dom": "^17.0.2", 24 | "react-icons": "^4.2.0" 25 | }, 26 | "devDependencies": { 27 | "@types/react": "^17.0.3", 28 | "compose-function": "^3.0.3", 29 | "typescript": "4.8.4" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/website/pages/_app.jsx: -------------------------------------------------------------------------------- 1 | import '../styles/globals.css' 2 | 3 | import { ColorModeSwitch, DokzProvider, GithubLink } from 'dokz' 4 | import { H2, H3, H4 } from '@finetwork/ui' 5 | 6 | import { ChakraProvider } from '@chakra-ui/react' 7 | import Head from 'next/head' 8 | import Link from 'next/link' 9 | 10 | export default function App(props) { 11 | const { Component, pageProps } = props 12 | return ( 13 | 14 | 15 | 20 | 21 | 26 | 27 | 28 | 29 | 32 | 33 |

Finetwork UI

34 |
35 | 36 | } 37 | headerItems={[ 38 | , 39 |
41 | setModeTheme((prev) => (prev === 'light' ? 'dark' : 'light')) 42 | } 43 | > 44 | 45 |
, 46 | ]} 47 | sidebarOrdering={{ 48 | 'index.mdx': true, 49 | 'getting-started.mdx': true, 50 | components: { 51 | 'accordion.mdx': true, 52 | 'button.mdx': true, 53 | 'card.mdx': true, 54 | 'checkbox.mdx': true, 55 | 'dialog.mdx': true, 56 | 'dropdown-menu.mdx': true, 57 | 'input.mdx': true, 58 | 'link.mdx': true, 59 | 'loading.mdx': true, 60 | 'radio.mdx': true, 61 | 'select.mdx': true, 62 | 'separator.mdx': true, 63 | 'skeleton.mdx': true, 64 | 'switch.mdx': true, 65 | 'tabs.mdx': true, 66 | 'tag.mdx': true, 67 | 'textarea.mdx': true, 68 | 'toast.mdx': true, 69 | 'tooltip.mdx': true, 70 | 'typography.mdx': true, 71 | }, 72 | sections: { 73 | 'price-card.mdx': true, 74 | }, 75 | }} 76 | > 77 | 78 |
79 |
80 | ) 81 | } 82 | -------------------------------------------------------------------------------- /packages/website/pages/_document.js: -------------------------------------------------------------------------------- 1 | import { getCssText } from '../styles/stitches.config' 2 | import { getCssText as getCssTextFiUi } from '@finetwork/ui' 3 | import { Html, Head, Main, NextScript } from 'next/document' 4 | 5 | export default function Document() { 6 | return ( 7 | 8 | 9 |