├── .babelrc ├── .eslintrc ├── .gitignore ├── .prettierrc ├── .travis.yml ├── LICENSE ├── README.md ├── package-lock.json ├── package.json ├── react-text-collapse.gif ├── src ├── ReactTextCollapse.js ├── example │ ├── codeblocks.js │ ├── component.css │ ├── example.js │ └── styles.css └── index.js ├── test ├── .eslintrc └── index.js ├── webpack.config.js └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@babel/preset-env", 4 | "@babel/preset-react" 5 | ], 6 | "plugins": [ 7 | "css-modules-transform", 8 | "@babel/plugin-proposal-class-properties", 9 | "@babel/plugin-syntax-object-rest-spread" 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "rules": { 4 | "quotes": 0, 5 | "no-trailing-spaces": 0, 6 | "eqeqeq": 0, 7 | "no-underscore-dangle": 0, 8 | "no-undef": 0, 9 | "no-extra-boolean-cast": 0, 10 | "no-mixed-spaces-and-tabs": 0, 11 | "no-alert": 0, 12 | "no-shadow": 0, 13 | "no-empty": 0, 14 | "no-irregular-whitespace": 0, 15 | "no-multi-spaces": 0, 16 | "no-new": 0, 17 | "no-unused-vars": 2, // disallow declaration of variables that are not used in the code 18 | "no-redeclare": 2, // disallow declaring the same variable more then once 19 | "new-cap": 0, 20 | // 21 | // eslint-plugin-react 22 | // 23 | // React specific linting rules for ESLint 24 | // 25 | //"react/display-name": 0, // Prevent missing displayName in a React component definition 26 | "react/jsx-boolean-value": [2, "always"], // Enforce boolean attributes notation in JSX 27 | "react/jsx-no-undef": 2, // Disallow undeclared variables in JSX 28 | "react/jsx-quotes": 0, 29 | "react/jsx-sort-prop-types": 0, // Enforce propTypes declarations alphabetical sorting 30 | "react/jsx-sort-props": 0, // Enforce props alphabetical sorting 31 | "react/jsx-uses-react": 2, // Prevent React to be incorrectly marked as unused 32 | "react/jsx-uses-vars": 2, // Prevent variables used in JSX to be incorrectly marked as unused 33 | //"react/no-did-mount-set-state": 2, // Prevent usage of setState in componentDidMount 34 | "react/no-did-update-set-state": 2, // Prevent usage of setState in componentDidUpdate 35 | "react/no-multi-comp": 0, // Prevent multiple component definition per file 36 | "react/no-unknown-property": 2, // Prevent usage of unknown DOM property 37 | "react/prop-types": 2, // Prevent missing props validation in a React component definition 38 | "react/react-in-jsx-scope": 2, // Prevent missing React when using JSX 39 | "react/self-closing-comp": 2, // Prevent extra closing tags for components without children 40 | }, 41 | "globals": { 42 | "jQuery": true, 43 | "$": true, 44 | "reveal": true, 45 | "Pikaday": true, 46 | "NProgress": true, 47 | "cytoscape": true 48 | }, 49 | "plugins": ["react"], 50 | "ecmaFeatures": { 51 | "arrowFunctions": true, 52 | "binaryLiterals": true, 53 | "blockBindings": true, 54 | "classes": true, 55 | "defaultParams": true, 56 | "destructuring": true, 57 | "forOf": true, 58 | "generators": true, 59 | "modules": true, 60 | "objectLiteralComputedProperties": true, 61 | "objectLiteralDuplicateProperties": true, 62 | "objectLiteralShorthandMethods": true, 63 | "objectLiteralShorthandProperties": true, 64 | "octalLiterals": true, 65 | "regexUFlag": true, 66 | "regexYFlag": true, 67 | "spread": true, 68 | "superInFunctions": true, 69 | "templateStrings": true, 70 | "unicodeCodePointEscapes": true, 71 | "globalReturn": true, 72 | "jsx": true 73 | }, 74 | "env": { 75 | "browser": true, 76 | "es6": true 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | /dist/ 11 | 12 | node_modules 13 | 14 | # Precommit hook 15 | .jshint* 16 | 17 | /example/ 18 | .coveralls.yml 19 | /reports/ 20 | gulpfile.js 21 | 22 | coverage 23 | 24 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "all", 3 | "tabWidth": 2, 4 | "singleQuote": true, 5 | "semi": false, 6 | "arrowParens": "avoid" 7 | } 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - v5 4 | - v4 5 | - '0.12' 6 | - '0.10' 7 | after_script: 8 | - 'npm run coveralls' 9 | - 'npm run coveralls' 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Robert Chang 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 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

