├── .gitignore ├── LICENSE ├── README.md ├── configs ├── jest.json └── webpack │ ├── buildLibrary.js │ ├── common.js │ ├── dev.js │ ├── paths.js │ └── prod.js ├── docs ├── images │ ├── 1e1078af7fdf5d25ecebff1a6548f2b6.png │ └── 1e4566a5540c0b636cff03139622cc1f.png ├── index.html └── js │ ├── bundle.13ff8cd59faf2647dc0a.min.js │ └── bundle.13ff8cd59faf2647dc0a.min.js.map ├── express.js ├── npmlibrary ├── images │ └── 1e1078af7fdf5d25ecebff1a6548f2b6.png ├── index.js ├── index.js.map ├── main.css ├── main.css.map ├── style.css └── style.css.map ├── package-lock.json ├── package.json ├── src ├── App.jsx ├── PageContainer.jsx ├── Preferences.js ├── SrcReadme.md ├── assets │ ├── fonts │ │ ├── GothamBold.woff │ │ ├── GothamLight.woff │ │ ├── GothamMedium.woff │ │ ├── GothamThin.woff │ │ ├── NotoSansBold.woff │ │ ├── NotoSansLight.woff │ │ ├── NotoSansRegular.woff │ │ └── NotoSansThin.woff │ ├── img │ │ ├── boiler.scss │ │ ├── icon-more.png │ │ └── icon-multiple.png │ └── scss │ │ ├── boiler.scss │ │ ├── button.scss │ │ ├── code.scss │ │ ├── common.scss │ │ ├── etc │ │ ├── iconcountdown.scss │ │ ├── iconloading.scss │ │ ├── iconmorebutton.scss │ │ ├── iconshortnotice.scss │ │ ├── iconstep.scss │ │ ├── icontab.scss │ │ └── index.scss │ │ ├── index.scss │ │ ├── intro.scss │ │ ├── popup.scss │ │ └── variable.scss ├── buildIndex.js ├── buttons │ ├── ButtonContainer.jsx │ ├── ButtonRouter.js │ ├── components │ │ ├── FlatButton.jsx │ │ └── FloatButton.jsx │ └── index.js ├── chart │ ├── ChartContainer.jsx │ ├── ChartRouter.jsx │ ├── chart.md │ └── icondonutchart │ │ ├── IconDonutChart.jsx │ │ └── IconDonutChartContainer.jsx ├── common │ ├── Code.jsx │ ├── IconClipBoard.jsx │ ├── PropertyTable.jsx │ └── layout │ │ ├── ComponentTemplete.jsx │ │ ├── DescriptionTemplete.jsx │ │ ├── MainFooter.jsx │ │ ├── MainHeader.jsx │ │ ├── MainMenu.jsx │ │ ├── MainMenuItem.jsx │ │ └── MainTemplete.jsx ├── config │ ├── ConfigAction.js │ ├── ConfigReducer.js │ ├── ConfigRouter.js │ ├── ConfigStore.js │ └── combinedReducers.js ├── error │ ├── PageNotConnect.jsx │ └── PageNotFound.jsx ├── etc │ ├── EtcContainer.jsx │ ├── EtcRouter.jsx │ ├── etc.md │ ├── iconcountdown │ │ ├── Constants.js │ │ ├── IconCountDown.jsx │ │ ├── IconCountDownContainer.jsx │ │ └── IconCountDownController.jsx │ ├── iconloading │ │ ├── IconLoading.jsx │ │ └── IconLoadingContainer.jsx │ ├── iconmorebutton │ │ ├── IconMoreButton.jsx │ │ └── IconMoreButtonContainer.jsx │ ├── iconshortnotice │ │ ├── IconShortNotice.jsx │ │ └── IconShortNoticeContainer.jsx │ ├── iconstep │ │ ├── IconStep.jsx │ │ └── IconStepContainer.jsx │ └── icontab │ │ ├── IconTab.jsx │ │ └── IconTabContainer.jsx ├── index.html.ejs ├── index.js ├── intro │ ├── Intro.jsx │ ├── IntroContainer.jsx │ ├── IntroRouter.jsx │ └── components │ │ ├── IntroBody.jsx │ │ ├── IntroFooter.jsx │ │ └── IntroHeader.jsx ├── library │ ├── layerpopup │ │ ├── EventName.js │ │ ├── LayerKeyGen.js │ │ ├── LayerPopup.js │ │ ├── LayerPopupContainer.jsx │ │ └── index.js │ ├── localstorage │ │ ├── Constants.js │ │ ├── StorageController.js │ │ ├── StorageControllerForChromeApp.js │ │ ├── StorageControllerForWeb.js │ │ ├── StorageListener.jsx │ │ └── SyncStorageToRedux.js │ ├── passwordmask │ │ ├── index.js │ │ └── styles.js │ ├── queryrouter │ │ ├── QueryRoute.jsx │ │ ├── QuerySwitch.jsx │ │ ├── index.js │ │ ├── matchQueryString.js │ │ └── parseQueryString.js │ ├── rcslider │ │ ├── Handle.jsx │ │ ├── Range.jsx │ │ ├── Slider.jsx │ │ ├── common │ │ │ ├── Marks.jsx │ │ │ ├── Steps.jsx │ │ │ ├── Track.jsx │ │ │ └── createSlider.jsx │ │ ├── createSliderWithTooltip.jsx │ │ ├── index.js │ │ └── utils.js │ ├── routerconnection │ │ ├── RouterConnectionForChromeExtension.jsx │ │ ├── RouterConnectionForWeb.jsx │ │ ├── RouterSwitchForChromeExtension.jsx │ │ └── RouterUtil.jsx │ ├── services │ │ └── APIJoin.js │ └── spin │ │ ├── EventName.js │ │ ├── SpinController.js │ │ └── SpinInjector.js ├── popup │ ├── Popup.js │ ├── components │ │ └── modals │ │ │ ├── ConfirmModal.jsx │ │ │ ├── ModalContainer.jsx │ │ │ └── NoticeModal.jsx │ └── popup.md ├── style │ ├── color.js │ ├── components │ │ ├── Button.jsx │ │ ├── Divider.jsx │ │ └── index.js │ ├── font.js │ ├── index.js │ ├── layout.js │ ├── spacing.js │ ├── style.md │ └── theme.js └── util │ ├── UtilContainer.jsx │ ├── UtilRouter.jsx │ ├── excel │ ├── Excel.js │ └── ExcelContainer.jsx │ └── util.md ├── temp └── tests ├── App.test.jsx └── __mocks__ ├── fileMock.js ├── shim.js └── styleMock.js /.gitignore: -------------------------------------------------------------------------------- 1 | # dependencies 2 | /node_modules/ 3 | 4 | # production 5 | /dist/* 6 | 7 | # misc 8 | .DS_Store 9 | .env 10 | npm-debug.log* 11 | 12 | package-lock.json 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Viktor Persson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [DEMO](https://sujkh85.github.io/react-icx-component/) 2 | 3 | # REACT-ICX-COMPONENT 4 | 5 | React icx component is ui library 6 | 7 | ## It's not an official thing! 8 | 9 | All rights are up to Icon. 10 | 11 | This project is my hobby. 12 | 13 | I will delete it if I have a problem. 14 | 15 | Please contact me if you have any problems.(wjdrudghks85@gmail.com) 16 | 17 | ## INSTALL 18 | 19 | ``` 20 | git clone https://github.com/sujkh85/react-icx-component.git 21 | npm install 22 | ``` 23 | 24 | ## START 25 | 26 | ``` 27 | npm run start 28 | ``` 29 | 30 | ## BUILD 31 | 32 | ``` 33 | npm run build 34 | ``` 35 | -------------------------------------------------------------------------------- /configs/jest.json: -------------------------------------------------------------------------------- 1 | { 2 | "rootDir": "..", 3 | "coverageDirectory": "/tests/__coverage__/", 4 | "setupFiles": [ 5 | "/tests/__mocks__/shim.js" 6 | ], 7 | "roots": [ 8 | "/src/", 9 | "/tests/" 10 | ], 11 | "moduleNameMapper": { 12 | "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "/tests/__mocks__/fileMock.js", 13 | "\\.(css|scss|less)$": "/tests/__mocks__/styleMock.js" 14 | }, 15 | "moduleFileExtensions": ["js", "jsx"], 16 | "transformIgnorePatterns": [ 17 | "[/\\\\]node_modules[/\\\\].+\\.(js|jsx)$" 18 | ], 19 | "testRegex": "/tests/.*\\.test\\.(js|jsx)$", 20 | "moduleDirectories": [ 21 | "node_modules" 22 | ], 23 | "globals": { 24 | "DEVELOPMENT": false, 25 | "FAKE_SERVER": false 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /configs/webpack/buildLibrary.js: -------------------------------------------------------------------------------- 1 | // production config 2 | 3 | const merge = require('webpack-merge'); 4 | const {resolve} = require('path'); 5 | const paths = require('./paths'); 6 | const ExtractTextPlugin = require("extract-text-webpack-plugin"); 7 | process.env.NODE_ENV = 'production'; 8 | process.env.BABEL_ENV = 'production'; 9 | 10 | const commonConfig = { 11 | resolve: { 12 | extensions: ['.js', '.jsx'], 13 | }, 14 | context: resolve(__dirname, '../../src'), 15 | module: { 16 | rules: [ 17 | { 18 | test: /\.(js|jsx)$/, 19 | use: ['babel-loader'], 20 | exclude: /node_modules/, 21 | }, 22 | { 23 | test: /\.scss$/, 24 | use: ExtractTextPlugin.extract({ 25 | fallback: 'style-loader', 26 | use: ['css-loader', 'sass-loader'] 27 | }) 28 | }, 29 | // { 30 | // test: /\.css$/, 31 | // use: [ 32 | // 'style-loader', 33 | // {loader: 'css-loader', options: {importLoaders: 1}}, 34 | // 'postcss-loader', 35 | // ], 36 | // }, 37 | // { 38 | // test: /\.scss$/, 39 | // loaders: [ 40 | // 'style-loader', 41 | // {loader: 'css-loader', options: {importLoaders: 1}}, 42 | // 'postcss-loader', 43 | // 'sass-loader', 44 | // ], 45 | // }, 46 | { 47 | test: /\.(jpe?g|png|gif|svg)$/i, 48 | loaders: [ 49 | 'file-loader?hash=sha512&digest=hex&name=images/[hash].[ext]', 50 | 'image-webpack-loader?bypassOnDebug&optipng.optimizationLevel=7&gifsicle.interlaced=false', 51 | ], 52 | }, 53 | ], 54 | }, 55 | externals: { 56 | 'react': 'React', 57 | 'react-dom': 'ReactDOM', 58 | }, 59 | performance: { 60 | hints: false, 61 | }, 62 | }; 63 | 64 | 65 | module.exports = merge(commonConfig, { 66 | entry: { 67 | 'index.js':paths.libraryBuildPath, 68 | 'main.css':paths.appStyleCss 69 | }, 70 | devtool: 'source-map', 71 | output: { 72 | filename: '[name]', 73 | path: resolve(__dirname, '../../npmlibrary'), 74 | publicPath: './', 75 | library: 'react-icx-component', 76 | libraryTarget: 'umd', 77 | umdNamedDefine: true 78 | }, 79 | plugins: [ 80 | new ExtractTextPlugin("style.css") 81 | ], 82 | }); 83 | -------------------------------------------------------------------------------- /configs/webpack/common.js: -------------------------------------------------------------------------------- 1 | // shared config (dev and prod) 2 | const {resolve} = require('path'); 3 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 4 | 5 | module.exports = { 6 | resolve: { 7 | extensions: ['.js', '.jsx'], 8 | }, 9 | context: resolve(__dirname, '../../src'), 10 | module: { 11 | rules: [ 12 | { 13 | test: /\.(js|jsx)$/, 14 | use: ['babel-loader'], 15 | exclude: /node_modules/, 16 | }, 17 | { 18 | test: /\.css$/, 19 | use: [ 20 | 'style-loader', 21 | {loader: 'css-loader', options: {importLoaders: 1}}, 22 | 'postcss-loader', 23 | ], 24 | }, 25 | { 26 | test: /\.scss$/, 27 | loaders: [ 28 | 'style-loader', 29 | {loader: 'css-loader', options: {importLoaders: 1}}, 30 | 'postcss-loader', 31 | 'sass-loader', 32 | ], 33 | }, 34 | { 35 | test: /\.(jpe?g|png|gif|svg)$/i, 36 | loaders: [ 37 | 'file-loader?hash=sha512&digest=hex&name=images/[hash].[ext]', 38 | 'image-webpack-loader?bypassOnDebug&optipng.optimizationLevel=7&gifsicle.interlaced=false', 39 | ], 40 | }, 41 | ], 42 | }, 43 | plugins: [ 44 | new HtmlWebpackPlugin({template: 'index.html.ejs',}), 45 | ], 46 | externals: { 47 | 'react': 'React', 48 | 'react-dom': 'ReactDOM', 49 | }, 50 | performance: { 51 | hints: false, 52 | }, 53 | }; 54 | -------------------------------------------------------------------------------- /configs/webpack/dev.js: -------------------------------------------------------------------------------- 1 | // development config 2 | const merge = require('webpack-merge'); 3 | const webpack = require('webpack'); 4 | const commonConfig = require('./common'); 5 | const LifecyclePlugin = require('webpack-lifecycle-plugin') 6 | const openBrowser = require('react-dev-utils/openBrowser'); 7 | const paths = require('./paths'); 8 | let isFirstBrowserOpen = true; 9 | 10 | process.env.NODE_ENV = 'development'; 11 | process.env.BABEL_ENV = 'development'; 12 | 13 | module.exports = merge(commonConfig, { 14 | entry: [ 15 | // require.resolve('react-dev-utils/webpackHotDevClient'), 16 | // 'react-hot-loader/patch', // activate HMR for React 17 | 'webpack-dev-server/client?http://localhost:8080',// bundle the client for webpack-dev-server and connect to the provided endpoint 18 | 'webpack/hot/only-dev-server', // bundle the client for hot reloading, only- means to only hot reload for successful updates 19 | paths.appIndexJs,// the entry point of our app 20 | paths.appStyleCss 21 | ], 22 | devServer: { 23 | hot: true // enable HMR on the server 24 | }, 25 | devtool: 'cheap-module-eval-source-map', 26 | plugins: [ 27 | new webpack.HotModuleReplacementPlugin(), // enable HMR globally 28 | new webpack.NamedModulesPlugin(), // prints more readable module names in the browser console on HMR updates 29 | new LifecyclePlugin({"done": (compilation, options, pluginOptions) => { 30 | if(isFirstBrowserOpen){ 31 | isFirstBrowserOpen = false 32 | openBrowser('http://localhost:8080'); 33 | } 34 | }}), // webpack lifecyclePlugin 35 | ], 36 | }); 37 | -------------------------------------------------------------------------------- /configs/webpack/paths.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var path = require('path'); 4 | var fs = require('fs'); 5 | var url = require('url'); 6 | 7 | // Make sure any symlinks in the project folder are resolved: 8 | // https://github.com/facebookincubator/create-react-app/issues/637 9 | var appDirectory = fs.realpathSync(process.cwd()); 10 | 11 | function resolveApp(relativePath) { 12 | return path.resolve(appDirectory, relativePath); 13 | } 14 | 15 | // We support resolving modules according to `NODE_PATH`. 16 | // This lets you use absolute paths in imports inside large monorepos: 17 | // https://github.com/facebookincubator/create-react-app/issues/253. 18 | 19 | // It works similar to `NODE_PATH` in Node itself: 20 | // https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders 21 | 22 | // We will export `nodePaths` as an array of absolute paths. 23 | // It will then be used by Webpack configs. 24 | // Jest doesn’t need this because it already handles `NODE_PATH` out of the box. 25 | 26 | // Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored. 27 | // Otherwise, we risk importing Node.js core modules into an app instead of Webpack shims. 28 | // https://github.com/facebookincubator/create-react-app/issues/1023#issuecomment-265344421 29 | 30 | var nodePaths = (process.env.NODE_PATH || '') 31 | .split(process.platform === 'win32' ? ';' : ':') 32 | .filter(Boolean) 33 | .filter(folder => !path.isAbsolute(folder)) 34 | .map(resolveApp); 35 | 36 | var envPublicUrl = process.env.PUBLIC_URL; 37 | 38 | function ensureSlash(path, needsSlash) { 39 | var hasSlash = path.endsWith('/'); 40 | if (hasSlash && !needsSlash) { 41 | return path.substr(path, path.length - 1); 42 | } else if (!hasSlash && needsSlash) { 43 | return path + '/'; 44 | } else { 45 | return path; 46 | } 47 | } 48 | 49 | function getPublicUrl(appPackageJson) { 50 | return envPublicUrl || require(appPackageJson).homepage; 51 | } 52 | 53 | // We use `PUBLIC_URL` environment variable or "homepage" field to infer 54 | // "public path" at which the app is served. 55 | // Webpack needs to know it to put the right 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /express.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const app = express(); 3 | const portNumber = 3000; 4 | const sourceDir = 'dist'; 5 | 6 | app.use(express.static(sourceDir)); 7 | 8 | app.listen(portNumber, () => { 9 | console.log(`Express web server started: http://localhost:${portNumber}`); 10 | console.log(`Serving content from /${sourceDir}/`); 11 | }); 12 | -------------------------------------------------------------------------------- /npmlibrary/images/1e1078af7fdf5d25ecebff1a6548f2b6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sujkh85/react-icx-component/f4371b84767832af6c0e37858b7dffbf0441a710/npmlibrary/images/1e1078af7fdf5d25ecebff1a6548f2b6.png -------------------------------------------------------------------------------- /npmlibrary/main.css: -------------------------------------------------------------------------------- 1 | (function webpackUniversalModuleDefinition(root, factory) { 2 | if(typeof exports === 'object' && typeof module === 'object') 3 | module.exports = factory(); 4 | else if(typeof define === 'function' && define.amd) 5 | define("react-icx-component", [], factory); 6 | else if(typeof exports === 'object') 7 | exports["react-icx-component"] = factory(); 8 | else 9 | root["react-icx-component"] = factory(); 10 | })(typeof self !== 'undefined' ? self : this, function() { 11 | return /******/ (function(modules) { // webpackBootstrap 12 | /******/ // The module cache 13 | /******/ var installedModules = {}; 14 | /******/ 15 | /******/ // The require function 16 | /******/ function __webpack_require__(moduleId) { 17 | /******/ 18 | /******/ // Check if module is in cache 19 | /******/ if(installedModules[moduleId]) { 20 | /******/ return installedModules[moduleId].exports; 21 | /******/ } 22 | /******/ // Create a new module (and put it into the cache) 23 | /******/ var module = installedModules[moduleId] = { 24 | /******/ i: moduleId, 25 | /******/ l: false, 26 | /******/ exports: {} 27 | /******/ }; 28 | /******/ 29 | /******/ // Execute the module function 30 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 31 | /******/ 32 | /******/ // Flag the module as loaded 33 | /******/ module.l = true; 34 | /******/ 35 | /******/ // Return the exports of the module 36 | /******/ return module.exports; 37 | /******/ } 38 | /******/ 39 | /******/ 40 | /******/ // expose the modules object (__webpack_modules__) 41 | /******/ __webpack_require__.m = modules; 42 | /******/ 43 | /******/ // expose the module cache 44 | /******/ __webpack_require__.c = installedModules; 45 | /******/ 46 | /******/ // define getter function for harmony exports 47 | /******/ __webpack_require__.d = function(exports, name, getter) { 48 | /******/ if(!__webpack_require__.o(exports, name)) { 49 | /******/ Object.defineProperty(exports, name, { 50 | /******/ configurable: false, 51 | /******/ enumerable: true, 52 | /******/ get: getter 53 | /******/ }); 54 | /******/ } 55 | /******/ }; 56 | /******/ 57 | /******/ // getDefaultExport function for compatibility with non-harmony modules 58 | /******/ __webpack_require__.n = function(module) { 59 | /******/ var getter = module && module.__esModule ? 60 | /******/ function getDefault() { return module['default']; } : 61 | /******/ function getModuleExports() { return module; }; 62 | /******/ __webpack_require__.d(getter, 'a', getter); 63 | /******/ return getter; 64 | /******/ }; 65 | /******/ 66 | /******/ // Object.prototype.hasOwnProperty.call 67 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 68 | /******/ 69 | /******/ // __webpack_public_path__ 70 | /******/ __webpack_require__.p = "./"; 71 | /******/ 72 | /******/ // Load entry module and return exports 73 | /******/ return __webpack_require__(__webpack_require__.s = 155); 74 | /******/ }) 75 | /************************************************************************/ 76 | /******/ ({ 77 | 78 | /***/ 155: 79 | /***/ (function(module, exports) { 80 | 81 | // removed by extract-text-webpack-plugin 82 | 83 | /***/ }) 84 | 85 | /******/ }); 86 | }); 87 | /*# sourceMappingURL=main.css.map*/ -------------------------------------------------------------------------------- /npmlibrary/main.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["webpack:///webpack/universalModuleDefinition","webpack:///webpack/bootstrap 5680636274370caa4135","webpack:///./assets/scss/index.scss"],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;AACD,O;ACVA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAK;AACL;AACA;;AAEA;AACA;AACA;AACA,mCAA2B,0BAA0B,EAAE;AACvD,yCAAiC,eAAe;AAChD;AACA;AACA;;AAEA;AACA,8DAAsD,+DAA+D;;AAErH;AACA;;AAEA;AACA;;;;;;;;AC7DA,yC","file":"main.css","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"react-icx-component\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"react-icx-component\"] = factory();\n\telse\n\t\troot[\"react-icx-component\"] = factory();\n})(typeof self !== 'undefined' ? self : this, function() {\nreturn \n\n\n// WEBPACK FOOTER //\n// webpack/universalModuleDefinition"," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"./\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 155);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 5680636274370caa4135","// removed by extract-text-webpack-plugin\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./assets/scss/index.scss\n// module id = 155\n// module chunks = 1"],"sourceRoot":""} -------------------------------------------------------------------------------- /npmlibrary/style.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":[],"names":[],"mappings":"","file":"style.css","sourceRoot":""} -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-icx-component", 3 | "version": "0.0.3", 4 | "description": "ICX UI COMPONENT", 5 | "keywords": [ 6 | "react", 7 | "component", 8 | "icx", 9 | "ui" 10 | ], 11 | "main": "./npmlibrary/index.js", 12 | "author": "sujkh85", 13 | "license": "MIT", 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/sujkh85/react-icx-component.git" 17 | }, 18 | "email": "wjdrudghks85@gmail.com", 19 | "scripts": { 20 | "build": "npm run clean-docs && webpack -p --config=configs/webpack/prod", 21 | "library": "npm run clean-npmlibrary && webpack -p --config=configs/webpack/buildLibrary", 22 | "clean-docs": "rm -f -r -d docs", 23 | "clean-npmlibrary": "rm -f -r -d npmlibrary", 24 | "lint": "npm run lint:js && npm run lint:sass", 25 | "lint:js": "jshint", 26 | "lint:sass": "stylelint ./src/**/*.scss", 27 | "start": "cross-env NODE_ENV=development && cross-env BABEL_ENV=development && npm run start-dev", 28 | "start-dev": "webpack-dev-server --config=configs/webpack/dev", 29 | "start-prod": "npm run build && node express.js", 30 | "test": "jest --watch --coverage --config=configs/jest.json" 31 | }, 32 | "devDependencies": { 33 | "babel-cli": "^6.26.0", 34 | "babel-core": "^6.26.0", 35 | "babel-eslint": "^8.2.2", 36 | "babel-jest": "^22.2.0", 37 | "babel-loader": "^7.1.2", 38 | "babel-plugin-module-resolver": "^3.0.0", 39 | "babel-plugin-transform-class-properties": "^6.24.1", 40 | "babel-plugin-transform-es2015-modules-commonjs": "^6.26.0", 41 | "babel-plugin-transform-object-rest-spread": "^6.26.0", 42 | "babel-preset-env": "^1.6.1", 43 | "babel-preset-react": "^6.24.1", 44 | "babel-preset-react-app": "^3.1.1", 45 | "babel-preset-stage-0": "^6.24.1", 46 | "babel-runtime": "^6.26.0", 47 | "cross-env": "^5.1.4", 48 | "css-loader": "^0.28.9", 49 | "eslint": "^4.19.1", 50 | "eslint-config-react-app": "^2.1.0", 51 | "eslint-loader": "^2.0.0", 52 | "eslint-plugin-flowtype": "^2.46.1", 53 | "eslint-plugin-import": "^2.10.0", 54 | "eslint-plugin-jsx-a11y": "^6.0.3", 55 | "eslint-plugin-react": "^7.7.0", 56 | "express": "^4.16.2", 57 | "extract-text-webpack-plugin": "^3.0.2", 58 | "file-loader": "^1.1.6", 59 | "html-webpack-plugin": "^2.30.1", 60 | "identity-obj-proxy": "^3.0.0", 61 | "image-webpack-loader": "^4.0.0", 62 | "install": "^0.11.0", 63 | "jest": "^22.2.1", 64 | "jshint": "^2.9.5", 65 | "node-sass": "^4.7.2", 66 | "npm": "^5.8.0", 67 | "postcss-loader": "^2.1.0", 68 | "react-hot-loader": "^3.1.3", 69 | "sass-loader": "^6.0.6", 70 | "style-loader": "^0.20.1", 71 | "webpack": "^3.10.0", 72 | "webpack-dev-middleware": "^2.0.4", 73 | "webpack-dev-server": "^2.11.1", 74 | "webpack-lifecycle-plugin": "^0.1.4", 75 | "webpack-merge": "^4.1.1" 76 | }, 77 | "dependencies": { 78 | "axios": "^0.18.0", 79 | "babel-polyfill": "^6.26.0", 80 | "chart.js": "^2.7.2", 81 | "classnames": "^2.2.5", 82 | "deepcopy": "^0.6.3", 83 | "file-saver": "^1.3.8", 84 | "history": "^4.7.2", 85 | "moment": "^2.22.0", 86 | "prop-types": "^15.6.1", 87 | "react": "^16.3.0", 88 | "react-addons-test-utils": "^15.6.2", 89 | "react-clipboard.js": "^1.1.3", 90 | "react-dev-utils": "^5.0.0", 91 | "react-dom": "^16.3.0", 92 | "react-redux": "5.0.7", 93 | "react-router": "4.2.0", 94 | "react-router-dom": "4.2.2", 95 | "react-short-notice": "^0.1.5", 96 | "redux": "3.7.2", 97 | "redux-logger": "3.0.6", 98 | "redux-thunk": "2.2.0", 99 | "styled-components": "^3.2.5", 100 | "xlsx": "^0.12.9" 101 | }, 102 | "postcss": {}, 103 | "eslintConfig": { 104 | "extends": "react-app" 105 | }, 106 | "babel": { 107 | "presets": [ 108 | "react-app" 109 | ] 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/App.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Provider} from 'react-redux'; 3 | import axios from 'axios'; 4 | import createHistory from 'history/createBrowserHistory'; 5 | // import createHistory from 'history/createHashHistory'; 6 | import RouterConnection from './library/routerconnection/RouterConnectionForWeb'; 7 | import ConfigStore from './config/ConfigStore'; 8 | import PageContainer from './PageContainer'; 9 | //timezone 10 | import moment from 'moment'; 11 | moment.locale('ko'); 12 | 13 | export const store = ConfigStore() 14 | const history = createHistory(); 15 | 16 | class App extends React.PureComponent { 17 | render() { 18 | return ( 19 | 20 | 25 | 26 | ); 27 | } 28 | } 29 | 30 | export default App; 31 | -------------------------------------------------------------------------------- /src/PageContainer.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import {connect} from 'react-redux'; 3 | import { LayerPopupContainer } from './library/layerpopup'; 4 | import ConfigRouter from './config/ConfigRouter'; 5 | // import WaitContainer from './common/components/waitcircle/WaitContainer'; 6 | // import ProjectLoader from './common/ProjectLoader'; 7 | // import StorageListener from './library/icopstorage/StorageListener' 8 | // import CustomListener from './library/CustomListener'; 9 | //import SpinController from './library/spin/SpinController'; 10 | 11 | class PageContainer extends Component { 12 | constructor(props) { 13 | super(props); 14 | this.reloadTime = ''; 15 | } 16 | 17 | // componentDidUpdate(prevProps, prevState) { 18 | // if (prevProps.location.search !== this.props.location.search) { 19 | // window.scrollTo(0, 0); 20 | // } 21 | // } 22 | 23 | componentDidMount() { 24 | //SpinController.showSpin(); 25 | } 26 | 27 | render() { 28 | console.log('inin?') 29 | return ( 30 |
31 | {/* 32 | */} 33 | 34 | 35 | {/* 36 | */} 37 |
38 | ); 39 | } 40 | } 41 | 42 | const mapDispatchToProps = (dispatch, ownProps) => { 43 | return { 44 | 45 | } 46 | } 47 | 48 | export default connect(null, mapDispatchToProps)(PageContainer); 49 | -------------------------------------------------------------------------------- /src/Preferences.js: -------------------------------------------------------------------------------- 1 | const basePreferences = { 2 | isOnTestData : false, 3 | apiCallTimeout:7000, 4 | isDev:process.env.NODE_ENV === 'development', 5 | } 6 | 7 | const pref = { 8 | local : { 9 | host:'', 10 | ...basePreferences 11 | }, 12 | amazon : { 13 | host:'', 14 | ...basePreferences 15 | }, 16 | } 17 | 18 | //local amazon 19 | window.Preferences = pref.local 20 | export default pref.local 21 | -------------------------------------------------------------------------------- /src/SrcReadme.md: -------------------------------------------------------------------------------- 1 | 2 | #구조 3 | 4 | ## 좌측메뉴에서 사용되는 폴더 5 | ``` 6 | chart 7 | popup 8 | library 9 | util 10 | style 11 | etc 12 | ``` 13 | 14 | 15 | ## ASSETS 16 | 17 | ``` 18 | 프로젝트에 필요한 fonts, img, scss넣는곳 19 | ``` 20 | 21 | ## CHART 22 | 23 | ``` 24 | 차트 컴포넌트 25 | ``` 26 | 27 | ## POPUP 28 | ``` 29 | 팝업 컴포넌트(모달) 30 | ``` 31 | 32 | ## ETC 33 | ``` 34 | 미분류된 컴포넌트 35 | ``` 36 | 37 | ## CONFIG 38 | ``` 39 | 프로젝트 세팅 관련 40 | ``` 41 | ## ERROR 42 | ``` 43 | 라우터 404 에러 표시 페이지 44 | ``` 45 | ## LIBRARY 46 | ``` 47 | 다른 라이브러리 커스텀 48 | ``` 49 | ## MAIN 50 | ``` 51 | 첫 페이지 52 | ``` 53 | 54 | ## STYLE 55 | ``` 56 | 스타일 컴포넌트 57 | ``` 58 | 59 | ## UTIL 60 | ``` 61 | 유틸로 사용할만한 함수 (엑셀 read, write등...) 62 | ``` -------------------------------------------------------------------------------- /src/assets/fonts/GothamBold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sujkh85/react-icx-component/f4371b84767832af6c0e37858b7dffbf0441a710/src/assets/fonts/GothamBold.woff -------------------------------------------------------------------------------- /src/assets/fonts/GothamLight.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sujkh85/react-icx-component/f4371b84767832af6c0e37858b7dffbf0441a710/src/assets/fonts/GothamLight.woff -------------------------------------------------------------------------------- /src/assets/fonts/GothamMedium.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sujkh85/react-icx-component/f4371b84767832af6c0e37858b7dffbf0441a710/src/assets/fonts/GothamMedium.woff -------------------------------------------------------------------------------- /src/assets/fonts/GothamThin.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sujkh85/react-icx-component/f4371b84767832af6c0e37858b7dffbf0441a710/src/assets/fonts/GothamThin.woff -------------------------------------------------------------------------------- /src/assets/fonts/NotoSansBold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sujkh85/react-icx-component/f4371b84767832af6c0e37858b7dffbf0441a710/src/assets/fonts/NotoSansBold.woff -------------------------------------------------------------------------------- /src/assets/fonts/NotoSansLight.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sujkh85/react-icx-component/f4371b84767832af6c0e37858b7dffbf0441a710/src/assets/fonts/NotoSansLight.woff -------------------------------------------------------------------------------- /src/assets/fonts/NotoSansRegular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sujkh85/react-icx-component/f4371b84767832af6c0e37858b7dffbf0441a710/src/assets/fonts/NotoSansRegular.woff -------------------------------------------------------------------------------- /src/assets/fonts/NotoSansThin.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sujkh85/react-icx-component/f4371b84767832af6c0e37858b7dffbf0441a710/src/assets/fonts/NotoSansThin.woff -------------------------------------------------------------------------------- /src/assets/img/boiler.scss: -------------------------------------------------------------------------------- 1 | html, body, div, span, h1, h2, h3, h4, h5, h6, p, em, img, small article, aside, footer, header, nav, address, section, main, time, ol, ul, li, hr, strong, figure, tr, th, td, dl, dt, dd, fieldset { 2 | margin: 0; 3 | padding: 0; 4 | border: 0; 5 | vertical-align: baseline; 6 | -webkit-text-size-adjust: none; 7 | font-style: normal; 8 | } 9 | 10 | ul, ol, li, dl { 11 | list-style: none; 12 | } 13 | 14 | a:link, a:visited, a:hover, a:active { 15 | @include font-main; 16 | color: #727272; 17 | } 18 | 19 | a:focus, 20 | a:active { 21 | //outline: 1px dotted #aaa; //180320 제거 22 | } 23 | 24 | 25 | hr { 26 | display: none; 27 | width: 100%; 28 | height: 1px; 29 | margin: 20px 0 18px; 30 | border-bottom: 2px dashed rgb(214, 116, 149); 31 | } 32 | 33 | button { 34 | @include font-main; 35 | display: block; 36 | margin: 0; 37 | padding: 0; 38 | cursor: pointer; 39 | border: none; 40 | background: none; 41 | 42 | &:focus { 43 | //outline: 1px dotted #aaa; //180309 제거 44 | outline: 0; 45 | } 46 | } 47 | 48 | caption { 49 | display: none; 50 | } 51 | 52 | i { 53 | font-style: normal; 54 | } 55 | 56 | ::-webkit-scrollbar-track{ 57 | background-color: #f7f7f7; 58 | } 59 | 60 | ::-webkit-scrollbar{ 61 | width: 9px; 62 | } 63 | 64 | ::-webkit-scrollbar-thumb{ 65 | background-color: #c7c7c7; 66 | } 67 | 68 | 69 | input { 70 | @include ellipsis; 71 | display: block; 72 | width: 100%; 73 | margin: 0; 74 | padding: 0; 75 | font-size: 15px; 76 | box-sizing: border-box; 77 | vertical-align: top; 78 | border-radius: 0; 79 | -webkit-border-radius: 0px; 80 | -webkit-apprearance: none; 81 | background-color: transparent; 82 | border: 1px solid transparent; 83 | 84 | $placeholder-size: 14px; 85 | $placeholder-color: #acaeb3; 86 | $placeholder-transition: color .3s; 87 | 88 | &::-webkit-input-placeholder { 89 | font-size: $placeholder-size; 90 | color: $placeholder-color; 91 | transition: $placeholder-transition 92 | } 93 | 94 | } 95 | 96 | select { 97 | &:focus { 98 | //outline: 1px dotted #aaa; //180320 제거 99 | } 100 | } 101 | 102 | 103 | html, body { 104 | @include font-main; 105 | position: relative; 106 | width: 100%; 107 | min-width: 100%; 108 | min-height: 100%; 109 | height: 100%; 110 | color: #323232; 111 | font-size: 16px; 112 | font-weight: 400; 113 | line-height: 1.3; 114 | } 115 | 116 | body { 117 | //overflow-y: scroll !important; 118 | overflow-y: scroll; //!! 119 | } -------------------------------------------------------------------------------- /src/assets/img/icon-more.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sujkh85/react-icx-component/f4371b84767832af6c0e37858b7dffbf0441a710/src/assets/img/icon-more.png -------------------------------------------------------------------------------- /src/assets/img/icon-multiple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sujkh85/react-icx-component/f4371b84767832af6c0e37858b7dffbf0441a710/src/assets/img/icon-multiple.png -------------------------------------------------------------------------------- /src/assets/scss/boiler.scss: -------------------------------------------------------------------------------- 1 | html, body, div, span, h1, h2, h3, h4, h5, h6, p, em, img, small article, aside, footer, header, nav, address, section, main, time, ol, ul, li, hr, strong, figure, tr, th, td, dl, dt, dd, fieldset { 2 | margin: 0; 3 | padding: 0; 4 | border: 0; 5 | vertical-align: baseline; 6 | -webkit-text-size-adjust: none; 7 | font-style: normal; 8 | } 9 | 10 | ul, ol, li, dl { 11 | list-style: none; 12 | } 13 | 14 | a:link, a:visited, a:hover, a:active { 15 | @include font-main; 16 | color: #727272; 17 | } 18 | 19 | a:focus, 20 | a:active { 21 | //outline: 1px dotted #aaa; //180320 제거 22 | } 23 | 24 | 25 | hr { 26 | display: none; 27 | width: 100%; 28 | height: 1px; 29 | margin: 20px 0 18px; 30 | border-bottom: 2px dashed rgb(214, 116, 149); 31 | } 32 | 33 | // button { 34 | // @include font-main; 35 | // display: block; 36 | // margin: 0; 37 | // padding: 0; 38 | // cursor: pointer; 39 | // border: none; 40 | // background: none; 41 | 42 | // &:focus { 43 | // //outline: 1px dotted #aaa; //180309 제거 44 | // outline: 0; 45 | // } 46 | // } 47 | 48 | caption { 49 | display: none; 50 | } 51 | 52 | i { 53 | font-style: normal; 54 | } 55 | 56 | ::-webkit-scrollbar-track{ 57 | background-color: #f7f7f7; 58 | } 59 | 60 | ::-webkit-scrollbar{ 61 | width: 9px; 62 | } 63 | 64 | ::-webkit-scrollbar-thumb{ 65 | background-color: #c7c7c7; 66 | } 67 | 68 | 69 | input { 70 | @include ellipsis; 71 | display: block; 72 | width: 100%; 73 | margin: 0; 74 | padding: 0; 75 | font-size: 15px; 76 | box-sizing: border-box; 77 | vertical-align: top; 78 | border-radius: 0; 79 | -webkit-border-radius: 0px; 80 | -webkit-apprearance: none; 81 | background-color: transparent; 82 | border: 1px solid transparent; 83 | 84 | $placeholder-size: 14px; 85 | $placeholder-color: #acaeb3; 86 | $placeholder-transition: color .3s; 87 | 88 | &::-webkit-input-placeholder { 89 | font-size: $placeholder-size; 90 | color: $placeholder-color; 91 | transition: $placeholder-transition 92 | } 93 | 94 | } 95 | 96 | select { 97 | &:focus { 98 | //outline: 1px dotted #aaa; //180320 제거 99 | } 100 | } 101 | 102 | 103 | html, body { 104 | @include font-main; 105 | position: relative; 106 | width: 100%; 107 | min-width: 100%; 108 | min-height: 100%; 109 | height: 100%; 110 | color: #323232; 111 | font-size: 16px; 112 | font-weight: 400; 113 | line-height: 1.3; 114 | } 115 | 116 | body { 117 | //overflow-y: scroll !important; 118 | overflow-y: scroll; //!! 119 | } -------------------------------------------------------------------------------- /src/assets/scss/button.scss: -------------------------------------------------------------------------------- 1 | .button{ 2 | background:#158c99; 3 | color:#fff; 4 | } -------------------------------------------------------------------------------- /src/assets/scss/code.scss: -------------------------------------------------------------------------------- 1 | .icon-code-container{ 2 | width: 100%; 3 | font-size: 14px; 4 | background-color: #f6f8fa; 5 | padding:10px; 6 | margin: 10px 0px; 7 | box-sizing: border-box; 8 | box-shadow: 0 0 30px rgba(149, 149, 149, 0.42); 9 | code{ 10 | .bold{ 11 | font-weight: bold; 12 | } 13 | .red{ 14 | color:#d14; 15 | } 16 | .blue{ 17 | color:#000080; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/assets/scss/etc/iconcountdown.scss: -------------------------------------------------------------------------------- 1 | .countdown { 2 | font-weight: 500; 3 | @include font-sub; 4 | 5 | .countdown-column { 6 | position: relative; 7 | display: inline-block; 8 | margin-left: 13px; 9 | width: 40px; 10 | 11 | &:before { 12 | display: block; 13 | position: absolute; 14 | top: 10px; 15 | left: -9px; 16 | font-family: sans-serif; 17 | color: rgba(255, 255, 255, 0.5); 18 | font-size: 15px; 19 | content: ':'; 20 | } 21 | 22 | &:first-child { 23 | margin-left: 0; 24 | &:before { 25 | display: none; 26 | } 27 | } 28 | } 29 | 30 | .countdown-time { 31 | display: block; 32 | width: 100%; 33 | height: 35px; 34 | text-align: center; 35 | line-height: 35px; 36 | font-size: 16.5px; 37 | color: #00a7bb; 38 | background-color: #fff; 39 | box-shadow: 0px 1px 3px rgba(136, 136, 136, 0.4); 40 | border-radius: 3px; 41 | } 42 | 43 | .countdown-text { 44 | display: block; 45 | margin-top: 8px; 46 | color: #008898; 47 | font-size: 12px; 48 | text-align: center; 49 | } 50 | } -------------------------------------------------------------------------------- /src/assets/scss/etc/iconloading.scss: -------------------------------------------------------------------------------- 1 | //로딩 2 | 3 | //Animation 4 | @keyframes spin { 5 | 0% { 6 | transform: rotate(0); 7 | } 8 | 100% { 9 | transform: rotate(360deg); 10 | } 11 | } 12 | 13 | @keyframes bounce-circle-01 { 14 | 0% { 15 | transform: translate3d(0, 0, 0); 16 | } 17 | 20% { 18 | transform: translate3d(6px, -4px, 0); 19 | } 20 | 35% { 21 | transform: translate3d(0, 0, 0); 22 | } 23 | 60% { 24 | transform: translate3d(6px, -4px, 0); 25 | } 26 | 75% { 27 | transform: translate3d(0, 0, 0); 28 | } 29 | } 30 | 31 | @keyframes bounce-circle-02 { 32 | 0% { 33 | transform: translate3d(0, 0, 0); 34 | } 35 | 20% { 36 | transform: translate3d(-6px, 4px, 0); 37 | } 38 | 35% { 39 | transform: translate3d(0, 0, 0); 40 | } 41 | 60% { 42 | transform: translate3d(-6px, 4px, 0); 43 | } 44 | 75% { 45 | transform: translate3d(0, 0, 0); 46 | } 47 | } 48 | 49 | .icon-loading-dim { 50 | z-index: 500; //불필요시 삭제! 51 | position: fixed; 52 | top: 0; 53 | left: 0; 54 | width: 100%; 55 | height: 100%; 56 | background-color: rgba(207, 207, 207, 0.5); 57 | 58 | } 59 | 60 | .icon-loading-box { 61 | 62 | $loading-size: 300px; 63 | 64 | position: absolute; 65 | top: 50%; 66 | left: 50%; 67 | width: $loading-size; 68 | height: $loading-size; 69 | margin-top: -($loading-size/2); 70 | margin-left: -($loading-size/2); 71 | background-color: #fff; 72 | //border-radius: 50%; 73 | border-radius: 14px; 74 | box-shadow: 0 23px 39px -20px rgba(0,0,0,.43); 75 | } 76 | 77 | .icon-loading-image { 78 | 79 | $icon-size: 54px; 80 | $icon-border-width: 16px; 81 | $icon-circle-size: 19px; 82 | $color-main: #00bfc1; 83 | $color-stick: #fff; 84 | 85 | 86 | position: absolute; 87 | width: 124px; 88 | height: 106px; 89 | top: 60px; 90 | left: 50%; 91 | margin-left: -62px; 92 | 93 | .icon-loading-image-icon { 94 | position: relative; 95 | top: 10px; 96 | left: 20px; 97 | width: $icon-size; 98 | height: $icon-size; 99 | border: $icon-border-width solid $color-main; 100 | border-radius: 50%; 101 | 102 | animation: spin 2s infinite; 103 | 104 | &:before { 105 | position: absolute; 106 | top: -25px; 107 | left: 20px; 108 | width: 12px; 109 | height: ($icon-size*2); 110 | transform: rotate(45deg); 111 | background-color: $color-stick; 112 | content: ''; 113 | } 114 | } 115 | 116 | .icon-loading-image-circle { 117 | width: $icon-circle-size; 118 | height: $icon-circle-size; 119 | background-color: $color-main; 120 | border-radius: 50%; 121 | 122 | &.one { 123 | position: absolute; 124 | top: 4px; 125 | right: 12px; 126 | animation: bounce-circle-01 1.2s infinite; 127 | } 128 | 129 | &.two { 130 | position: absolute; 131 | bottom: 4px; 132 | left: 12px; 133 | animation: bounce-circle-02 1.2s infinite; 134 | 135 | } 136 | 137 | } 138 | 139 | } 140 | 141 | .icon-loading-text { 142 | position: absolute; 143 | bottom: 60px; 144 | left: 50%; 145 | width: 100%; 146 | font-size: 15px; 147 | font-weight: 500; 148 | color: #5e5e5e; 149 | text-align: center; 150 | transform: translateX(-50%); 151 | } 152 | -------------------------------------------------------------------------------- /src/assets/scss/etc/iconmorebutton.scss: -------------------------------------------------------------------------------- 1 | .icon-more-button-container{ 2 | position: relative; 3 | padding: 30px 20px 15px; 4 | background-color: #fff; 5 | border-top-left-radius: 6px; 6 | border-top-right-radius: 6px; 7 | } 8 | 9 | .icon-contract-more { 10 | position: absolute; 11 | top: 20px; 12 | left: 0; 13 | width: 100%; 14 | height: 100%; 15 | .icon-contract-more-btn { //추가 기능 버튼 16 | opacity: .7; 17 | position: absolute; 18 | top: 0; 19 | right: 15px; 20 | width: 16px; 21 | height: 20px; 22 | background-image: url(#{$path-image}icon-more.png); 23 | background-size: 4px 18px; 24 | background-position: 50%; 25 | background-repeat: no-repeat; 26 | cursor: pointer; 27 | 28 | &:hover { 29 | opacity: 1; 30 | } 31 | 32 | &.on + .icon-contract-more-list { 33 | display: block; 34 | } 35 | } 36 | 37 | .icon-contract-more-list { //추가 기능 리스트 38 | display: none; 39 | z-index: 1; 40 | position: absolute; 41 | top: 28px; 42 | right: 11px; 43 | width: 194px; 44 | background-color: #f6f6f6; 45 | border: 1px solid #cac9c9; 46 | box-shadow: 0 3px 8px rgba(126, 126, 126, 0.5); 47 | 48 | li { 49 | font-size: 14px; 50 | padding: 9px 12px 9px 10px; 51 | box-sizing: border-box; 52 | //text-align: right; 53 | cursor: pointer; 54 | border-top: 1px solid #ddd; 55 | background-size: 20px 20px; 56 | background-repeat: no-repeat; 57 | background-position: 10px 8px; 58 | 59 | &:first-child { 60 | border-top: 0; 61 | } 62 | 63 | &:hover { 64 | background-color: #e7e7e7; 65 | } 66 | 67 | // &.more-balance { 68 | // background-image: url(#{$path-image}icon-withdraw-1.png); 69 | // } 70 | 71 | // &.more-remained { 72 | // background-image: url(#{$path-image}icon-withdraw-2.png); 73 | // } 74 | 75 | // &.more-airdrop { 76 | // background-size: 20px 18px; 77 | // background-image: url(#{$path-image}icon-airdrop.png); 78 | // } 79 | } 80 | 81 | // &:before { 82 | // content: ''; 83 | // width: 0; 84 | // height: 0; 85 | // position: absolute; 86 | // left: 50%; 87 | // top: -11px; 88 | // margin-left: -4px; 89 | // border-left: 9px solid transparent; 90 | // border-right: 9px solid transparent; 91 | // border-bottom: 10px solid #777; 92 | // } 93 | 94 | // &:after { 95 | // content: ''; 96 | // width: 0; 97 | // height: 0; 98 | // position: absolute; 99 | // left: 50%; 100 | // top: -10px; 101 | // margin-left: -5px; 102 | // border-left: 10px solid transparent; 103 | // border-right: 10px solid transparent; 104 | // border-bottom: 11px solid #fff; 105 | // } 106 | } 107 | } 108 | 109 | -------------------------------------------------------------------------------- /src/assets/scss/etc/iconshortnotice.scss: -------------------------------------------------------------------------------- 1 | .short-notice { 2 | display: block; 3 | font-style: normal; 4 | font-size: 11px; 5 | color: #2dbdd3; 6 | } 7 | -------------------------------------------------------------------------------- /src/assets/scss/etc/iconstep.scss: -------------------------------------------------------------------------------- 1 | 2 | .icon-step { 3 | 4 | 5 | .icon-step-description { 6 | margin-top: 18px; 7 | text-align: center; 8 | font-size: 15px; 9 | letter-spacing: -0.025rem; 10 | } 11 | 12 | } 13 | 14 | .icon-step-container { 15 | display: -webkit-flex; 16 | display: flex; 17 | justify-content: center; 18 | } 19 | 20 | .icon-step-list { 21 | display: inline-block; 22 | position: relative; 23 | //width: auto; 24 | width: 116px; 25 | padding: 0 10px; 26 | text-align: center; 27 | 28 | &:before { //요소의 선 (왼쪽) 29 | display: block; 30 | position: absolute; 31 | bottom: 8px; 32 | left: 0; 33 | width: 50%; 34 | height: 2px; 35 | background-color: #ebe8e4; 36 | content: ''; 37 | } 38 | 39 | &:after { //요소의 선 (오른쪽) 40 | display: block; 41 | position: absolute; 42 | bottom: 8px; 43 | left: 100%; 44 | width: 50%; 45 | height: 2px; 46 | margin-left: -50%; 47 | background-color: #ebe8e4; 48 | content: ''; 49 | } 50 | 51 | &:first-child { 52 | padding-left: 0; 53 | } 54 | 55 | &:last-child { 56 | padding-right: 0; 57 | 58 | .icon-step-title { 59 | margin-left: -2px; 60 | } 61 | } 62 | 63 | &:first-child:before { //첫번째 단계의 왼쪽 선 숨기기 64 | display: none; 65 | } 66 | 67 | &:last-child:after { //마지막 단계의 오른쪽 선 숨기기 68 | display: none; 69 | } 70 | 71 | &.on { 72 | 73 | &:before { //활성화된 단계의 왼쪽 선 색을 바꿈 74 | background-color: $color-main; 75 | } 76 | 77 | .icon-step-title { //활성화된 단계의 타이틀을 강조 78 | color: $color-main; 79 | } 80 | 81 | .icon-step-circle { //활성화 된 딘계를 크게 함 82 | background-color: $color-main; 83 | box-shadow: 0 3px 10px $color-main-shadow; 84 | transform: scale(1.35); 85 | 86 | &:after { 87 | width: 40%; 88 | height: 40%; 89 | } 90 | } 91 | } 92 | 93 | &.done { //이미 완료한 단계의 선 및 원 색을 바꿈 94 | &:before { 95 | background-color: $color-main; 96 | } 97 | &:after { 98 | background-color: $color-main; 99 | } 100 | .icon-step-circle { 101 | background-color: $color-main; 102 | } 103 | } 104 | 105 | .icon-step-title { 106 | position: relative; 107 | width: 100%; 108 | margin-bottom: 6px; 109 | font-size: 11px; 110 | color: #808487; 111 | 112 | } 113 | 114 | .icon-step-circle { 115 | z-index: 1; 116 | position: relative; 117 | left: 50%; 118 | width: 16px; 119 | height: 16px; 120 | margin-left: -10px; 121 | background-color: #ebe8e4; 122 | border-radius: 50%; 123 | 124 | &:after { 125 | display: block; 126 | position: absolute; 127 | top: 50%; 128 | left: 50%; 129 | width: 45%; 130 | height: 45%; 131 | transform: translateX(-50%) translateY(-50%); 132 | background-color: #fff; 133 | content: ''; 134 | border-radius: 50%; 135 | } 136 | } 137 | 138 | } -------------------------------------------------------------------------------- /src/assets/scss/etc/icontab.scss: -------------------------------------------------------------------------------- 1 | .icon-contract-category { 2 | display: block; 3 | margin-top: 30px; 4 | margin-left: 30px; 5 | margin-bottom: 20px; 6 | width: calc(100% - 60px); 7 | font-size: 20px; 8 | @include font-sub; 9 | border-bottom: 2px solid #323232; 10 | box-sizing: border-box; 11 | 12 | .icon-contract-tab { 13 | position: relative; 14 | display: inline-block; 15 | width: 190px; 16 | color: #4c4c4c; 17 | vertical-align: middle; 18 | padding: 13px 0; 19 | text-align: center; 20 | cursor: pointer; 21 | overflow: hidden; 22 | 23 | &:hover { 24 | font-weight: 600; 25 | } 26 | 27 | .isAfter { 28 | opacity: 0; 29 | display: block; 30 | height: 4px; 31 | color: #262626; 32 | background-color: #323232; 33 | margin: 4px auto; 34 | position: absolute; 35 | width: 100%; 36 | left: 0; 37 | bottom: -5px; 38 | transform: translateY(5px); 39 | content: ''; 40 | transition: all .2s; 41 | } 42 | } 43 | .icon-contract-tab.on { 44 | font-weight: 600; 45 | 46 | .isAfter { 47 | opacity: 1; 48 | transform: translateY(0px); 49 | transition: all .2s; 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /src/assets/scss/etc/index.scss: -------------------------------------------------------------------------------- 1 | @import './iconstep.scss'; 2 | @import './iconloading.scss'; 3 | @import './iconshortnotice.scss'; 4 | @import './iconcountdown.scss'; 5 | @import './icontab.scss'; 6 | @import './iconmorebutton.scss'; -------------------------------------------------------------------------------- /src/assets/scss/index.scss: -------------------------------------------------------------------------------- 1 | @import './variable.scss'; 2 | @import './boiler.scss'; 3 | @import './common.scss'; 4 | @import './popup.scss'; 5 | @import './intro.scss'; 6 | @import './etc/index.scss'; 7 | @import './code.scss'; 8 | @import './button.scss'; -------------------------------------------------------------------------------- /src/assets/scss/intro.scss: -------------------------------------------------------------------------------- 1 | 2 | .intro-icx-header{ 3 | margin:0px auto; 4 | text-align: center; 5 | position: fixed; 6 | top: 0px; 7 | width: 100%; 8 | height: 50px; 9 | } 10 | 11 | .intro-icx-body-container{ 12 | padding: 50px 0 50px 0; 13 | margin:0px auto 0px; 14 | text-align: center; 15 | width: 100%; 16 | height: calc(100% - 100px); 17 | } 18 | 19 | .intro-icx-footer{ 20 | margin:32px auto 0px; 21 | position: fixed; 22 | bottom: 0px; 23 | text-align: center; 24 | } -------------------------------------------------------------------------------- /src/assets/scss/variable.scss: -------------------------------------------------------------------------------- 1 | // PATH 2 | $path-image: '../img/'; 3 | $path-font: '../fonts/'; 4 | 5 | // COLOR 6 | $color-main: #00bfc1; 7 | $color-main-shadow: rgba(26, 165, 167, 0.37); 8 | $color-tooltip: rgba(57, 57, 57, 0.66); 9 | $color-login-bg: #f6fbff; 10 | 11 | ////////////////// 12 | /// MIXIN TIME /// 13 | ////////////////// 14 | 15 | @mixin font-main { 16 | font-family: 'Noto Sans', AppleGothic, sans-serif, Helvetica; 17 | } 18 | 19 | @mixin font-sub { 20 | font-family: 'Gotham', 'Noto Sans', AppleGothic, sans-serif, Helvetica; 21 | } 22 | 23 | @mixin ellipsis ($lines: 1) { 24 | @if ($lines == 1) { 25 | overflow: hidden; 26 | text-overflow: ellipsis; 27 | white-space: nowrap; 28 | } @else { 29 | display: -webkit-box; 30 | overflow: hidden; 31 | text-overflow: ellipsis; 32 | -webkit-line-clamp: $lines; 33 | -webkit-box-orient: vertical; 34 | } 35 | } -------------------------------------------------------------------------------- /src/buildIndex.js: -------------------------------------------------------------------------------- 1 | //etc 2 | import IconStep from './etc/iconstep/iconStep'; 3 | import {ShortNoticeController} from 'react-short-notice'; 4 | import IconShortNotice from './etc/iconshortnotice/IconShortNotice' 5 | import IconCountDown from './etc/iconcountdown/IconCountDown'; 6 | import IconCountDownController from './etc/iconcountdown/IconCountDownController'; 7 | import IconLoading from './etc/iconloading/IconLoading'; 8 | //style 9 | import { FlatButton, FloatButton } from './buttons'; 10 | import Divider from './style/components/Divider' 11 | export { 12 | IconStep, 13 | IconCountDown, 14 | IconCountDownController, 15 | IconShortNotice, 16 | ShortNoticeController, 17 | IconLoading, 18 | Divider, 19 | FlatButton, 20 | FloatButton, 21 | } -------------------------------------------------------------------------------- /src/buttons/ButtonContainer.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { ShortNoticeContainer, ShortNoticeController } from 'react-short-notice'; 3 | // import IconLoading from './IconLoading'; 4 | import MainTemplete from '../common/layout/MainTemplete'; 5 | import DescriptionTemplete from '../common/layout/DescriptionTemplete' 6 | import ComponentTemplete from '../common/layout/ComponentTemplete'; 7 | import Code from '../common/Code'; 8 | import PropertyTable from '../common/PropertyTable'; 9 | import FlatButton from './components/FlatButton' 10 | import FloatButton from './components/FloatButton' 11 | import {Divider} from '../style/components' 12 | import IconLoading from '../etc/iconloading/IconLoading'; 13 | 14 | class ButtonContainer extends Component { 15 | importFromList = [ 16 | { React: 'react' }, 17 | { '{FlatButton}': 'react-icx-component' } 18 | ] 19 | importFromList2 = [ 20 | { React: 'react' }, 21 | { '{FloatButton}': 'react-icx-component' } 22 | ] 23 | 24 | libraryObject = { 25 | name: 'FlatButton', 26 | param: [ 27 | { bsStyle: '"primary"' }, 28 | { label: '"라벨"' } 29 | ], 30 | } 31 | libraryObject2 = { 32 | name: 'FloatButton', 33 | param: [ 34 | { bsStyle: '"primary"' }, 35 | { label: '"라벨"' } 36 | ], 37 | } 38 | 39 | propertyTableList = [ 40 | { 41 | name: 'icxStyle', 42 | type: 'one of "primary","secondary","disabled"', 43 | require: false, 44 | default: '"default"', 45 | description: '보여줄지 말지 결정하는 속성' }, 46 | { 47 | name: 'label', 48 | type: 'string', 49 | require: false, 50 | default: '"버튼 텍스트"', 51 | description: '라벨' 52 | }, 53 | { 54 | name: 'disabled', 55 | type: 'bool', 56 | require: false, 57 | default: '"false"', 58 | description: '비활성' 59 | }, 60 | { 61 | name: 'onClick', 62 | type: 'function', 63 | require: true, 64 | default: '', 65 | description: 'onClick 이벤트' 66 | }, 67 | ] 68 | 69 | onClickBtn = () => { 70 | ShortNoticeController.show('iconLoading') 71 | } 72 | 73 | render() { 74 | return ( 75 | 76 | 77 | 간단한 ui 플랫 버튼입니다. 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 플로팅 버튼 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | ); 111 | } 112 | } 113 | 114 | export default ButtonContainer; -------------------------------------------------------------------------------- /src/buttons/ButtonRouter.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import PageNotFound from '../error/PageNotFound'; 3 | import { QuerySwitch, QueryRoute } from '../library/queryrouter/'; 4 | import ButtonContainer from './ButtonContainer' 5 | 6 | class ButtonRouter extends Component { 7 | render() { 8 | return ( 9 | 10 | 11 | 12 | 13 | 14 | ); 15 | } 16 | } 17 | 18 | export default ButtonRouter; -------------------------------------------------------------------------------- /src/buttons/components/FlatButton.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { FlatStyle } from '../../style/components' 4 | 5 | class FlatButton extends Component { 6 | 7 | onClickButton = (e) => { 8 | const { onClick } = this.props 9 | if(onClick){ 10 | onClick(e) 11 | } 12 | } 13 | 14 | render() { 15 | const { label, icxStyle, disabled } = this.props 16 | return ( 17 | 18 | {label} 19 | 20 | ); 21 | } 22 | } 23 | 24 | FlatButton.propTypes = { 25 | icxStyle: PropTypes.oneOf(['default', 'primary', 'secondary', 'disabled']), 26 | onClick: PropTypes.func, 27 | disabled: PropTypes.bool 28 | } 29 | 30 | FlatButton.defaultProps = { 31 | icxStyle: 'default', 32 | label: '버튼 텍스트', 33 | disabled: false 34 | } 35 | 36 | export default FlatButton; -------------------------------------------------------------------------------- /src/buttons/components/FloatButton.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import styled from 'styled-components' 4 | import { FloatStyle } from '../../style/components'; 5 | 6 | // const FloatStyle = styled(Button) ` 7 | // background: mediumblue; 8 | // color: white; 9 | // &:hover { 10 | // background-color: rgba(255,255,255,1); 11 | // } 12 | // ` 13 | const FloatWrap = styled.div ` 14 | color: rgba(0, 0, 0, 0.87); 15 | background-color: rgb(255, 255, 255); 16 | transition: all 450ms cubic-bezier(0.23, 1, 0.32, 1) 0ms; 17 | box-sizing: border-box; 18 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 19 | box-shadow: rgba(0, 0, 0, 0.12) 0px 1px 6px, rgba(0, 0, 0, 0.12) 0px 1px 4px; 20 | border-radius: 2px; 21 | display: inline-block; 22 | min-width: 88px; 23 | margin: 12px; 24 | 25 | & .inner { 26 | height: 36px; 27 | border-radius: 2px; 28 | transition: all 450ms cubic-bezier(0.23, 1, 0.32, 1) 0ms; 29 | top: 0px; 30 | 31 | 32 | &:hover { 33 | background-color: rgba(255,255,255,.4) 34 | } 35 | } 36 | ` 37 | 38 | class FloatButton extends Component { 39 | 40 | onClickButton = (e) => { 41 | const {onClick} = this.props 42 | console.log(e.target) 43 | if(onClick){ 44 | onClick(e) 45 | } 46 | } 47 | 48 | render() { 49 | const { label, icxStyle, disabled, target, } = this.props 50 | 51 | return ( 52 | 53 | 54 |
55 |
56 | {label} 57 |
58 |
59 |
60 |
61 | ); 62 | } 63 | } 64 | 65 | FloatButton.propTypes = { 66 | icxStyle: PropTypes.oneOf(['default', 'primary', 'secondary', 'disabled']), 67 | label: PropTypes.string, 68 | disabled: PropTypes.bool 69 | } 70 | 71 | FloatButton.defaultProps = { 72 | icxStyle: 'default', 73 | label: '버튼 텍스트', 74 | disabled: false 75 | } 76 | 77 | export default FloatButton; -------------------------------------------------------------------------------- /src/buttons/index.js: -------------------------------------------------------------------------------- 1 | import FlatButton from './components/FlatButton' 2 | import FloatButton from './components/FloatButton' 3 | 4 | export {FlatButton, FloatButton} -------------------------------------------------------------------------------- /src/chart/ChartContainer.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ChartRouter from './ChartRouter'; 3 | 4 | const ChartContainer = (props) => { 5 | return ( 6 |
7 | 8 |
9 | ); 10 | }; 11 | 12 | export default ChartContainer 13 | -------------------------------------------------------------------------------- /src/chart/ChartRouter.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import PageNotFound from '../error/PageNotFound'; 3 | import {QuerySwitch, QueryRoute} from '../library/queryrouter/'; 4 | 5 | import IconDonutChartContainer from './icondonutchart/IconDonutChartContainer'; 6 | 7 | class EtcRouter extends Component { 8 | render() { 9 | return ( 10 | 11 | 12 | 13 | 14 | 15 | 16 | ); 17 | } 18 | } 19 | 20 | export default EtcRouter; -------------------------------------------------------------------------------- /src/chart/chart.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sujkh85/react-icx-component/f4371b84767832af6c0e37858b7dffbf0441a710/src/chart/chart.md -------------------------------------------------------------------------------- /src/chart/icondonutchart/IconDonutChart.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import chartjs from 'chart.js'; 3 | 4 | class IconDonutChart extends Component { 5 | options={ 6 | //레이아웃 7 | layout: { 8 | padding: { 9 | left: 0, 10 | right: 50, 11 | top: 0, 12 | bottom: 0 13 | } 14 | }, 15 | //타이틀 16 | title:{ 17 | display:false, 18 | position:'top', 19 | fontSize:20, 20 | fontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif", 21 | fontColor:'#666', 22 | fontStyle:'bold', 23 | text:'chart!!!' 24 | }, 25 | //튤팁 26 | tooltips:{ 27 | enabled:false 28 | }, 29 | //라벨 30 | legend:{ 31 | display:false, 32 | position:'right', 33 | labels:{ 34 | //라벨컬러 35 | fontColor:'rgb(255, 99, 132)', 36 | }, 37 | }, 38 | //호버 이벤트 발생하여 재랜더링 방지코드 39 | hover:{ 40 | mode:null 41 | }, 42 | events:[], 43 | animation: { 44 | duration: 0 45 | }, 46 | percentageInnerCutout : 10 47 | } 48 | 49 | getBackgroundColor=()=>{ 50 | let {dataList, index, chartColor=['#00bfc1','#e0e0e0']} = this.props; 51 | let backgroundColorList = []; 52 | 53 | dataList.forEach((item, idx)=>{ 54 | if(index === idx){ 55 | backgroundColorList.push(chartColor[0]) 56 | } else { 57 | backgroundColorList.push(chartColor[1]) 58 | } 59 | }) 60 | return backgroundColorList; 61 | } 62 | 63 | getData=()=>{ 64 | let {dataList} = this.props 65 | let data = { 66 | datasets: [{ 67 | data: dataList, 68 | backgroundColor: this.getBackgroundColor(), 69 | borderWidth:0 70 | }] 71 | }; 72 | 73 | return data; 74 | } 75 | 76 | drawScore=(centerText)=>{ 77 | let {centerFontSize='13px'} = this.props; 78 | let ctx = this.chartController.ctx; 79 | ctx.fillStyle = '#000000'; 80 | ctx.textAlign = 'center'; 81 | ctx.textBaseline = 'middle'; 82 | ctx.font = `${centerFontSize} Arial`; 83 | ctx.fillText(centerText, this.chartController.chart.width/3, this.chartController.chart.height/2); 84 | } 85 | 86 | componentWillReceiveProps(nextProps) { 87 | const {centerText , dataList} = this.props 88 | if(centerText !== nextProps.centerText || dataList !== nextProps.dataList){ 89 | this.chartController.chart.config.data.datasets[0].data = nextProps.dataList; 90 | this.chartController.update() 91 | this.drawScore(nextProps.centerText ? nextProps.centerText : 0); 92 | } 93 | } 94 | 95 | 96 | componentDidMount() { 97 | const {centerText} = this.props 98 | let ctx = this.canvas.getContext('2d'); 99 | this.chartController = new chartjs(ctx,{ 100 | type: 'doughnut', 101 | data: this.getData(), 102 | options: this.options 103 | }); 104 | 105 | setTimeout(() => { 106 | this.drawScore(centerText?centerText:0); 107 | }, 1000); 108 | setTimeout(() => { 109 | this.drawScore(centerText?centerText:0); 110 | }, 2000); 111 | setTimeout(() => { 112 | this.drawScore(centerText?centerText:0); 113 | }, 3000); 114 | } 115 | 116 | render() { 117 | const {width=300, height=300} = this.props; 118 | return ( 119 |
120 | {this.canvas = canvas}}> 121 |
122 | ); 123 | } 124 | } 125 | 126 | export default IconDonutChart; -------------------------------------------------------------------------------- /src/chart/icondonutchart/IconDonutChartContainer.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import MainTemplete from '../../common/layout/MainTemplete'; 3 | import DescriptionTemplete from '../../common/layout/DescriptionTemplete' 4 | import ComponentTemplete from '../../common/layout/ComponentTemplete'; 5 | import Code from '../../common/Code'; 6 | import PropertyTable from '../../common/PropertyTable'; 7 | import IconDonutChart from './IconDonutChart'; 8 | 9 | class IconLoadingContainer extends Component { 10 | importFromList=[ 11 | {React:'react'}, 12 | {'{IconDonutChart}':'react-icx-component'} 13 | ] 14 | 15 | propertyTableList=[ 16 | {name:'dataList', type:'array', require:true, default:'', description:'[40,60]같은 퍼센트 배열'}, 17 | {name:'index', type:'number', require:true, default:'', description:'dataList의 타겟 index'}, 18 | {name:'width', type:'number', require:false, default:'300', description:'chart width'}, 19 | {name:'height', type:'number', require:false, default:'300', description:'chart height'}, 20 | {name:'centerFontSize', type:'string', require:false, default:'13px', description:'font size'}, 21 | {name:'chartColor', type:'array', require:false, default:"['#00bfc1','#e0e0e0']", description:'[타겟 index의 색상, 그외 색상] '}, 22 | ] 23 | 24 | render() { 25 | return ( 26 | 27 | 28 | Chart.js에 도넛 차트 29 | 30 | 31 | {""}

32 | {" "}
33 |
34 | 35 | 36 | chart.js의 donutChart를 사용하여 구현하였습니다.
37 | 38 |
39 | 40 | 41 |
42 | 43 | 44 |
45 |
46 | 47 | 48 |
49 | ); 50 | } 51 | } 52 | 53 | export default IconLoadingContainer; -------------------------------------------------------------------------------- /src/common/Code.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import styled from 'styled-components' 3 | // import Clipboard from 'react-clipboard.js'; 4 | 5 | class Code extends Component { 6 | getImportRenderer=()=>{ 7 | let importRender= []; 8 | const {importFromList} = this.props 9 | if(importFromList){ 10 | importFromList.forEach((item, index)=>{ 11 | let key = Object.keys(item)[0] 12 | let value = item[key] 13 | importRender.push( 14 |
15 | import {key} from '{value}'; 16 |
17 | ) 18 | }) 19 | return importRender; 20 | } 21 | else{ 22 | return null 23 | } 24 | } 25 | 26 | getLibraryObjectRenderer=()=>{ 27 | const {libraryObject} = this.props 28 | console.log('libraryObject', libraryObject) 29 | if(libraryObject){ 30 | return( 31 |
32 | {'<'}{libraryObject.name}
33 | {libraryObject.param.map((item)=>{ 34 | let key = Object.keys(item)[0] 35 | let value = item[key] 36 | return( 37 |
38 |   {key}= 39 | {value} 40 |
41 | ) 42 | })} 43 | {'/>'} 44 |
45 | ) 46 | } 47 | else{ 48 | return null 49 | } 50 | } 51 | 52 | getCodeChildrunRenderer=()=>{ 53 | let {children} = this.props; 54 | let childrenResultList = [] 55 | if(Array.isArray(children) === true){ 56 | children.forEach((child, index)=>{ 57 | if(typeof child === 'string'){ 58 | if(child.startsWith('<') === true){ 59 | let splitArr = child.split(' ') 60 | splitArr.forEach((item)=>{ 61 | let itemIndex = item.indexOf('='); 62 | if(itemIndex === -1){ 63 | childrenResultList.push({item+' '}) 64 | } 65 | else{ 66 | let itemSubstring1 = item.substring(0, itemIndex+1) 67 | let itemSubstring2 = item.substring(itemIndex+1, itemIndex+2) 68 | let itemSubstring3 = item.substring(itemIndex+2, item.length) 69 | 70 | childrenResultList.push({itemSubstring1}) 71 | childrenResultList.push({itemSubstring2}) 72 | 73 | if(itemSubstring2 === '"'){ 74 | let idx = itemSubstring3.indexOf('"') 75 | let itemSubstring3Sub1 = itemSubstring3.substring(0, idx+1) 76 | let itemSubstring3Sub2 = itemSubstring3.substring(idx+1, itemSubstring3.length) 77 | childrenResultList.push({itemSubstring3Sub1}) 78 | childrenResultList.push({itemSubstring3Sub2+ ' '}) 79 | } 80 | else if(itemSubstring2 === '{'){ 81 | let idx = itemSubstring3.lastIndexOf('}') 82 | let itemSubstring3Sub1 = itemSubstring3.substring(0, idx+1) 83 | let itemSubstring3Sub2 = itemSubstring3.substring(idx+1, itemSubstring3.length) 84 | childrenResultList.push({itemSubstring3Sub1}) 85 | childrenResultList.push({itemSubstring3Sub2+ ' '}) 86 | } 87 | } 88 | }) 89 | } 90 | else if(child.startsWith('//') === true){ 91 | childrenResultList.push(child) 92 | } 93 | else { 94 | childrenResultList.push(child) 95 | } 96 | } 97 | else { 98 | childrenResultList.push(child) 99 | } 100 | }) 101 | } 102 | else { 103 | childrenResultList.push(children) 104 | } 105 | return childrenResultList; 106 | } 107 | 108 | 109 | render() { 110 | let childrenResultList = this.getCodeChildrunRenderer(); 111 | const IconCodeContainer = styled.div` 112 | width: 100%; 113 | font-size: 14px; 114 | background-color: #f6f8fa; 115 | padding: 10px; 116 | margin: 10px 0px; 117 | box-sizing: border-box; 118 | ` 119 | return ( 120 | 121 | 122 | {this.getImportRenderer()}
123 | {this.getLibraryObjectRenderer()} 124 |
125 | {/* {this.props.children} */} 126 | {/* {this.props.children}

*/} 127 | {childrenResultList} 128 |
129 |
130 | ); 131 | } 132 | } 133 | 134 | export default Code; -------------------------------------------------------------------------------- /src/common/IconClipBoard.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import Clipboard from 'react-clipboard.js'; 3 | 4 | class IconClipBoard extends Component { 5 | onSuccess=(e)=>{ 6 | if(this.props.onSuccess){ 7 | this.props.onSuccess(e) 8 | } 9 | } 10 | 11 | getText=()=>{ 12 | const {text="empty copy"} = this.props 13 | return text; 14 | } 15 | 16 | render() { 17 | const {className="button-in-input button-style-copy"} = this.props 18 | return ( 19 | 20 | copy to clipboard 21 | 22 | ); 23 | } 24 | } 25 | 26 | export default IconClipBoard; -------------------------------------------------------------------------------- /src/common/PropertyTable.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | class PropertyTable extends Component { 4 | render() { 5 | const {propertyTableList=[]}= this.props 6 | if(propertyTableList.length === 0){ 7 | return null 8 | } 9 | return ( 10 |
11 |
12 | Properties 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | {propertyTableList.map((item)=>{ 33 | return( 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | ) 42 | })} 43 | 44 |
NameTypeRequireDefaultDescription
{item.name}{item.type}{item.require?'O':'X'}{item.default}{item.description}
45 |
46 | ); 47 | } 48 | } 49 | 50 | export default PropertyTable; -------------------------------------------------------------------------------- /src/common/layout/ComponentTemplete.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import styled from 'styled-components' 3 | 4 | const IconComponentContainer = styled.div` 5 | box-shadow: rgba(0, 0, 0, 0.12) 0px 1px 6px, rgba(0, 0, 0, 0.12) 0px 1px 4px; 6 | border-radius: 2px; 7 | margin-bottom: 32px; 8 | 9 | ` 10 | const Header = styled.div` 11 | height: 56px; 12 | padding: 0 15px; 13 | background-color: #eee; 14 | & h2 { 15 | font-size: 20px; 16 | line-height: 56px; 17 | } 18 | ` 19 | const Content = styled.div` 20 | padding: 24px; 21 | ` 22 | 23 | class ComponentTemplete extends Component { 24 | render() { 25 | return ( 26 | 27 |
28 |

Sample examples

29 |
30 | 31 | {this.props.children} 32 | 33 |
34 | ); 35 | } 36 | } 37 | 38 | export default ComponentTemplete; -------------------------------------------------------------------------------- /src/common/layout/DescriptionTemplete.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import styled from 'styled-components' 3 | 4 | const IconDescriptionContainer = styled.div` 5 | margin-top: 20px; 6 | margin-bottom: 20px; 7 | padding: 0px 10px; 8 | ` 9 | const Header = styled.div` 10 | padding: 0 15px; 11 | & h2 { 12 | font-size: 20px; 13 | margin-bottom: 10px; 14 | } 15 | ` 16 | const Content = styled.div` 17 | padding: 14px 24px; 18 | ` 19 | 20 | class DescriptionTemplete extends Component { 21 | render() { 22 | const { title, children } = this.props 23 | console.log(this.props) 24 | return ( 25 | 26 |
27 |

{title}

28 |
29 | 30 |

{children}

31 |
32 |
33 | ); 34 | } 35 | } 36 | 37 | export default DescriptionTemplete; -------------------------------------------------------------------------------- /src/common/layout/MainFooter.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default ()=>{ 4 | return( 5 |
6 |
7 |
8 |

© 2018 ICON Foundation

9 |
10 | 11 | 12 |
13 |
14 |
15 |
16 | ) 17 | } -------------------------------------------------------------------------------- /src/common/layout/MainHeader.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components' 3 | 4 | const Header = styled.div` 5 | color: rgba(0, 0, 0, 0.87); 6 | background-color: rgb(0, 188, 212); 7 | transition: all 450ms cubic-bezier(0.23, 1, 0.32, 1) 0ms; 8 | box-sizing: border-box; 9 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 10 | border-radius: 0px; 11 | position: fixed; 12 | z-index: 1101; 13 | width: 100%; 14 | display: flex; 15 | padding-left: 24px; 16 | padding-right: 24px; 17 | ` 18 | 19 | const H1 = styled.h1` 20 | white-space: nowrap; 21 | overflow: hidden; 22 | text-overflow: ellipsis; 23 | margin: 0px; 24 | padding-top: 0px; 25 | letter-spacing: 0px; 26 | font-size: 24px; 27 | font-weight: 400; 28 | color: rgb(255, 255, 255); 29 | height: 64px; 30 | line-height: 64px; 31 | flex: 1 1 0%; 32 | ` 33 | export default ()=>{ 34 | return( 35 |
36 |

