├── site ├── style │ ├── hljs.scss │ ├── index.js │ └── _config.scss ├── tycheUI.png ├── demo │ ├── umi │ │ ├── index.js │ │ └── _index.md │ ├── Switch │ │ ├── basic.md │ │ ├── index.js │ │ ├── color.md │ │ ├── _props.md │ │ └── disabled.md │ ├── create-react-app │ │ └── index.js │ ├── checkbox │ │ ├── basic.md │ │ ├── index.js │ │ ├── disabled.md │ │ ├── icon.md │ │ ├── layout.md │ │ ├── checkboxGroup.md │ │ ├── _props.md │ │ └── checkAll.md │ ├── radio │ │ ├── basic.md │ │ ├── index.js │ │ ├── radioGroup.md │ │ ├── layout.md │ │ ├── _props.md │ │ ├── equal.md │ │ ├── disabled.md │ │ └── color.md │ ├── layout │ │ ├── index.js │ │ ├── _props.md │ │ └── basic.md │ ├── icon │ │ ├── index.js │ │ ├── _props.md │ │ ├── basic.md │ │ ├── material.md │ │ └── iconfont.md │ ├── drawer │ │ ├── index.js │ │ ├── _props.md │ │ └── basic.md │ ├── portal │ │ ├── index.js │ │ ├── purePortal.md │ │ ├── _props.md │ │ └── portal.md │ ├── appBar │ │ ├── default.md │ │ ├── index.js │ │ ├── _props.md │ │ └── basic.md │ ├── message │ │ ├── index.js │ │ ├── basic.md │ │ ├── duration.md │ │ ├── loading.md │ │ ├── type.md │ │ └── _props.md │ ├── input │ │ ├── icon.md │ │ ├── index.js │ │ ├── fix.md │ │ ├── error.md │ │ ├── count.md │ │ ├── textarea.md │ │ ├── _props.md │ │ └── basic.md │ ├── buttons │ │ ├── index.js │ │ ├── basic.md │ │ ├── round.md │ │ ├── outlined.md │ │ ├── text.md │ │ ├── circle-fab.md │ │ ├── size.md │ │ ├── _props.md │ │ └── icon.md │ ├── grid │ │ ├── pull-push.md │ │ ├── index.js │ │ ├── order.md │ │ ├── responsive.md │ │ ├── basic.md │ │ ├── offset.md │ │ ├── responsive-others.md │ │ ├── gutter.md │ │ ├── align.md │ │ ├── _props.md │ │ └── justify.md │ ├── modal │ │ ├── index.js │ │ ├── confirm.md │ │ ├── confirm-props.md │ │ ├── confirm-update.md │ │ ├── promise.md │ │ ├── basic.md │ │ ├── confirm-destroyAll.md │ │ ├── footer.md │ │ └── _props.md │ └── index.js ├── react-code-view │ └── lib │ │ ├── parseDom.js │ │ ├── index.js │ │ ├── Preview.js │ │ ├── parseHTML.js │ │ └── style │ │ ├── index.scss │ │ └── dracula.css ├── pages │ ├── Switch.tsx │ ├── Icon.tsx │ ├── Message.tsx │ ├── Radio.tsx │ ├── Layout.tsx │ ├── Portal.tsx │ ├── Drawer.tsx │ ├── Grid.tsx │ └── Input.tsx ├── utils.js ├── index.jsx ├── components │ ├── generatePage.jsx │ ├── Code.jsx │ └── AppBar.tsx └── index.html ├── components ├── icon │ ├── style │ │ ├── index.tsx │ │ └── index.scss │ ├── utils.ts │ ├── svgs │ │ ├── circle-info.svg │ │ ├── list.svg │ │ ├── warning.svg │ │ ├── clear.svg │ │ ├── loading.svg │ │ ├── checked.svg │ │ ├── info.svg │ │ ├── github.svg │ │ ├── code-close.svg │ │ └── code-open.svg │ ├── __test__ │ │ ├── __snapshots__ │ │ │ └── index.test.jsx.snap │ │ └── index.test.jsx │ ├── loadSvgSprite.tsx │ └── IconFont.tsx ├── col │ ├── style │ │ └── index.tsx │ └── index.tsx ├── drawer │ ├── style │ │ ├── index.tsx │ │ └── index.scss │ ├── index.tsx │ ├── __test__ │ │ └── index.test.jsx │ └── drawer.tsx ├── input │ ├── style │ │ └── index.tsx │ ├── index.tsx │ ├── Textarea.tsx │ └── __test__ │ │ └── index.test.jsx ├── layout │ ├── style │ │ ├── index.tsx │ │ └── index.scss │ ├── index.tsx │ └── __test__ │ │ └── index.test.jsx ├── row │ ├── style │ │ └── index.tsx │ └── index.tsx ├── button-base │ ├── style │ │ ├── index.tsx │ │ └── index.scss │ ├── Loading.tsx │ ├── __test__ │ │ └── index.test.jsx │ ├── Ripple.tsx │ └── index.tsx ├── grid │ ├── style │ │ ├── index.tsx │ │ ├── row.scss │ │ └── col.scss │ ├── index.tsx │ ├── RowContext.tsx │ └── __test__ │ │ ├── __snapshots__ │ │ └── index.test.jsx.snap │ │ └── index.test.jsx ├── radio │ ├── index.tsx │ ├── style │ │ ├── index.tsx │ │ └── index.scss │ ├── RadioContext.tsx │ ├── __test__ │ │ ├── __snapshots__ │ │ │ └── index.test.jsx.snap │ │ └── index.test.jsx │ └── RadioGroup.tsx ├── appBar │ ├── index.tsx │ ├── style │ │ ├── index.tsx │ │ └── index.scss │ ├── __test__ │ │ ├── index.test.jsx │ │ └── __snapshots__ │ │ │ └── index.test.jsx.snap │ ├── AppBar.tsx │ └── AppBarInner.tsx ├── portal │ ├── index.tsx │ ├── util.ts │ └── PurePortal.tsx ├── switch │ ├── index.tsx │ ├── style │ │ ├── index.tsx │ │ └── index.scss │ └── __test__ │ │ ├── __snapshots__ │ │ └── index.test.jsx.snap │ │ └── index.test.jsx ├── checkbox │ ├── index.tsx │ ├── style │ │ ├── index.tsx │ │ └── index.scss │ ├── CheckboxContext.tsx │ └── __test__ │ │ └── Checkbox.test.jsx ├── _util │ ├── isBrowser.ts │ ├── omit.ts │ ├── hooks.ts │ ├── type.ts │ ├── transition.ts │ ├── reactHelpers.ts │ ├── getScrollYBarWidth.ts │ └── memoize-one.ts ├── message │ ├── style │ │ ├── index.tsx │ │ └── index.scss │ ├── Message.tsx │ └── __test__ │ │ └── index.test.jsx ├── button │ ├── style │ │ └── index.tsx │ ├── index.tsx │ ├── Button.tsx │ └── __test__ │ │ ├── index.test.jsx │ │ └── __snapshots__ │ │ └── index.test.jsx.snap ├── modal │ ├── style │ │ ├── index.tsx │ │ └── confirm.scss │ ├── index.tsx │ ├── ActionButton.tsx │ ├── __test__ │ │ ├── Modal.test.jsx │ │ └── Confirm.test.jsx │ └── ModalWrapper.tsx ├── theme │ ├── _timing-functions.scss │ ├── mixins │ │ ├── _utils.scss │ │ ├── _config.scss │ │ ├── _function.scss │ │ └── mixins.scss │ └── default.scss ├── context │ ├── __test__ │ │ └── index.test.jsx │ └── ConfigContext.tsx └── index.tsx ├── tests ├── __mocks__ │ ├── object-mock.js │ └── file-mock.js └── setup.js ├── deploy.sh ├── types └── custom.d.ts ├── babel.config.js ├── scripts ├── utils │ └── projectHelper.ts └── config │ ├── postcssConfig.js │ ├── webpack.site.dev.ts │ ├── webpack.base.ts │ ├── webpack.dist.ts │ └── webpack.site.docs.ts ├── .codecov.yml ├── .prettierrc ├── .gitignore ├── .jest.ci.js ├── README.md ├── .eslintrc.js ├── .stylelintrc ├── index.js ├── tsconfig.json ├── LICENSE ├── jest.config.js └── .circleci └── config.yml /site/style/hljs.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/icon/style/index.tsx: -------------------------------------------------------------------------------- 1 | import './index.scss'; 2 | -------------------------------------------------------------------------------- /tests/__mocks__/object-mock.js: -------------------------------------------------------------------------------- 1 | module.exports = {}; 2 | -------------------------------------------------------------------------------- /components/col/style/index.tsx: -------------------------------------------------------------------------------- 1 | import '../../grid/style'; 2 | -------------------------------------------------------------------------------- /components/drawer/style/index.tsx: -------------------------------------------------------------------------------- 1 | import './index.scss'; 2 | -------------------------------------------------------------------------------- /components/input/style/index.tsx: -------------------------------------------------------------------------------- 1 | import './index.scss'; 2 | -------------------------------------------------------------------------------- /components/layout/style/index.tsx: -------------------------------------------------------------------------------- 1 | import './index.scss'; 2 | -------------------------------------------------------------------------------- /components/row/style/index.tsx: -------------------------------------------------------------------------------- 1 | import '../../grid/style'; 2 | -------------------------------------------------------------------------------- /tests/__mocks__/file-mock.js: -------------------------------------------------------------------------------- 1 | module.exports = 'test-file'; 2 | -------------------------------------------------------------------------------- /components/button-base/style/index.tsx: -------------------------------------------------------------------------------- 1 | import './index.scss'; 2 | -------------------------------------------------------------------------------- /deploy.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | npm version patch && \ 3 | git push -------------------------------------------------------------------------------- /components/grid/style/index.tsx: -------------------------------------------------------------------------------- 1 | import './col.scss'; 2 | import './row.scss'; 3 | -------------------------------------------------------------------------------- /components/col/index.tsx: -------------------------------------------------------------------------------- 1 | import { Col } from '../grid'; 2 | 3 | export default Col; 4 | -------------------------------------------------------------------------------- /components/row/index.tsx: -------------------------------------------------------------------------------- 1 | import { Row } from '../grid'; 2 | 3 | export default Row; 4 | -------------------------------------------------------------------------------- /site/tycheUI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buyou0821/tyche-ui/HEAD/site/tycheUI.png -------------------------------------------------------------------------------- /components/input/index.tsx: -------------------------------------------------------------------------------- 1 | import Input from './Input'; 2 | 3 | export default Input; 4 | -------------------------------------------------------------------------------- /components/radio/index.tsx: -------------------------------------------------------------------------------- 1 | import Radio from './Radio'; 2 | 3 | export default Radio; 4 | -------------------------------------------------------------------------------- /components/appBar/index.tsx: -------------------------------------------------------------------------------- 1 | import AppBar from './AppBar'; 2 | 3 | export default AppBar; 4 | -------------------------------------------------------------------------------- /components/drawer/index.tsx: -------------------------------------------------------------------------------- 1 | import drawer from './drawer'; 2 | 3 | export default drawer; 4 | -------------------------------------------------------------------------------- /components/layout/index.tsx: -------------------------------------------------------------------------------- 1 | import Layout from './Layout'; 2 | 3 | export default Layout; 4 | -------------------------------------------------------------------------------- /components/portal/index.tsx: -------------------------------------------------------------------------------- 1 | import Portal from './Portal'; 2 | 3 | export default Portal; 4 | -------------------------------------------------------------------------------- /components/switch/index.tsx: -------------------------------------------------------------------------------- 1 | import Switch from './Switch'; 2 | 3 | export default Switch; 4 | -------------------------------------------------------------------------------- /components/checkbox/index.tsx: -------------------------------------------------------------------------------- 1 | import Checkbox from './Checkbox'; 2 | 3 | export default Checkbox; 4 | -------------------------------------------------------------------------------- /site/style/index.js: -------------------------------------------------------------------------------- 1 | import './index.scss'; 2 | import './markdown.scss'; 3 | import './hljs.scss'; 4 | -------------------------------------------------------------------------------- /types/custom.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.svg' { 2 | const content: any; 3 | export default content; 4 | } 5 | -------------------------------------------------------------------------------- /components/_util/isBrowser.ts: -------------------------------------------------------------------------------- 1 | export default !!(typeof window !== 'undefined' && window && window.document); 2 | -------------------------------------------------------------------------------- /components/grid/index.tsx: -------------------------------------------------------------------------------- 1 | import Row from './Row'; 2 | import Col from './Col'; 3 | 4 | export { Row, Col }; 5 | -------------------------------------------------------------------------------- /components/message/style/index.tsx: -------------------------------------------------------------------------------- 1 | import './index.scss'; 2 | 3 | // style dependencies 4 | import '../../icon/style'; 5 | -------------------------------------------------------------------------------- /components/radio/style/index.tsx: -------------------------------------------------------------------------------- 1 | // style dependencies 2 | import '../../button/style'; 3 | 4 | import './index.scss'; 5 | -------------------------------------------------------------------------------- /components/appBar/style/index.tsx: -------------------------------------------------------------------------------- 1 | import './index.scss'; 2 | 3 | // style dependencies 4 | import '../../button/style'; 5 | -------------------------------------------------------------------------------- /components/checkbox/style/index.tsx: -------------------------------------------------------------------------------- 1 | // style dependencies 2 | import '../../button/style'; 3 | 4 | import './index.scss'; 5 | -------------------------------------------------------------------------------- /components/switch/style/index.tsx: -------------------------------------------------------------------------------- 1 | // style dependencies 2 | import '../../button/style'; 3 | 4 | import './index.scss'; 5 | -------------------------------------------------------------------------------- /components/button/style/index.tsx: -------------------------------------------------------------------------------- 1 | import './index.scss'; 2 | 3 | // style dependencies 4 | import '../../button-base/style'; 5 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [['@babel/preset-env', { targets: { node: 'current' } }], '@babel/preset-react'], 3 | }; 4 | -------------------------------------------------------------------------------- /components/modal/style/index.tsx: -------------------------------------------------------------------------------- 1 | import './index.scss'; 2 | import './confirm.scss'; 3 | 4 | // style dependencies 5 | import '../../button/style'; 6 | -------------------------------------------------------------------------------- /components/icon/utils.ts: -------------------------------------------------------------------------------- 1 | export const svgBaseProps = { 2 | width: '1em', 3 | height: '1em', 4 | fill: 'currentColor', 5 | 'aria-hidden': 'true', 6 | }; 7 | -------------------------------------------------------------------------------- /tests/setup.js: -------------------------------------------------------------------------------- 1 | const enzyme = require('enzyme'); 2 | const Adapter = require('enzyme-adapter-react-16'); 3 | 4 | enzyme.configure({ adapter: new Adapter() }); 5 | -------------------------------------------------------------------------------- /components/button/index.tsx: -------------------------------------------------------------------------------- 1 | import Button from './Button'; 2 | 3 | export { ButtonShape, ButtonColor, ButtonSize, ButtonProps } from './Button'; 4 | 5 | export default Button; 6 | -------------------------------------------------------------------------------- /site/demo/umi/index.js: -------------------------------------------------------------------------------- 1 | import generatePage from '../../components/generatePage'; 2 | 3 | export default generatePage({ 4 | component: 'umi', 5 | markdownList: ['_index'], 6 | }); 7 | -------------------------------------------------------------------------------- /scripts/utils/projectHelper.ts: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | const cwd = process.cwd(); 3 | 4 | export function getProjectPath(...filePath: string[]) { 5 | return path.join(cwd, ...filePath); 6 | } 7 | -------------------------------------------------------------------------------- /.codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | branch: master 3 | 4 | coverage: 5 | status: 6 | project: 7 | default: 8 | # Fail the status if coverage drops by >= 0.1% 9 | threshold: 0.1 10 | -------------------------------------------------------------------------------- /site/demo/Switch/basic.md: -------------------------------------------------------------------------------- 1 | ## Switch 开关 2 | 3 | 需要表示开关状态/两种状态之间的切换时; 4 | 5 | ## 基本用法 6 | 7 | 8 | 9 | ```jsx 10 | ReactDOM.render(); 11 | ``` 12 | 13 | 14 | -------------------------------------------------------------------------------- /site/demo/create-react-app/index.js: -------------------------------------------------------------------------------- 1 | import generatePage from '../../components/generatePage'; 2 | 3 | export default generatePage({ 4 | component: 'create-react-app', 5 | markdownList: ['_index'], 6 | }); 7 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "all", 4 | "printWidth": 100, 5 | "overrides": [ 6 | { 7 | "files": ".prettierrc", 8 | "options": { 9 | "parser": "json" 10 | } 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .idea 3 | *.iml 4 | /dist 5 | /coverage 6 | /test-results 7 | /.vscode 8 | /docs 9 | .DS_Store 10 | *.bak 11 | npm-debug.log 12 | package-lock.json 13 | yarn-error.log 14 | *.swp 15 | yarn.lock 16 | .history 17 | es 18 | lib 19 | -------------------------------------------------------------------------------- /.jest.ci.js: -------------------------------------------------------------------------------- 1 | const base = require('./jest.config'); 2 | 3 | module.exports = Object.assign({}, base, { 4 | collectCoverage: true, 5 | coverageDirectory: 'coverage', 6 | coverageReporters: ['text', 'lcov'], 7 | reporters: ['default', 'jest-junit'], 8 | }); 9 | -------------------------------------------------------------------------------- /components/_util/omit.ts: -------------------------------------------------------------------------------- 1 | const omit = (obj: Object, keys: string[]): Object => { 2 | const resultObj = Object.assign({}, obj); 3 | keys.forEach(key => { 4 | delete resultObj[key]; 5 | }); 6 | return resultObj; 7 | }; 8 | 9 | export default omit; 10 | -------------------------------------------------------------------------------- /site/demo/checkbox/basic.md: -------------------------------------------------------------------------------- 1 | ## Checkbox 多选框 2 | 3 | 在一组可选项中进行多项选择时使用。 4 | 5 | ## 基本用法 6 | 7 | 8 | 9 | ```jsx 10 | ReactDOM.render( 11 |
12 | A 13 |
, 14 | ); 15 | ``` 16 | 17 | 18 | -------------------------------------------------------------------------------- /components/grid/RowContext.tsx: -------------------------------------------------------------------------------- 1 | import { createContext, Context } from 'react'; 2 | 3 | export interface RowContextState { 4 | gutter?: number; 5 | } 6 | 7 | const RowContext: Context = createContext({}); 8 | 9 | export default RowContext; 10 | -------------------------------------------------------------------------------- /site/demo/radio/basic.md: -------------------------------------------------------------------------------- 1 | ## Radio 单选框 2 | 3 | 用于在多个备选项中选中单个状态。 4 | Radio 所有选项默认可见,方便用户在比较中选择,因此选项不宜过多。 5 | 6 | ## 基本用法 7 | 8 | 9 | 10 | ```jsx 11 | const radio = A; 12 | ReactDOM.render(radio); 13 | ``` 14 | 15 | 16 | -------------------------------------------------------------------------------- /components/_util/hooks.ts: -------------------------------------------------------------------------------- 1 | import { useContext } from 'react'; 2 | import { ConfigContext } from '../context/ConfigContext'; 3 | 4 | export const usePrefixCls = (prefixCls: string) => { 5 | const { getPrefixCls } = useContext(ConfigContext); 6 | return getPrefixCls(prefixCls); 7 | }; 8 | -------------------------------------------------------------------------------- /components/theme/_timing-functions.scss: -------------------------------------------------------------------------------- 1 | $timing-fn-ease-in-out: cubic-bezier(0.5, 0, 0.5, 0.1); // 组件内变化 2 | $timing-fn-ease-in: cubic-bezier(0.17, 0.84, 0.44, 0.1); // 入场 3 | $timing-fn-ease-out: cubic-bezier(0.18, 0.66, 0.6, 0.82); // 出场 4 | $timing-fn-linear: cubic-bezier(0, 0, 0.1, 0.1); // 线性 5 | -------------------------------------------------------------------------------- /site/demo/layout/index.js: -------------------------------------------------------------------------------- 1 | import generatePage from '../../components/generatePage'; 2 | import { Layout } from 'components'; 3 | 4 | export default generatePage({ 5 | component: 'layout', 6 | markdownList: ['basic', '_props'], 7 | dependencies: { 8 | Layout, 9 | }, 10 | }); 11 | -------------------------------------------------------------------------------- /site/react-code-view/lib/parseDom.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = parseDom; 7 | function parseDom(arg) { 8 | var objE = document.createElement('div'); 9 | objE.innerHTML = arg; 10 | return objE; 11 | } -------------------------------------------------------------------------------- /site/demo/icon/index.js: -------------------------------------------------------------------------------- 1 | import generatePage from '../../components/generatePage'; 2 | import { Icon } from 'components'; 3 | 4 | export default generatePage({ 5 | component: 'icon', 6 | markdownList: ['basic', 'material', 'iconfont', '_props'], 7 | dependencies: { 8 | Icon, 9 | }, 10 | }); 11 | -------------------------------------------------------------------------------- /site/demo/drawer/index.js: -------------------------------------------------------------------------------- 1 | import generatePage from '../../components/generatePage'; 2 | import { Button, Drawer } from 'components'; 3 | 4 | export default generatePage({ 5 | component: 'drawer', 6 | markdownList: ['basic', '_props'], 7 | dependencies: { 8 | Button, 9 | Drawer, 10 | }, 11 | }); 12 | -------------------------------------------------------------------------------- /site/demo/portal/index.js: -------------------------------------------------------------------------------- 1 | import generatePage from '../../components/generatePage'; 2 | import { Portal, Button } from 'components'; 3 | 4 | export default generatePage({ 5 | component: 'portal', 6 | markdownList: ['purePortal', 'portal', '_props'], 7 | dependencies: { 8 | Portal, 9 | Button, 10 | }, 11 | }); 12 | -------------------------------------------------------------------------------- /site/demo/Switch/index.js: -------------------------------------------------------------------------------- 1 | import generatePage from '../../components/generatePage'; 2 | import { Switch, Button } from 'components'; 3 | 4 | export default generatePage({ 5 | component: 'Switch', 6 | markdownList: ['basic', 'disabled', 'color', '_props'], 7 | dependencies: { 8 | Switch, 9 | Button, 10 | }, 11 | }); 12 | -------------------------------------------------------------------------------- /site/demo/appBar/default.md: -------------------------------------------------------------------------------- 1 | ## AppBar 应用栏 2 | 3 | 4 | 5 | ```js 6 | const { IconButton, Typography, ToolBar } = AppBar; 7 | 8 | const appBar = ( 9 | 10 | Title 11 | 12 | ); 13 | ReactDOM.render(appBar); 14 | ``` 15 | 16 | 17 | -------------------------------------------------------------------------------- /scripts/config/postcssConfig.js: -------------------------------------------------------------------------------- 1 | const rucksack = require('rucksack-css'); 2 | const autoprefixer = require('autoprefixer'); 3 | 4 | module.exports = { 5 | plugins: [ 6 | rucksack(), 7 | autoprefixer({ 8 | browsers: ['last 2 versions', 'Firefox ESR', '> 1%', 'ie >= 9', 'iOS >= 8', 'Android >= 4'], 9 | }), 10 | ], 11 | }; 12 | -------------------------------------------------------------------------------- /site/demo/appBar/index.js: -------------------------------------------------------------------------------- 1 | import generatePage from '../../components/generatePage'; 2 | import { Button, Icon, AppBar } from 'components'; 3 | 4 | export default generatePage({ 5 | component: 'appBar', 6 | markdownList: ['default', 'basic', '_props'], 7 | dependencies: { 8 | Button, 9 | Icon, 10 | AppBar, 11 | }, 12 | }); 13 | -------------------------------------------------------------------------------- /components/_util/type.ts: -------------------------------------------------------------------------------- 1 | export type Omit = Pick>; 2 | // https://stackoverflow.com/questions/46176165/ways-to-get-string-literal-type-of-array-values-without-enum-overhead 3 | export const tuple = (...args: T) => args; 4 | // export const tupleNum = (...args: T) => args; 5 | -------------------------------------------------------------------------------- /site/demo/message/index.js: -------------------------------------------------------------------------------- 1 | import generatePage from '../../components/generatePage'; 2 | import { Button, message } from 'components'; 3 | 4 | export default generatePage({ 5 | component: 'message', 6 | markdownList: ['basic', 'type', 'duration', 'loading', '_props'], 7 | dependencies: { 8 | Button, 9 | message, 10 | }, 11 | }); 12 | -------------------------------------------------------------------------------- /site/demo/input/icon.md: -------------------------------------------------------------------------------- 1 | ## 显示图标 2 | 3 | 4 | 5 | ```jsx 6 | const input = ( 7 | 8 | 9 | } label="Icon" placeholder="Placeholder" labelFloat /> 10 | 11 | 12 | ); 13 | ReactDOM.render(input); 14 | ``` 15 | 16 | 17 | -------------------------------------------------------------------------------- /site/demo/radio/index.js: -------------------------------------------------------------------------------- 1 | import generatePage from '../../components/generatePage'; 2 | import { Radio, Row } from 'components'; 3 | 4 | export default generatePage({ 5 | component: 'radio', 6 | markdownList: ['basic', 'disabled', 'radioGroup', 'color', 'layout', 'equal', '_props'], 7 | dependencies: { 8 | Radio, 9 | Row, 10 | }, 11 | }); 12 | -------------------------------------------------------------------------------- /site/demo/buttons/index.js: -------------------------------------------------------------------------------- 1 | import generatePage from '../../components/generatePage'; 2 | import { Button, Icon } from 'components'; 3 | 4 | export default generatePage({ 5 | component: 'buttons', 6 | markdownList: ['basic', 'text', 'outlined', 'circle-fab', 'round', 'icon', 'size', '_props'], 7 | dependencies: { 8 | Button, 9 | Icon, 10 | }, 11 | }); 12 | -------------------------------------------------------------------------------- /site/demo/message/basic.md: -------------------------------------------------------------------------------- 1 | ## Message 全局提示 2 | 3 | 全局展示操作反馈信息。 4 | 5 | ## 基本用法 6 | 7 | 8 | 9 | ```jsx 10 | const info = () => { 11 | message.info('This is a normal message'); 12 | }; 13 | 14 | ReactDOM.render( 15 | , 18 | ); 19 | ``` 20 | 21 | 22 | -------------------------------------------------------------------------------- /site/demo/input/index.js: -------------------------------------------------------------------------------- 1 | import generatePage from '../../components/generatePage'; 2 | import { Input, Icon, Row, Col } from 'components'; 3 | 4 | export default generatePage({ 5 | component: 'input', 6 | markdownList: ['basic', 'fix', 'icon', 'error', 'count', 'textarea', '_props'], 7 | dependencies: { 8 | Input, 9 | Icon, 10 | Row, 11 | Col, 12 | }, 13 | }); 14 | -------------------------------------------------------------------------------- /site/demo/icon/_props.md: -------------------------------------------------------------------------------- 1 | ## API 2 | 3 | #### Icon 4 | | 参数 | 说明 | 类型 | 默认值 | 5 | | --- | --- | --- | --- | 6 | | className | `Icon`的`className` | string | - | 7 | | style | 设置图标的样式,例如 `fontSize` 和 `color` | CSSProperties | - | 8 | | scriptUrl | [iconfont.cn](http://iconfont.cn/) 项目在线生成的 `js` 地址 | string | - | 9 | | spin | 是否有旋转动画 | boolean | false | 10 | | rotate | 图标旋转角度 | number | - | 11 | -------------------------------------------------------------------------------- /site/demo/message/duration.md: -------------------------------------------------------------------------------- 1 | ## 修改延时 2 | 3 | 自定义时长 10s,默认时长为 3s。 4 | 5 | 6 | 7 | ```jsx 8 | const success = () => { 9 | message.success('This is a prompt message for success, and it will disappear in 10 seconds', 10); 10 | }; 11 | 12 | ReactDOM.render( 13 | , 14 | ); 15 | ``` 16 | 17 | 18 | -------------------------------------------------------------------------------- /site/demo/message/loading.md: -------------------------------------------------------------------------------- 1 | ## 加载中 2 | 3 | 进行全局 loading,异步自行移除。 4 | 5 | 6 | 7 | ```jsx 8 | const success = () => { 9 | const hide = message.loading('Action in progress..', 0); 10 | // Dismiss manually and asynchronously 11 | setTimeout(hide, 2500); 12 | }; 13 | 14 | ReactDOM.render( 15 | , 16 | ); 17 | ``` 18 | 19 | 20 | -------------------------------------------------------------------------------- /site/react-code-view/lib/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, '__esModule', { 4 | value: true, 5 | }); 6 | 7 | var _CodeView = require('./CodeView'); 8 | 9 | var _CodeView2 = _interopRequireDefault(_CodeView); 10 | 11 | function _interopRequireDefault(obj) { 12 | return obj && obj.__esModule ? obj : { default: obj }; 13 | } 14 | 15 | exports.default = _CodeView2.default; 16 | -------------------------------------------------------------------------------- /components/theme/mixins/_utils.scss: -------------------------------------------------------------------------------- 1 | %clearfix { 2 | $selector: &; 3 | 4 | @at-root { 5 | #{$selector}::before, 6 | #{$selector}::after { 7 | display: table; 8 | content: ''; 9 | } 10 | 11 | #{$selector}::after { 12 | clear: both; 13 | } 14 | } 15 | } 16 | 17 | %ellipsis { 18 | overflow: hidden; 19 | white-space: nowrap; 20 | text-overflow: ellipsis; 21 | } 22 | -------------------------------------------------------------------------------- /site/demo/checkbox/index.js: -------------------------------------------------------------------------------- 1 | import generatePage from '../../components/generatePage'; 2 | import { Checkbox, Row, Col, Icon } from 'components'; 3 | 4 | export default generatePage({ 5 | component: 'checkbox', 6 | markdownList: ['basic', 'disabled', 'icon', 'checkboxGroup', 'layout', 'checkAll', '_props'], 7 | dependencies: { 8 | Checkbox, 9 | Row, 10 | Col, 11 | Icon, 12 | }, 13 | }); 14 | -------------------------------------------------------------------------------- /components/_util/transition.ts: -------------------------------------------------------------------------------- 1 | export const duration = { 2 | shortest: 150, 3 | shorter: 200, 4 | short: 250, 5 | // most basic recommended timing 6 | standard: 300, 7 | // this is to be used in complex animations 8 | complex: 375, 9 | // recommended when something is entering screen 10 | enteringScreen: 225, 11 | // recommended when something is leaving screen 12 | leavingScreen: 195, 13 | }; 14 | -------------------------------------------------------------------------------- /components/button-base/Loading.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { usePrefixCls } from '../_util/hooks'; 3 | import { Icon } from '../index'; 4 | 5 | const Loading: React.FunctionComponent = () => { 6 | const prefixCls = usePrefixCls('btn'); 7 | 8 | return ( 9 | 10 | 11 | 12 | ); 13 | }; 14 | 15 | export default Loading; 16 | -------------------------------------------------------------------------------- /site/demo/grid/pull-push.md: -------------------------------------------------------------------------------- 1 | ## 栅格排序 2 | 3 | 通过使用 push 和 pull 属性改变列(column)的顺序。 4 | 5 | 6 | 7 | ```jsx 8 | const grid = ( 9 |
10 | 11 | 12 | col-18 col-push-6 13 | 14 | 15 | col-6 col-pull-18 16 | 17 | 18 |
19 | ); 20 | ReactDOM.render(grid); 21 | ``` 22 | 23 | 24 | -------------------------------------------------------------------------------- /site/pages/Switch.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Switch } from 'components'; 3 | 4 | export default () => { 5 | return ( 6 |
7 | { 10 | console.log(checked, e); 11 | }} 12 | /> 13 | 14 | 15 |
16 | ); 17 | }; 18 | -------------------------------------------------------------------------------- /site/demo/input/fix.md: -------------------------------------------------------------------------------- 1 | ## 修饰输入 2 | 3 | 使用`prefix`和`suffix`属性,可以向`Input`添加前缀或后缀。 4 | 5 | 6 | 7 | ```jsx 8 | const input = ( 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | ); 18 | ReactDOM.render(input); 19 | ``` 20 | 21 | 22 | -------------------------------------------------------------------------------- /components/button-base/__test__/index.test.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render, mount } from 'enzyme'; 3 | import BaseButton from '../index'; 4 | 5 | describe('Ripple', () => { 6 | it('render correctly', () => { 7 | const wrapper = mount(); 8 | wrapper.simulate('mousedown'); 9 | wrapper.simulate('mouseup'); 10 | wrapper.simulate('touchstart'); 11 | wrapper.simulate('touchend'); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /site/demo/buttons/basic.md: -------------------------------------------------------------------------------- 1 | ## 按钮 2 | 3 | ### 实心 4 | 5 | 6 | 7 | ```js 8 | const instance = ( 9 |
10 | 11 | 12 | 13 | 14 | 15 |
16 | ); 17 | ReactDOM.render(instance); 18 | ``` 19 | 20 | 21 | -------------------------------------------------------------------------------- /site/demo/Switch/color.md: -------------------------------------------------------------------------------- 1 | ## 更改颜色 2 | 3 | 在`Switch`上使用`color`设置组件颜色。 4 | 5 | 6 | 7 | ```jsx 8 | ReactDOM.render( 9 |
10 | 11 | 12 | 13 | 14 | 15 |
, 16 | ); 17 | ``` 18 | 19 | 20 | -------------------------------------------------------------------------------- /site/demo/drawer/_props.md: -------------------------------------------------------------------------------- 1 | ## API 2 | 3 | #### Drawer 4 | | 属性 | 说明 | 类型 | 默认值 | 5 | | --- | --- | --- | --- | 6 | | className | 容器`className` | string | - | 7 | | mask | 是否显示遮罩层 | boolean | true | 8 | | placement | 抽屉的方向 | `top` / `right` / `bottom`/`left` | `left` | 9 | | visible | `Drawer`是否显示 | boolean | - | 10 | | width | 宽度, 在`placement`为`left`或`right`时使用 | string/number | 256 | 11 | | height | 高度, 在`placement`为`top`或`bottom`时使用 | string/number | 256 | 12 | -------------------------------------------------------------------------------- /components/modal/index.tsx: -------------------------------------------------------------------------------- 1 | import Modal, { ModalFuncProps } from './Modal'; 2 | import confirm, { destroyFns } from './Confirm'; 3 | 4 | Modal.confirm = (props: ModalFuncProps) => { 5 | const config = { ...props }; 6 | return confirm(config); 7 | }; 8 | 9 | Modal.destroyAll = () => { 10 | while (destroyFns.length) { 11 | const close = destroyFns.pop(); 12 | if (close) { 13 | close(); 14 | } 15 | } 16 | }; 17 | 18 | export default Modal; 19 | -------------------------------------------------------------------------------- /site/demo/modal/index.js: -------------------------------------------------------------------------------- 1 | import generatePage from '../../components/generatePage'; 2 | import { Modal, Button } from 'components'; 3 | 4 | export default generatePage({ 5 | component: 'modal', 6 | markdownList: [ 7 | 'basic', 8 | 'footer', 9 | 'confirm', 10 | 'confirm-props', 11 | 'promise', 12 | 'confirm-destroyAll', 13 | 'confirm-update', 14 | '_props', 15 | ], 16 | dependencies: { 17 | Button, 18 | Modal, 19 | }, 20 | }); 21 | -------------------------------------------------------------------------------- /site/demo/grid/index.js: -------------------------------------------------------------------------------- 1 | import generatePage from '../../components/generatePage'; 2 | import { Row, Col } from 'components'; 3 | 4 | export default generatePage({ 5 | component: 'grid', 6 | markdownList: [ 7 | 'basic', 8 | 'gutter', 9 | 'offset', 10 | 'pull-push', 11 | 'justify', 12 | 'align', 13 | 'order', 14 | 'responsive', 15 | 'responsive-others', 16 | '_props', 17 | ], 18 | dependencies: { 19 | Row, 20 | Col, 21 | }, 22 | }); 23 | -------------------------------------------------------------------------------- /site/demo/checkbox/disabled.md: -------------------------------------------------------------------------------- 1 | ## 禁用状态 2 | 3 | 在`Radio`或`Radio.Group`上使用`disabled`设置禁用状态。 4 | 5 | 6 | 7 | ```jsx 8 | ReactDOM.render( 9 |
10 | A 11 | 12 | B 13 | 14 | 15 | A 16 | B 17 | 18 |
, 19 | ); 20 | ``` 21 | 22 | 23 | -------------------------------------------------------------------------------- /site/demo/Switch/_props.md: -------------------------------------------------------------------------------- 1 | ## API 2 | #### Switch 3 | 4 | | 参数 | 说明 | 类型 | 默认值 | 5 | | --- | --- | --- | --- | 6 | | disabled | 设置禁用状态 | boolean | false | 7 | | defaultChecked | 初始是否选中 | boolean | false | 8 | | checked | 指定当前是否选中 | boolean | false | 9 | | color | 设置颜色类型,可选值为`primary`、 `secondary`、 `success`、 `warning`、 `danger` 或者不设 | string | primary | 10 | | onChange | 选项变化时的回调函数 | Function(checked: boolean, event: Event) | - | 11 | | onClick | 点击时回调函数 | Function(checked: boolean, event: Event) | - | 12 | -------------------------------------------------------------------------------- /site/demo/buttons/round.md: -------------------------------------------------------------------------------- 1 | ### 圆角 2 | 3 | 4 | 5 | ```js 6 | const instance = ( 7 |
8 | 9 | 12 | 15 | 18 |
19 | ); 20 | ReactDOM.render(instance); 21 | ``` 22 | 23 | 24 | -------------------------------------------------------------------------------- /site/demo/icon/basic.md: -------------------------------------------------------------------------------- 1 | ## 基础图标 2 | 3 | 4 | 5 | ```jsx 6 | const instance = ( 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | ); 20 | ReactDOM.render(instance); 21 | ``` 22 | 23 | 24 | -------------------------------------------------------------------------------- /site/demo/umi/_index.md: -------------------------------------------------------------------------------- 1 | ## 在 UmiJS 中使用 2 | [umi](https://umijs.org/) 是一个可插拔的企业级 react 应用框架。 3 | 可参考官方文档快速创建项目。 4 | 5 | ## 按需加载 6 | 7 | 在`umi`创建的项目中添加 [babel-plugin-import](https://github.com/ant-design/babel-plugin-import) 配置。 8 | 9 | ```js 10 | extraBabelPlugins: [ 11 | // ... 12 | [ 13 | 'import', 14 | { 15 | libraryName: "tyche-ui", 16 | libraryDirectory: 'es', 17 | style: "css", 18 | }, 19 | ] 20 | ] 21 | ``` 22 | 再如下使用组件即可按需加载。 23 | ```js 24 | import { Button } from 'tyche-ui'; 25 | ``` -------------------------------------------------------------------------------- /site/demo/checkbox/icon.md: -------------------------------------------------------------------------------- 1 | ## 自定义图标 2 | 3 | 4 | 5 | ```jsx 6 | ReactDOM.render( 7 |
8 | } 11 | checkedIcon={} 12 | > 13 | checkbox 14 | 15 | } 17 | checkedIcon={} 18 | > 19 | checkbox 20 | 21 |
, 22 | ); 23 | ``` 24 | 25 | 26 | -------------------------------------------------------------------------------- /components/icon/svgs/circle-info.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /site/demo/radio/radioGroup.md: -------------------------------------------------------------------------------- 1 | ## 单选组合 2 | 3 | 一组互斥的 Radio 配合使用。 4 | 5 | 6 | 7 | ```jsx 8 | const RadioGroup = () => { 9 | const [val, setVal] = React.useState(1); 10 | 11 | const handleChange = e => { 12 | console.log(e); 13 | setVal(e.target.value); 14 | }; 15 | 16 | return ( 17 | 18 | A 19 | B 20 | 21 | ); 22 | }; 23 | ReactDOM.render(); 24 | ``` 25 | 26 | 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Tyche-UI

2 | 3 |
4 | 5 | [![CircleCI](https://circleci.com/gh/buyou0821/tyche-ui.svg?style=svg)](https://circleci.com/gh/buyou0821/tyche-ui) 6 | ![CircleCI (all branches)](https://img.shields.io/circleci/project/github/buyou0821/tyche-ui.svg?style=flat-square) 7 | ![Codecov](https://img.shields.io/codecov/c/github/buyou0821/tyche-ui.svg?style=flat-square) 8 | ![npm type definitions](https://img.shields.io/npm/types/tyche-ui.svg?style=flat-square) 9 | ![npm](https://img.shields.io/npm/v/tyche-ui.svg?style=flat-square) 10 | -------------------------------------------------------------------------------- /components/icon/svgs/list.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/icon/svgs/warning.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /site/demo/Switch/disabled.md: -------------------------------------------------------------------------------- 1 | ## 不可用 2 | 3 | `Switch`失效状态。 4 | 5 | 6 | 7 | ```jsx 8 | const App = () => { 9 | const [disabled, setDisabled] = React.useState(true); 10 | const toggle = () => { 11 | setDisabled(!disabled); 12 | }; 13 | 14 | return ( 15 |
16 | 17 |
18 | 21 |
22 | ); 23 | }; 24 | ReactDOM.render(); 25 | ``` 26 | 27 | 28 | -------------------------------------------------------------------------------- /site/demo/input/error.md: -------------------------------------------------------------------------------- 1 | ## 错误状态 2 | 3 | 使用`errorMessage`可以使`Input`以错误状态显示。 4 | 5 | 6 | 7 | ```jsx 8 | const input = ( 9 | 10 | 11 | 12 | 13 | 14 | } 16 | errorMessage="error message" 17 | label="Error" 18 | labelFloat 19 | /> 20 | 21 | 22 | ); 23 | ReactDOM.render(input); 24 | ``` 25 | 26 | 27 | -------------------------------------------------------------------------------- /components/icon/style/index.scss: -------------------------------------------------------------------------------- 1 | @import '../../theme/mixins/mixins.scss'; 2 | 3 | @include b(icon) { 4 | display: inline-block; 5 | line-height: 0; 6 | // vertical-align: -0.125em; 7 | @include m(spin) { 8 | animation: loadingCircle 1s infinite linear; 9 | } 10 | @include m(left) { 11 | margin-right: 8px; 12 | } 13 | @include m(right) { 14 | margin-left: 8px; 15 | } 16 | &.material-icons { 17 | font-size: 24px; 18 | line-height: 1; 19 | } 20 | } 21 | 22 | @keyframes loadingCircle { 23 | 100% { 24 | transform: rotate(360deg); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /components/layout/style/index.scss: -------------------------------------------------------------------------------- 1 | @import '../../theme/mixins/mixins.scss'; 2 | @import '../../theme/default.scss'; 3 | 4 | @include b(layout) { 5 | display: flex; 6 | flex: auto; 7 | flex-direction: column; 8 | 9 | @include e(header) { 10 | height: 64px; 11 | line-height: 64px; 12 | } 13 | 14 | @include e(content) { 15 | flex: auto; 16 | } 17 | 18 | @include e(footer) { 19 | padding: 24px 50px; 20 | } 21 | 22 | @include m(hasSider) { 23 | flex-direction: row; 24 | @include e(content) { 25 | overflow-x: hidden; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /site/demo/grid/order.md: -------------------------------------------------------------------------------- 1 | ## Flex 排序 2 | 3 | 使用`Col`元素的`order`属性改变元素的排序。 4 | 5 | 6 | 7 | ```jsx 8 | const grid = ( 9 |
10 | 11 | 12 | 1 col-order-4 13 | 14 | 15 | 2 col-order-3 16 | 17 | 18 | 3 col-order-2 19 | 20 | 21 | 4 col-order-1 22 | 23 | 24 |
25 | ); 26 | ReactDOM.render(grid); 27 | ``` 28 | 29 | 30 | -------------------------------------------------------------------------------- /components/_util/reactHelpers.ts: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export function setRef(ref: any, value: any) { 4 | if (typeof ref === 'function') { 5 | ref(value); 6 | } else if (ref) { 7 | ref.current = value; 8 | } 9 | } 10 | 11 | export function useForkRef(refA: React.RefObject, refB: React.RefObject) { 12 | return React.useMemo(() => { 13 | if (refA == null && refB == null) { 14 | return null; 15 | } 16 | return (refValue: any) => { 17 | setRef(refA, refValue); 18 | setRef(refB, refValue); 19 | }; 20 | }, [refA, refB]); 21 | } 22 | -------------------------------------------------------------------------------- /site/demo/appBar/_props.md: -------------------------------------------------------------------------------- 1 | ## API 2 | 3 | #### AppBar 4 | AppBar包含组件`IconButton` `Typography` `ToolBar`可以用来组成应用栏 5 | 6 | | 属性 | 说明 | 类型 | 默认值 | 7 | | --- | --- | --- | --- | 8 | | color | 设置颜色类型,可选值为`primary`、 `secondary`、 `success`、 `warning`、 `danger` 或者不设 | string | default | 9 | | IconButton | 组件左边的内容,可以用来显示一个按钮,支持`col`的响应式 | ReactNode | - | 10 | | Typography | 组件中间的内容 | string/ReactNode | - | 11 | | ToolBar | 组件右边的内容 | string/ReactNode | - | 12 | 13 | #### AppBar.IconButton 14 | 15 | | 属性 | 说明 | 类型 | 默认值 | 16 | | --- | --- | --- | --- | 17 | | ButtonProps | `Button`组件的属性 | ButtonProps | - | -------------------------------------------------------------------------------- /site/utils.js: -------------------------------------------------------------------------------- 1 | export const DOMAPI = { 2 | hasClass(elem, className) { 3 | if (~elem.className.split(/\s+/).indexOf(className)) { 4 | return true; 5 | } 6 | return false; 7 | }, 8 | addClass(elem, className) { 9 | if (!this.hasClass(elem, className)) { 10 | elem.className = elem.className + ' ' + className; 11 | } 12 | }, 13 | removeClass(elem, className) { 14 | if (this.hasClass(elem, className)) { 15 | const reg = new RegExp('(\\s|^)' + className + '(\\s|$)'); 16 | elem.className = elem.className.replace(reg, ''); 17 | } 18 | }, 19 | }; 20 | -------------------------------------------------------------------------------- /site/demo/buttons/outlined.md: -------------------------------------------------------------------------------- 1 | ### 描边 2 | 3 | 4 | 5 | ```js 6 | const instance = ( 7 |
8 | 9 | 12 | 15 | 18 | 21 |
22 | ); 23 | ReactDOM.render(instance); 24 | ``` 25 | 26 | 27 | -------------------------------------------------------------------------------- /site/demo/grid/responsive.md: -------------------------------------------------------------------------------- 1 | ## 响应式布局 2 | 3 | 参考 Bootstrap 的[响应式设计](http://getbootstrap.com/css/#grid-media-queries),预设六个响应尺寸:`xs` `sm` `md` `lg` `xl` `xxl`。 4 | 5 | 6 | 7 | ```jsx 8 | const grid = ( 9 |
10 | 11 | 12 | Col 13 | 14 | 15 | Col 16 | 17 | 18 | Col 19 | 20 | 21 |
22 | ); 23 | ReactDOM.render(grid); 24 | ``` 25 | 26 | 27 | -------------------------------------------------------------------------------- /components/modal/style/confirm.scss: -------------------------------------------------------------------------------- 1 | @import '../../theme/mixins/mixins.scss'; 2 | @import '../../theme/default.scss'; 3 | 4 | @include b(confirm) { 5 | padding: 32px 32px 24px; 6 | @include e(title) { 7 | color: $--color-black-heavy; 8 | font-weight: 500; 9 | font-size: 16px; 10 | text-align: center; 11 | } 12 | @include e(content) { 13 | margin-top: 8px; 14 | color: $--color-black; 15 | font-size: 14px; 16 | } 17 | @include e(buttons) { 18 | margin-top: 24px; 19 | text-align: right; 20 | button + button { 21 | margin-left: 8px; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /components/portal/util.ts: -------------------------------------------------------------------------------- 1 | export const getNodeFromSelector = (selector: string | Element): Element | null => { 2 | const node = typeof selector === 'string' ? document.querySelector(selector) : selector; 3 | return node; 4 | }; 5 | 6 | export const removeAllChildren = (node: Node) => { 7 | while (node && node.firstChild) { 8 | node.removeChild(node.firstChild); 9 | } 10 | }; 11 | 12 | export const hasScrollYbar = (element: Element) => { 13 | if (element === document.body) { 14 | return element.scrollHeight > window.innerHeight; 15 | } 16 | return element.scrollHeight > element.clientHeight; 17 | }; 18 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: 'babel-eslint', 3 | extends: ['plugin:prettier/recommended'], 4 | plugins: ['prettier', 'markdown', 'react', 'babel'], 5 | env: { 6 | browser: true, 7 | node: true, 8 | jasmine: true, 9 | jest: true, 10 | es6: true, 11 | }, 12 | parserOptions: { 13 | sourceType: 'module', 14 | ecmaFeatures: { 15 | jsx: true, 16 | modules: true, 17 | }, 18 | }, 19 | rules: { 20 | 'prettier/prettier': [ 21 | 'error', 22 | { 23 | singleQuote: true, 24 | trailingComma: 'all', 25 | }, 26 | ], 27 | }, 28 | }; 29 | -------------------------------------------------------------------------------- /site/demo/appBar/basic.md: -------------------------------------------------------------------------------- 1 | ## 带按钮的应用栏 2 | 3 | 4 | 5 | ```js 6 | const { IconButton, Typography, ToolBar } = AppBar; 7 | 8 | const appBar = ( 9 | 10 | 11 | 12 | 13 | Title 14 | 15 | 21 | 22 | 23 | ); 24 | ReactDOM.render(appBar); 25 | ``` 26 | 27 | 28 | -------------------------------------------------------------------------------- /site/demo/grid/basic.md: -------------------------------------------------------------------------------- 1 | ## Grid 栅格 2 | 3 | 24 栅格系统。 4 | 5 | 6 | 7 | ```jsx 8 | const grid = ( 9 |
10 | 11 | col-12 12 | col-12 13 | 14 | 15 | col-8 16 | col-8 17 | col-8 18 | 19 | 20 | col-6 21 | col-6 22 | col-6 23 | col-6 24 | 25 |
26 | ); 27 | ReactDOM.render(grid); 28 | ``` 29 | 30 | 31 | -------------------------------------------------------------------------------- /site/demo/buttons/text.md: -------------------------------------------------------------------------------- 1 | ### 文字 2 | 3 | 4 | 5 | ```js 6 | const instance = ( 7 |
8 | 9 | 13 | 16 | 19 | 22 |
23 | ); 24 | ReactDOM.render(instance); 25 | ``` 26 | 27 | 28 | -------------------------------------------------------------------------------- /site/demo/input/count.md: -------------------------------------------------------------------------------- 1 | ## 显示计数器 2 | 3 | 受控组件使用`maxLength`和`showCount`属性,可以显示计数器。 4 | 5 | 6 | 7 | ```jsx 8 | const InputCount = () => { 9 | const [val, setVal] = React.useState(1); 10 | 11 | return ( 12 | 13 | 14 | { 20 | setVal(e.target.value); 21 | }} 22 | /> 23 | 24 | 25 | ); 26 | }; 27 | ReactDOM.render(); 28 | ``` 29 | 30 | 31 | -------------------------------------------------------------------------------- /site/pages/Icon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Icon } from 'components'; 3 | 4 | export default () => { 5 | const IconFont = Icon.createFromIconfont({ 6 | scriptUrl: '//at.alicdn.com/t/font_8d5l8fzk5b87iudi.js', 7 | }); 8 | return ( 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | ); 18 | }; 19 | -------------------------------------------------------------------------------- /site/demo/layout/_props.md: -------------------------------------------------------------------------------- 1 | ## API 2 | 3 | #### Layout 4 | | 参数 | 说明 | 类型 | 默认值 | 5 | | --- | --- | --- | --- | 6 | | className | 容器 className | string | - | 7 | | style | 指定样式 | object | - | 8 | 9 | #### Layout.Sider 10 | 11 | | 参数 | 说明 | 类型 | 默认值 | 12 | | --- | --- | --- | --- | 13 | | width | 容器宽度 | number/string | - | 14 | | breakpoint | 触发响应式布局的断点 | Enum { 'xs', 'sm', 'md', 'lg', 'xl', 'xxl' } | - | 15 | | onBreakpoint | 触发响应式布局断点时的回调 | (broken) => {} | - | 16 | 17 | #### breakpoint width 18 | 19 | ``` 20 | { 21 | xs: '480px', 22 | sm: '576px', 23 | md: '768px', 24 | lg: '992px', 25 | xl: '1200px', 26 | xxl: '1600px', 27 | } 28 | ``` -------------------------------------------------------------------------------- /site/demo/input/textarea.md: -------------------------------------------------------------------------------- 1 | ## textarea 输入框 2 | 3 | 将`type`属性设置为`textarea`可以使用`textarea`控件。 4 | 使用`autoSize`属性让控件自动计算高度。 5 | 6 | 7 | 8 | ```jsx 9 | const input = ( 10 | 11 | 12 | 13 | 14 | 15 | } 21 | placeholder="Placeholder" 22 | /> 23 | 24 | 25 | ); 26 | ReactDOM.render(input); 27 | ``` 28 | 29 | 30 | -------------------------------------------------------------------------------- /site/demo/message/type.md: -------------------------------------------------------------------------------- 1 | ## 其他提示类型 2 | 3 | 包括成功、警告、失败。 4 | 5 | 6 | 7 | ```jsx 8 | const success = () => { 9 | message.success('This is a success message'); 10 | }; 11 | 12 | const error = () => { 13 | message.error('This is an error message'); 14 | }; 15 | 16 | const warning = () => { 17 | message.warning('This is a warning message'); 18 | }; 19 | 20 | ReactDOM.render( 21 |
22 | 23 | 24 | 25 |
, 26 | ); 27 | ``` 28 | 29 | 30 | -------------------------------------------------------------------------------- /components/icon/svgs/clear.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/theme/mixins/_config.scss: -------------------------------------------------------------------------------- 1 | $namespace: 'ty'; 2 | $element-separator: '__'; 3 | $modifier-separator: '--'; 4 | $state-prefix: '_'; 5 | 6 | // Break-point 7 | $--xs: 576px !default; 8 | $--sm: 576px !default; 9 | $--md: 768px !default; 10 | $--lg: 992px !default; 11 | $--xl: 1200px !default; 12 | $--xxl: 1600px !default; 13 | 14 | $--breakpoints: ( 15 | 'xs': ( 16 | max-width: $--xs - 1 17 | ), 18 | 'sm': ( 19 | min-width: $--sm 20 | ), 21 | 'md': ( 22 | min-width: $--md 23 | ), 24 | 'lg': ( 25 | min-width: $--lg 26 | ), 27 | 'xl': ( 28 | min-width: $--xl 29 | ), 30 | 'xxl': ( 31 | min-width: $--xxl 32 | ) 33 | ); 34 | -------------------------------------------------------------------------------- /components/radio/RadioContext.tsx: -------------------------------------------------------------------------------- 1 | import { createContext } from 'react'; 2 | import eq from 'lodash-es/eq'; 3 | import { RadioEvent, RadioColor } from './Radio'; 4 | 5 | export interface RadioContext { 6 | value: unknown; 7 | onRadioChange: ((e: RadioEvent) => void) | null; 8 | color: RadioColor; 9 | isValueEqual: (a: unknown, b: unknown) => boolean; 10 | disabled: boolean; 11 | hasRadioGroup: boolean; 12 | } 13 | 14 | const RadioContext = createContext({ 15 | value: [], 16 | isValueEqual: eq, 17 | onRadioChange: null, 18 | color: 'primary', 19 | disabled: false, 20 | hasRadioGroup: false, 21 | }); 22 | 23 | export default RadioContext; 24 | -------------------------------------------------------------------------------- /site/demo/grid/offset.md: -------------------------------------------------------------------------------- 1 | ## 向右偏移 2 | 3 | 使用`offset`可以将列向右侧偏移。 4 | 5 | 6 | 7 | ```jsx 8 | const grid = ( 9 |
10 | 11 | col-8 12 | 13 | col-8 14 | 15 | 16 | 17 | 18 | col-6 col-offset-6 19 | 20 | 21 | col-6 col-offset-6 22 | 23 | 24 | 25 | 26 | col-12 col-offset-6 27 | 28 | 29 |
30 | ); 31 | ReactDOM.render(grid); 32 | ``` 33 | 34 | 35 | -------------------------------------------------------------------------------- /site/demo/radio/layout.md: -------------------------------------------------------------------------------- 1 | ## 布局 2 | 3 | 4 | 5 | ```jsx 6 | const RadioGroup = () => { 7 | const [val, setVal] = React.useState(1); 8 | 9 | const handleChange = e => { 10 | console.log(e); 11 | setVal(e.target.value); 12 | }; 13 | 14 | return ( 15 | 16 | 17 | A 18 | B 19 | C 20 | D 21 | 22 | 23 | ); 24 | }; 25 | ReactDOM.render(); 26 | ``` 27 | 28 | 29 | -------------------------------------------------------------------------------- /site/demo/icon/material.md: -------------------------------------------------------------------------------- 1 | ## 使用 Material Design Icons 2 | 3 | 参考[Material Design Icons](https://material.io/tools/icons/?style=baseline),需要先引入字体库文件: 4 | 5 | ```html 6 | 10 | ``` 11 | 12 | 13 | ```jsx 14 | const instance = ( 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | ); 24 | ReactDOM.render(instance); 25 | ``` 26 | 27 | 28 | -------------------------------------------------------------------------------- /components/context/__test__/index.test.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render, mount } from 'enzyme'; 3 | import ConfigProvider from '../ConfigContext'; 4 | import { Button } from '../../index'; 5 | 6 | describe('ConfigProvider', () => { 7 | it('prefixCls', () => { 8 | const wrapper = mount( 9 | 10 | 30 |
31 | ); 32 | }; 33 | ReactDOM.render(); 34 | ``` 35 | 36 | 37 | -------------------------------------------------------------------------------- /components/checkbox/CheckboxContext.tsx: -------------------------------------------------------------------------------- 1 | import { createContext } from 'react'; 2 | import eq from 'lodash-es/eq'; 3 | import { CheckboxColor, CheckboxEvent } from './Checkbox'; 4 | import { CheckboxValueType } from './CheckboxGroup'; 5 | 6 | export interface CheckboxContext { 7 | value: Array; 8 | color: CheckboxColor; 9 | disabled: boolean; 10 | isValueEqual: (a: unknown, b: unknown) => boolean; 11 | onCheckboxChange: ((e: CheckboxEvent) => void) | null; 12 | hasCheckboxGroup: boolean; 13 | } 14 | 15 | export default createContext({ 16 | value: [], 17 | color: 'primary', 18 | disabled: false, 19 | isValueEqual: eq, 20 | onCheckboxChange: null, 21 | hasCheckboxGroup: false, 22 | }); 23 | -------------------------------------------------------------------------------- /components/icon/svgs/loading.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /site/style/_config.scss: -------------------------------------------------------------------------------- 1 | // color 2 | $--color-white: #fff !default; 3 | $--color-white-heavy: #f5f5f5; 4 | $--color-primary: #2196f3 !default; 5 | $--color-primary-light: #6ec6ff !default; 6 | $--color-primary-dark: #0069c0 !default; 7 | $--color-secondary: #ec407a !default; 8 | $--color-success: #4caf50 !default; 9 | $--color-warning: #fb8c00 !default; 10 | $--color-danger: #ff5252 !default; 11 | $--color-black: rgba(0, 0, 0, 0.65); 12 | $--color-black-heavy: rgba(0, 0, 0, 0.85); 13 | $--color-black-light: rgba(0, 0, 0, 0.38); 14 | $--color-gray: #e0e0e0; 15 | $--color-gray-heavy: #8c8c8c; 16 | 17 | $--button-disable-background: rgba(0, 0, 0, 0.12); 18 | $--button-loading-background: #d6d8db; 19 | $--button-disable-color: rgba(0, 0, 0, 0.26); 20 | -------------------------------------------------------------------------------- /components/switch/__test__/__snapshots__/index.test.jsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Switch should render correctly 1`] = ` 4 | 5 | 28 | 29 | `; 30 | -------------------------------------------------------------------------------- /site/demo/index.js: -------------------------------------------------------------------------------- 1 | export { default as createReactApp } from './create-react-app'; 2 | export { default as umi } from './umi'; 3 | export { default as appBar } from './appBar'; 4 | export { default as buttons } from './buttons'; 5 | export { default as drawer } from './drawer'; 6 | export { default as grid } from './grid'; 7 | export { default as icon } from './icon'; 8 | export { default as layout } from './layout'; 9 | export { default as modal } from './modal'; 10 | export { default as portal } from './portal'; 11 | export { default as input } from './input'; 12 | export { default as radio } from './radio'; 13 | export { default as checkbox } from './checkbox'; 14 | export { default as message } from './message'; 15 | export { default as Switch } from './Switch'; 16 | -------------------------------------------------------------------------------- /components/drawer/__test__/index.test.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { mount } from 'enzyme'; 3 | import Drawer from '..'; 4 | 5 | describe('Drawer', () => { 6 | it('render correctly', () => { 7 | const wrapper = mount( 8 | 9 | Here is content of Drawer 10 | , 11 | ); 12 | expect(wrapper.find('.ty-drawer__sider--left').length).toBeTruthy(); 13 | }); 14 | 15 | it('should support mask', () => { 16 | const closeFn = jest.fn(); 17 | const wrapper = mount( 18 | 19 | Here is content of Drawer 20 | , 21 | ); 22 | wrapper.find('.ty-drawer__mask').simulate('click'); 23 | expect(closeFn).toHaveBeenCalled(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /site/demo/grid/gutter.md: -------------------------------------------------------------------------------- 1 | ## 栅格间隔 2 | 3 | 使用 Row 的 gutter 属性设置栅格间隔,支持响应式可以设置成`{ xs: 8, sm: 16, md: 24, lg: 32 }`。 4 | 5 | 6 | 7 | ```jsx 8 | const grid = ( 9 |
10 | 11 | 12 |
col-6
13 | 14 | 15 |
col-6
16 | 17 | 18 |
col-6
19 | 20 | 21 |
col-6
22 | 23 |
24 |
25 | ); 26 | ReactDOM.render(grid); 27 | ``` 28 | 29 | 30 | -------------------------------------------------------------------------------- /site/demo/input/_props.md: -------------------------------------------------------------------------------- 1 | ## API 2 | 3 | #### Input 4 | | 参数 | 说明 | 类型 | 默认值 | 5 | | --- | --- | --- | --- | 6 | | autoFocus | `Input`自动focus | boolean | false | 7 | | className | 容器 className | string | - | 8 | | disabled | 是否禁用 | boolean | false | 9 | | errorMessage | 错误信息 | string | - | 10 | | icon | 输入框左边的图标 | ReactNode | - | 11 | | label | 标签文本 | string | - | 12 | | labelFloat | 标签是否浮动 | boolean | - | 13 | | maxLength | 最大长度 | number | - | 14 | | onChange | 输入框内容变化时的回调 | function(e) | - | 15 | | onPressEnter | 按下回车的回调 | function(e) | - | 16 | | prefix | 前缀 | ReactNode | - | 17 | | showCount | 显示计数,需要和`maxLength`配合使用 | boolean | false | 18 | | suffix | 后缀 | ReactNode | - | 19 | 20 | #### Textarea 21 | | 参数 | 说明 | 类型 | 默认值 | 22 | | --- | --- | --- | --- | 23 | | autoSize | 自动高度 | boolean | false | 24 | -------------------------------------------------------------------------------- /site/demo/radio/equal.md: -------------------------------------------------------------------------------- 1 | ## 自定义比较函数 2 | 3 | 在`Radio.Group`上使用`isValueEqual`自定义比较函数。 4 | 5 | 6 | 7 | ```jsx 8 | const RadioGroup = () => { 9 | const [val, setVal] = React.useState({ foo: 1 }); 10 | 11 | const handleChange = e => { 12 | console.log(e); 13 | setVal(e.target.value); 14 | }; 15 | 16 | const isValueEqual = (a, b) => a && b && a.foo === b.foo; 17 | 18 | return ( 19 |
20 | 25 | foo: 1 26 | foo: 2 27 | 28 |
29 | ); 30 | }; 31 | ReactDOM.render(); 32 | ``` 33 | 34 | 35 | -------------------------------------------------------------------------------- /components/icon/svgs/checked.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.stylelintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "stylelint-config-standard", 4 | "stylelint-config-rational-order", 5 | "stylelint-config-prettier" 6 | ], 7 | "plugins": ["stylelint-scss", "stylelint-order", "stylelint-declaration-block-no-ignored-properties"], 8 | "rules": { 9 | "comment-empty-line-before": null, 10 | "declaration-empty-line-before": null, 11 | "no-invalid-double-slash-comments": null, 12 | "no-descending-specificity": null, 13 | "plugin/declaration-block-no-ignored-properties": true, 14 | "at-rule-no-unknown": null, 15 | "scss/at-rule-no-unknown": true, 16 | "function-name-case": ["lower", { "ignoreFunctions": ["/colorPalette/", "/selectorToString/"] }] 17 | }, 18 | "ignoreFiles": ["components/style/color/{bezierEasing,colorPalette,tinyColor}.less"] 19 | } -------------------------------------------------------------------------------- /site/demo/modal/confirm-props.md: -------------------------------------------------------------------------------- 1 | ## confirm 自定义页脚按钮属性 2 | 3 | 4 | 5 | ```jsx 6 | const Confirm = () => { 7 | const handleClick = () => { 8 | Modal.confirm({ 9 | title: 'Are you sure delete this task?', 10 | content: 'Some descriptions', 11 | okShape: 'round', 12 | okText: 'Yes', 13 | cancelText: 'No', 14 | okColor: 'success', 15 | cancelColor: 'danger', 16 | onOk() { 17 | console.log('Ok'); 18 | }, 19 | onCancel() { 20 | console.log('Cancel'); 21 | }, 22 | }); 23 | }; 24 | 25 | return ( 26 |
27 | 30 |
31 | ); 32 | }; 33 | ReactDOM.render(); 34 | ``` 35 | 36 | 37 | -------------------------------------------------------------------------------- /site/demo/buttons/circle-fab.md: -------------------------------------------------------------------------------- 1 | ### 圆形/浮动 2 | 3 | 4 | 5 | ```js 6 | const instance = ( 7 |
8 | 11 | 14 | 17 | 20 | 23 | 26 |
27 | ); 28 | ReactDOM.render(instance); 29 | ``` 30 | 31 | 32 | -------------------------------------------------------------------------------- /components/input/Textarea.tsx: -------------------------------------------------------------------------------- 1 | import React, { forwardRef, useEffect } from 'react'; 2 | import autosize from 'autosize'; 3 | 4 | export interface TextareaPorps extends React.TextareaHTMLAttributes { 5 | className?: string; 6 | autoSize?: boolean; 7 | } 8 | 9 | const Textarea = forwardRef((props: TextareaPorps, ref: React.RefObject) => { 10 | const { autoSize, ...rest } = props; 11 | 12 | useEffect(() => { 13 | if (autoSize && ref.current instanceof HTMLTextAreaElement) { 14 | autosize(ref.current); 15 | } 16 | return () => { 17 | if (ref.current instanceof HTMLTextAreaElement) { 18 | autosize.destroy(ref.current); 19 | } 20 | }; 21 | }, [autoSize]); 22 | 23 | return