├── .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: /,
6 | relevance: 0,
7 | contains: [
8 | {
9 | className: 'attr',
10 | begin: XML_IDENT_RE,
11 | relevance: 0
12 | },
13 | {
14 | begin: /=\s*/,
15 | relevance: 0,
16 | contains: [
17 | {
18 | className: 'string',
19 | endsParent: true,
20 | variants: [
21 | { begin: /"/, end: /"/ },
22 | { begin: /'/, end: /'/ },
23 | { begin: /[^\s"'=<>`]+/ }
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 | '',
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{{ text }}\n\n\n