├── .browserslistrc ├── .npmignore ├── demo ├── favicon.ico ├── index.html ├── css │ ├── app.fb7c943b.css │ └── chunk-vendors.fb88a4ae.css └── js │ ├── app.a1f17b0e.js │ └── vue.ddfe293c.js ├── public ├── favicon.ico └── index.html ├── postcss.config.js ├── babel.config.js ├── .editorconfig ├── README.md ├── src ├── main.js ├── vue-lang.js ├── components │ ├── Clamp.js │ └── utils.js └── App.vue ├── .gitignore ├── CHANGELOG.md ├── rollup.config.js ├── vue.config.js ├── LICENSE ├── package.json └── .eslintrc.js /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | not ie <= 8 4 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .* 2 | *.config.js 3 | /demo 4 | /public 5 | /src 6 | -------------------------------------------------------------------------------- /demo/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boyuai/vue-clamp/HEAD/demo/favicon.ico -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boyuai/vue-clamp/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | autoprefixer: {} 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*.{js,jsx,ts,tsx,vue}] 2 | indent_style = space 3 | indent_size = 2 4 | trim_trailing_whitespace = true 5 | insert_final_newline = true 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # <vue-clamp> 2 | 3 | Clamping multiline contents with ease. 4 | 5 | See more in our [docs & demo](https://boyuai.github.io/vue-clamp/demo/). 6 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | 4 | Vue.config.productionTip = false 5 | 6 | new Vue({ 7 | render: h => h(App) 8 | }).$mount('#app') 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | # local env files 6 | .env.local 7 | .env.*.local 8 | 9 | # Log files 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # Editor directories and files 15 | .idea 16 | .vscode 17 | *.suo 18 | *.ntvs* 19 | *.njsproj 20 | *.sln 21 | *.sw* 22 | 23 | Clamp.js 24 | utils.js 25 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.3.1 2 | 3 | * Fix SSR support. 4 | * Fix RTL support. 5 | 6 | ## 0.3.0 7 | 8 | * Add `clampchange` event. 9 | 10 | ## 0.2.2 11 | 12 | * Preserve at lease a single line of content when even a single line would exceeds `max-height`. 13 | 14 | ## 0.2.1 15 | 16 | * Update layout when clamp status has been changed. 17 | 18 | ## 0.2.0 19 | 20 | * Add `clamped: boolean` and `expanded: boolean` to scoped slot `before`/`after`. 21 | * Fix content extraction. 22 | 23 | ## 0.1.0 24 | 25 | * First release. -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import vue from 'rollup-plugin-vue' 2 | import buble from '@rollup/plugin-buble' 3 | import { terser } from 'rollup-plugin-terser' 4 | import resolve from '@rollup/plugin-node-resolve' 5 | 6 | export default { 7 | input: 'src/components/Clamp.js', 8 | output: { 9 | file: 'dist/vue-clamp.js', 10 | name: 'VueClamp', 11 | format: 'umd', 12 | globals: { 13 | vue: 'Vue' 14 | } 15 | }, 16 | external: [ 17 | 'vue' 18 | ], 19 | plugins: [ 20 | resolve(), 21 | vue({ 22 | compileTemplate: true 23 | }), 24 | buble(), 25 | terser() 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | vue-clamp 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | publicPath: process.env.NODE_ENV === 'production' ? './' : '/', 3 | outputDir: 'demo', 4 | transpileDependencies: ['resize-detector'], 5 | chainWebpack: config => { 6 | config.optimization.clear('splitChunks').splitChunks({ 7 | cacheGroups: { 8 | vue: { 9 | name: 'vue', 10 | test: /[\\/]node_modules[\\/]vue[\\/]/, 11 | priority: 0, 12 | chunks: 'initial' 13 | }, 14 | vendors: { 15 | name: 'chunk-vendors', 16 | test: /[\\/]node_modules[\\/]/, 17 | priority: -10, 18 | chunks: 'initial' 19 | }, 20 | common: { 21 | name: 'chunk-common', 22 | minChunks: 2, 23 | priority: -20, 24 | chunks: 'initial', 25 | reuseExistingChunk: true 26 | } 27 | } 28 | }) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /demo/index.html: -------------------------------------------------------------------------------- 1 | vue-clamp
-------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 GU Yiling 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 | -------------------------------------------------------------------------------- /demo/css/app.fb7c943b.css: -------------------------------------------------------------------------------- 1 | html{scroll-behavior:smooth}h1{padding-top:3rem;-webkit-box-align:center;-ms-flex-align:center;align-items:center}#lang{position:absolute;top:1rem;right:0}h2{margin-top:2rem}article{position:relative;margin:0 auto;width:560px}@media (min-width:320px){article{width:290px}}@media (min-width:400px){article{width:370px}}@media (min-width:480px){article{width:450px}}@media screen and (min-width:600px){article{width:580px}}.divider[data-content]{margin:2rem 0}.form-horizontal{width:60%}.slider{height:1.8rem}.demo{padding:1rem;background:#f8f8f8;border:1px solid #f1f1f1;border-radius:2px;line-height:2}.hyphens{-webkit-hyphens:auto;-ms-hyphens:auto;hyphens:auto}.rtl{direction:rtl}.toggle{margin-left:.4rem}.rtl .toggle{margin-left:0}.featured,.rtl .toggle{margin-right:.4rem}.rtl .featured{margin-right:0;margin-left:.4rem}ul{list-style:disc outside}ul p{margin-bottom:.6rem}.hljs{padding:0}.secondary{font-size:90%}footer{margin:6rem 0 3rem;text-align:center}::-webkit-details-marker{display:none}details{margin-bottom:1em}summary{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;margin-bottom:.5em;cursor:pointer}summary h4{margin:0}summary:before{content:"";width:.4rem;height:.4rem;margin-right:.4rem;border:2px solid currentColor;border-style:none solid solid none;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);-webkit-transition:-webkit-transform .3s;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s;-webkit-transform-origin:50% 50%;transform-origin:50% 50%}details[open] summary:before{-webkit-transform:rotate(45deg);transform:rotate(45deg)} -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@boyuai/vue-clamp", 3 | "version": "0.4.2", 4 | "description": "Clamping multiline contents with ease.", 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "NODE_ENV=production rollup -c", 8 | "lint": "vue-cli-service lint", 9 | "build:demo": "vue-cli-service build", 10 | "prepublishOnly": "cp ./src/components/* .", 11 | "publish": "rm ./Clamp.js ./utils.js" 12 | }, 13 | "main": "dist/vue-clamp.js", 14 | "module": "Clamp.js", 15 | "dependencies": { 16 | "core-js": "^3.6.5", 17 | "raf": "^3.4.1", 18 | "resize-detector": "^0.1.10" 19 | }, 20 | "devDependencies": { 21 | "@rollup/plugin-buble": "^0.21.3", 22 | "@rollup/plugin-node-resolve": "^7.1.3", 23 | "@vue/cli-plugin-babel": "^4.4.6", 24 | "@vue/cli-plugin-eslint": "^4.4.6", 25 | "@vue/cli-service": "^4.4.6", 26 | "@vue/eslint-config-standard": "^4.0.0", 27 | "babel-eslint": "^10.1.0", 28 | "eslint": "^6.8.0", 29 | "eslint-config-prettier": "^6.11.0", 30 | "eslint-config-standard": "^14.1.1", 31 | "eslint-plugin-vue": "^6.2.2", 32 | "highlight.js": "^9.18.3", 33 | "prettier": "^2.0.5", 34 | "prettier-eslint": "^9.0.2", 35 | "qs": "^6.9.4", 36 | "rollup": "^2.23.0", 37 | "rollup-plugin-terser": "^5.3.0", 38 | "rollup-plugin-vue": "^5.1.9", 39 | "spectre.css": "^0.5.9", 40 | "stylus": "^0.54.8", 41 | "stylus-loader": "^3.0.2", 42 | "vue": "^2.6.11", 43 | "vue-template-compiler": "^2.6.11" 44 | }, 45 | "peerDependencies": { 46 | "vue": "^2.6.0" 47 | }, 48 | "bugs": { 49 | "url": "https://github.com/boyuai/vue-clamp/issues" 50 | }, 51 | "homepage": "https://boyuai.github.io/vue-clamp/demo/", 52 | "license": "MIT", 53 | "repository": { 54 | "type": "git", 55 | "url": "git+https://github.com/boyuai/vue-clamp.git" 56 | }, 57 | "keywords": [ 58 | "clamp", 59 | "ellipsis", 60 | "clamp-text", 61 | "truncate-text", 62 | "multiline-text", 63 | "vue" 64 | ] 65 | } 66 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | // http://eslint.org/docs/user-guide/configuring 2 | 3 | module.exports = { 4 | root: true, 5 | parserOptions: { 6 | parser: 'babel-eslint', 7 | sourceType: 'module' 8 | }, 9 | extends: [ 10 | // https://github.com/vuejs/eslint-plugin-vue#bulb-rules 11 | 'plugin:vue/essential', 12 | 'plugin:vue/recommended', 13 | 'plugin:vue/strongly-recommended', 14 | // https://github.com/standard/standard/blob/master/docs/RULES-en.md 15 | 'standard', 16 | 'prettier/standard', 17 | 'prettier/vue' 18 | ], 19 | // required to lint *.vue files 20 | plugins: ['vue'], 21 | // add your custom rules here 22 | rules: { 23 | // allow paren-less arrow functions 24 | 'arrow-parens': 0, 25 | // allow async-await 26 | 'generator-star-spacing': 0, 27 | // allow debugger during development 28 | 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0, 29 | 'no-multi-spaces': ['error', { ignoreEOLComments: true }], 30 | 'no-template-curly-in-string': 0, 31 | // to many false positives 32 | 'vue/no-side-effects-in-computed-properties': 0, 33 | // fix unused var error for JSX custom tags 34 | 'vue/jsx-uses-vars': 2, 35 | 'vue/require-default-prop': 0, 36 | 'vue/name-property-casing': ['error', 'kebab-case'], 37 | 'vue/component-name-in-template-casing': ['error', 'kebab-case'], 38 | 'vue/html-indent': [ 39 | 'error', 40 | 2, 41 | { 42 | attribute: 1, 43 | baseIndent: 0, 44 | closeBracket: 0, 45 | alignAttributesVertically: true 46 | } 47 | ], 48 | 'vue/html-self-closing': [ 49 | 'error', 50 | { 51 | html: { 52 | void: 'never', 53 | normal: 'always', 54 | component: 'always' 55 | }, 56 | svg: 'always', 57 | math: 'always' 58 | } 59 | ], 60 | 'vue/html-closing-bracket-spacing': [ 61 | 'error', 62 | { 63 | startTag: 'never', 64 | endTag: 'never', 65 | selfClosingTag: 'never' 66 | } 67 | ], 68 | 'vue/no-v-html': 0 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/vue-lang.js: -------------------------------------------------------------------------------- 1 | export default function (hljs) { 2 | const XML_IDENT_RE = '[A-Za-z0-9\\._:-]+' 3 | const TAG_INTERNALS = { 4 | endsWithParent: true, 5 | illegal: /`]+/ } 24 | ] 25 | } 26 | ] 27 | } 28 | ] 29 | } 30 | return { 31 | case_insensitive: true, 32 | contains: [ 33 | hljs.COMMENT('', { 34 | relevance: 10 35 | }), 36 | { 37 | className: 'tag', 38 | /* 39 | The lookahead pattern (?=...) ensures that 'begin' only matches 40 | '|$)', 45 | end: '>', 46 | keywords: { name: 'style' }, 47 | contains: [TAG_INTERNALS], 48 | starts: { 49 | end: '', 50 | returnEnd: true, 51 | subLanguage: ['css', 'less', 'scss', 'stylus'] 52 | } 53 | }, 54 | { 55 | className: 'tag', 56 | // See the comment in the 653 | 654 | 655 | 656 | 766 | -------------------------------------------------------------------------------- /demo/js/app.a1f17b0e.js: -------------------------------------------------------------------------------- 1 | (function(e){function t(t){for(var n,o,r=t[0],l=t[1],c=t[2],h=0,p=[];h")]),a("div",{staticClass:"lang btn-group",attrs:{id:"lang"}},[a("button",{staticClass:"btn btn-sm",class:{active:!e.zh},on:{click:function(t){e.zh=!1}}},[e._v("English")]),a("button",{staticClass:"btn btn-sm",class:{active:e.zh},on:{click:function(t){e.zh=!0}}},[e._v("中文")])]),a("p",[e._v(e._s(e.zh?"轻松实现多行内容的截断。":"Clamping multiline contents with ease."))]),a("p",[a("a",{staticClass:"tooltip",attrs:{href:"https://github.com/boyuai/vue-clamp","data-tooltip":e.zh?"前往 GitHub 仓库":"Visit GitHub repo"}},[e._v("GitHub →")])]),a("h2",{attrs:{id:"features"}},[a("a",{attrs:{href:"#features"}},[e._v("#")]),e._v(" "+e._s(e.zh?"功能":"Features")+" ")]),a("ul",[a("li",[e._v(e._s(e.zh?"支持限制最大行数和最大高度,多行文字无需指定行高。":"Clamps contents with max lines and max height. No need to specify line height for text."))]),a("li",[e._v(e._s(e.zh?"支持在布局变化时自动更新。":"Automatically updates upon layout change."))]),a("li",[e._v(e._s(e.zh?"支持展开/收起被截断部分内容。":"The clamped contents can be expanded/collapsed."))]),a("li",[e._v(e._s(e.zh?"支持自定义截断内容的前后区域,并且进行响应式更新。":"Customizable and responsive content before/after clamped contents."))])]),e._m(0),a("div",{staticClass:"divider text-center",attrs:{"data-content":"↓ max-lines(with line-height) & slot `after`"}}),a("section",{staticClass:"case"},[a("div",{staticClass:"form-horizontal"},[a("div",{staticClass:"form-group"},[a("label",{staticClass:"form-label col-5 col-sm-12",attrs:{for:"lines"}},[e._v(e._s(e.zh?"最大行数":"Max lines"))]),a("div",{staticClass:"col-7 col-sm-12"},[a("input",{directives:[{name:"model",rawName:"v-model.number",value:e.lines0,expression:"lines0",modifiers:{number:!0}}],staticClass:"form-input",attrs:{id:"lines0",type:"number",min:"1",max:"8",step:"1"},domProps:{value:e.lines0},on:{input:function(t){t.target.composing||(e.lines0=e._n(t.target.value))},blur:function(t){return e.$forceUpdate()}}})])]),a("div",{staticClass:"form-group"},[a("label",{staticClass:"form-label col-5 col-sm-12",attrs:{for:"width0"}},[e._v(e._s(e.zh?"容器宽度":"Container width"))]),a("div",{staticClass:"col-7 col-sm-12 tooltip",attrs:{"data-tooltip":e.width0+"%"}},[a("input",{directives:[{name:"model",rawName:"v-model",value:e.width0,expression:"width0"}],staticClass:"slider",attrs:{id:"width0",type:"range",min:"50",max:"100"},domProps:{value:e.width0},on:{__r:function(t){e.width0=t.target.value}}})])])]),a("v-clamp",{class:{demo:!0},style:{width:e.width0+"%",lineHeight:"40px"},attrs:{"max-lines":e.lines0,"line-height":40,autoresize:""},scopedSlots:e._u([{key:"after",fn:function(t){var n=t.toggle,s=t.expanded,i=t.clamped;return[s||i?a("button",{staticClass:"toggle btn btn-sm",on:{click:n}},[e._v(e._s(e.zh?"切换":"Toggle"))]):e._e()]}}])},e._l(Array.from(Array(40).keys()),(function(t){return a("span",{key:t,staticClass:"featured label label-rounded label-primary"},[e._v(" "+e._s("tag-"+87*t)+" ")])})),0)],1),a("div",{staticClass:"divider text-center",attrs:{"data-content":"↓ max-lines & slot `after`"}}),a("section",{staticClass:"case"},[a("div",{staticClass:"form-horizontal"},[a("div",{staticClass:"form-group"},[a("label",{staticClass:"form-label col-5 col-sm-12",attrs:{for:"lines"}},[e._v(e._s(e.zh?"最大行数":"Max lines"))]),a("div",{staticClass:"col-7 col-sm-12"},[a("input",{directives:[{name:"model",rawName:"v-model.number",value:e.lines1,expression:"lines1",modifiers:{number:!0}}],staticClass:"form-input",attrs:{id:"lines1",type:"number",min:"1",max:"8",step:"1"},domProps:{value:e.lines1},on:{input:function(t){t.target.composing||(e.lines1=e._n(t.target.value))},blur:function(t){return e.$forceUpdate()}}})])]),a("div",{staticClass:"form-group"},[a("label",{staticClass:"form-label col-5 col-sm-12",attrs:{for:"width1"}},[e._v(e._s(e.zh?"容器宽度":"Container width"))]),a("div",{staticClass:"col-7 col-sm-12 tooltip",attrs:{"data-tooltip":e.width1+"%"}},[a("input",{directives:[{name:"model",rawName:"v-model",value:e.width1,expression:"width1"}],staticClass:"slider",attrs:{id:"width1",type:"range",min:"50",max:"100"},domProps:{value:e.width1},on:{__r:function(t){e.width1=t.target.value}}})])]),e.zh?e._e():a("div",{staticClass:"form-group"},[a("div",{staticClass:"col-5 col-sm-12"},[a("label",{staticClass:"form-checkbox"},[a("input",{directives:[{name:"model",rawName:"v-model",value:e.hyphens1,expression:"hyphens1"}],attrs:{type:"checkbox"},domProps:{checked:Array.isArray(e.hyphens1)?e._i(e.hyphens1,null)>-1:e.hyphens1},on:{change:function(t){var a=e.hyphens1,n=t.target,s=!!n.checked;if(Array.isArray(a)){var i=null,o=e._i(a,i);n.checked?o<0&&(e.hyphens1=a.concat([i])):o>-1&&(e.hyphens1=a.slice(0,o).concat(a.slice(o+1)))}else e.hyphens1=s}}}),a("i",{staticClass:"form-icon"}),e._v(" CSS Hyphens ")])]),a("div",{staticClass:"col-5 col-sm-12"},[a("label",{staticClass:"form-checkbox"},[a("input",{directives:[{name:"model",rawName:"v-model",value:e.rtl1,expression:"rtl1"}],attrs:{type:"checkbox"},domProps:{checked:Array.isArray(e.rtl1)?e._i(e.rtl1,null)>-1:e.rtl1},on:{change:function(t){var a=e.rtl1,n=t.target,s=!!n.checked;if(Array.isArray(a)){var i=null,o=e._i(a,i);n.checked?o<0&&(e.rtl1=a.concat([i])):o>-1&&(e.rtl1=a.slice(0,o).concat(a.slice(o+1)))}else e.rtl1=s}}}),a("i",{staticClass:"form-icon"}),e._v(" RTL ")])])])]),a("v-clamp",{class:{demo:!0,hyphens:e.hyphens1,rtl:e.rtl1},style:{width:e.width1+"%"},attrs:{"max-lines":e.lines1,autoresize:""},scopedSlots:e._u([{key:"after",fn:function(t){var n=t.toggle,s=t.expanded,i=t.clamped;return[s||i?a("button",{staticClass:"toggle btn btn-sm",on:{click:n}},[e._v(e._s(e.zh?"切换":"Toggle"))]):e._e()]}}])},[e._v(" "+e._s(e.zh?e.textZh:e.text)+" ")])],1),a("div",{staticClass:"divider text-center",attrs:{"data-content":"↓ max-height & slot `before`"}}),a("section",{staticClass:"case"},[a("div",{staticClass:"form-horizontal"},[a("div",{staticClass:"form-group"},[a("label",{staticClass:"form-label col-5 col-sm-12",attrs:{for:"height"}},[e._v(e._s(e.zh?"最大高度":"Max height"))]),a("div",{staticClass:"col-7 col-sm-12 tooltip",attrs:{"data-tooltip":e.zh?"任意 CSS 长度值":"Any valid CSS length value"}},[a("input",{directives:[{name:"model",rawName:"v-model",value:e.height,expression:"height"}],staticClass:"form-input",attrs:{id:"height"},domProps:{value:e.height},on:{input:function(t){t.target.composing||(e.height=t.target.value)}}})])]),a("div",{staticClass:"form-group"},[a("label",{staticClass:"form-label col-5 col-sm-12",attrs:{for:"width2"}},[e._v(e._s(e.zh?"容器宽度":"Container width"))]),a("div",{staticClass:"col-7 col-sm-12 tooltip",attrs:{"data-tooltip":e.width2+"%"}},[a("input",{directives:[{name:"model",rawName:"v-model",value:e.width2,expression:"width2"}],staticClass:"slider",attrs:{id:"width2",type:"range",min:"50",max:"100"},domProps:{value:e.width2},on:{__r:function(t){e.width2=t.target.value}}})])]),e.zh?e._e():a("div",{staticClass:"form-group"},[a("div",{staticClass:"col-5 col-sm-12"},[a("label",{staticClass:"form-checkbox"},[a("input",{directives:[{name:"model",rawName:"v-model",value:e.hyphens2,expression:"hyphens2"}],attrs:{type:"checkbox"},domProps:{checked:Array.isArray(e.hyphens2)?e._i(e.hyphens2,null)>-1:e.hyphens2},on:{change:function(t){var a=e.hyphens2,n=t.target,s=!!n.checked;if(Array.isArray(a)){var i=null,o=e._i(a,i);n.checked?o<0&&(e.hyphens2=a.concat([i])):o>-1&&(e.hyphens2=a.slice(0,o).concat(a.slice(o+1)))}else e.hyphens2=s}}}),a("i",{staticClass:"form-icon"}),e._v(" CSS Hyphens ")])]),a("div",{staticClass:"col-5 col-sm-12"},[a("label",{staticClass:"form-checkbox"},[a("input",{directives:[{name:"model",rawName:"v-model",value:e.rtl2,expression:"rtl2"}],attrs:{type:"checkbox"},domProps:{checked:Array.isArray(e.rtl2)?e._i(e.rtl2,null)>-1:e.rtl2},on:{change:function(t){var a=e.rtl2,n=t.target,s=!!n.checked;if(Array.isArray(a)){var i=null,o=e._i(a,i);n.checked?o<0&&(e.rtl2=a.concat([i])):o>-1&&(e.rtl2=a.slice(0,o).concat(a.slice(o+1)))}else e.rtl2=s}}}),a("i",{staticClass:"form-icon"}),e._v(" RTL ")])])]),a("div",{staticClass:"form-group"},[a("div",{staticClass:"col-5 col-sm-12"},[a("label",{staticClass:"form-checkbox"},[a("input",{directives:[{name:"model",rawName:"v-model",value:e.expanded1,expression:"expanded1"}],attrs:{type:"checkbox"},domProps:{checked:Array.isArray(e.expanded1)?e._i(e.expanded1,null)>-1:e.expanded1},on:{change:function(t){var a=e.expanded1,n=t.target,s=!!n.checked;if(Array.isArray(a)){var i=null,o=e._i(a,i);n.checked?o<0&&(e.expanded1=a.concat([i])):o>-1&&(e.expanded1=a.slice(0,o).concat(a.slice(o+1)))}else e.expanded1=s}}}),a("i",{staticClass:"form-icon"}),e._v(" "+e._s(e.zh?"展开内容":"Expanded")+" ")])])])]),a("v-clamp",{class:{demo:!0,hyphens:e.hyphens2,rtl:e.rtl2},style:{width:e.width2+"%"},attrs:{"max-height":e.height,autoresize:"",expanded:e.expanded1},on:{"update:expanded":function(t){e.expanded1=t}},scopedSlots:e._u([{key:"before",fn:function(){return[a("span",{staticClass:"featured label label-rounded label-primary"},[e._v(e._s(e.zh?"推荐":"Featured"))])]},proxy:!0}])},[e._v(" "+e._s(e.zh?e.textZh:e.text)+" ")])],1),a("div",{staticClass:"divider text-center",attrs:{"data-content":"↓ `clampchange` event"}}),a("section",{staticClass:"case"},[a("div",{staticClass:"form-horizontal"},[a("div",{staticClass:"form-group"},[a("label",{staticClass:"form-label col-5 col-sm-12",attrs:{for:"lines3"}},[e._v(e._s(e.zh?"最大行数":"Max lines"))]),a("div",{staticClass:"col-7 col-sm-12"},[a("input",{directives:[{name:"model",rawName:"v-model.number",value:e.lines3,expression:"lines3",modifiers:{number:!0}}],staticClass:"form-input",attrs:{id:"lines3",type:"number",min:"1",max:"8",step:"1"},domProps:{value:e.lines3},on:{input:function(t){t.target.composing||(e.lines3=e._n(t.target.value))},blur:function(t){return e.$forceUpdate()}}})])]),a("div",{staticClass:"form-group"},[a("label",{staticClass:"form-label col-5 col-sm-12",attrs:{for:"width3"}},[e._v(e._s(e.zh?"容器宽度":"Container width"))]),a("div",{staticClass:"col-7 col-sm-12 tooltip",attrs:{"data-tooltip":e.width3+"%"}},[a("input",{directives:[{name:"model",rawName:"v-model",value:e.width3,expression:"width3"}],staticClass:"slider",attrs:{id:"width3",type:"range",min:"50",max:"100"},domProps:{value:e.width3},on:{__r:function(t){e.width3=t.target.value}}})])]),e.zh?e._e():a("div",{staticClass:"form-group"},[a("div",{staticClass:"col-5 col-sm-12"},[a("label",{staticClass:"form-checkbox"},[a("input",{directives:[{name:"model",rawName:"v-model",value:e.hyphens3,expression:"hyphens3"}],attrs:{type:"checkbox"},domProps:{checked:Array.isArray(e.hyphens3)?e._i(e.hyphens3,null)>-1:e.hyphens3},on:{change:function(t){var a=e.hyphens3,n=t.target,s=!!n.checked;if(Array.isArray(a)){var i=null,o=e._i(a,i);n.checked?o<0&&(e.hyphens3=a.concat([i])):o>-1&&(e.hyphens3=a.slice(0,o).concat(a.slice(o+1)))}else e.hyphens3=s}}}),a("i",{staticClass:"form-icon"}),e._v(" CSS Hyphens ")])]),a("div",{staticClass:"col-5 col-sm-12"},[a("label",{staticClass:"form-checkbox"},[a("input",{directives:[{name:"model",rawName:"v-model",value:e.rtl3,expression:"rtl3"}],attrs:{type:"checkbox"},domProps:{checked:Array.isArray(e.rtl3)?e._i(e.rtl3,null)>-1:e.rtl3},on:{change:function(t){var a=e.rtl3,n=t.target,s=!!n.checked;if(Array.isArray(a)){var i=null,o=e._i(a,i);n.checked?o<0&&(e.rtl3=a.concat([i])):o>-1&&(e.rtl3=a.slice(0,o).concat(a.slice(o+1)))}else e.rtl3=s}}}),a("i",{staticClass:"form-icon"}),e._v(" RTL ")])])])]),a("v-clamp",{class:{demo:!0,hyphens:e.hyphens3,rtl:e.rtl3},style:{width:e.width3+"%"},attrs:{"max-lines":e.lines3,autoresize:""},on:{clampchange:function(t){e.clamped3=t}}},[e._v(e._s(e.zh?e.textZh:e.text))]),a("p",{staticClass:"mt-2"},[e._v(e._s(e.zh?"截断状态:"+(e.clamped3?"已截断":"未截断"):"Clamped: "+(e.clamped3?"Yes":"No")))])],1),a("h2",{attrs:{id:"usage"}},[a("a",{attrs:{href:"#usage"}},[e._v("#")]),e._v(" "+e._s(e.zh?"使用方法":"Usage")+" ")]),a("div",{staticClass:"divider text-center",attrs:{"data-content":e.zh?"↓ 安装":"↓ Installation"}}),e._m(1),a("div",{staticClass:"divider text-center",attrs:{"data-content":e.zh?"↓ 配置":"↓ Configuration"}}),e.zh?a("p",[e._v(" 对于基于 webpack 的项目, "),a("code",[e._v("import")]),e._v(" 会自动引入未经转译的 ES Module 版本。请确保按如下指导配置相关工具。 ")]):a("p",[e._v(" For project based on webpack, "),a("code",[e._v("import")]),e._v(" will load the untranspiled ES Module version. Please make sure to add the correct config according to following instructions. ")]),a("details",{attrs:{open:""}},[e._m(2),e.zh?a("p",[e._v(" 对于使用 Vue CLI 3 创建的项目,请确保将 "),a("code",[e._v("@boyuai/vue-clamp")]),e._v(" 与 "),a("code",[e._v("resize-detector")]),e._v(" 加入 "),a("code",[e._v("vue.config.js")]),e._v(" 文件的 "),a("code",[e._v("transpileDependencies")]),e._v(" 选项中: ")]):a("p",[e._v(" For projects created with Vue CLI 3, remember to add "),a("code",[e._v("@boyuai/vue-clamp")]),e._v(" and "),a("code",[e._v("resize-detector")]),e._v(" into the "),a("code",[e._v("transpileDependencies")]),e._v(" option in "),a("code",[e._v("vue.config.js")]),e._v(": ")]),e._m(3)]),a("details",[e._m(4),e.zh?a("p",[e._v(" 如果使用的是 Vue CLI 2 的 "),a("code",[e._v("webpack")]),e._v(" 模板,请按如下方式修改 "),a("code",[e._v("build/webpack.base.conf.js")]),e._v(": ")]):a("p",[e._v(" For Vue CLI 2 with the "),a("code",[e._v("webpack")]),e._v(" template, modify "),a("code",[e._v("build/webpack.base.conf.js")]),e._v(" like this: ")]),e._m(5)]),a("details",[e._m(6),e.zh?a("p",[e._v(" 在 Nuxt.js 中使用时,请确保将 "),a("code",[e._v("@boyuai/vue-clamp")]),e._v(" 与 "),a("code",[e._v("resize-detector")]),e._v(" 加入 "),a("code",[e._v("nuxt.config.js")]),e._v(" 文件的 "),a("code",[e._v("build.transpile")]),e._v(" 选项中: ")]):a("p",[e._v(" When using in Nuxt.js, remember to add "),a("code",[e._v("@boyuai/vue-clamp")]),e._v(" and "),a("code",[e._v("resize-detector")]),e._v(" into the "),a("code",[e._v("build.transpile")]),e._v(" option in "),a("code",[e._v("nuxt.config.js")]),e._v(": ")]),e._m(7)]),a("div",{staticClass:"divider text-center",attrs:{"data-content":e.zh?"↓ 代码样例":"↓ Code example"}}),e._m(8),e._m(9),a("div",{staticClass:"divider text-center",attrs:{"data-content":"↓ Props"}}),a("section",[a("ul",[a("li",[e._m(10),a("p",[e._v(e._s(e.zh?"生成的根元素的标签名。":"The tag name of the generated root element."))]),a("p",[e._v(" "+e._s(e.defaultText)+" "),a("code",[e._v("div")])])]),a("li",[e._m(11),a("p",[e._v(e._s(e.zh?"是否要自动适配根元素的尺寸变化。":"Whether to observe the root element's size."))]),a("p",[e._v(" "+e._s(e.defaultText)+" "),a("code",[e._v("false")])])]),a("li",[e._m(12),a("p",[e._v(e._s(e.zh?"可以显示的最大行数。":"The max number of lines that can be displayed."))])]),a("li",[e._m(13),a("p",[e._v(e._s(e.zh?"“非文本”内容需要手动指定行高以便截断。":"Non-text contents must provide their line-height for clamping."))])]),a("li",[e._m(14),e.zh?a("p",[e._v(" 根元素的最大高度。数字值将被转换为 "),a("code",[e._v("px")]),e._v(" 单位;字符串值将直接作为 CSS 属性 "),a("code",[e._v("max-height")]),e._v(" 输出。 ")]):a("p",[e._v(" The max height of the root element. Number values are converted to "),a("code",[e._v("px")]),e._v(" units. String values are used directly as the "),a("code",[e._v("max-height")]),e._v(" CSS property. ")])]),a("li",[e._m(15),a("p",[e._v(e._s(e.zh?"当文字被截断时需要显示的省略号字符串。":"The ellipsis characters displayed when the text is clamped."))]),a("p",[e._v(" "+e._s(e.defaultText)+" "),a("code",[e._v("'…'")])])]),a("li",[e._m(16),a("p",[a("span",{staticClass:"label label-primary tooltip",attrs:{"data-tooltip":e.zh?"支持 .sync 修饰符":"Supports .sync modifier"}},[e._v(".sync")])]),a("p",[e._v(e._s(e.zh?"是否展开显式被截断的内容。":"Whether the clamped area is expanded."))]),a("p",[e._v(" "+e._s(e.defaultText)+" "),a("code",[e._v("false")])])])])]),a("div",{staticClass:"divider text-center",attrs:{"data-content":"↓ Slots"}}),a("section",[a("ul",[a("li",[e._m(17),a("p",[e._v(e._s(e.zh?"需要截断的内容。内容类型必须一致,比如纯文本或者多个标签。":"The contents to clamp. Only supports pure text or same type html node."))])]),a("li",[e._m(18),a("p",[e._v(" Slot "+e._s(e.zh?"作用域:":"scope:")+" "),a("code",[e._v("{ expand, collapse, toggle, clamped, expanded }")])]),a("section",{staticClass:"secondary"},[a("p",[a("code",[e._v("expand: function(): void")]),e._v(" - "+e._s(e.zh?"展开被截断的内容。":"Expand the clamped contents.")+" ")]),a("p",[a("code",[e._v("collapse: function(): void")]),e._v(" - "+e._s(e.zh?"收起展开后的内容。":"Collapse the expanded contents.")+" ")]),a("p",[a("code",[e._v("toggle: function(): void")]),e._v(" - "+e._s(e.zh?"切换被截断内容的展开状态。":"Toggle the expand state of clamped contents.")+" ")]),a("p",[a("code",[e._v("clamped: Boolean")]),e._v(" - "+e._s(e.zh?"内容是否处于截断状态。":"Whether contents are clamped.")+" ")]),a("p",[a("code",[e._v("expanded: Boolean")]),e._v(" - "+e._s(e.zh?"内容是否处于展开状态。":"Whether contents are expanded.")+" ")])]),a("p",[e._v(e._s(e.zh?"在被截断的内容前显式的内容,可以是任意类型的内容。":"Content displayed before the clamped contents. Can contain anything."))])]),a("li",[e._m(19),e.zh?a("p",[e._v(" Slot 作用域:与 "),a("code",[e._v("before")]),e._v(" 相同。 ")]):a("p",[e._v(" Slot scope: Same as "),a("code",[e._v("before")]),e._v(". ")]),a("p",[e._v(e._s(e.zh?"在被截断的内容后显式的内容,可以是任意类型的内容。":"Content displayed after the clamped contents. Can contain anything."))])])])]),a("div",{staticClass:"divider text-center",attrs:{"data-content":"↓ Events"}}),a("section",[a("ul",[a("li",[e._m(20),a("p",[e._v(e._s(e.zh?"截断状态变化时触发。":"Emitted when clamp state changes."))]),a("p",[e._v(" "+e._s(e.parameterText)+" "),a("code",[e._v("(clamped: Boolean)")])])])])]),a("footer",[e.zh?a("p",[e._v(" 作者: "),a("a",{attrs:{href:"https://github.com/Justineo"}},[e._v("@Justineo")]),e._v(e._s(" ")+" "),a("a",{attrs:{href:"https://github.com/helsonxiao"}},[e._v("@helsonxiao")])]):a("p",[e._v(" Authors:"+e._s(" ")+" "),a("a",{attrs:{href:"https://github.com/Justineo"}},[e._v("@Justineo")]),e._v(e._s(" ")+" "),a("a",{attrs:{href:"https://github.com/helsonxiao"}},[e._v("@helsonxiao")])]),a("p",[e.zh?a("small",[e._v(" 本页基于 "),a("a",{attrs:{href:"https://picturepan2.github.io/spectre/"}},[e._v("Spectre.css")]),e._v(" 开发。 ")]):a("small",[e._v(" This page is based on "),a("a",{attrs:{href:"https://picturepan2.github.io/spectre/"}},[e._v("Spectre.css")]),e._v(". ")])])])])},r=[function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("h2",{attrs:{id:"demo"}},[a("a",{attrs:{href:"#demo"}},[e._v("#")]),e._v(" Demo ")])},function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("pre",{staticClass:"code shell",attrs:{"data-lang":"Shell"}},[a("code",[e._v("$ npm i --save @boyuai/vue-clamp")])])},function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("summary",[a("h4",[e._v(" Vue CLI "),a("small",[e._v("v3")])])])},function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("pre",{staticClass:"code javascript",attrs:{"data-lang":"JavaScript"}},[a("code",[e._v("module.exports = {\n transpileDependencies: ['@boyuai/vue-clamp', 'resize-detector']\n}\n")])])},function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("summary",[a("h4",[e._v(" Vue CLI "),a("small",[e._v("v2")])])])},function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("pre",{staticClass:"code diff",attrs:{"data-lang":"Diff"}},[a("code",[e._v(" {\n test: /\\.js$/,\n loader: 'babel-loader',\n- include: [resolve('src'), resolve('test')]\n+ include: [\n+ resolve('src'),\n+ resolve('test'),\n+ resolve('node_modules/@boyuai/vue-clamp'),\n+ resolve('node_modules/resize-detector')\n+ ]\n }\n")])])},function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("summary",[a("h4",[e._v(" Nuxt.js "),a("small",[e._v("v2")])])])},function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("pre",{staticClass:"code javascript",attrs:{"data-lang":"JavaScript"}},[a("code",[e._v("module.exports = {\n build: {\n transpile: ['@boyuai/vue-clamp', 'resize-detector']\n }\n}\n")])])},function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("pre",{pre:!0,attrs:{class:"code vue","data-lang":"Vue"}},[a("code",[e._v("\n\n