REACT-ICX-COMPONENT

37 |
38 | ) 39 | } -------------------------------------------------------------------------------- /src/common/layout/MainMenu.jsx: -------------------------------------------------------------------------------- 1 | import React, { PureComponent } from 'react'; 2 | // import cn from 'classnames'; 3 | import { withRouter } from 'react-router'; 4 | import MainMenuItem from './MainMenuItem' 5 | import styled from 'styled-components' 6 | 7 | const MainMenuContainer = styled.div` 8 | color: rgba(0, 0, 0, 0.87); 9 | background-color: rgb(255, 255, 255); 10 | transition: transform 450ms cubic-bezier(0.23, 1, 0.32, 1) 0ms; 11 | box-sizing: border-box; 12 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 13 | box-shadow: rgba(0, 0, 0, 0.16) 0px 3px 10px, rgba(0, 0, 0, 0.23) 0px 3px 10px; 14 | border-radius: 0px; 15 | height: 100%; 16 | width: 256px; 17 | position: fixed; 18 | z-index: 1200; 19 | left: 0px; 20 | top: 64px; 21 | transform: translate(0px, 0px); 22 | overflow: auto; 23 | ` 24 | class MainMenu extends PureComponent { 25 | onClickMenu=(e)=>{ 26 | let targetPageName = this.props.location.query.pagename 27 | let route = e.currentTarget.getAttribute('route') 28 | if(route !== targetPageName){ 29 | this.props.history.push(`/?pagename=${route}`) 30 | } 31 | } 32 | render() { 33 | let targetPageName = this.props.location.query.pagename 34 | return ( 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | ); 48 | } 49 | } 50 | 51 | export default withRouter(MainMenu); -------------------------------------------------------------------------------- /src/common/layout/MainMenuItem.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import cn from 'classnames'; 3 | import styled from 'styled-components' 4 | class MainMenuItem extends Component { 5 | render() { 6 | const {targetPageName, route="etc/iconstep", label} = this.props 7 | const MainMenuTab = styled.div.attrs({ 8 | className: targetPageName === route && 'on', 9 | route, 10 | // onClick: (e) => this.props.onClickMenu 11 | })` 12 | padding: 15px; 13 | /* margin-left: 10px; */ 14 | &.on { 15 | background-color: #eee; 16 | } 17 | ` 18 | return ( 19 |
20 |
21 | {/*
*/} 22 | { this.props.onClickMenu(e)}}> 23 | 24 | {label} 25 | 26 | 27 |
28 |
29 | ); 30 | } 31 | } 32 | 33 | export default MainMenuItem; -------------------------------------------------------------------------------- /src/common/layout/MainTemplete.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import MainHeader from './MainHeader'; 3 | import MainFooter from './MainFooter'; 4 | import MainMenu from './MainMenu'; 5 | import { ThemeProvider } from 'styled-components' 6 | import { theme } from '../../style' 7 | import styled from 'styled-components' 8 | 9 | const MainContentContainer = styled.div` 10 | padding-top: 64px; 11 | min-height: 400px; 12 | padding-left: 256px; 13 | 14 | & .icon-body { 15 | margin: 48px 35px; 16 | } 17 | ` 18 | class MainTemplete extends Component { 19 | render() { 20 | return ( 21 | 22 |
23 | 24 | 25 | 26 |
27 | {this.props.children} 28 |
29 |
30 | 31 |
32 |
33 | ); 34 | } 35 | } 36 | 37 | export default MainTemplete; -------------------------------------------------------------------------------- /src/config/ConfigAction.js: -------------------------------------------------------------------------------- 1 | 2 | export const ActionTypes = Object.freeze({ 3 | CHANGE_LANGUAGE:'CHANGE_LANGUAGE', 4 | }); 5 | 6 | export function changeLanguage(language){ 7 | return (dispatch, getState)=> dispatch(()=>{ 8 | dispatch({ 9 | type:ActionTypes.CHANGE_LANGUAGE, 10 | payload:{ 11 | language:language 12 | } 13 | }) 14 | }) 15 | } 16 | 17 | -------------------------------------------------------------------------------- /src/config/ConfigReducer.js: -------------------------------------------------------------------------------- 1 | import {ActionTypes as types} from './ConfigAction'; 2 | 3 | const initialState = { 4 | language:'korean', 5 | } 6 | 7 | export default function ConfigReducer(state = initialState, action) { 8 | switch(action.type) { 9 | case types.CHANGE_LANGUAGE: 10 | return Object.assign(state, { 11 | language:action.payload.language 12 | }); 13 | default: 14 | return state; 15 | } 16 | } -------------------------------------------------------------------------------- /src/config/ConfigRouter.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PageNotFound from '../error/PageNotFound'; 3 | import PageNotConnect from '../error/PageNotConnect'; 4 | import { QuerySwitch, QueryRoute } from '../library/queryrouter/'; 5 | import IntroContainer from '../intro/IntroContainer'; 6 | import EtcContainer from '../etc/EtcContainer'; 7 | import ButtonContainer from '../buttons/ButtonContainer'; 8 | import ChartContainer from '../chart/ChartContainer'; 9 | import UtilContainer from '../util/UtilContainer'; 10 | 11 | const ConfigRouter = props => { 12 | return ( 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | ); 25 | }; 26 | 27 | export default ConfigRouter; 28 | -------------------------------------------------------------------------------- /src/config/ConfigStore.js: -------------------------------------------------------------------------------- 1 | import { createStore, applyMiddleware } from 'redux'; 2 | import thunkMiddleware from 'redux-thunk'; 3 | import { createLogger } from 'redux-logger'; 4 | import combinedReducers from './combinedReducers' 5 | 6 | let createStoreWithMiddleware; 7 | if (process.env.NODE_ENV === 'production') { 8 | const loggerMiddleware = createLogger({ 9 | level: 'info', 10 | collapsed: true, 11 | }); 12 | createStoreWithMiddleware = applyMiddleware( 13 | thunkMiddleware, 14 | loggerMiddleware, 15 | )(createStore); 16 | } else { 17 | const loggerMiddleware = createLogger({ 18 | level: 'info', 19 | collapsed: true, 20 | }); 21 | createStoreWithMiddleware = applyMiddleware( 22 | thunkMiddleware, 23 | loggerMiddleware, 24 | )(createStore); 25 | } 26 | 27 | export default function ConfigStore(initialState) { 28 | return createStoreWithMiddleware(combinedReducers, initialState); 29 | }; 30 | -------------------------------------------------------------------------------- /src/config/combinedReducers.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | import ConfigReducer from './ConfigReducer'; 3 | 4 | export default combineReducers({ 5 | ConfigReducer, 6 | }); 7 | -------------------------------------------------------------------------------- /src/error/PageNotConnect.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | class PageNotConnect extends Component { 4 | render() { 5 | return ( 6 |
7 | PageNotConnect 8 |
9 | ); 10 | } 11 | } 12 | 13 | export default PageNotConnect -------------------------------------------------------------------------------- /src/error/PageNotFound.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | class PageNotFound extends Component { 4 | render() { 5 | return ( 6 |
7 |

404 error

8 |
9 | ); 10 | } 11 | } 12 | 13 | export default PageNotFound; 14 | 15 | -------------------------------------------------------------------------------- /src/etc/EtcContainer.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import EtcRouter from './EtcRouter'; 3 | 4 | const EtcContainer = (props) => { 5 | return ( 6 |
7 | 8 |
9 | ); 10 | }; 11 | 12 | export default EtcContainer 13 | -------------------------------------------------------------------------------- /src/etc/EtcRouter.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import PageNotFound from '../error/PageNotFound'; 3 | import {QuerySwitch, QueryRoute} from '../library/queryrouter/'; 4 | 5 | import IconStepContainer from './iconstep/IconStepContainer'; 6 | import IconLoadingContainer from './iconloading/IconLoadingContainer'; 7 | import IconShortNoticeContainer from './iconshortnotice/IconShortNoticeContainer'; 8 | import IconCountDownContainer from './iconcountdown/IconCountDownContainer'; 9 | import IconTabContainer from './icontab/IconTabContainer'; 10 | import IconMoreButtonContainer from './iconmorebutton/IconMoreButtonContainer' 11 | class EtcRouter extends Component { 12 | render() { 13 | return ( 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | ); 25 | } 26 | } 27 | 28 | export default EtcRouter; -------------------------------------------------------------------------------- /src/etc/etc.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sujkh85/react-icx-component/f4371b84767832af6c0e37858b7dffbf0441a710/src/etc/etc.md -------------------------------------------------------------------------------- /src/etc/iconcountdown/Constants.js: -------------------------------------------------------------------------------- 1 | 2 | export let LISTENER_KEY = { 3 | INTERVAL_TIMER:'INTERVAL_TIMER' 4 | } 5 | 6 | export let EVENT_TYPE = { 7 | countDown:'countDown' 8 | } -------------------------------------------------------------------------------- /src/etc/iconcountdown/IconCountDown.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import moment from 'moment'; 3 | import {LISTENER_KEY, EVENT_TYPE} from './Constants' 4 | 5 | class IconCountDown extends Component { 6 | //내부 타입 before(기간전) in(기간중) after(기간후)를 갖습니다. 7 | constructor(props){ 8 | super(props) 9 | const {scheduleStartDate, scheduleEndDate} = this.props 10 | this.countdownTimer = null 11 | this.state = { 12 | ...this.getBeforeTime(), 13 | scheduleStartDate:scheduleStartDate, 14 | scheduleEndDate:scheduleEndDate, 15 | dateType:this.getDateType({scheduleStartDate, scheduleEndDate}), 16 | } 17 | } 18 | 19 | getDateType({scheduleStartDate,scheduleEndDate}){ 20 | let startDate = scheduleStartDate 21 | let endDate = scheduleEndDate 22 | 23 | if(moment().isBetween(startDate, endDate) === true){ 24 | return 'in' 25 | } 26 | else if(moment().isBefore(startDate) === true){ 27 | return 'before' 28 | } 29 | else { 30 | return 'after' 31 | } 32 | } 33 | 34 | getBeforeTime=()=>{ 35 | const {beforeTimeLabel} = this.props 36 | if(beforeTimeLabel){ 37 | return beforeTimeLabel 38 | } 39 | else{ 40 | return { 41 | day:'--', 42 | hour:'--', 43 | minute:'--', 44 | second:'--' 45 | } 46 | } 47 | } 48 | 49 | getAfterTime=()=>{ 50 | const {afterTimeLabel} = this.props 51 | if(afterTimeLabel){ 52 | return afterTimeLabel 53 | } 54 | else{ 55 | return { 56 | day:'00', 57 | hour:'00', 58 | minute:'00', 59 | second:'00' 60 | } 61 | } 62 | } 63 | 64 | calculation=()=>{ 65 | const {scheduleStartDate, scheduleEndDate} = this.state 66 | const {isActive = false} = this.props 67 | let dateType = this.getDateType({scheduleStartDate, scheduleEndDate}) 68 | switch (dateType) { 69 | case 'before': 70 | if(isActive === true){ 71 | this.runBefore() 72 | } 73 | else if(isActive === false){ 74 | this.runFinish() 75 | } 76 | break; 77 | case 'in': 78 | if(isActive === true){ 79 | this.runIn() 80 | } 81 | else if(isActive === false){ 82 | this.runFinish() 83 | } 84 | break; 85 | case 'after': 86 | this.runAfter() 87 | break; 88 | default: 89 | break; 90 | } 91 | } 92 | 93 | runBefore=()=>{ 94 | const {dateType} = this.state 95 | if(dateType !== 'before'){ 96 | this.setState({ 97 | dateType:'before', 98 | ...this.getBeforeTime() 99 | }) 100 | } 101 | } 102 | 103 | runIn=()=>{ 104 | const {scheduleEndDate} = this.state 105 | let now = moment().format('x') * 1 106 | 107 | this.setState({ 108 | dateType:'in', 109 | day:moment(scheduleEndDate*1).diff(now,'days'), 110 | hour:(moment(scheduleEndDate*1).diff(now,'hours')%24).toString().padStart(2, "0"), 111 | minute:(moment(scheduleEndDate*1).diff(now,'minutes')%60).toString().padStart(2, "0"), 112 | second:(moment(scheduleEndDate*1).diff(now,'seconds')%60).toString().padStart(2, "0"), 113 | }) 114 | } 115 | 116 | runAfter=()=>{ 117 | const {dateType} = this.state 118 | if(dateType !== 'after'){ 119 | this.setState({ 120 | dateType:'after', 121 | ...this.getAfterTime() 122 | }) 123 | } 124 | } 125 | 126 | runFinish=()=>{ 127 | const {dateType} = this.state 128 | if(dateType !== 'finished'){ 129 | this.setState({ 130 | dateType:'finished', 131 | ...this.getAfterTime() 132 | }) 133 | } 134 | } 135 | 136 | onCountDown=()=>{ 137 | this.calculation() 138 | } 139 | 140 | onListener=(e)=>{ 141 | const {type} = e.detail; 142 | 143 | switch (type) { 144 | case EVENT_TYPE.countDown: 145 | this.onCountDown(e.detail.payload) 146 | break; 147 | default: 148 | break; 149 | } 150 | } 151 | 152 | componentDidMount() { 153 | window.addEventListener(LISTENER_KEY.INTERVAL_TIMER, this.onListener, false); 154 | } 155 | 156 | componentWillUnmount() { 157 | window.removeEventListener(LISTENER_KEY.INTERVAL_TIMER,this.onListener, false); 158 | } 159 | 160 | render() { 161 | const {day, hour, minute, second} = this.state 162 | return ( 163 |
164 |
165 | {day} 166 | DAYS 167 |
168 |
169 | {hour} 170 | HRS 171 |
172 |
173 | {minute} 174 | MINS 175 |
176 |
177 | {second} 178 | SECS 179 |
180 |
181 | ); 182 | } 183 | } 184 | 185 | export default IconCountDown; -------------------------------------------------------------------------------- /src/etc/iconcountdown/IconCountDownContainer.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import moment from 'moment'; 3 | import MainTemplete from '../../common/layout/MainTemplete'; 4 | import ComponentTemplete from '../../common/layout/ComponentTemplete'; 5 | import DescriptionTemplete from '../../common/layout/DescriptionTemplete'; 6 | import Code from '../../common/Code'; 7 | import PropertyTable from '../../common/PropertyTable'; 8 | import IconCountDown from './IconCountDown'; 9 | import IconCountDownController from './IconCountDownController'; 10 | // import 11 | 12 | class IconCountDownContainer extends Component { 13 | importFromList=[ 14 | {React:'react'}, 15 | {'{IconCountDown}':'react-icx-component'} 16 | ] 17 | //scheduleStartDate, scheduleEndDate 18 | libraryObject={ 19 | name:'IconCountDown', 20 | param:[ 21 | {scheduleStartDate:"{1523250124972}"}, 22 | {scheduleEndDate:"{1573250124972}"}, 23 | {isActive:"{true}"}, 24 | ], 25 | } 26 | 27 | propertyTableList=[ 28 | {name:'scheduleStartDate', type:'number', require:true, default:'',description:'시작시간'}, 29 | {name:'scheduleEndDate', type:'number', require:true, default:'',description:'종료시간'}, 30 | {name:'isActive', type:'bool', require:true, default:'true',description:'타이머를 활성화 시킬지 결정합니다.'}, 31 | {name:'beforeTimeLabel', type:'object', require:false, default:'',description:'코드를 참고하세요.'}, 32 | {name:'afterTimeLabel', type:'object', require:false, default:'',description:'코드를 참고하세요.'}, 33 | ] 34 | 35 | componentDidMount() { 36 | IconCountDownController.on() 37 | } 38 | 39 | render() { 40 | return ( 41 | 42 | 43 | 카운트 다운 컴포넌트입니다. 44 | 45 | 46 | {'componentDidMount() {'}
47 |   {'//1초에 한번씩 이벤트가 발생시켜 컴포넌트들에게 전달합니다.'}
48 |   IconCountDownController.on()
49 |   {'//controller가 동작여부를 반환합니다.'}
50 |   {'//IconCountDownController.getIsOn()'}
51 |   {'//이벤트발생을 종료시킵니다.'}
52 |   {'//IconCountDownController.off()'}
53 | {'}'}

