├── .babelrc ├── .eslintignore ├── .eslintrc.json ├── .gitignore ├── .npmignore ├── .storybook ├── config.js ├── preview-head.html └── webpack.config.js ├── CHANGELOG.md ├── LICENSE ├── README.md ├── components ├── index.js ├── raw.js ├── raw │ ├── Message │ │ ├── index.js │ │ └── message.css │ └── Modal │ │ └── ShortMessage │ │ ├── index.js │ │ └── message.css ├── react │ ├── Button │ │ ├── BaseButton │ │ │ ├── button.css │ │ │ └── index.jsx │ │ ├── Button │ │ │ └── index.jsx │ │ ├── ButtonGroup │ │ │ ├── group.css │ │ │ └── index.jsx │ │ ├── ClassicButton │ │ │ ├── button.css │ │ │ └── index.jsx │ │ ├── FloatingActionButton │ │ │ ├── fab.css │ │ │ └── index.jsx │ │ └── IconButton │ │ │ ├── button.css │ │ │ └── index.jsx │ ├── Card │ │ ├── CardGroup │ │ │ ├── group.css │ │ │ └── index.jsx │ │ ├── ClassicCard │ │ │ ├── card.css │ │ │ └── index.jsx │ │ └── InfoCard │ │ │ ├── card.css │ │ │ └── index.jsx │ ├── ClassicText │ │ ├── index.jsx │ │ └── text.css │ ├── Dropdown │ │ ├── dropdown.css │ │ └── index.jsx │ ├── Form │ │ ├── Input │ │ │ ├── index.jsx │ │ │ └── input.css │ │ ├── InputGroup │ │ │ ├── group.css │ │ │ └── index.jsx │ │ ├── InputGroupV2 │ │ │ ├── group.css │ │ │ └── index.jsx │ │ ├── Selector │ │ │ ├── index.jsx │ │ │ └── selector.css │ │ ├── SelectorV2 │ │ │ ├── Option.jsx │ │ │ ├── index.jsx │ │ │ └── selector.css │ │ └── Textarea │ │ │ ├── index.jsx │ │ │ └── textarea.css │ ├── Label │ │ ├── index.jsx │ │ └── label.css │ ├── Modal │ │ ├── BaseModal │ │ │ ├── index.jsx │ │ │ └── modal.css │ │ ├── Loading │ │ │ ├── animation.css │ │ │ ├── index.jsx │ │ │ └── loading.css │ │ ├── PortalModal │ │ │ └── index.jsx │ │ ├── PortalModalWithState │ │ │ └── index.jsx │ │ └── ShortMessage │ │ │ ├── index.jsx │ │ │ └── message.css │ ├── Slider │ │ ├── Dragger.jsx │ │ ├── ProgressBar.jsx │ │ ├── index.jsx │ │ └── slider.css │ ├── Switcher │ │ ├── index.jsx │ │ └── switcher.css │ └── Tipso │ │ ├── BaseTipso │ │ ├── index.jsx │ │ └── tipso.css │ │ └── Tipso │ │ └── index.jsx └── shared │ ├── components │ ├── AnimationComponent.jsx │ └── OutsideClickHandler.jsx │ ├── styles │ ├── border.css │ ├── color.css │ ├── font.css │ ├── shadow.css │ └── z-index.css │ └── utils │ ├── darg.js │ ├── helper.js │ ├── icons.js │ └── validator.js ├── examples ├── ButtonWrapper.jsx ├── CardWrapper.jsx ├── CustomSelectorWrapper.jsx ├── DropdownWrapper.jsx ├── FormWrapper.jsx ├── LabelWrapper.jsx ├── LoadingWrapper.jsx ├── MessageWrapper.jsx ├── ShortMessageWrapper.jsx ├── SliderWrapper.jsx ├── SwitcherWrapper.jsx ├── TipsoWrapper.jsx └── shared │ └── styles.css ├── package.json ├── postcss.config.js ├── screenshots ├── 1.png ├── 2.png ├── 3.png ├── 4.png ├── button.gif ├── input.gif ├── range.gif ├── switcher.gif └── tipso.gif └── stories ├── Button.js ├── Card.js ├── CustomSelector.js ├── Dropdown.js ├── Form.js ├── Label.js ├── Loading.js ├── Message.js ├── ShortMessage.js ├── Slider.js ├── Switcher.js └── Tipso.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "env", 4 | "stage-0", 5 | "react" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | dist/** 2 | lib/** 3 | node_modules/** 4 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "extends": "standard", 4 | "plugins": [ 5 | "react", 6 | "import", 7 | "babel" 8 | ], 9 | "parserOptions": { 10 | "ecmaFeatures": { 11 | "jsx": true 12 | } 13 | }, 14 | "env": { 15 | "browser": true, 16 | "node": true, 17 | "es6": true, 18 | "jquery": true, 19 | "commonjs": true, 20 | "phantomjs": true, 21 | "mocha": true 22 | }, 23 | "rules": { 24 | "strict": 0, 25 | "no-console": 1, 26 | "no-debugger": 1, 27 | "no-extra-semi": 1, 28 | "no-constant-condition": 2, 29 | "no-extra-boolean-cast": 2, 30 | "no-return-assign": 0, 31 | "use-isnan": 2, 32 | "no-undef-init": 2, 33 | "camelcase": 2, 34 | "no-mixed-spaces-and-tabs": 2, 35 | "no-const-assign":2, 36 | "no-func-assign": 2, 37 | "no-else-return": 1, 38 | "no-obj-calls": 2, 39 | "valid-typeof": 2, 40 | "no-unused-vars": 1, 41 | "quotes": 0, 42 | "block-spacing": 1, 43 | "semi": 0, 44 | "keyword-spacing": 1, 45 | "comma-dangle": 0, 46 | "array-bracket-spacing": 1, 47 | "space-before-function-paren": 0, 48 | "no-extra-bind": 1, 49 | "no-var": "error", 50 | "arrow-spacing": ["error", { "before": true, "after": true }], 51 | "arrow-body-style": ["error", "as-needed"], 52 | "no-empty-function": ["error", { "allow": ["arrowFunctions", "constructors"] }], 53 | "react/no-did-mount-set-state": "error", 54 | "react/no-did-update-set-state": "error", 55 | "react/react-in-jsx-scope": "error", 56 | "react/jsx-uses-vars": [2], 57 | "react/jsx-uses-react": [2], 58 | "import/no-unresolved": [2, {"commonjs": true, "amd": true}], 59 | "import/namespace": 2, 60 | "import/default": 2, 61 | "import/export": 2, 62 | "babel/new-cap": 1, 63 | "babel/object-curly-spacing": 0, 64 | "babel/no-invalid-this": 1, 65 | "babel/semi": 0 66 | }, 67 | "settings": { 68 | "import/resolver": { 69 | "node": { 70 | "extensions": [".js", ".jsx"] 71 | }, 72 | "webpack": { 73 | "config": "webpack.config.js" 74 | } 75 | }, 76 | "import/ignore": ["node_modules"] 77 | }, 78 | "globals": { 79 | "require": true 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /lib 3 | /.out 4 | package-lock.json 5 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | /components/ 2 | /examples 3 | /stories 4 | /webpack 5 | /.storybook 6 | /CHANGELOG.md 7 | /screenshots 8 | -------------------------------------------------------------------------------- /.storybook/config.js: -------------------------------------------------------------------------------- 1 | import moment from 'moment'; 2 | import { configure, addDecorator } from '@storybook/react'; 3 | 4 | addDecorator((story) => { 5 | moment.locale('zh-cn'); 6 | return (story()); 7 | }); 8 | 9 | function loadStories() { 10 | require('../stories/Button'); 11 | require('../stories/Form'); 12 | require('../stories/ShortMessage'); 13 | require('../stories/Message'); 14 | require('../stories/Tipso'); 15 | require('../stories/Loading'); 16 | require('../stories/Card'); 17 | require('../stories/Slider'); 18 | require('../stories/Label'); 19 | require('../stories/Switcher'); 20 | require('../stories/CustomSelector'); 21 | require('../stories/Dropdown'); 22 | } 23 | 24 | configure(loadStories, module); 25 | -------------------------------------------------------------------------------- /.storybook/preview-head.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 26 | -------------------------------------------------------------------------------- /.storybook/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const webpack = require('webpack'); 3 | 4 | const SOURCE_PATH = path.join(__dirname, '../components'); 5 | const WRAPPER_PATH = path.join(__dirname, '../examples'); 6 | const cssLoaders = [ 7 | 'style-loader', 8 | { 9 | loader: 'css-loader', 10 | options: { 11 | modules: true, 12 | sourceMaps: true, 13 | importLoaders: 1, 14 | localIdentName: '[name]__[local]___[hash:base64:5]' 15 | } 16 | }, 17 | 'postcss-loader' 18 | ]; 19 | 20 | module.exports = { 21 | context: SOURCE_PATH, 22 | module: { 23 | rules: [ 24 | { 25 | test: /\.jsx?$/, 26 | enforce: "pre", 27 | loader: "eslint-loader", 28 | exclude: /node_modules/, 29 | include: SOURCE_PATH, 30 | }, 31 | { 32 | test: /\.css$/, 33 | include: SOURCE_PATH, 34 | use: cssLoaders, 35 | }, 36 | { 37 | test: /\.css$/, 38 | include: WRAPPER_PATH, 39 | use: cssLoaders, 40 | }, 41 | { 42 | test: /\.(js|jsx)$/, 43 | include: SOURCE_PATH, 44 | use: ['babel-loader'], 45 | exclude: /node_modules/ 46 | }, 47 | ] 48 | }, 49 | resolve: { 50 | modules: ['node_modules'], 51 | extensions: ['.js', '.jsx'], 52 | }, 53 | plugins: [ 54 | new webpack.LoaderOptionsPlugin({ 55 | debug: true, 56 | minimize: true, 57 | options: { 58 | context: SOURCE_PATH, 59 | } 60 | }), 61 | new webpack.DefinePlugin({ 62 | 'process.env': { NODE_ENV: JSON.stringify(process.env.NODE_ENV || 'development') } 63 | }), 64 | ], 65 | devtool: '#source-map', 66 | }; 67 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ecmadao/light-ui/0cc48d53738454a7d6161840bbc0b56058fb827e/CHANGELOG.md -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 ecmadao 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | **Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* 4 | 5 | - [Light-UI](#light-ui) 6 | - [Doc](#doc) 7 | - [Screenshots](#screenshots) 8 | - [Todo](#todo) 9 | - [License](#license) 10 | - [Author](#author) 11 | 12 | 13 | 14 | ## Light-UI 15 | 16 | [![npm version](https://badge.fury.io/js/light-ui.svg)](https://badge.fury.io/js/light-ui) [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com) [![light-ui](http://img.shields.io/npm/dm/light-ui.svg)](https://www.npmjs.com/package/light-ui) [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/ecmadao/light-ui/master/LICENSE) 17 | 18 | [![NPM](https://nodei.co/npm/light-ui.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/light-ui) 19 | 20 | > UI Components for [hacknical](https://github.com/ecmadao/hacknical) 21 | 22 | ### Doc & Demo 23 | 24 | - [Documents](https://github.com/ecmadao/light-ui/wiki) 25 | - [Examples](https://github.com/ecmadao/light-ui/tree/master/examples) 26 | - [Online demo](https://ecmadao.github.io/light-ui) 27 | 28 | ### Screenshots 29 | 30 | ![](./screenshots/switcher.gif) 31 | 32 | ![](./screenshots/range.gif) 33 | 34 | ![](./screenshots/tipso.gif) 35 | 36 | ![](./screenshots/input.gif) 37 | 38 | ![](./screenshots/button.gif) 39 | 40 | ![](./screenshots/1.png) 41 | 42 | ![](./screenshots/2.png) 43 | 44 | ![](./screenshots/3.png) 45 | 46 | ![](./screenshots/4.png) 47 | 48 | ### Todo 49 | 50 | - [x] README 51 | - [x] API Doc 52 | - [x] Raw javascript components 53 | - [x] EsLint 54 | 55 | ### License 56 | 57 | [MIT License](./LICENSE) 58 | 59 | ### Author 60 | 61 | [ecmadao](https://github.com/ecmadao) -------------------------------------------------------------------------------- /components/index.js: -------------------------------------------------------------------------------- 1 | 2 | export Button from './react/Button/Button' 3 | export IconButton from './react/Button/IconButton' 4 | export ButtonGroup from './react/Button/ButtonGroup' 5 | export FloatingActionButton from './react/Button/FloatingActionButton' 6 | export ClassicButton from './react/Button/ClassicButton' 7 | 8 | export Input from './react/Form/Input' 9 | export InputGroup from './react/Form/InputGroup' 10 | export InputGroupV2 from './react/Form/InputGroupV2' 11 | export Selector from './react/Form/Selector' 12 | export SelectorV2 from './react/Form/SelectorV2' 13 | export Textarea from './react/Form/Textarea' 14 | 15 | export Loading from './react/Modal/Loading' 16 | export PortalModal from './react/Modal/PortalModal' 17 | export PortalModalWithState from './react/Modal/PortalModalWithState' 18 | export ShortMessage from './react/Modal/ShortMessage' 19 | 20 | export Tipso from './react/Tipso/Tipso' 21 | 22 | export InfoCard from './react/Card/InfoCard' 23 | export ClassicCard from './react/Card/ClassicCard' 24 | export CardGroup from './react/Card/CardGroup' 25 | 26 | export Label from './react/Label' 27 | export Switcher from './react/Switcher' 28 | export Slider from './react/Slider' 29 | export Dropdown from './react/Dropdown' 30 | 31 | export ClassicText from './react/ClassicText' 32 | 33 | export OutsideClickHandler from './shared/components/OutsideClickHandler' 34 | export AnimationComponent from './shared/components/AnimationComponent' 35 | -------------------------------------------------------------------------------- /components/raw.js: -------------------------------------------------------------------------------- 1 | 2 | export Message from './raw/Message'; 3 | export ShortMessage from './raw/Modal/ShortMessage'; 4 | -------------------------------------------------------------------------------- /components/raw/Message/index.js: -------------------------------------------------------------------------------- 1 | 2 | import cx from 'classnames'; 3 | import styles from './message.css'; 4 | import helper from '../../shared/utils/helper'; 5 | 6 | const Message = (...args) => { 7 | let messageComponent = null; 8 | return (() => { 9 | if (!messageComponent) { 10 | messageComponent = new MessageComponent(...args); 11 | } 12 | return messageComponent; 13 | })(); 14 | }; 15 | 16 | class MessageComponent { 17 | constructor(options = {}) { 18 | const { 19 | content = '', 20 | className = '', 21 | timeout = 2500, 22 | showClose = true, 23 | isMobile = false, 24 | theme = 'banner', 25 | type = 'positive', 26 | } = options; 27 | this.state = { 28 | type, 29 | theme, 30 | content, 31 | timeout, 32 | isMobile, 33 | showClose, 34 | className, 35 | }; 36 | this.timeout = null; 37 | this.$body = document.body; 38 | 39 | this.resetTemplate(); 40 | } 41 | 42 | update(options) { 43 | this._setState(options); 44 | } 45 | 46 | _setState(newState) { 47 | this.timeout && clearTimeout(this.timeout); 48 | this.timeout = null; 49 | Object.assign(this.state, newState); 50 | this.resetTemplate(); 51 | } 52 | 53 | error(msg, timeout) { 54 | this.$message.classList.remove(styles.positive); 55 | this.$message.classList.remove(styles.tips); 56 | this.$message.classList.add(styles.negative); 57 | this.$message.childNodes[0].innerHTML = msg; 58 | 59 | this.showMessage(timeout); 60 | } 61 | 62 | notice(msg, timeout) { 63 | this.$message.classList.remove(styles.negative); 64 | this.$message.classList.remove(styles.tips); 65 | this.$message.classList.add(styles.positive); 66 | this.$message.childNodes[0].innerHTML = msg; 67 | 68 | this.showMessage(timeout); 69 | } 70 | 71 | tips(msg, timeout) { 72 | this.$message.classList.remove(styles.negative); 73 | this.$message.classList.remove(styles.positive); 74 | this.$message.classList.add(styles.tips); 75 | this.$message.childNodes[0].innerHTML = msg; 76 | 77 | this.showMessage(timeout); 78 | } 79 | 80 | showMessage(timeout = this.state.timeout) { 81 | this.$message.classList.add(styles.active); 82 | this.autoHideMessage(timeout); 83 | } 84 | 85 | autoHideMessage(timeout) { 86 | const hideMessage = () => { 87 | this.$message.classList.remove(styles.active); 88 | }; 89 | this.timeout = setTimeout(hideMessage, timeout); 90 | } 91 | 92 | appendMessage() { 93 | this.$body.appendChild(this.$message); 94 | const closeIcon = this.$message.childNodes[1]; 95 | if (!closeIcon) return; 96 | 97 | const closeFunc = () => { 98 | this.$message.classList.remove(styles.active); 99 | }; 100 | if (closeIcon.addEventListener) { 101 | closeIcon.addEventListener('click', closeFunc.bind(this), true); 102 | } else { 103 | closeIcon.attachEvent('onmousedown', closeFunc.bind(this)); 104 | } 105 | } 106 | 107 | messageTemplate() { 108 | const { className, type, content, theme, isMobile, showClose } = this.state; 109 | const id = helper.uuid(); 110 | const message = document.createElement('div'); 111 | message.className = cx( 112 | styles.messageComponent, 113 | styles[type], 114 | styles[theme], 115 | isMobile && styles.mobileMessage, 116 | className 117 | ); 118 | 119 | message.innerHTML = `
${content}
${!showClose ? '' : ''}`; 120 | this.state.id = id; 121 | return message; 122 | } 123 | 124 | resetTemplate() { 125 | this.$message && this.$message.remove(); 126 | this.$message = this.messageTemplate(); 127 | this.appendMessage(); 128 | } 129 | } 130 | 131 | export default Message; 132 | -------------------------------------------------------------------------------- /components/raw/Message/message.css: -------------------------------------------------------------------------------- 1 | @import "../../shared/styles/z-index.css"; 2 | @import "../../shared/styles/color.css"; 3 | @import "../../shared/styles/border.css"; 4 | 5 | .messageComponent { 6 | position: fixed; 7 | min-height: 50px; 8 | font-size: 14px; 9 | user-select: none; 10 | overflow: hidden; 11 | color: var(--white); 12 | z-index: var(--zIndex9999); 13 | border-radius: var(--radius-small); 14 | background-color: var(--gray-light); 15 | box-shadow: 0 8px 8px 0 rgba(0, 0, 0, 0.12), 0 0 8px 0 rgba(0, 0, 0, 0.08); 16 | 17 | display: flex; 18 | flex-direction: column; 19 | 20 | &.positive { 21 | background-color: var(--green-dark); 22 | } 23 | 24 | &.negative { 25 | background-color: var(--red-dark); 26 | } 27 | 28 | &.tips { 29 | background-color: var(--green); 30 | } 31 | 32 | & i { 33 | cursor: pointer; 34 | } 35 | } 36 | 37 | .messageContent { 38 | padding: 15px; 39 | display: flex; 40 | flex-direction: row; 41 | justify-content: center; 42 | align-items: center; 43 | flex-grow: 1; 44 | } 45 | 46 | .banner { 47 | width: 80%; 48 | top: -120%; 49 | left: 10%; 50 | right: 10%; 51 | text-align: center; 52 | transition: top 400ms cubic-bezier(0.165, 0.84, 0.44, 1); 53 | 54 | &.active { 55 | top: 20px; 56 | } 57 | 58 | & i { 59 | position: absolute; 60 | top: 50%; 61 | right: 25px; 62 | transform: translateY(-50%); 63 | } 64 | } 65 | 66 | .notify { 67 | top: 20px; 68 | width: 250px; 69 | opacity: 0; 70 | right: -100%; 71 | transition: right 0.3s cubic-bezier(0.165, 0.84, 0.44, 1), opacity 0.3s cubic-bezier(0.165, 0.84, 0.44, 1); 72 | 73 | &.active { 74 | opacity: 1; 75 | right: 20px; 76 | } 77 | 78 | & i { 79 | position: absolute; 80 | top: 7px; 81 | right: 7px; 82 | } 83 | } 84 | 85 | .mobileMessage { 86 | width: 80%; 87 | top: inherit; 88 | bottom: -120%; 89 | left: 10%; 90 | right: 10%; 91 | transition: bottom 400ms cubic-bezier(0.165, 0.84, 0.44, 1); 92 | 93 | &.active { 94 | bottom: 20px; 95 | top: inherit; 96 | } 97 | 98 | & i { 99 | display: none; 100 | } 101 | } 102 | 103 | @media (max-width: 500px) { 104 | .messageComponent { 105 | font-size: 12px; 106 | 107 | & i { 108 | display: none; 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /components/raw/Modal/ShortMessage/index.js: -------------------------------------------------------------------------------- 1 | 2 | import cx from 'classnames'; 3 | import styles from './message.css'; 4 | 5 | const ShortMessage = (...args) => { 6 | let messageComponent = null; 7 | return (() => { 8 | if (!messageComponent) { 9 | messageComponent = new MessageComponent(...args); 10 | } 11 | return messageComponent; 12 | })(); 13 | }; 14 | 15 | class MessageComponent { 16 | constructor(timeout = 2500, options = {}) { 17 | this.state = { 18 | timeout, 19 | style: options.style || {}, 20 | className: options.className || '', 21 | }; 22 | this.$message = null; 23 | this.$body = document.body; 24 | } 25 | 26 | update(newState) { 27 | Object.assign(this.state, newState); 28 | } 29 | 30 | show(msg, time = this.state.timeout) { 31 | this.$message = this._messageTemplate(msg); 32 | this.$body.appendChild(this.$message); 33 | this._autoHide(time); 34 | } 35 | 36 | _hide() { 37 | try { 38 | this.$body.removeChild(this.$message); 39 | } catch (err) {} 40 | this.$message = null; 41 | } 42 | 43 | remove() { 44 | this.$message && this._hide(); 45 | } 46 | 47 | _autoHide(time) { 48 | const hideMessage = () => this._hide(); 49 | setTimeout(hideMessage, time); 50 | } 51 | 52 | _messageTemplate(msg) { 53 | const message = document.createElement('div'); 54 | message.className = cx( 55 | styles.messageComponent, 56 | this.state.className 57 | ); 58 | Object.keys(this.state.style).forEach((key) => { message.style[key] = this.state.style[key]; }); 59 | message.innerHTML = msg; 60 | return message; 61 | } 62 | } 63 | 64 | export default ShortMessage; 65 | -------------------------------------------------------------------------------- /components/raw/Modal/ShortMessage/message.css: -------------------------------------------------------------------------------- 1 | @import "../../../shared/styles/z-index.css"; 2 | @import '../../../shared/styles/border.css'; 3 | 4 | .messageComponent { 5 | position: fixed; 6 | top: 50%; 7 | left: 50%; 8 | transform: translate(-50%, -50%); 9 | background-color: rgba(0, 0, 0, 0.7); 10 | border-radius: var(--radius); 11 | padding: 23px 30px; 12 | color: #fff; 13 | font-size: 14px; 14 | z-index: var(--zIndex9999); 15 | } 16 | -------------------------------------------------------------------------------- /components/react/Button/BaseButton/button.css: -------------------------------------------------------------------------------- 1 | @import "../../../shared/styles/shadow.css"; 2 | @import "../../../shared/styles/z-index.css"; 3 | @import '../../../shared/styles/color.css'; 4 | @import '../../../shared/styles/border.css'; 5 | @import '../../../shared/styles/font.css'; 6 | 7 | :root { 8 | --background-transition : background-color 0.2s; 9 | --color-transition : color 0.2s; 10 | } 11 | 12 | .button { 13 | text-align: center; 14 | cursor: default; 15 | padding: 10px 20px; 16 | border-radius: var(--radius-small); 17 | margin: 15px 5px; 18 | display: inline-flex; 19 | justify-content: center; 20 | align-items: center; 21 | flex-direction: row; 22 | user-select: none; 23 | position: relative; 24 | composes: baseSubText; 25 | 26 | & .wrapper { 27 | transform: translateY(0); 28 | } 29 | 30 | &.clickable:not(.disabled) { 31 | &:hover { 32 | &::before { 33 | background-color: var(--black); 34 | } 35 | } 36 | } 37 | 38 | &.clickable { 39 | cursor: pointer; 40 | } 41 | 42 | & i:first-child { 43 | margin-right: 10px; 44 | } 45 | 46 | & i:last-child { 47 | margin-left: 10px; 48 | } 49 | 50 | &:first-child { 51 | &:not(.floating-action-button) { 52 | margin-left: 0; 53 | } 54 | } 55 | 56 | &:last-child { 57 | &:not(.floating-action-button) { 58 | margin-right: 0; 59 | } 60 | } 61 | 62 | &::before { 63 | content: ''; 64 | display: block; 65 | position: absolute; 66 | top: 0; 67 | right: 0; 68 | bottom: 0; 69 | left: 0; 70 | margin: -1px; 71 | opacity: 0.3; 72 | border-radius: var(--radius-small); 73 | background-color: transparent; 74 | transition: var(--background-transition); 75 | } 76 | } 77 | 78 | .flat { 79 | transition: var(--background-transition), var(--color-transition); 80 | 81 | &.white { 82 | border: none; 83 | color: var(--gray-dark); 84 | background-color: var(--white); 85 | 86 | & i { 87 | color: var(--gray-dark); 88 | } 89 | } 90 | 91 | &.green { 92 | border: 1px solid var(--green-dark); 93 | color: var(--green-dark); 94 | 95 | & i { 96 | color: var(--green-dark); 97 | } 98 | 99 | &.active, 100 | &.clickable:not(.disabled):hover { 101 | background-color: var(--green-dark); 102 | color: var(--white); 103 | 104 | & i { 105 | color: var(--white); 106 | } 107 | } 108 | } 109 | 110 | &.red { 111 | border: 1px solid var(--red-dark); 112 | color: var(--red-dark); 113 | 114 | & i { 115 | color: var(--red-dark); 116 | } 117 | 118 | &.active, 119 | &.clickable:not(.disabled):hover { 120 | background-color: var(--red-dark); 121 | color: var(--white); 122 | 123 | & i { 124 | color: var(--white); 125 | } 126 | } 127 | } 128 | 129 | &.blue { 130 | border: 1px solid var(--blue-dark); 131 | color: var(--blue-dark); 132 | 133 | & i { 134 | color: var(--blue-dark); 135 | } 136 | 137 | &.active, 138 | &.clickable:not(.disabled):hover { 139 | background-color: var(--blue-dark); 140 | color: var(--white); 141 | 142 | & i { 143 | color: var(--white); 144 | } 145 | } 146 | } 147 | 148 | &.dark { 149 | border: 1px solid var(--gray-dark); 150 | color: var(--gray-dark); 151 | 152 | & i { 153 | color: var(--gray-dark); 154 | } 155 | 156 | &.active, 157 | &.clickable:not(.disabled):hover { 158 | background-color: var(--gray-dark); 159 | color: var(--white); 160 | 161 | & i { 162 | color: var(--white); 163 | } 164 | } 165 | } 166 | 167 | &.gray { 168 | border: 1px solid var(--gray); 169 | color: var(--gray); 170 | 171 | & i { 172 | color: var(--gray); 173 | } 174 | 175 | &.active, 176 | &.clickable:not(.disabled):hover { 177 | background-color: var(--gray); 178 | color: var(--white); 179 | 180 | & i { 181 | color: var(--white); 182 | } 183 | } 184 | } 185 | } 186 | 187 | .material { 188 | color: var(--white); 189 | border: 1px solid transparent; 190 | box-shadow: var(--shadow4); 191 | transition: box-shadow 200ms cubic-bezier(0.165, 0.84, 0.44, 1); 192 | 193 | &.active, 194 | &.clickable:not(.disabled):hover { 195 | box-shadow: var(--shadow6); 196 | } 197 | 198 | &.white { 199 | color: var(--gray-dark); 200 | background-color: var(--white); 201 | } 202 | 203 | &.green { 204 | background-color: var(--green-dark); 205 | } 206 | 207 | &.red { 208 | background-color: var(--red-dark); 209 | } 210 | 211 | &.dark { 212 | background-color: var(--gray-dark); 213 | } 214 | 215 | &.gray { 216 | background-color: var(--gray); 217 | } 218 | 219 | &.blue { 220 | background-color: var(--blue-dark); 221 | } 222 | } 223 | 224 | .floating-action-button { 225 | padding: 0; 226 | border-radius: var(--radius-half); 227 | color: var(--white); 228 | box-shadow: var(--shadow5); 229 | transition: box-shadow 200ms cubic-bezier(0.165, 0.84, 0.44, 1); 230 | 231 | &::before { 232 | border-radius: var(--radius-half); 233 | } 234 | 235 | &.white { 236 | color: var(--gray-dark); 237 | background-color: var(--white); 238 | } 239 | 240 | &.green { 241 | background-color: var(--green-dark); 242 | } 243 | 244 | &.red { 245 | background-color: var(--red-dark); 246 | } 247 | 248 | &.dark { 249 | background-color: var(--gray-dark); 250 | } 251 | 252 | &.gray { 253 | background-color: var(--gray); 254 | } 255 | 256 | &.blue { 257 | background-color: var(--blue-dark); 258 | } 259 | } 260 | 261 | .clickable.pressDown { 262 | &.material.material { 263 | box-shadow: var(--shadow2); 264 | } 265 | 266 | &.floating-action-button.floating-action-button { 267 | box-shadow: var(--shadow2); 268 | } 269 | 270 | & .wrapper { 271 | transform: translateY(1px); 272 | } 273 | } 274 | 275 | .disabled { 276 | cursor: not-allowed !important; 277 | 278 | &::before { 279 | z-index: var(--zIndex1); 280 | background-color: var(--gray); 281 | } 282 | } 283 | 284 | .ghost { 285 | color: var(--gray-dark); 286 | border: 1px solid transparent; 287 | transition: var(--background-transition), var(--color-transition); 288 | 289 | &.active, 290 | &.clickable:not(.disabled):hover { 291 | color: var(--white); 292 | 293 | & i { 294 | color: var(--white); 295 | } 296 | 297 | &.green { 298 | background-color: var(--green); 299 | } 300 | 301 | &.red { 302 | background-color: var(--red); 303 | } 304 | 305 | &.dark { 306 | background-color: var(--gray-dark); 307 | } 308 | 309 | &.white { 310 | background-color: var(--gray-dark); 311 | } 312 | 313 | &.gray { 314 | background-color: var(--gray); 315 | } 316 | 317 | &.blue { 318 | background-color: var(--blue); 319 | } 320 | } 321 | 322 | &.green { 323 | color: var(--green-dark); 324 | } 325 | 326 | &.red { 327 | color: var(--red-dark); 328 | } 329 | 330 | &.dark { 331 | color: var(--gray-dark); 332 | } 333 | 334 | &.white { 335 | color: var(--gray-dark); 336 | } 337 | 338 | &.gray { 339 | color: var(--gray); 340 | } 341 | 342 | &.blue { 343 | color: var(--blue-dark); 344 | } 345 | } 346 | 347 | .label { 348 | & i:first-child { 349 | margin-right: 5px; 350 | } 351 | } 352 | -------------------------------------------------------------------------------- /components/react/Button/BaseButton/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import cx from 'classnames'; 3 | import PropTypes from 'prop-types'; 4 | import styles from './button.css'; 5 | 6 | class BaseButton extends React.Component { 7 | constructor(props) { 8 | super(props); 9 | this.state = { 10 | pressed: false 11 | }; 12 | this.onClick = this.onClick.bind(this); 13 | this.onMouseDown = this.onMouseDown.bind(this); 14 | this.onMouseUp = this.onMouseUp.bind(this); 15 | this.onMouseEnter = this.onMouseEnter.bind(this); 16 | this.onMouseLeave = this.onMouseLeave.bind(this); 17 | } 18 | 19 | onClick() { 20 | const { onClick } = this.props; 21 | onClick && onClick(); 22 | } 23 | 24 | onMouseDown() { 25 | this.setState({ pressed: true }); 26 | } 27 | 28 | onMouseUp() { 29 | this.setState({ pressed: false }); 30 | } 31 | 32 | onMouseEnter() { 33 | const { onMouseEnter } = this.props; 34 | onMouseEnter && onMouseEnter(); 35 | } 36 | 37 | onMouseLeave() { 38 | this.onMouseUp(); 39 | const { onMouseLeave } = this.props; 40 | onMouseLeave && onMouseLeave(); 41 | } 42 | 43 | render() { 44 | const { 45 | id, 46 | type, 47 | theme, 48 | color, 49 | style, 50 | active, 51 | disabled, 52 | children, 53 | clickable, 54 | className, 55 | onTransitionEnd 56 | } = this.props 57 | const { pressed } = this.state 58 | 59 | const buttonClass = cx( 60 | styles.button, 61 | styles[type], 62 | styles[theme], 63 | styles[color], 64 | !disabled && clickable && styles.clickable, 65 | !disabled && pressed && styles.pressDown, 66 | active && styles.active, 67 | disabled && styles.disabled, 68 | className 69 | ); 70 | const onClick = disabled ? Function.prototype : this.onClick 71 | 72 | return ( 73 |
85 |
86 | {children} 87 |
88 |
89 | ) 90 | } 91 | } 92 | 93 | BaseButton.propTypes = { 94 | id: PropTypes.string, 95 | onClick: PropTypes.func, 96 | onTransitionEnd: PropTypes.func, 97 | color: PropTypes.string, 98 | className: PropTypes.string, 99 | style: PropTypes.object, 100 | theme: PropTypes.string, 101 | type: PropTypes.string, 102 | active: PropTypes.bool, 103 | disabled: PropTypes.bool, 104 | children: PropTypes.oneOfType([ 105 | PropTypes.element, 106 | PropTypes.node, 107 | PropTypes.array, 108 | PropTypes.string 109 | ]), 110 | clickable: PropTypes.bool 111 | }; 112 | 113 | BaseButton.defaultProps = { 114 | id: '', 115 | color: 'green', 116 | theme: 'material', 117 | type: 'button', 118 | onClick: Function.prototype, 119 | className: '', 120 | style: {}, 121 | active: false, 122 | disabled: false, 123 | children:
, 124 | clickable: true 125 | }; 126 | 127 | export default BaseButton; 128 | -------------------------------------------------------------------------------- /components/react/Button/Button/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import BaseButton from '../BaseButton'; 4 | 5 | const Button = (props) => { 6 | const { 7 | value, 8 | leftIcon, 9 | rightIcon 10 | } = props; 11 | const baseProps = Object.assign({}, props); 12 | 13 | const leftIconElement = typeof leftIcon === 'string' 14 | ? (