React text collapse

2 | 3 |

4 | 5 | NPM Version 7 | 8 | 9 | 10 | Coverage Status 11 | 12 | 13 | 14 | Build Status 16 | 17 | 18 | 19 | Downloads 21 | 22 | 23 | 24 | License 26 | 27 |

28 | 29 |

30 | 31 |

32 | 33 | ![React text collapse](react-text-collapse.gif) 34 | 35 | ## Philosophy 36 | 37 | > Keep things simple! You don't need jQuery... 38 | 39 | ## Installation 40 | 41 | [![Join the chat at https://gitter.im/cht8687/react-text-collapse](https://badges.gitter.im/cht8687/react-text-collapse.svg)](https://gitter.im/cht8687/react-text-collapse?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 42 | 43 | ### npm 44 | 45 | ``` 46 | $ npm install --save react-text-collapse 47 | ``` 48 | 49 | ## Demo 50 | 51 | [Demo](http://cht8687.github.io/react-text-collapse/example/) 52 | 53 | ## Example code 54 | 55 | [Code Example](https://github.com/cht8687/react-text-collapse/blob/master/src/example/example.js) 56 | 57 | ## Usage 58 | 59 | ```js 60 | 61 |

62 | React text collapse is awesome. React text collapse is awesome. 63 |
64 | React text collapse is awesome. React text collapse is awesome. 65 |
66 | React text collapse is awesome. React text collapse is awesome. 67 |
68 | React text collapse is awesome. React text collapse is awesome. 69 |
70 |