54 | 55 | {""}
56 | {""}
57 | {""}
58 | {""}
59 | {""}
60 |
61 | 62 | scheduleStartDate 포맷은 unix time ms입니다. 63 | 64 | 65 | 66 | 67 | 68 | 69 | 77 | 85 | 86 | 87 | 88 | 89 | 90 |
91 | ); 92 | } 93 | } 94 | 95 | export default IconCountDownContainer; -------------------------------------------------------------------------------- /src/etc/iconcountdown/IconCountDownController.jsx: -------------------------------------------------------------------------------- 1 | import {LISTENER_KEY, EVENT_TYPE} from './Constants'; 2 | 3 | export default class TimerController { 4 | static isOn = false 5 | static interval = 1000 6 | static timer = null 7 | 8 | static getIsOn(){ 9 | return this.isOn 10 | } 11 | 12 | static on(){ 13 | this.isOn = true 14 | if(this.timer){ 15 | clearInterval(this.timer) 16 | this.timer = null 17 | } 18 | 19 | this.timer = setInterval(()=>{ 20 | let event = new window.CustomEvent(LISTENER_KEY.INTERVAL_TIMER, { 21 | detail:{ 22 | type:EVENT_TYPE.countDown, 23 | payload:{} 24 | } 25 | }) 26 | window.dispatchEvent(event); 27 | }, this.interval) 28 | 29 | } 30 | 31 | static off(){ 32 | this.isOn = false 33 | if(this.timer){ 34 | clearInterval(this.timer) 35 | this.timer = null 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /src/etc/iconloading/IconLoading.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | class IconLoading extends Component { 4 | render() { 5 | const {label='처리중입니다.'} = this.props 6 | if(this.props.isShow === true){ 7 | return ( 8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |

16 |

17 |
18 | ); 19 | } 20 | else { 21 | return null 22 | } 23 | } 24 | } 25 | 26 | export default IconLoading; -------------------------------------------------------------------------------- /src/etc/iconloading/IconLoadingContainer.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import {ShortNoticeContainer, ShortNoticeController} from 'react-short-notice'; 3 | import IconLoading from './IconLoading'; 4 | import MainTemplete from '../../common/layout/MainTemplete'; 5 | import DescriptionTemplete from '../../common/layout/DescriptionTemplete' 6 | import ComponentTemplete from '../../common/layout/ComponentTemplete'; 7 | import Code from '../../common/Code'; 8 | import PropertyTable from '../../common/PropertyTable'; 9 | import {FloatButton} from '../../buttons' 10 | 11 | class IconLoadingContainer extends Component { 12 | importFromList=[ 13 | {React:'react'}, 14 | {'{IconLoading}':'react-icx-component'} 15 | ] 16 | 17 | libraryObject={ 18 | name:'IconLoading', 19 | param:[ 20 | {isShow:'{true}'}, 21 | {label:'"처리중입니다.
잠시만 기달려주세요."'} 22 | ], 23 | } 24 | 25 | propertyTableList=[ 26 | {name:'isShow', type:'bool', require:false, default:'false', description:'보여줄지 말지 결정하는 속성'}, 27 | {name:'label', type:'string', require:false, default:'처리중입니다.', description:'라벨'}, 28 | ] 29 | 30 | showLoading=()=>{ 31 | ShortNoticeController.show('iconLoading') 32 | } 33 | 34 | render() { 35 | return ( 36 | 37 | 38 | API호출시 대기 시간동안 보여주는 Wait Circle 컴포넌트 39 | 40 | 41 | 42 | 43 | api호출시 대기 시간동안 Loading을 보여줄때 사용합니다.
44 | Click Me를 눌러보세요. 45 |
46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 |
55 | ); 56 | } 57 | } 58 | 59 | export default IconLoadingContainer; -------------------------------------------------------------------------------- /src/etc/iconmorebutton/IconMoreButton.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import cn from 'classnames'; 3 | 4 | class IconMoreButton extends Component { 5 | constructor(props){ 6 | super(props); 7 | 8 | this.state = { 9 | isOn:false 10 | } 11 | } 12 | 13 | onClickMenuButton=()=>{ 14 | const {isOn} = this.state 15 | this.setState({ 16 | isOn:!isOn 17 | }) 18 | } 19 | 20 | onBlurMenu=()=>{ 21 | this.setState({ 22 | isOn:false 23 | }) 24 | } 25 | 26 | getTypeStyle=()=>{ 27 | const {type='right'} = this.props 28 | if(type === 'right'){ 29 | return { right:0 } 30 | } 31 | else{ 32 | return { left:0 } 33 | } 34 | } 35 | 36 | render() { 37 | const {isOn} = this.state; 38 | const getTypeStyle = this.getTypeStyle() 39 | return ( 40 |
41 |
42 |
43 |
44 |
    45 | {this.props.children} 46 |
47 | 48 |
49 |
50 | ); 51 | } 52 | } 53 | 54 | export default IconMoreButton; -------------------------------------------------------------------------------- /src/etc/iconmorebutton/IconMoreButtonContainer.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import MainTemplete from '../../common/layout/MainTemplete'; 3 | import ComponentTemplete from '../../common/layout/ComponentTemplete'; 4 | import DescriptionTemplete from '../../common/layout/DescriptionTemplete'; 5 | import Code from '../../common/Code'; 6 | import PropertyTable from '../../common/PropertyTable'; 7 | import IconMoreButton from './IconMoreButton'; 8 | 9 | class IconMoreButtonContainer extends Component { 10 | importFromList=[ 11 | {React:'react'}, 12 | {'{IconMoreButton}':'react-icx-component'} 13 | ] 14 | 15 | propertyTableList=[ 16 | {name:'type', type:'string', require:false, default:'right',description:'좌측 우측 선택'}, 17 | {name:'child', type:'dom', require:true, default:'',description:'클릭시 나오게할 메뉴를 넣어줍니다.'}, 18 | ] 19 | 20 | render() { 21 | return ( 22 | 23 | 24 | MoreButton 25 | 26 | 27 | {''}
28 |   {'
  • 메뉴1
  • 메뉴2
  • '}
    29 | {'
    '}
    30 | 31 |
    32 | 33 | 34 | ...클릭시 하단에 메뉴가 나옵니다. 35 | 36 | 37 | 38 | 39 |
  • 메뉴1
  • 40 |
  • 메뉴2
  • 41 |
    42 |
    43 | 44 | 45 |
    46 | ); 47 | } 48 | } 49 | 50 | export default IconMoreButtonContainer; -------------------------------------------------------------------------------- /src/etc/iconshortnotice/IconShortNotice.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import {ShortNoticeContainer} from 'react-short-notice'; 3 | 4 | class IconShortNotice extends Component { 5 | render() { 6 | const {timeout, id="empty", label='아이디를 입력해주세요.', style} = this.props 7 | return ( 8 | 9 | {this.props.children} 10 | {this.props.children ? null: 11 | 12 | {label} 13 | } 14 | 15 | ); 16 | } 17 | } 18 | 19 | export default IconShortNotice; -------------------------------------------------------------------------------- /src/etc/iconshortnotice/IconShortNoticeContainer.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import {ShortNoticeContainer, ShortNoticeController} from 'react-short-notice'; 3 | import MainTemplete from '../../common/layout/MainTemplete'; 4 | import DescriptionTemplete from '../../common/layout/DescriptionTemplete' 5 | import ComponentTemplete from '../../common/layout/ComponentTemplete'; 6 | import Code from '../../common/Code'; 7 | import PropertyTable from '../../common/PropertyTable'; 8 | import IconShortNotice from './IconShortNotice'; 9 | import { FloatButton } from '../../buttons' 10 | 11 | class IconLoadingContainer extends Component { 12 | importFromList=[ 13 | {React:'react'}, 14 | {'{IconShortNotice, IconShortNoticeController}':'react-icx-component'} 15 | ] 16 | 17 | libraryObject={ 18 | name:'IconShortNotice', 19 | param:[ 20 | {id:'"notice1"'}, 21 | {timeout:'"2000"'}, 22 | {label:'"아이디를 입력해주세요.1"'} 23 | ], 24 | } 25 | 26 | propertyTableList=[ 27 | {name:'id', type:'string', require:true, default:'', description:'short-notice id값으로 ShortNoticeController.show(id)호출시 노티가 출력됩니다.'}, 28 | {name:'timeout', type:'number', require:false, default:'', description:'show 후 몇초동안 켜질지 설정할수있습니다. 안넣으면 계속 노티가 출력됩니다.'}, 29 | {name:'label', type:'string', require:false, default:'', description:'출력할 노티문구'}, 30 | ] 31 | 32 | showLoading = (target) => { 33 | console.log(target) 34 | // let target = e.target.getAttribute('target'); 35 | // ShortNoticeController.show(target) 36 | } 37 | 38 | render() { 39 | return ( 40 | 41 | 42 | 짧게 노티를 보여주는 컴포넌트 43 | 44 | 45 | {''}
    46 |   {"아이디를 입력해주세요.2"}
    47 | {'
    '}

    48 | {'
    43 | 44 |
    45 | 46 | 47 | ); 48 | } 49 | } 50 | 51 | export default ConfirmModal; -------------------------------------------------------------------------------- /src/popup/components/modals/ModalContainer.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | class ModalContainer extends Component { 4 | constructor(props) { 5 | super(props); 6 | 7 | this.scrollY = 0; 8 | } 9 | 10 | componentWillMount() { 11 | this.scrollY = document.querySelector('body').scrollTop; 12 | } 13 | 14 | componentWillUnmount() { 15 | setTimeout(() => { 16 | document.querySelector('body').scrollTop = this.scrollY 17 | }); 18 | } 19 | 20 | render() { 21 | const newProps = { 22 | location: this.props.location, 23 | history: this.props.history, 24 | layerKey: this.props.layerKey, 25 | layerCount: this.props.layerCount 26 | } 27 | return ( 28 |
    this.divContainer = ref}> 29 |
    30 |
    31 | {React.cloneElement(this.props.children, newProps)} 32 |
    33 |
    34 |
    35 | ); 36 | } 37 | } 38 | 39 | 40 | export default ModalContainer 41 | -------------------------------------------------------------------------------- /src/popup/components/modals/NoticeModal.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import LayerPopup from '../../../library/layerpopup'; 3 | 4 | class NoticeModal extends Component { 5 | constructor(props){ 6 | super(props); 7 | 8 | this.onClick = this.onClick.bind(this); 9 | } 10 | 11 | onClick(e, type) { 12 | e.preventDefault(); 13 | if('CLOSE' === type){ 14 | let {callback, param} = this.props; 15 | let resultCallback = false; 16 | if (callback) { 17 | resultCallback = callback(type, param); 18 | if (resultCallback === undefined) { 19 | resultCallback = true; 20 | } 21 | } else{ 22 | resultCallback = true; 23 | } 24 | if (resultCallback && this.props.layerKey) { 25 | LayerPopup.hide(this.props.layerKey); 26 | } 27 | } 28 | else if('XCLOSE' === type){ 29 | if(this.props.layerKey){ 30 | LayerPopup.hide(this.props.layerKey); 31 | } 32 | } 33 | 34 | } 35 | 36 | render() { 37 | let {title="title", message="message", buttonLabel='Confirm ', type="text"} = this.props; 38 | return ( 39 |
    40 |
    41 |
    42 | {title} 43 |
    44 |
    45 | 46 | {type === 'html' &&
    47 |
    48 |
    } 49 | 50 | {type === 'text' &&
    51 |
    52 | {message} 53 |
    54 |
    } 55 | 56 | 57 |
    58 | 59 |
    60 | 61 | 62 | 63 |
    64 | ); 65 | } 66 | } 67 | 68 | export default NoticeModal; 69 | -------------------------------------------------------------------------------- /src/popup/popup.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sujkh85/react-icx-component/f4371b84767832af6c0e37858b7dffbf0441a710/src/popup/popup.md -------------------------------------------------------------------------------- /src/style/color.js: -------------------------------------------------------------------------------- 1 | // 컬러정의 입니다. 2 | // primary : 메인컬러 3 | // secondary : 세컨더리 컬러 4 | // warning : 경고컬러 5 | // danger : 위험컬러 6 | import { css } from "styled-components"; 7 | 8 | const color = { 9 | default: { 10 | color: css`color: rgba(0, 0, 0, 0.87);`, 11 | backgroundColor: css`background-color: #fff;` 12 | }, 13 | primary: { 14 | color: css`color: rgb(0, 188, 212);`, 15 | backgroundColor: css`background-color: rgb(0, 188, 212);` 16 | }, 17 | secondary: { 18 | color: css`color: rgb(255, 64, 129);`, 19 | backgroundColor: css`background-color: rgb(255, 64, 129);` 20 | }, 21 | disabled: { 22 | color: css`color: rgba(0, 0, 0, 0.3);`, 23 | backgroundColor: css`background-color: rgba(0, 0, 0, 0.3);` 24 | }, 25 | } 26 | 27 | export default color -------------------------------------------------------------------------------- /src/style/components/Button.jsx: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | import color from '../color' 3 | 4 | const Button = styled.button` 5 | border: 10px; 6 | box-sizing: border-box; 7 | display: inline-block; 8 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 9 | cursor: pointer; 10 | text-decoration: none; 11 | margin: 0px; 12 | padding: 0px; 13 | outline: none; 14 | font-size: inherit; 15 | font-weight: inherit; 16 | position: relative; 17 | height: 36px; 18 | line-height: 36px; 19 | min-width: 88px; 20 | transition: all 450ms cubic-bezier(0.23, 1, 0.32, 1) 0ms; 21 | border-radius: 2px; 22 | user-select: none; 23 | overflow: hidden; 24 | background-color: rgba(0, 0, 0, 0); 25 | text-align: center; 26 | ` 27 | 28 | export const FlatStyle = styled(Button)` 29 | ${props => { 30 | return color[props.icxStyle].color 31 | }} 32 | & > span { 33 | position: relative; 34 | padding-left: 16px; 35 | padding-right: 16px; 36 | letter-spacing: 0px; 37 | text-transform: uppercase; 38 | font-weight: 500; 39 | font-size: 14px; 40 | } 41 | &:hover { 42 | background-color: rgba(153,153,153,0.2) 43 | } 44 | 45 | &:disabled, 46 | &[disabled]{ 47 | cursor: not-allowed; 48 | } 49 | ` 50 | 51 | export const FloatStyle = styled(Button)` 52 | ${ 53 | props => props.theme ? 54 | props.theme.bg[props.icxStyle] : 55 | color[props.icxStyle].backgroundColor 56 | } 57 | color: ${props => props.icxStyle !== 'default' && '#fff'}; 58 | 59 | &:disabled, 60 | &[disabled]{ 61 | cursor: not-allowed; 62 | } 63 | ` 64 | 65 | 66 | -------------------------------------------------------------------------------- /src/style/components/Divider.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components' 3 | 4 | const Hr = styled.div` 5 | height: 1px; 6 | width:100%; 7 | margin: 24px 0; 8 | background: #e8e8e8; 9 | ` 10 | const Divider = () => { 11 | return ( 12 |
    13 | ); 14 | }; 15 | 16 | export default Divider; -------------------------------------------------------------------------------- /src/style/components/index.js: -------------------------------------------------------------------------------- 1 | import Divider from './Divider' 2 | import { FlatStyle, FloatStyle} from './Button' 3 | 4 | export { 5 | Divider, 6 | FlatStyle, 7 | FloatStyle 8 | } -------------------------------------------------------------------------------- /src/style/font.js: -------------------------------------------------------------------------------- 1 | 2 | export const fontSize = { 3 | // heading 4 | displayLarge: '32px', 5 | displayMedium: '26px', 6 | displaySmall: '20px', 7 | heading: '18px', 8 | subheading: '16px', 9 | 10 | // body 11 | body: '17px', 12 | caption: '15px', 13 | }; 14 | 15 | export const fontWeight = { 16 | bold: 700, 17 | semibold: 600, 18 | normal: 400, 19 | light: 200, 20 | }; 21 | 22 | export const tagMapping = { 23 | h1: 'displayLarge', 24 | h2: 'displayMedium', 25 | h3: 'displaySmall', 26 | h4: 'heading', 27 | h5: 'subheading', 28 | }; 29 | 30 | export const lineHeight = { 31 | // heading 32 | displayLarge: '48px', 33 | displayMedium: '48px', 34 | displaySmall: '24px', 35 | heading: '24px', 36 | subheading: '24px', 37 | 38 | // body 39 | body: '24px', 40 | caption: '24px', 41 | }; 42 | -------------------------------------------------------------------------------- /src/style/index.js: -------------------------------------------------------------------------------- 1 | import theme from './theme' 2 | 3 | // export * from './layout'; 4 | // export * from './font'; 5 | // export * from './spacing'; 6 | // export * from './color'; 7 | export { theme }; 8 | -------------------------------------------------------------------------------- /src/style/layout.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | 3 | function getWidthString(span) { 4 | if (!span) return; 5 | 6 | let width = span / 12 * 100; 7 | return `width: ${width}%;` 8 | } 9 | 10 | const Row = styled.div` 11 | &::after{ 12 | content: ""; 13 | clear: both; 14 | display: table; 15 | } 16 | ` 17 | 18 | const Column = styled.div` 19 | float: left; 20 | ${({ xs }) => (xs ? getWidthString(xs) : "width:100%")}; 21 | @media only screen and (min-width: 768px) { 22 | ${({ sm }) => sm && getWidthString(sm)}; 23 | } 24 | @media only screen and (min-width: 992px) { 25 | ${({ md }) => md && getWidthString(md)}; 26 | } 27 | @media only screen and (min-width: 1200px) { 28 | ${({ lg }) => lg && getWidthString(lg)}; 29 | } 30 | ` 31 | 32 | export { Row, Column } -------------------------------------------------------------------------------- /src/style/spacing.js: -------------------------------------------------------------------------------- 1 | // * 폰트 & 간격 2 | const spacingFactor = 8; 3 | export const spacing = { 4 | space0: `${computeGoldenRatio(spacingFactor, 0)}px`, // 8 5 | space1: `${computeGoldenRatio(spacingFactor, 1)}px`, // 13 6 | space2: `${computeGoldenRatio(spacingFactor, 2)}px`, // 21 7 | space3: `${computeGoldenRatio(spacingFactor, 3)}px`, // 34 8 | space4: `${computeGoldenRatio(spacingFactor, 4)}px`, // 55 9 | space5: `${computeGoldenRatio(spacingFactor, 5)}px`, // 89 10 | }; 11 | 12 | function computeGoldenRatio(spacingFactor, exp) { 13 | return Math.round(spacingFactor * Math.pow(1.618, exp)); 14 | } 15 | -------------------------------------------------------------------------------- /src/style/style.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sujkh85/react-icx-component/f4371b84767832af6c0e37858b7dffbf0441a710/src/style/style.md -------------------------------------------------------------------------------- /src/style/theme.js: -------------------------------------------------------------------------------- 1 | // 테마쪽에서는 각종 폰트사이즈와 컬러를 정의 합니다. 2 | // styled-component 에서 공통 스타일정의 합니다. 3 | import {fontSize,fontWeight} from './font'; 4 | import { spacing } from './spacing'; 5 | import color from './color'; 6 | 7 | const theme = { 8 | main: 'mediumseagreen', 9 | color: { 10 | default: color.default.color, 11 | primary: color.primary.color, 12 | secondary: color.secondary.color, 13 | disabled: color.disabled.color, 14 | }, 15 | bg: { 16 | default: color.default.backgroundColor, 17 | primary: color.primary.backgroundColor, 18 | secondary: color.secondary.backgroundColor, 19 | disabled: color.disabled.backgroundColor, 20 | } 21 | }; 22 | 23 | export default theme -------------------------------------------------------------------------------- /src/util/UtilContainer.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import UtilRouter from './UtilRouter'; 3 | 4 | const UtilContainer = (props) => { 5 | return ( 6 |
    7 | 8 |
    9 | ); 10 | }; 11 | 12 | export default UtilContainer 13 | -------------------------------------------------------------------------------- /src/util/UtilRouter.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import PageNotFound from '../error/PageNotFound'; 3 | import {QuerySwitch, QueryRoute} from '../library/queryrouter/'; 4 | import ExcelContainer from './excel/ExcelContainer'; 5 | 6 | class EtcRouter extends Component { 7 | render() { 8 | return ( 9 | 10 | 11 | 12 | 13 | 14 | ); 15 | } 16 | } 17 | 18 | export default EtcRouter; -------------------------------------------------------------------------------- /src/util/excel/Excel.js: -------------------------------------------------------------------------------- 1 | import XLSX from 'xlsx'; 2 | import fileSaver from 'file-saver'; 3 | 4 | class Excel { 5 | static _datenum(v, date1904) { 6 | if(date1904) v+=1462; 7 | var epoch = Date.parse(v); 8 | return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000); 9 | } 10 | 11 | static _sheet_from_array_of_arrays(data, opts){ 12 | var ws = {}; 13 | var range = {s: {c:10000000, r:10000000}, e: {c:0, r:0 }}; 14 | for(var R = 0; R !== data.length; ++R) { 15 | for(var C = 0; C !== data[R].length; ++C) { 16 | if(range.s.r > R) range.s.r = R; 17 | if(range.s.c > C) range.s.c = C; 18 | if(range.e.r < R) range.e.r = R; 19 | if(range.e.c < C) range.e.c = C; 20 | var cell = {v: data[R][C] }; 21 | if(cell.v == null) continue; 22 | var cell_ref = XLSX.utils.encode_cell({c:C,r:R}); 23 | 24 | if(typeof cell.v === 'number') cell.t = 'n'; 25 | else if(typeof cell.v === 'boolean') cell.t = 'b'; 26 | else if(cell.v instanceof Date) { 27 | cell.t = 'n'; cell.z = XLSX.SSF._table[14]; 28 | cell.v = this._datenum(cell.v); 29 | } 30 | else cell.t = 's'; 31 | 32 | ws[cell_ref] = cell; 33 | } 34 | } 35 | if(range.s.c < 10000000){ 36 | ws['!ref'] = XLSX.utils.encode_range(range); 37 | } 38 | return ws; 39 | } 40 | 41 | static _s2ab(s) { 42 | var buf = new ArrayBuffer(s.length); 43 | var view = new Uint8Array(buf); 44 | for (var i=0; i!==s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF; 45 | return buf; 46 | } 47 | 48 | static _createWorkbook() { 49 | return {SheetNames:[], Sheets:{}}; 50 | } 51 | 52 | /* 53 | example 54 | var fileName = '파일명.xlsx' 55 | var data = [[1,2,3],[true, false, null, "sheetjs"],["foo","bar",new Date("2014-02-19T14:30Z"), "0.3"], ["baz", null, "qux"]] 56 | var title = "SheetJS"; 57 | write(title, data) 58 | */ 59 | 60 | static getUnlockFormat(fileName, title, callback){ 61 | let data = [['txHash'],['0x068c55b2b43421b4e66188de9fce20bea49b26a7935e4c6169343e4ce71943af'],['0x29d865f8fe3594e290a6009f47498ab57706cfce022a98ffc10269d453409fb2']] 62 | this.write(fileName, title, data, callback) 63 | } 64 | 65 | static getWhiteListFormat(fileName, title, callback){ 66 | let data = [ 67 | ['from','min','max'], 68 | ['0xc98636822709323660e429e015D4E739BD25dab5',0,10], 69 | ['0x9717Df991e66f18411056Ae8186f1aC2Fa5c6299',3,20], 70 | ['0x627306090abaB3A6e1400e9345bC60c78a8BEf57',1,10], 71 | ['0xA70Dff406A82344c43F8416f5530a6Cd0FD8F83D',0,11] 72 | ] 73 | this.write(fileName, title, data, callback) 74 | } 75 | 76 | static write(fileName='test.xlsx', title='sheet', data=[[1,2,3]], callback){ 77 | var wb = this._createWorkbook(), ws = this._sheet_from_array_of_arrays(data); 78 | 79 | /* add worksheet to workbook */ 80 | wb.SheetNames.push(title); 81 | wb.Sheets[title] = ws; 82 | var wbout = XLSX.write(wb, {bookType:'xlsx', bookSST:true, type: 'binary'}); 83 | 84 | fileSaver.saveAs(new Blob([this._s2ab(wbout)],{type:"application/octet-stream"}), fileName) 85 | 86 | if(callback){ 87 | callback() 88 | } 89 | } 90 | 91 | static xlsxReader(files, type){ 92 | return new Promise((resolve, reject)=>{ 93 | if(files.length === 0){ 94 | reject('length 0') 95 | } 96 | //let fileNameObject = this.getFileNameObject(files[0]); 97 | let file = files[0]; 98 | 99 | let fileReader = new FileReader(); 100 | fileReader.onload =(e)=>{ 101 | let data = new Uint8Array(e.target.result); 102 | let workbook = XLSX.read(data, {type:'array'}) 103 | let result 104 | if(type === 'whiteList'){ 105 | result = this.xlsxPaserAddDiff(workbook, 3) 106 | } 107 | else if(type === 'unlock'){ 108 | result = this.xlsxPaserAddDiff(workbook, 1) 109 | } 110 | else { 111 | result = this.xlsxPaser(workbook) 112 | } 113 | 114 | resolve(result) 115 | } 116 | fileReader.readAsArrayBuffer(file) 117 | 118 | }) 119 | } 120 | static xlsxPaserAddDiff(workbook, diff){ 121 | let SheetNames = workbook.SheetNames[0] 122 | let Sheets = workbook.Sheets[SheetNames] 123 | //let diff = this._getDiff(Sheets) 124 | let result = {} 125 | let keyArr = [] 126 | Object.keys(Sheets).forEach((objKey, index)=>{ 127 | if(index !==0){ 128 | if(index <= (diff)){ 129 | keyArr.push(Sheets[objKey].w) 130 | result[Sheets[objKey].w] = [] 131 | } 132 | else { 133 | let keyIdx = (index-1)%(diff) 134 | let resultKey = keyArr[keyIdx] 135 | result[resultKey].push(Sheets[objKey].w) 136 | } 137 | } 138 | }) 139 | return result 140 | } 141 | } 142 | 143 | export default Excel -------------------------------------------------------------------------------- /src/util/excel/ExcelContainer.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import MainTemplete from '../../common/layout/MainTemplete'; 3 | import ComponentTemplete from '../../common/layout/ComponentTemplete'; 4 | import DescriptionTemplete from '../../common/layout/DescriptionTemplete'; 5 | import Code from '../../common/Code'; 6 | import PropertyTable from '../../common/PropertyTable'; 7 | import Excel from './Excel'; 8 | import {FloatButton} from '../../buttons' 9 | import IconShortNotice from '../../etc/iconshortnotice/IconShortNotice' 10 | import {ShortNoticeController} from 'react-short-notice'; 11 | 12 | class ExcelContainer extends Component { 13 | importFromList=[ 14 | {React:'react'}, 15 | {'{Excel}':'react-icx-component'} 16 | ] 17 | 18 | onWrite=()=>{ 19 | let dataList = [ 20 | ['a','b','c'], 21 | [1,2,3], 22 | [4,5,6], 23 | ] 24 | 25 | Excel.write('fileName.xlsx','sheetName',dataList,()=>{ 26 | console.log('in') 27 | ShortNoticeController.show('notice1') 28 | }); 29 | } 30 | 31 | render() { 32 | return ( 33 | 34 | 35 | 엑셀 쓰기 36 | 37 | 38 | {'let callback=()=>{console.log("in")}'}

    39 | {'let write=()=>{'}
    40 |   {'let dataList = ['}
    41 |     {'[a,b,c],'}
    42 |     {'[1,2,3],'}
    43 |     {'[4,5,6],'}
    44 |   {']'}
    45 |   {"Excel.write('fileName.xlsx, sheetName, dataList, callback)"}
    46 | {'}'}
    47 | {'write()'} 48 |
    49 | 50 | 51 | 버튼을 누르면 write함수가 호출됩니다.
    52 | write함수 인자값으로 파일명, 시트명, 데이터리스트, 콜백함수를 넣어주세요.
    53 |
    54 | 55 | 56 | 57 | 58 | 59 | 60 | {/* */} 61 |
    62 | ); 63 | } 64 | } 65 | 66 | export default ExcelContainer; -------------------------------------------------------------------------------- /src/util/util.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sujkh85/react-icx-component/f4371b84767832af6c0e37858b7dffbf0441a710/src/util/util.md -------------------------------------------------------------------------------- /temp: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "env": { 4 | "es6": true 5 | }, 6 | "plugins": [ 7 | "react" 8 | ], 9 | "rules":{ 10 | "jsx-a11y/href-no-hash": "off", 11 | "jsx-a11y/anchor-is-valid": ["info", { "aspects": ["invalidHref"] }] 12 | }, 13 | "parserOptions": { 14 | "ecmaVersion": 7, 15 | "sourceType": "module", 16 | "ecmaFeatures": { 17 | "jsx": true, 18 | "modules": true 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /tests/App.test.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import TestUtils from 'react-dom/test-utils'; 4 | import App from '../src/components/App'; 5 | 6 | it('App is rendered', () => { 7 | // Render App in the document 8 | const appElement = TestUtils.renderIntoDocument( 9 | 10 | ); 11 | 12 | const appNode = ReactDOM.findDOMNode(appElement); 13 | 14 | // Verify text content 15 | expect(appNode.textContent).toEqual('Hello World!Foo to the bar'); 16 | }); 17 | -------------------------------------------------------------------------------- /tests/__mocks__/fileMock.js: -------------------------------------------------------------------------------- 1 | module.exports = 'test-file-stub'; 2 | -------------------------------------------------------------------------------- /tests/__mocks__/shim.js: -------------------------------------------------------------------------------- 1 | global.requestAnimationFrame = (callback) => { 2 | setTimeout(callback, 0); 3 | }; 4 | -------------------------------------------------------------------------------- /tests/__mocks__/styleMock.js: -------------------------------------------------------------------------------- 1 | module.exports = {}; 2 | --------------------------------------------------------------------------------