mirror of
https://github.com/nextui-org/nextui.git
synced 2025-12-08 19:26:11 +00:00
initial commit
This commit is contained in:
commit
26583faa40
17
.babelrc
Normal file
17
.babelrc
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"presets": ["next/babel"],
|
||||||
|
"plugins": [
|
||||||
|
[
|
||||||
|
"module-resolver",
|
||||||
|
{
|
||||||
|
"root": ["./"],
|
||||||
|
"alias": {
|
||||||
|
"@components": "./src/components",
|
||||||
|
"@hooks": "./src/hooks",
|
||||||
|
"@utils": "./src/utils",
|
||||||
|
"@theme": "./src/theme"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
13
.editorconfig
Normal file
13
.editorconfig
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Editor configuration, see http://editorconfig.org
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
max_line_length = off
|
||||||
|
trim_trailing_whitespace = false
|
||||||
9
.eslintignore
Normal file
9
.eslintignore
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
.now/*
|
||||||
|
.next/*
|
||||||
|
examples/*
|
||||||
|
dist/*
|
||||||
|
esm/*
|
||||||
|
public/*
|
||||||
|
scripts/*
|
||||||
|
tests/*
|
||||||
|
*.config.js
|
||||||
79
.eslintrc
Normal file
79
.eslintrc
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
{
|
||||||
|
"plugins": ["prettier", "@typescript-eslint"],
|
||||||
|
"extends": ["eslint:recommended", "plugin:react/recommended", "prettier"],
|
||||||
|
"parser": "@typescript-eslint/parser",
|
||||||
|
"parserOptions": {
|
||||||
|
"project": "./tsconfig.json",
|
||||||
|
"ecmaFeatures": {
|
||||||
|
"jsx": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"react": {
|
||||||
|
"pragma": "React",
|
||||||
|
"version": "detect"
|
||||||
|
},
|
||||||
|
"import/resolver": {
|
||||||
|
"typescript": {
|
||||||
|
"alwaysTryTypes": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"object-curly-spacing": ["warn", "always"],
|
||||||
|
"no-unused-vars": [
|
||||||
|
"warn",
|
||||||
|
{
|
||||||
|
"vars": "all",
|
||||||
|
"args": "none"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@typescript-eslint/no-unused-vars": [
|
||||||
|
"warn",
|
||||||
|
{
|
||||||
|
"vars": "all",
|
||||||
|
"args": "none"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@typescript-eslint/no-explicit-any": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"ignoreRestArgs": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"max-len": [
|
||||||
|
"warn",
|
||||||
|
{
|
||||||
|
"code": 80,
|
||||||
|
"ignoreStrings": true,
|
||||||
|
"ignoreTemplateLiterals": true,
|
||||||
|
"ignoreComments": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"no-plusplus": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"allowForLoopAfterthoughts": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"react/jsx-key": "error",
|
||||||
|
"react/jsx-props-no-spreading": "off",
|
||||||
|
"import/prefer-default-export": "off",
|
||||||
|
"react/jsx-boolean-value": "off",
|
||||||
|
"react/prop-types": "off",
|
||||||
|
"react/no-unescaped-entities": "off",
|
||||||
|
"react/jsx-one-expression-per-line": "off",
|
||||||
|
"react/jsx-wrap-multilines": "off",
|
||||||
|
"react/destructuring-assignment": "off",
|
||||||
|
"@typescript-eslint/comma-dangle": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"arrays": "only-multiline",
|
||||||
|
"objects": "only-multiline",
|
||||||
|
"imports": "only-multiline",
|
||||||
|
"exports": "only-multiline",
|
||||||
|
"functions": "never"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
33
.gitignore
vendored
Normal file
33
.gitignore
vendored
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
|
||||||
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
/.pnp
|
||||||
|
.pnp.js
|
||||||
|
|
||||||
|
# testing
|
||||||
|
/coverage
|
||||||
|
|
||||||
|
# next.js
|
||||||
|
/.next/
|
||||||
|
/out/
|
||||||
|
|
||||||
|
# production
|
||||||
|
/build
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.DS_Store
|
||||||
|
.env*
|
||||||
|
|
||||||
|
# debug
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
.now
|
||||||
|
dist
|
||||||
|
esm
|
||||||
|
examples/**/yarn.lock
|
||||||
|
examples/**/out
|
||||||
|
examples/**/.next
|
||||||
12
.prettierignore
Normal file
12
.prettierignore
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
.github
|
||||||
|
.next
|
||||||
|
.now
|
||||||
|
.circleci
|
||||||
|
dist
|
||||||
|
coverage
|
||||||
|
public
|
||||||
|
esm
|
||||||
|
*.json
|
||||||
|
*.d.ts
|
||||||
|
*.yml
|
||||||
|
*.snap
|
||||||
6
.prettierrc
Normal file
6
.prettierrc
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"printWidth": 80,
|
||||||
|
"singleQuote": true,
|
||||||
|
"trailingComma": "es5",
|
||||||
|
"tabWidth": 2
|
||||||
|
}
|
||||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2020 Next UI
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
2
next-env.d.ts
vendored
Normal file
2
next-env.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
/// <reference types="next" />
|
||||||
|
/// <reference types="next/types/global" />
|
||||||
5
next.config.js
Normal file
5
next.config.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
module.exports = {
|
||||||
|
future: {
|
||||||
|
webpack5: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
95
package.json
Normal file
95
package.json
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
{
|
||||||
|
"name": "nextui",
|
||||||
|
"version": "0.1.1",
|
||||||
|
"main": "dist/index.js",
|
||||||
|
"module": "esm/index.js",
|
||||||
|
"types": "dist/index.d.ts",
|
||||||
|
"unpkg": "dist/index.min.js",
|
||||||
|
"license": "MIT",
|
||||||
|
"description": "🚀 Beautiful and modern React UI library.",
|
||||||
|
"homepage": "https://nextui.org",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/jrgarciadev/next-ui/issues/new/choose"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/jrgarciadev/next-ui"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"next",
|
||||||
|
"next ui",
|
||||||
|
"components",
|
||||||
|
"modern components",
|
||||||
|
"react components",
|
||||||
|
"react ui"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"dev": "next dev",
|
||||||
|
"start": "next start",
|
||||||
|
"contributor-collect": "node scripts/collect-contributors.js",
|
||||||
|
"build:esm": "babel --config-file ./scripts/babel.config.js --extensions \".js,.ts,.tsx\" ./components --out-dir ./esm --ignore \"**/__tests__/**/*,**/*.d.ts\"",
|
||||||
|
"build:webpack": "webpack --config scripts/webpack.config.js",
|
||||||
|
"build:types": "tsc -p ./scripts",
|
||||||
|
"build": "yarn clear && yarn build:esm && yarn build:webpack && yarn build:types",
|
||||||
|
"clear": "rm -rf ./dist ./esm",
|
||||||
|
"lint": "eslint --ext .js,.jsx,.ts,.tsx src --color",
|
||||||
|
"format": "prettier --write 'src/**/*.{ts,tsx,scss,css,json}'",
|
||||||
|
"prettier": "prettier --write .",
|
||||||
|
"test": "jest --config .jest.config.js --no-cache",
|
||||||
|
"test-update": "jest --config .jest.config.js --no-cache --update-snapshot",
|
||||||
|
"coverage": "yarn test --coverage",
|
||||||
|
"release": "yarn build && yarn publish --access public --non-interactive"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"/dist",
|
||||||
|
"/esm"
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"styled-jsx": "^3.4.4"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/cli": "^7.13.16",
|
||||||
|
"@babel/plugin-transform-runtime": "^7.13.15",
|
||||||
|
"@babel/preset-typescript": "^7.13.0",
|
||||||
|
"@babel/runtime": "^7.13.17",
|
||||||
|
"@mapbox/rehype-prism": "^0.6.0",
|
||||||
|
"@mdx-js/loader": "^1.6.22",
|
||||||
|
"@next/mdx": "^10.1.3",
|
||||||
|
"@rollup/plugin-commonjs": "^18.0.0",
|
||||||
|
"@rollup/plugin-node-resolve": "^11.2.1",
|
||||||
|
"@types/react": "^17.0.3",
|
||||||
|
"@types/react-dom": "^17.0.3",
|
||||||
|
"@types/styled-jsx": "^2.2.8",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^4.22.0",
|
||||||
|
"@typescript-eslint/parser": "^4.22.0",
|
||||||
|
"babel-eslint": "^10.1.0",
|
||||||
|
"babel-jest": "^26.6.3",
|
||||||
|
"babel-loader": "^8.2.2",
|
||||||
|
"babel-plugin-module-resolver": "^4.1.0",
|
||||||
|
"eslint": "^7.24.0",
|
||||||
|
"eslint-config-airbnb": "^18.2.1",
|
||||||
|
"eslint-config-airbnb-typescript": "^12.3.1",
|
||||||
|
"eslint-config-prettier": "^8.2.0",
|
||||||
|
"eslint-config-react-app": "^6.0.0",
|
||||||
|
"eslint-config-ts-lambdas": "^1.2.3",
|
||||||
|
"eslint-import-resolver-typescript": "^2.4.0",
|
||||||
|
"eslint-loader": "^4.0.2",
|
||||||
|
"eslint-plugin-flowtype": "^5.7.1",
|
||||||
|
"eslint-plugin-import": "^2.22.1",
|
||||||
|
"eslint-plugin-jsx-a11y": "^6.4.1",
|
||||||
|
"eslint-plugin-prettier": "^3.4.0",
|
||||||
|
"eslint-plugin-react": "^7.23.2",
|
||||||
|
"eslint-plugin-react-hooks": "^4.2.0",
|
||||||
|
"next": "^10.1.3",
|
||||||
|
"prettier": "^2.2.1",
|
||||||
|
"prettier-eslint": "^12.0.0",
|
||||||
|
"prettier-eslint-cli": "^5.0.1",
|
||||||
|
"react": "^17.0.2",
|
||||||
|
"react-dom": "^17.0.2",
|
||||||
|
"rollup-plugin-babel": "^4.4.0",
|
||||||
|
"rollup-plugin-local-resolve": "^1.0.7",
|
||||||
|
"typescript": "^4.2.4",
|
||||||
|
"webpack": "^5.35.0",
|
||||||
|
"webpack-cli": "^4.6.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
15
pages/index.tsx
Normal file
15
pages/index.tsx
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import Checkbox from '@components/checkbox';
|
||||||
|
|
||||||
|
const IndexPage = () => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1>Checkbox</h1>
|
||||||
|
<Checkbox checked={true} size="medium">
|
||||||
|
medium
|
||||||
|
</Checkbox>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default IndexPage;
|
||||||
82
rollup.config.js
Normal file
82
rollup.config.js
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
import commonjs from '@rollup/plugin-commonjs'
|
||||||
|
import nodeResolve from '@rollup/plugin-node-resolve'
|
||||||
|
import localResolve from 'rollup-plugin-local-resolve'
|
||||||
|
import babel from 'rollup-plugin-babel'
|
||||||
|
import fs from 'fs-extra'
|
||||||
|
import path from 'path'
|
||||||
|
const componentsPath = path.join(__dirname, 'components')
|
||||||
|
const distPath = path.join(__dirname, 'dist')
|
||||||
|
|
||||||
|
const extensions = ['.js', '.jsx', '.ts', '.tsx']
|
||||||
|
|
||||||
|
const plugins = [
|
||||||
|
babel({
|
||||||
|
exclude: 'node_modules/**',
|
||||||
|
extensions,
|
||||||
|
presets: ['@babel/preset-env', '@babel/preset-react', '@babel/preset-typescript'],
|
||||||
|
plugins: ['styled-jsx/babel'],
|
||||||
|
}),
|
||||||
|
localResolve(),
|
||||||
|
nodeResolve({
|
||||||
|
browser: true,
|
||||||
|
extensions,
|
||||||
|
}),
|
||||||
|
commonjs(),
|
||||||
|
]
|
||||||
|
|
||||||
|
const globals = {
|
||||||
|
react: 'React',
|
||||||
|
'react-dom': 'ReactDOM',
|
||||||
|
}
|
||||||
|
|
||||||
|
const external = id => /^react|react-dom|styled-jsx|next\/link/.test(id)
|
||||||
|
|
||||||
|
const cjsOutput = {
|
||||||
|
format: 'cjs',
|
||||||
|
exports: 'named',
|
||||||
|
entryFileNames: '[name]/index.js',
|
||||||
|
dir: 'dist',
|
||||||
|
globals,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default (async () => {
|
||||||
|
await fs.remove(distPath)
|
||||||
|
const files = await fs.readdir(componentsPath)
|
||||||
|
|
||||||
|
const components = await Promise.all(
|
||||||
|
files.map(async name => {
|
||||||
|
const comPath = path.join(componentsPath, name)
|
||||||
|
const entry = path.join(comPath, 'index.ts')
|
||||||
|
|
||||||
|
const stat = await fs.stat(comPath)
|
||||||
|
if (!stat.isDirectory()) return null
|
||||||
|
|
||||||
|
const hasFile = await fs.pathExists(entry)
|
||||||
|
if (!hasFile) return null
|
||||||
|
|
||||||
|
return { name, url: entry }
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
return [
|
||||||
|
...components
|
||||||
|
.filter(r => r)
|
||||||
|
.map(({ name, url }) => ({
|
||||||
|
input: { [name]: url },
|
||||||
|
output: [cjsOutput],
|
||||||
|
external,
|
||||||
|
plugins,
|
||||||
|
})),
|
||||||
|
{
|
||||||
|
input: { index: path.join(componentsPath, 'index.ts') },
|
||||||
|
output: [
|
||||||
|
{
|
||||||
|
...cjsOutput,
|
||||||
|
entryFileNames: 'index.js',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
external,
|
||||||
|
plugins,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
})()
|
||||||
21
src/components/checkbox/checkbox-context.ts
Normal file
21
src/components/checkbox/checkbox-context.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export interface CheckboxConfig {
|
||||||
|
updateState?: (value: string, checked: boolean) => void;
|
||||||
|
disabledAll: boolean;
|
||||||
|
values: string[];
|
||||||
|
inGroup: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultContext = {
|
||||||
|
disabledAll: false,
|
||||||
|
inGroup: false,
|
||||||
|
values: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const CheckboxContext = React.createContext<CheckboxConfig>(
|
||||||
|
defaultContext
|
||||||
|
);
|
||||||
|
|
||||||
|
export const useCheckbox = (): CheckboxConfig =>
|
||||||
|
React.useContext<CheckboxConfig>(CheckboxContext);
|
||||||
85
src/components/checkbox/checkbox-group.tsx
Normal file
85
src/components/checkbox/checkbox-group.tsx
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
import React, { useEffect, useMemo, useState } from 'react';
|
||||||
|
import { CheckboxContext } from './checkbox-context';
|
||||||
|
import useWarning from '@hooks/use-warning';
|
||||||
|
import { NormalSizes } from '@utils/prop-types';
|
||||||
|
import withDefaults from '@utils/with-defaults';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
value: string[];
|
||||||
|
disabled?: boolean;
|
||||||
|
size?: NormalSizes;
|
||||||
|
onChange?: (values: string[]) => void;
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultProps = {
|
||||||
|
disabled: false,
|
||||||
|
size: 'small' as NormalSizes,
|
||||||
|
className: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
type NativeAttrs = Omit<React.HTMLAttributes<unknown>, keyof Props>;
|
||||||
|
export type CheckboxGroupProps = Props & typeof defaultProps & NativeAttrs;
|
||||||
|
|
||||||
|
export const getCheckboxSize = (size: NormalSizes): string => {
|
||||||
|
const sizes: { [key in NormalSizes]: string } = {
|
||||||
|
mini: '.75rem',
|
||||||
|
small: '.875rem',
|
||||||
|
medium: '1rem',
|
||||||
|
large: '1.125rem',
|
||||||
|
};
|
||||||
|
return sizes[size];
|
||||||
|
};
|
||||||
|
|
||||||
|
const CheckboxGroup: React.FC<React.PropsWithChildren<CheckboxGroupProps>> = ({
|
||||||
|
disabled,
|
||||||
|
onChange,
|
||||||
|
value,
|
||||||
|
size,
|
||||||
|
children,
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}) => {
|
||||||
|
const [selfVal, setSelfVal] = useState<string[]>([]);
|
||||||
|
if (!value) {
|
||||||
|
value = [];
|
||||||
|
useWarning('Props "value" is required.', 'Checkbox Group');
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateState = (val: string, checked: boolean) => {
|
||||||
|
const removed = selfVal.filter((v) => v !== val);
|
||||||
|
const next = checked ? [...removed, val] : removed;
|
||||||
|
setSelfVal(next);
|
||||||
|
onChange && onChange(next);
|
||||||
|
};
|
||||||
|
|
||||||
|
const providerValue = useMemo(() => {
|
||||||
|
return {
|
||||||
|
updateState,
|
||||||
|
disabledAll: disabled,
|
||||||
|
inGroup: true,
|
||||||
|
values: selfVal,
|
||||||
|
};
|
||||||
|
}, [disabled, selfVal]);
|
||||||
|
const fontSize = useMemo(() => getCheckboxSize(size), [size]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setSelfVal(value);
|
||||||
|
}, [value.join(',')]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<CheckboxContext.Provider value={providerValue}>
|
||||||
|
<div className={`group ${className}`} {...props}>
|
||||||
|
{children}
|
||||||
|
<style jsx>{`
|
||||||
|
.group :global(label) {
|
||||||
|
margin-right: calc(${fontSize} * 2);
|
||||||
|
--checkbox-size: ${fontSize};
|
||||||
|
}
|
||||||
|
`}</style>
|
||||||
|
</div>
|
||||||
|
</CheckboxContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default withDefaults(CheckboxGroup, defaultProps);
|
||||||
54
src/components/checkbox/checkbox-icon.tsx
Normal file
54
src/components/checkbox/checkbox-icon.tsx
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import React, { useMemo } from 'react';
|
||||||
|
import useTheme from '@hooks/use-theme';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
disabled?: boolean;
|
||||||
|
checked?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CheckboxIcon: React.FC<Props> = ({ disabled, checked }) => {
|
||||||
|
const theme = useTheme();
|
||||||
|
|
||||||
|
const { fill, bg, stroke } = useMemo(() => {
|
||||||
|
return {
|
||||||
|
fill: theme.palette.foreground,
|
||||||
|
bg: theme.palette.background,
|
||||||
|
stroke: theme.palette.accents_5,
|
||||||
|
};
|
||||||
|
}, [theme.palette]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{checked ? (
|
||||||
|
<svg viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path
|
||||||
|
d="M12.1429 0H3.85714C1.7269 0 0 1.79086 0 4V12C0 14.2091 1.7269 16 3.85714 16H12.1429C14.2731 16 16 14.2091 16 12V4C16 1.79086 14.2731 0 12.1429 0Z"
|
||||||
|
fill={fill}
|
||||||
|
/>
|
||||||
|
<path d="M16 3L7.72491 11L5 8" stroke={bg} strokeWidth="1.5" />
|
||||||
|
</svg>
|
||||||
|
) : (
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 12" fill="none">
|
||||||
|
<path
|
||||||
|
d="M8.5 0.5H3.5C1.84315 0.5 0.5 1.84315 0.5 3.5V8.5C0.5 10.1569 1.84315 11.5 3.5 11.5H8.5C10.1569 11.5 11.5 10.1569 11.5 8.5V3.5C11.5 1.84315 10.1569 0.5 8.5 0.5Z"
|
||||||
|
stroke={stroke}
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
)}
|
||||||
|
<style jsx>{`
|
||||||
|
svg {
|
||||||
|
display: inline-flex;
|
||||||
|
width: calc(0.86 * var(--checkbox-size));
|
||||||
|
height: calc(0.86 * var(--checkbox-size));
|
||||||
|
user-select: none;
|
||||||
|
opacity: ${disabled ? 0.4 : 1};
|
||||||
|
cursor: ${disabled ? 'not-allowed' : 'pointer'};
|
||||||
|
}
|
||||||
|
`}</style>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const MemoCheckboxIcon = React.memo(CheckboxIcon);
|
||||||
|
|
||||||
|
export default MemoCheckboxIcon;
|
||||||
155
src/components/checkbox/checkbox.tsx
Normal file
155
src/components/checkbox/checkbox.tsx
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
|
import { useCheckbox } from './checkbox-context';
|
||||||
|
import CheckboxGroup, { getCheckboxSize } from './checkbox-group';
|
||||||
|
import CheckboxIcon from './checkbox-icon';
|
||||||
|
import useWarning from '@hooks/use-warning';
|
||||||
|
import { NormalSizes } from '@utils/prop-types';
|
||||||
|
|
||||||
|
interface CheckboxEventTarget {
|
||||||
|
checked: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CheckboxEvent {
|
||||||
|
target: CheckboxEventTarget;
|
||||||
|
stopPropagation: () => void;
|
||||||
|
preventDefault: () => void;
|
||||||
|
nativeEvent: React.ChangeEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
checked?: boolean;
|
||||||
|
disabled?: boolean;
|
||||||
|
initialChecked?: boolean;
|
||||||
|
onChange?: (e: CheckboxEvent) => void;
|
||||||
|
size?: NormalSizes;
|
||||||
|
className?: string;
|
||||||
|
value?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultProps = {
|
||||||
|
disabled: false,
|
||||||
|
initialChecked: false,
|
||||||
|
size: 'small' as NormalSizes,
|
||||||
|
className: '',
|
||||||
|
value: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
type NativeAttrs = Omit<React.InputHTMLAttributes<unknown>, keyof Props>;
|
||||||
|
export type CheckboxProps = Props & typeof defaultProps & NativeAttrs;
|
||||||
|
|
||||||
|
const Checkbox: React.FC<CheckboxProps> = ({
|
||||||
|
checked,
|
||||||
|
initialChecked,
|
||||||
|
disabled,
|
||||||
|
onChange,
|
||||||
|
className,
|
||||||
|
children,
|
||||||
|
size,
|
||||||
|
value,
|
||||||
|
...props
|
||||||
|
}) => {
|
||||||
|
const [selfChecked, setSelfChecked] = useState<boolean>(initialChecked);
|
||||||
|
const { updateState, inGroup, disabledAll, values } = useCheckbox();
|
||||||
|
const isDisabled = inGroup ? disabledAll || disabled : disabled;
|
||||||
|
|
||||||
|
if (inGroup && checked) {
|
||||||
|
useWarning(
|
||||||
|
'Remove props "checked" when [Checkbox] component is in the group.',
|
||||||
|
'Checkbox'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (inGroup) {
|
||||||
|
useEffect(() => {
|
||||||
|
const next = values.includes(value);
|
||||||
|
if (next === selfChecked) return;
|
||||||
|
setSelfChecked(next);
|
||||||
|
}, [values.join(',')]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const fontSize = useMemo(() => getCheckboxSize(size), [size]);
|
||||||
|
const changeHandle = useCallback(
|
||||||
|
(ev: React.ChangeEvent) => {
|
||||||
|
if (isDisabled) return;
|
||||||
|
const selfEvent: CheckboxEvent = {
|
||||||
|
target: {
|
||||||
|
checked: !selfChecked,
|
||||||
|
},
|
||||||
|
stopPropagation: ev.stopPropagation,
|
||||||
|
preventDefault: ev.preventDefault,
|
||||||
|
nativeEvent: ev,
|
||||||
|
};
|
||||||
|
if (inGroup && updateState) {
|
||||||
|
updateState && updateState(value, !selfChecked);
|
||||||
|
}
|
||||||
|
|
||||||
|
setSelfChecked(!selfChecked);
|
||||||
|
onChange && onChange(selfEvent);
|
||||||
|
},
|
||||||
|
[updateState, onChange, isDisabled, selfChecked]
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (checked === undefined) return;
|
||||||
|
setSelfChecked(checked);
|
||||||
|
}, [checked]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<label className={`${className}`}>
|
||||||
|
<CheckboxIcon disabled={isDisabled} checked={selfChecked} />
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
disabled={isDisabled}
|
||||||
|
checked={selfChecked}
|
||||||
|
onChange={changeHandle}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
<span className="text">{children}</span>
|
||||||
|
|
||||||
|
<style jsx>{`
|
||||||
|
label {
|
||||||
|
--checkbox-size: ${fontSize};
|
||||||
|
display: inline-flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: auto;
|
||||||
|
cursor: ${isDisabled ? 'not-allowed' : 'pointer'};
|
||||||
|
opacity: ${isDisabled ? 0.75 : 1};
|
||||||
|
height: var(--checkbox-size);
|
||||||
|
line-height: var(--checkbox-size);
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
font-size: var(--checkbox-size);
|
||||||
|
line-height: var(--checkbox-size);
|
||||||
|
padding-left: calc(var(--checkbox-size) * 0.57);
|
||||||
|
user-select: none;
|
||||||
|
cursor: ${isDisabled ? 'not-allowed' : 'pointer'};
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
opacity: 0;
|
||||||
|
outline: none;
|
||||||
|
position: absolute;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
z-index: -1;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
`}</style>
|
||||||
|
</label>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
Checkbox.defaultProps = defaultProps;
|
||||||
|
|
||||||
|
type CheckboxComponent<P = {}> = React.FC<P> & {
|
||||||
|
Group: typeof CheckboxGroup;
|
||||||
|
};
|
||||||
|
|
||||||
|
type ComponentProps = Partial<typeof defaultProps> &
|
||||||
|
Omit<Props, keyof typeof defaultProps> &
|
||||||
|
NativeAttrs;
|
||||||
|
|
||||||
|
export default Checkbox as CheckboxComponent<ComponentProps>;
|
||||||
10
src/components/checkbox/index.ts
Normal file
10
src/components/checkbox/index.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import Checkbox from './checkbox'
|
||||||
|
import CheckboxGroup from './checkbox-group'
|
||||||
|
import { CheckboxProps, CheckboxEvent } from './checkbox'
|
||||||
|
|
||||||
|
export type Props = CheckboxProps
|
||||||
|
export type Event = CheckboxEvent
|
||||||
|
|
||||||
|
Checkbox.Group = CheckboxGroup
|
||||||
|
|
||||||
|
export default Checkbox
|
||||||
1
src/components/index.ts
Normal file
1
src/components/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default as Checkbox } from './checkbox';
|
||||||
7
src/hooks/use-theme.ts
Normal file
7
src/hooks/use-theme.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import ThemeContext from '@theme/theme-context'
|
||||||
|
import { NextUIThemes } from '@theme/index'
|
||||||
|
|
||||||
|
const useTheme = (): NextUIThemes => React.useContext<NextUIThemes>(ThemeContext)
|
||||||
|
|
||||||
|
export default useTheme
|
||||||
16
src/hooks/use-warning.ts
Normal file
16
src/hooks/use-warning.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
const warningStack: { [key: string]: boolean } = {}
|
||||||
|
|
||||||
|
const useWarning = (message: string, component?: string) => {
|
||||||
|
const tag = component ? ` [${component}]` : ' '
|
||||||
|
const log = `[Next UI]${tag}: ${message}`
|
||||||
|
if (typeof console === 'undefined') return
|
||||||
|
if (warningStack[log]) return
|
||||||
|
warningStack[log] = true
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
return console.error(log)
|
||||||
|
}
|
||||||
|
console.warn(log)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useWarning
|
||||||
72
src/theme/default.ts
Normal file
72
src/theme/default.ts
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
import { NextUIThemes, NextUIThemesPalette, NextUIThemesExpressiveness } from './index'
|
||||||
|
import { defaultFont, defaultBreakpoints, defaultLayout } from './shared'
|
||||||
|
|
||||||
|
export const palette: NextUIThemesPalette = {
|
||||||
|
accents_1: '#fafafa',
|
||||||
|
accents_2: '#eaeaea',
|
||||||
|
accents_3: '#999',
|
||||||
|
accents_4: '#888',
|
||||||
|
accents_5: '#666',
|
||||||
|
accents_6: '#444',
|
||||||
|
accents_7: '#333',
|
||||||
|
accents_8: '#111',
|
||||||
|
background: '#fff',
|
||||||
|
foreground: '#000',
|
||||||
|
selection: '#79ffe1',
|
||||||
|
secondary: '#666',
|
||||||
|
code: '#f81ce5',
|
||||||
|
border: '#eaeaea',
|
||||||
|
error: '#e00',
|
||||||
|
errorLight: '#ff1a1a',
|
||||||
|
errorLighter: '#f7d4d6',
|
||||||
|
errorDark: '#c50000',
|
||||||
|
success: '#0070f3',
|
||||||
|
successLight: '#3291ff',
|
||||||
|
successLighter: '#d3e5ff',
|
||||||
|
successDark: '#0761d1',
|
||||||
|
warning: '#f5a623',
|
||||||
|
warningLight: '#f7b955',
|
||||||
|
warningLighter: '#ffefcf',
|
||||||
|
warningDark: '#ab570a',
|
||||||
|
cyan: '#50e3c2',
|
||||||
|
cyanLighter: '#aaffec',
|
||||||
|
cyanLight: '#79ffe1',
|
||||||
|
cyanDark: '#29bc9b',
|
||||||
|
violet: '#7928ca',
|
||||||
|
violetLighter: '#e3d7fc',
|
||||||
|
violetLight: '#8a63d2',
|
||||||
|
violetDark: '#4c2889',
|
||||||
|
purple: '#f81ce5',
|
||||||
|
alert: '#ff0080',
|
||||||
|
magenta: '#eb367f',
|
||||||
|
link: '#0070f3',
|
||||||
|
}
|
||||||
|
|
||||||
|
export const expressiveness: NextUIThemesExpressiveness = {
|
||||||
|
linkStyle: 'none',
|
||||||
|
linkHoverStyle: 'none',
|
||||||
|
dropdownBoxShadow: '0 4px 4px 0 rgba(0, 0, 0, 0.02)',
|
||||||
|
scrollerStart: 'rgba(255, 255, 255, 1)',
|
||||||
|
scrollerEnd: 'rgba(255, 255, 255, 0)',
|
||||||
|
shadowSmall: '0 5px 10px rgba(0, 0, 0, 0.12)',
|
||||||
|
shadowMedium: '0 8px 30px rgba(0, 0, 0, 0.12)',
|
||||||
|
shadowLarge: '0 30px 60px rgba(0, 0, 0, 0.12)',
|
||||||
|
portalOpacity: 0.25,
|
||||||
|
}
|
||||||
|
|
||||||
|
export const font = defaultFont
|
||||||
|
|
||||||
|
export const breakpoints = defaultBreakpoints
|
||||||
|
|
||||||
|
export const layout = defaultLayout
|
||||||
|
|
||||||
|
export const themes: NextUIThemes = {
|
||||||
|
type: 'light',
|
||||||
|
font,
|
||||||
|
layout,
|
||||||
|
palette,
|
||||||
|
breakpoints,
|
||||||
|
expressiveness,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default themes
|
||||||
96
src/theme/index.ts
Normal file
96
src/theme/index.ts
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
import { ThemeTypes } from '@utils/prop-types'
|
||||||
|
|
||||||
|
export interface NextUIThemesPalette {
|
||||||
|
accents_1: string
|
||||||
|
accents_2: string
|
||||||
|
accents_3: string
|
||||||
|
accents_4: string
|
||||||
|
accents_5: string
|
||||||
|
accents_6: string
|
||||||
|
accents_7: string
|
||||||
|
accents_8: string
|
||||||
|
background: string
|
||||||
|
foreground: string
|
||||||
|
selection: string
|
||||||
|
secondary: string
|
||||||
|
code: string
|
||||||
|
border: string
|
||||||
|
success: string
|
||||||
|
successLighter: string
|
||||||
|
successLight: string
|
||||||
|
successDark: string
|
||||||
|
error: string
|
||||||
|
errorLighter: string
|
||||||
|
errorLight: string
|
||||||
|
errorDark: string
|
||||||
|
warning: string
|
||||||
|
warningLighter: string
|
||||||
|
warningLight: string
|
||||||
|
warningDark: string
|
||||||
|
cyan: string
|
||||||
|
cyanLighter: string
|
||||||
|
cyanLight: string
|
||||||
|
cyanDark: string
|
||||||
|
violet: string
|
||||||
|
violetLighter: string
|
||||||
|
violetLight: string
|
||||||
|
violetDark: string
|
||||||
|
link: string
|
||||||
|
purple: string
|
||||||
|
magenta: string
|
||||||
|
alert: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NextUIThemesExpressiveness {
|
||||||
|
linkStyle: string
|
||||||
|
linkHoverStyle: string
|
||||||
|
dropdownBoxShadow: string
|
||||||
|
scrollerStart: string
|
||||||
|
scrollerEnd: string
|
||||||
|
shadowSmall: string
|
||||||
|
shadowMedium: string
|
||||||
|
shadowLarge: string
|
||||||
|
portalOpacity: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NextUIThemesLayout {
|
||||||
|
gap: string
|
||||||
|
gapNegative: string
|
||||||
|
gapHalf: string
|
||||||
|
gapHalfNegative: string
|
||||||
|
gapQuarter: string
|
||||||
|
gapQuarterNegative: string
|
||||||
|
pageMargin: string
|
||||||
|
pageWidth: string
|
||||||
|
pageWidthWithMargin: string
|
||||||
|
breakpointMobile: string
|
||||||
|
breakpointTablet: string
|
||||||
|
radius: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NextUIThemesFont {
|
||||||
|
sans: string
|
||||||
|
mono: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BreakpointsItem {
|
||||||
|
min: string
|
||||||
|
max: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NextUIThemesBreakpoints {
|
||||||
|
xs: BreakpointsItem
|
||||||
|
sm: BreakpointsItem
|
||||||
|
md: BreakpointsItem
|
||||||
|
lg: BreakpointsItem
|
||||||
|
xl: BreakpointsItem
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NextUIThemes {
|
||||||
|
type: ThemeTypes
|
||||||
|
font: NextUIThemesFont
|
||||||
|
layout: NextUIThemesLayout
|
||||||
|
palette: NextUIThemesPalette
|
||||||
|
breakpoints: NextUIThemesBreakpoints
|
||||||
|
expressiveness: NextUIThemesExpressiveness
|
||||||
|
}
|
||||||
51
src/theme/shared.ts
Normal file
51
src/theme/shared.ts
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import {
|
||||||
|
NextUIThemesBreakpoints,
|
||||||
|
NextUIThemesFont,
|
||||||
|
NextUIThemesLayout,
|
||||||
|
} from './index'
|
||||||
|
|
||||||
|
export const defaultFont: NextUIThemesFont = {
|
||||||
|
sans:
|
||||||
|
'-apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif',
|
||||||
|
mono:
|
||||||
|
'Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace',
|
||||||
|
}
|
||||||
|
|
||||||
|
export const defaultBreakpoints: NextUIThemesBreakpoints = {
|
||||||
|
xs: {
|
||||||
|
min: '0',
|
||||||
|
max: '650px',
|
||||||
|
},
|
||||||
|
sm: {
|
||||||
|
min: '650px',
|
||||||
|
max: '900px',
|
||||||
|
},
|
||||||
|
md: {
|
||||||
|
min: '900px',
|
||||||
|
max: '1280px',
|
||||||
|
},
|
||||||
|
lg: {
|
||||||
|
min: '1280px',
|
||||||
|
max: '1920px',
|
||||||
|
},
|
||||||
|
xl: {
|
||||||
|
min: '1920px',
|
||||||
|
max: '10000px',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export const defaultLayout: NextUIThemesLayout = {
|
||||||
|
gap: '16pt',
|
||||||
|
gapNegative: '-16pt',
|
||||||
|
gapHalf: '8pt',
|
||||||
|
gapHalfNegative: '-8pt',
|
||||||
|
gapQuarter: '4pt',
|
||||||
|
gapQuarterNegative: '-4pt',
|
||||||
|
pageMargin: '16pt',
|
||||||
|
pageWidth: '750pt',
|
||||||
|
pageWidthWithMargin: '782pt',
|
||||||
|
breakpointMobile: defaultBreakpoints.xs.max,
|
||||||
|
breakpointTablet: defaultBreakpoints.sm.max,
|
||||||
|
radius: '5px',
|
||||||
|
}
|
||||||
|
|
||||||
7
src/theme/theme-context.ts
Normal file
7
src/theme/theme-context.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { NextUIThemes } from './index'
|
||||||
|
import defaultTheme from './default'
|
||||||
|
|
||||||
|
const ThemeContext: React.Context<NextUIThemes> = React.createContext<NextUIThemes>(defaultTheme)
|
||||||
|
|
||||||
|
export default ThemeContext
|
||||||
77
src/utils/prop-types.ts
Normal file
77
src/utils/prop-types.ts
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
export const tuple = <T extends string[]>(...args: T) => args
|
||||||
|
|
||||||
|
const buttonTypes = tuple(
|
||||||
|
'default',
|
||||||
|
'secondary',
|
||||||
|
'success',
|
||||||
|
'warning',
|
||||||
|
'error',
|
||||||
|
'abort',
|
||||||
|
'secondary-light',
|
||||||
|
'success-light',
|
||||||
|
'warning-light',
|
||||||
|
'error-light',
|
||||||
|
)
|
||||||
|
|
||||||
|
const normalSizes = tuple('mini', 'small', 'medium', 'large')
|
||||||
|
|
||||||
|
const normalTypes = tuple('default', 'secondary', 'success', 'warning', 'error')
|
||||||
|
|
||||||
|
const themeTypes = tuple('dark', 'light')
|
||||||
|
|
||||||
|
const snippetTypes = tuple('default', 'secondary', 'success', 'warning', 'error', 'dark', 'lite')
|
||||||
|
|
||||||
|
const cardTypes = tuple(
|
||||||
|
'default',
|
||||||
|
'secondary',
|
||||||
|
'success',
|
||||||
|
'warning',
|
||||||
|
'error',
|
||||||
|
'dark',
|
||||||
|
'lite',
|
||||||
|
'alert',
|
||||||
|
'purple',
|
||||||
|
'violet',
|
||||||
|
'cyan',
|
||||||
|
)
|
||||||
|
|
||||||
|
const copyTypes = tuple('default', 'slient', 'prevent')
|
||||||
|
|
||||||
|
const triggerTypes = tuple('hover', 'click')
|
||||||
|
|
||||||
|
const placement = tuple(
|
||||||
|
'top',
|
||||||
|
'topStart',
|
||||||
|
'topEnd',
|
||||||
|
'left',
|
||||||
|
'leftStart',
|
||||||
|
'leftEnd',
|
||||||
|
'bottom',
|
||||||
|
'bottomStart',
|
||||||
|
'bottomEnd',
|
||||||
|
'right',
|
||||||
|
'rightStart',
|
||||||
|
'rightEnd',
|
||||||
|
)
|
||||||
|
|
||||||
|
const dividerAlign = tuple('start', 'center', 'end', 'left', 'right')
|
||||||
|
|
||||||
|
export type ButtonTypes = typeof buttonTypes[number]
|
||||||
|
|
||||||
|
export type NormalSizes = typeof normalSizes[number]
|
||||||
|
|
||||||
|
export type NormalTypes = typeof normalTypes[number]
|
||||||
|
|
||||||
|
export type ThemeTypes = typeof themeTypes[number]
|
||||||
|
|
||||||
|
export type SnippetTypes = typeof snippetTypes[number]
|
||||||
|
|
||||||
|
export type CardTypes = typeof cardTypes[number]
|
||||||
|
|
||||||
|
export type CopyTypes = typeof copyTypes[number]
|
||||||
|
|
||||||
|
export type TriggerTypes = typeof triggerTypes[number]
|
||||||
|
|
||||||
|
export type Placement = typeof placement[number]
|
||||||
|
|
||||||
|
export type DividerAlign = typeof dividerAlign[number]
|
||||||
9
src/utils/with-defaults.ts
Normal file
9
src/utils/with-defaults.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
const withDefaults = <P, DP>(component: React.ComponentType<P>, defaultProps: DP) => {
|
||||||
|
type Props = Partial<DP> & Omit<P, keyof DP>
|
||||||
|
component.defaultProps = defaultProps
|
||||||
|
return component as React.ComponentType<Props>
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withDefaults
|
||||||
47
tsconfig.json
Normal file
47
tsconfig.json
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"@components/*": ["./src/components/*"],
|
||||||
|
"@hooks/*": ["./src/hooks/*"],
|
||||||
|
"@utils/*": ["./src/utils/*"],
|
||||||
|
"@theme/*": ["./src/theme/*"]
|
||||||
|
},
|
||||||
|
"strictNullChecks": true,
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"jsx": "preserve",
|
||||||
|
"noUnusedParameters": true,
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"noImplicitAny": true,
|
||||||
|
"target": "es6",
|
||||||
|
"lib": [
|
||||||
|
"dom",
|
||||||
|
"es2017"
|
||||||
|
],
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"allowJs": true,
|
||||||
|
"strict": false,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"module": "esnext",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"typeRoots": [
|
||||||
|
"node_modules/@types",
|
||||||
|
"./typings"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"exclude": ["node_modules"],
|
||||||
|
"include": [
|
||||||
|
"next-env.d.ts",
|
||||||
|
"**/*.ts",
|
||||||
|
"**/*.tsx",
|
||||||
|
"**/*.js",
|
||||||
|
"**/*.jsx",
|
||||||
|
"src/**/*.tsx"
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Loading…
x
Reference in New Issue
Block a user