71 |
72 | ``` 73 | 74 | ## Options 75 | 76 | #### `options`: PropTypes.object.isRequired 77 | 78 | ```js 79 | const TEXT_COLLAPSE_OPTIONS = { 80 | collapse: false, // default state when component rendered 81 | collapseText: '... show more', // text to show when collapsed 82 | expandText: 'show less', // text to show when expanded 83 | minHeight: 100, // component height when closed 84 | maxHeight: 250, // expanded to 85 | textStyle: { // pass the css for the collapseText and expandText here 86 | color: "blue", 87 | fontSize: "20px" 88 | } 89 | } 90 | ``` 91 | 92 | ## Development 93 | 94 | ``` 95 | $ git clone git@github.com:cht8687/react-text-collapse.git 96 | $ cd react-text-collapse 97 | $ npm install 98 | $ webpack-dev-server 99 | ``` 100 | 101 | Then 102 | 103 | ``` 104 | open http://localhost:8080/webpack-dev-server/ 105 | ``` 106 | 107 | ## License 108 | 109 | MIT 110 | 111 | ## Contributors 112 | 113 | Thanks to these wonderful developers for helping this project: 114 | 115 |

116 | 117 | 118 |

119 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-text-collapse", 3 | "version": "0.6.1", 4 | "description": "React text collapse expand tool", 5 | "main": "dist/index.js", 6 | "scripts": { 7 | "dev": "webpack-dev-server -d --history-api-fallback --hot --inline --progress --colors --port 8080", 8 | "prepublish": "npm run build:dist -s && npm run build:example -s", 9 | "prebuild": "rimraf dist example build", 10 | "build:dist": "babel src --out-dir dist --source-maps --ignore src/example", 11 | "build:example": "webpack --config webpack.config.js", 12 | "postbuild": "npm run test -s", 13 | "test": "babel-node test/index.js | tnyan", 14 | "coverage": "babel-node node_modules/isparta/bin/isparta cover test/index.js", 15 | "coveralls": "npm run coverage -s && coveralls < coverage/lcov.info", 16 | "postcoveralls": "rimraf ./coverage" 17 | }, 18 | "repository": { 19 | "type": "git", 20 | "url": "git+https://github.com/cht8687/react-text-collapse.git" 21 | }, 22 | "keywords": [ 23 | "react", 24 | "react-component", 25 | "component", 26 | "react-text", 27 | "react-text-collapse", 28 | "react-text-expand", 29 | "text", 30 | "accordion", 31 | "expand" 32 | ], 33 | "files": [ 34 | "dist" 35 | ], 36 | "author": "Robert Chang ", 37 | "license": "MIT", 38 | "bugs": { 39 | "url": "https://github.com/cht8687/react-text-collapse/issues" 40 | }, 41 | "homepage": "https://github.com/cht8687/react-text-collapse#readme", 42 | "peerDependencies": { 43 | "react": ">=0.14", 44 | "react-motion": "^0.4 || ^0.5" 45 | }, 46 | "devDependencies": { 47 | "@babel/cli": "^7.0.0", 48 | "@babel/core": "^7.0.1", 49 | "@babel/node": "^7.0.0", 50 | "@babel/plugin-syntax-object-rest-spread": "^7.0.0", 51 | "@babel/preset-env": "^7.0.0", 52 | "@babel/preset-react": "^7.0.0", 53 | "babel-eslint": "^9.0.0", 54 | "babel-loader": "^8.0.2", 55 | "babel-plugin-css-modules-transform": "^1.2.7", 56 | "coveralls": "^3.0.2", 57 | "css-loader": "^3.2.0", 58 | "eslint": "^5.6.0", 59 | "eslint-loader": "^2.1.0", 60 | "eslint-plugin-react": "^7.11.1", 61 | "extract-text-webpack-plugin": "^3.0.2", 62 | "html-webpack-plugin": "^3.2.0", 63 | "isparta": "^4.0.0", 64 | "mini-css-extract-plugin": "^0.4.2", 65 | "prettier": "^2.0.5", 66 | "react": "^16.13.1", 67 | "react-code-blocks": "0.0.9-0", 68 | "react-dom": "^16.13.1", 69 | "react-hot-loader": "^1.2.9", 70 | "react-motion": "^0.5.0", 71 | "rimraf": "^2.4.3", 72 | "snazzy": "^8.0.0", 73 | "standard": "^7.1.2", 74 | "tap-nyan": "0.0.2", 75 | "tape": "^4.4.0", 76 | "webpack": "^4.19.0", 77 | "webpack-cli": "^3.1.0", 78 | "webpack-dev-server": "^3.1.14" 79 | }, 80 | "dependencies": { 81 | "prop-types": "^15.5.10" 82 | }, 83 | "husky": { 84 | "hooks": { 85 | "pre-commit": "lint-staged" 86 | } 87 | }, 88 | "lint-staged": { 89 | "*.{js,ts,tsx,json,css,md}": [ 90 | "prettier --write", 91 | "git add" 92 | ] 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /react-text-collapse.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cht8687/react-text-collapse/8bfc0740dfbc4c493833b0806b47e4a519917f45/react-text-collapse.gif -------------------------------------------------------------------------------- /src/ReactTextCollapse.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { Motion, spring } from 'react-motion' 3 | import PropTypes from 'prop-types' 4 | 5 | export default class ReactTextCollapse extends Component { 6 | static propTypes = { 7 | children: PropTypes.node.isRequired, 8 | options: PropTypes.object.isRequired, 9 | } 10 | 11 | constructor(props) { 12 | super(props) 13 | 14 | const { 15 | options: { collapse }, 16 | } = this.props 17 | this.state = { 18 | collapse: collapse ? collapse : true, 19 | } 20 | } 21 | 22 | renderHelperText() { 23 | const { 24 | options: { collapseText, expandText, textStyle }, 25 | } = this.props 26 | const { collapse } = this.state 27 | 28 | if (collapse) { 29 | return
{collapseText}
30 | } 31 | 32 | return
{expandText}
33 | } 34 | 35 | toggleAction = () => { 36 | this.setState(state => ({ collapse: !state.collapse })) 37 | } 38 | 39 | render() { 40 | const { 41 | options: { minHeight, maxHeight }, 42 | children, 43 | } = this.props 44 | const { collapse } = this.state 45 | return ( 46 | 50 | {({ h }) => ( 51 | 52 |
59 | {children} 60 |
61 |
{this.renderHelperText()}
62 |
63 | )} 64 |
65 | ) 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/example/codeblocks.js: -------------------------------------------------------------------------------- 1 | export const customComponentSnippet = ` 2 | const TEXT_COLLAPSE_OPTIONS = { 3 | collapse: false, 4 | collapseText: '... show more', 5 | expandText: 'show less', 6 | minHeight: 100, 7 | maxHeight: 200, 8 | textStyle: { 9 | color: 'blue', 10 | fontSize: '20px', 11 | }, 12 | } 13 | 14 |

15 | React text collapse is awesome. React text collapse is awesome.
16 | React text collapse is awesome. React text collapse is awesome.
17 | React text collapse is awesome. React text collapse is awesome.
18 | React text collapse is awesome. React text collapse is awesome.
19 | React text collapse is awesome. React text collapse is awesome.
20 | React text collapse is awesome. React text collapse is awesome.
21 | React text collapse is awesome. React text collapse is awesome.
22 | React text collapse is awesome. React text collapse is awesome.
23 |

24 | ` 25 | -------------------------------------------------------------------------------- /src/example/component.css: -------------------------------------------------------------------------------- 1 | .hover { 2 | background-color: papayawhip; 3 | width: 300px; 4 | height: 150px; 5 | border-style: dashed; 6 | border-color: chocolate; 7 | } 8 | 9 | .trigger { 10 | background-color: #44b39d; 11 | color: white; 12 | width: 200px; 13 | } 14 | 15 | .quote { 16 | padding: 15px 25px; 17 | } 18 | 19 | .thumbnail { 20 | float: left; 21 | margin-top: 40px; 22 | } 23 | 24 | .people { 25 | float: right; 26 | margin-top: -23px; 27 | } 28 | -------------------------------------------------------------------------------- /src/example/example.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { render } from 'react-dom' 3 | import { CopyBlock, nord } from 'react-code-blocks' 4 | import { customComponentSnippet } from './codeblocks' 5 | import ReactTextCollapse from '..' 6 | import './styles.css' 7 | import './component.css' 8 | 9 | const TEXT_COLLAPSE_OPTIONS = { 10 | collapse: false, 11 | collapseText: '... show more', 12 | expandText: 'show less', 13 | minHeight: 100, 14 | maxHeight: 200, 15 | textStyle: { 16 | color: 'blue', 17 | fontSize: '20px', 18 | }, 19 | } 20 | class App extends Component { 21 | render() { 22 | return ( 23 |
24 |
25 | {' '} 26 | React-text-collapse 27 |
28 | Github 29 |
30 |
31 |
32 |

Make your collapsable texts easily

33 |
34 |
35 | 43 |
44 |
45 | 46 |

47 | React text collapse is awesome. React text collapse is 48 | awesome. 49 |
50 | React text collapse is awesome. React text collapse is 51 | awesome. 52 |
53 | React text collapse is awesome. React text collapse is 54 | awesome. 55 |
56 | React text collapse is awesome. React text collapse is 57 | awesome. 58 |
59 | React text collapse is awesome. React text collapse is 60 | awesome. 61 |
62 | React text collapse is awesome. React text collapse is 63 | awesome. 64 |
65 | React text collapse is awesome. React text collapse is 66 | awesome. 67 |
68 | React text collapse is awesome. React text collapse is 69 | awesome. 70 |
71 |

72 |
73 |
74 |
75 |
76 |
77 | ) 78 | } 79 | } 80 | 81 | const appRoot = document.createElement('div') 82 | appRoot.id = 'app' 83 | document.body.appendChild(appRoot) 84 | 85 | render(, appRoot) 86 | -------------------------------------------------------------------------------- /src/example/styles.css: -------------------------------------------------------------------------------- 1 | .container { 2 | } 3 | 4 | .title { 5 | color: #fff; 6 | text-align: center; 7 | background-color: #44b39d; 8 | position: relative; 9 | font-size: 16px; 10 | line-height: 1.5; 11 | text-align: center; 12 | padding: 5rem; 13 | margin-bottom: 2rem; 14 | font-size: 3.25rem; 15 | } 16 | 17 | .main { 18 | padding: 0 7rem; 19 | font-size: 1.1rem; 20 | } 21 | 22 | .description { 23 | color: rgba(255, 255, 255, 0.7); 24 | background-color: rgba(255, 255, 255, 0.08); 25 | -webkit-transition: color 0.2s, background-color 0.2s, border-color 0.2s; 26 | transition: color 0.2s, background-color 0.2s, border-color 0.2s; 27 | text-decoration: none; 28 | text-align: center; 29 | padding: 0.6rem 0.9rem; 30 | font-size: 0.9rem; 31 | width: 50px; 32 | margin: 0 auto; 33 | } 34 | 35 | .description a { 36 | color: rgba(255, 255, 255, 0.7); 37 | } 38 | 39 | .subtitle { 40 | margin-top: 2rem; 41 | margin-bottom: 1rem; 42 | font-weight: normal; 43 | color: #44b39d; 44 | text-align: center; 45 | } 46 | 47 | .subcontainer { 48 | display: flex; 49 | -ms-flex-align: stretch; 50 | align-items: stretch; 51 | -ms-flex-pack: justify; 52 | justify-content: space-between; 53 | background-color: #eae9e9; 54 | } 55 | 56 | .subleft { 57 | width: calc(50% - 30px); 58 | overflow-x: auto; 59 | border: 1px dashed rgb(68 179 157); 60 | } 61 | 62 | .subright { 63 | width: calc(50% - 30px); 64 | border: 1px dashed rgb(68 179 157); 65 | display: flex; 66 | justify-content: center; 67 | align-items: top; 68 | height: 800px; 69 | } 70 | 71 | .p { 72 | margin: 0; 73 | } 74 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import ReactTextCollapse from './ReactTextCollapse' 2 | export default ReactTextCollapse 3 | -------------------------------------------------------------------------------- /test/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../src/.eslintrc", 3 | 4 | "env": { 5 | "jasmine": true 6 | }, 7 | 8 | "rules": { 9 | "one-var": 0, 10 | "no-undefined": 0 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | import test from 'tape'; 2 | import ReactTextCollapse from '../src/ReactTextCollapse'; 3 | 4 | test('ReactTextCollapse', t => { 5 | t.ok(ReactTextCollapse instanceof Function, 'should be function'); 6 | t.end(); 7 | }); 8 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack') 2 | var HtmlWebpackPlugin = require('html-webpack-plugin') 3 | var path = require('path') 4 | var env = process.env.NODE_ENV || 'development' 5 | const MiniCssExtractPlugin = require('mini-css-extract-plugin') 6 | 7 | module.exports = { 8 | devtool: 'source-map', 9 | entry: [ 10 | './src/example/Example.js', 11 | 'webpack-dev-server/client?http://localhost:8080', 12 | 'webpack/hot/only-dev-server', 13 | ], 14 | output: { filename: 'bundle.js', path: path.resolve('example') }, 15 | plugins: [ 16 | new HtmlWebpackPlugin({ 17 | title: 'React-text-collapse', 18 | }), 19 | new webpack.DefinePlugin({ 20 | 'process.env': { 21 | NODE_ENV: '"' + env + '"', 22 | }, 23 | }), 24 | new webpack.HotModuleReplacementPlugin(), 25 | new MiniCssExtractPlugin({ 26 | // Options similar to the same options in webpackOptions.output 27 | // both options are optional 28 | filename: '[name].css', 29 | chunkFilename: '[id].css', 30 | }), 31 | ], 32 | module: { 33 | rules: [ 34 | { 35 | test: /\.js$/, 36 | loaders: ['babel-loader'], 37 | include: [path.resolve('src')], 38 | }, 39 | { 40 | test: /\.css$/, 41 | use: [ 42 | { 43 | loader: MiniCssExtractPlugin.loader, 44 | options: { 45 | // you can specify a publicPath here 46 | // by default it use publicPath in webpackOptions.output 47 | publicPath: '../', 48 | }, 49 | }, 50 | 'css-loader', 51 | ], 52 | }, 53 | { 54 | enforce: 'pre', 55 | test: /\.js$/, 56 | loaders: ['eslint-loader'], 57 | include: [path.resolve('src')], 58 | }, 59 | ], 60 | }, 61 | resolve: { extensions: ['.js'] }, 62 | stats: { colors: true }, 63 | devServer: { 64 | hot: true, 65 | historyApiFallback: true, 66 | stats: { 67 | chunkModules: false, 68 | colors: true, 69 | }, 70 | }, 71 | } 72 | --------------------------------------------------------------------------------