You've already forked vue-clamp
feat: add clampchange event, revert raf
This commit is contained in:
@@ -1,3 +1,7 @@
|
||||
## 0.3.0
|
||||
|
||||
* Add `clampchange` event.
|
||||
|
||||
## 0.2.2
|
||||
|
||||
* Preserve at lease a single line of content when even a single line would exceeds `max-height`.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
module.exports = {
|
||||
presets: [
|
||||
'@vue/app'
|
||||
'@vue/cli-plugin-babel/preset'
|
||||
]
|
||||
}
|
||||
|
||||
7783
package-lock.json
generated
7783
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
79
package.json
79
package.json
@@ -1,55 +1,56 @@
|
||||
{
|
||||
"name": "vue-clamp",
|
||||
"version": "0.2.2",
|
||||
"license": "MIT",
|
||||
"version": "0.3.0",
|
||||
"description": "Clamping multiline text with ease.",
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"build:demo": "vue-cli-service build",
|
||||
"lint": "vue-cli-service lint",
|
||||
"build": "NODE_ENV=production rollup -c",
|
||||
"lint": "vue-cli-service lint",
|
||||
"build:demo": "vue-cli-service build",
|
||||
"prepublishOnly": "cp ./src/components/Clamp.js .",
|
||||
"publish": "rm ./Clamp.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/Justineo/vue-clamp.git"
|
||||
"main": "dist/vue-clamp.js",
|
||||
"module": "Clamp.js",
|
||||
"dependencies": {
|
||||
"core-js": "^3.6.4",
|
||||
"resize-detector": "^0.1.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-buble": "^0.21.1",
|
||||
"@rollup/plugin-node-resolve": "^7.1.1",
|
||||
"@vue/cli-plugin-babel": "^4.2.3",
|
||||
"@vue/cli-plugin-eslint": "^4.2.3",
|
||||
"@vue/cli-service": "^4.2.3",
|
||||
"@vue/eslint-config-standard": "^4.0.0",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-config-prettier": "^6.10.1",
|
||||
"eslint-config-standard": "^14.1.1",
|
||||
"eslint-plugin-vue": "^6.2.2",
|
||||
"highlight.js": "^9.18.1",
|
||||
"prettier": "^2.0.2",
|
||||
"prettier-eslint": "^9.0.1",
|
||||
"qs": "^6.9.3",
|
||||
"rollup": "^2.2.0",
|
||||
"rollup-plugin-terser": "^5.3.0",
|
||||
"rollup-plugin-vue": "^5.1.6",
|
||||
"spectre.css": "^0.5.8",
|
||||
"stylus": "^0.54.7",
|
||||
"stylus-loader": "^3.0.2",
|
||||
"vue": "^2.6.11",
|
||||
"vue-template-compiler": "^2.6.11"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": "^2.5.17"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/Justineo/vue-clamp/issues"
|
||||
},
|
||||
"homepage": "https://justineo.github.io/vue-clamp/demo/",
|
||||
"main": "dist/vue-clamp.js",
|
||||
"module": "Clamp.js",
|
||||
"dependencies": {
|
||||
"resize-detector": "^0.1.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "^3.11.0",
|
||||
"@vue/cli-plugin-eslint": "^3.11.0",
|
||||
"@vue/cli-service": "^3.11.0",
|
||||
"@vue/eslint-config-standard": "^4.0.0",
|
||||
"babel-eslint": "^10.0.3",
|
||||
"eslint": "^5.16.0",
|
||||
"eslint-config-prettier": "^4.3.0",
|
||||
"eslint-config-standard": "^6.2.1",
|
||||
"eslint-plugin-vue": "^5.2.3",
|
||||
"highlight.js": "^9.15.10",
|
||||
"prettier": "^1.18.2",
|
||||
"prettier-eslint": "^8.8.2",
|
||||
"qs": "^6.8.0",
|
||||
"rollup": "^0.68.2",
|
||||
"rollup-plugin-buble": "^0.19.8",
|
||||
"rollup-plugin-node-resolve": "^4.2.4",
|
||||
"rollup-plugin-terser": "^3.0.0",
|
||||
"rollup-plugin-vue": "^4.7.2",
|
||||
"spectre.css": "^0.5.8",
|
||||
"stylus": "^0.54.7",
|
||||
"stylus-loader": "^3.0.2",
|
||||
"vue": "^2.6.10",
|
||||
"vue-template-compiler": "^2.6.10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": "^2.5.17"
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/Justineo/vue-clamp.git"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import vue from 'rollup-plugin-vue'
|
||||
import buble from 'rollup-plugin-buble'
|
||||
import buble from '@rollup/plugin-buble'
|
||||
import { terser } from 'rollup-plugin-terser'
|
||||
import resolve from 'rollup-plugin-node-resolve'
|
||||
import resolve from '@rollup/plugin-node-resolve'
|
||||
|
||||
export default {
|
||||
input: 'src/components/Clamp.js',
|
||||
|
||||
111
src/App.vue
111
src/App.vue
@@ -32,7 +32,6 @@
|
||||
GitHub →
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<h2 id="features"><a href="#features">#</a> {{ zh ? '功能' : 'Features' }}</h2>
|
||||
<ul>
|
||||
<li>{{ zh ? '可以选择限制行数与/或最大高度,无需指定行高。' : 'Clamps text with max lines and/or max height. No need to specify line height.' }}</li>
|
||||
@@ -40,7 +39,6 @@
|
||||
<li>{{ zh ? '支持展开/收起被截断部分内容。' : 'The clamped text can be expanded/collapsed.' }}</li>
|
||||
<li>{{ zh ? '支持自定义截断文本前后内容,并且进行响应式更新。' : 'Customizable and responsive content before/after clamped text.' }}</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="demo"><a href="#demo">#</a> Demo</h2>
|
||||
<div
|
||||
class="divider text-center"
|
||||
@@ -224,6 +222,88 @@
|
||||
</template>
|
||||
</v-clamp>
|
||||
</section>
|
||||
<div
|
||||
class="divider text-center"
|
||||
data-content="↓ `clampchange` event"
|
||||
/>
|
||||
<section class="case">
|
||||
<div class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<label
|
||||
class="form-label col-5 col-sm-12"
|
||||
for="lines3"
|
||||
>
|
||||
{{ zh ? '最大行数' : 'Max lines' }}
|
||||
</label>
|
||||
<div
|
||||
class="col-7 col-sm-12"
|
||||
>
|
||||
<input
|
||||
id="lines3"
|
||||
v-model.number="lines3"
|
||||
class="form-input"
|
||||
type="number"
|
||||
min="1"
|
||||
max="8"
|
||||
step="1"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label
|
||||
class="form-label col-5 col-sm-12"
|
||||
for="width3"
|
||||
>
|
||||
{{ zh ? '容器宽度' : 'Container width' }}
|
||||
</label>
|
||||
<div
|
||||
class="col-7 col-sm-12 tooltip"
|
||||
:data-tooltip="`${width3}px`"
|
||||
>
|
||||
<input
|
||||
id="width3"
|
||||
v-model="width3"
|
||||
class="slider"
|
||||
type="range"
|
||||
min="240"
|
||||
max="600"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="!zh"
|
||||
class="form-group"
|
||||
>
|
||||
<div class="col-5 col-sm-12">
|
||||
<label class="form-checkbox">
|
||||
<input
|
||||
v-model="hyphens3"
|
||||
type="checkbox"
|
||||
>
|
||||
<i class="form-icon"/>
|
||||
CSS <code>hyphens</code>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<v-clamp
|
||||
:class="{
|
||||
demo: true,
|
||||
hyphens: hyphens3
|
||||
}"
|
||||
:max-lines="lines3"
|
||||
autoresize
|
||||
:style="{
|
||||
width: `${width3}px`
|
||||
}"
|
||||
@clampchange="clamped3 = $event"
|
||||
>
|
||||
{{ zh ? textZh : text }}
|
||||
</v-clamp>
|
||||
<p class="mt-2">
|
||||
{{ zh ? '截断状态:' + (clamped3 ? '已截断' : '未截断') : 'Clamped: ' + (clamped3 ? 'Yes' : 'No')}}
|
||||
</p>
|
||||
</section>
|
||||
<h2 id="usage"><a href="#usage">#</a> {{ zh ? '使用方法' : 'Usage' }}</h2>
|
||||
<div
|
||||
class="divider text-center"
|
||||
@@ -392,6 +472,19 @@ export default {
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
<div
|
||||
class="divider text-center"
|
||||
data-content="↓ Events"
|
||||
/>
|
||||
<section>
|
||||
<ul>
|
||||
<li>
|
||||
<p><code>clampchange</code></p>
|
||||
<p>{{ zh ? '截断状态变化时触发。' : 'Emitted when clamp state changes.' }}</p>
|
||||
<p>{{ parameterText }}<code>(clamped: Boolean)</code></p>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
<footer>
|
||||
<p v-if="zh">由 <a href="https://github.com/Justineo">@Justineo</a> 创作。</p>
|
||||
<p v-else>Made by <a href="https://github.com/Justineo">@Justineo</a>.</p>
|
||||
@@ -417,9 +510,9 @@ hljs.registerLanguage('javascript', javascript)
|
||||
hljs.registerLanguage('diff', diff)
|
||||
hljs.registerLanguage('shell', shell)
|
||||
|
||||
let search = location.search.replace(/^\?/, '')
|
||||
let query = qs.parse(search)
|
||||
let zh = query.lang === 'zh'
|
||||
const search = location.search.replace(/^\?/, '')
|
||||
const query = qs.parse(search)
|
||||
const zh = query.lang === 'zh'
|
||||
|
||||
export default {
|
||||
name: 'app',
|
||||
@@ -435,6 +528,10 @@ export default {
|
||||
height: 'calc(48px + 12em)',
|
||||
width2: 600,
|
||||
hyphens2: true,
|
||||
lines3: 5,
|
||||
width3: 600,
|
||||
hyphens3: true,
|
||||
clamped3: false,
|
||||
text:
|
||||
'Vue (pronounced /vjuː/, like view) is a progressive framework for building user interfaces. Unlike other monolithic frameworks, Vue is designed from the ground up to be incrementally adoptable. The core library is focused on the view layer only, and is easy to pick up and integrate with other libraries or existing projects. On the other hand, Vue is also perfectly capable of powering sophisticated Single-Page Applications when used in combination with modern tooling and supporting libraries.',
|
||||
textZh:
|
||||
@@ -446,6 +543,9 @@ export default {
|
||||
computed: {
|
||||
defaultText () {
|
||||
return this.zh ? '默认值:' : 'Default:'
|
||||
},
|
||||
parameterText () {
|
||||
return this.zh ? '回调参数:' : 'Callback parameter list:'
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -548,6 +648,7 @@ summary
|
||||
display flex
|
||||
align-items center
|
||||
margin-bottom 0.5em
|
||||
cursor pointer
|
||||
|
||||
h4
|
||||
margin 0
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import { addListener, removeListener } from 'resize-detector'
|
||||
|
||||
const UPDATE_TRIGGERS = ['maxLines', 'maxHeight', 'ellipsis', 'isClamped']
|
||||
const INIT_TRIGGERS = ['tag', 'text', 'autoresize']
|
||||
|
||||
export default {
|
||||
name: 'vue-clamp',
|
||||
props: {
|
||||
@@ -46,7 +43,7 @@ export default {
|
||||
if (this.localExpanded) {
|
||||
return null
|
||||
}
|
||||
let { maxHeight } = this
|
||||
const { maxHeight } = this
|
||||
if (!maxHeight) {
|
||||
return null
|
||||
}
|
||||
@@ -57,13 +54,6 @@ export default {
|
||||
expanded (val) {
|
||||
this.localExpanded = val
|
||||
},
|
||||
isClamped: {
|
||||
handler (val) {
|
||||
this.$nextTick()
|
||||
.then(() => this.$emit('change', val))
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
localExpanded (val) {
|
||||
if (val) {
|
||||
this.clampAt(this.text.length)
|
||||
@@ -73,18 +63,19 @@ export default {
|
||||
if (this.expanded !== val) {
|
||||
this.$emit('update:expanded', val)
|
||||
}
|
||||
},
|
||||
isClamped: {
|
||||
handler (val) {
|
||||
this.$nextTick(() => this.$emit('clampchange', val))
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.init()
|
||||
|
||||
INIT_TRIGGERS.forEach(prop => {
|
||||
this.$watch(prop, this.init)
|
||||
})
|
||||
|
||||
UPDATE_TRIGGERS.forEach(prop => {
|
||||
this.$watch(prop, this.update)
|
||||
})
|
||||
this.$watch(vm => [vm.maxLines, vm.maxHeight, vm.ellipsis, vm.isClamped].join(), this.update)
|
||||
this.$watch(vm => [vm.tag, vm.text, vm.autoresize].join(), this.init)
|
||||
},
|
||||
updated () {
|
||||
this.text = this.getText()
|
||||
@@ -95,7 +86,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
init () {
|
||||
let contents = this.$slots.default
|
||||
const contents = this.$slots.default
|
||||
if (!contents) {
|
||||
return
|
||||
}
|
||||
@@ -105,12 +96,9 @@ export default {
|
||||
this.cleanUp()
|
||||
|
||||
if (this.autoresize) {
|
||||
let resizeCallback = () => {
|
||||
window.requestAnimationFrame(this.update)
|
||||
}
|
||||
addListener(this.$el, resizeCallback)
|
||||
addListener(this.$el, this.update)
|
||||
this.unregisterResizeCallback = () => {
|
||||
removeListener(this.$el, resizeCallback)
|
||||
removeListener(this.$el, this.update)
|
||||
}
|
||||
}
|
||||
this.update()
|
||||
@@ -156,7 +144,7 @@ export default {
|
||||
},
|
||||
getText () {
|
||||
// Look for the first non-empty text node
|
||||
let [content] = (this.$slots.default || []).filter(
|
||||
const [content] = (this.$slots.default || []).filter(
|
||||
node => !node.tag && !node.isComment
|
||||
)
|
||||
return content ? content.text : ''
|
||||
@@ -189,12 +177,12 @@ export default {
|
||||
}
|
||||
},
|
||||
search (...range) {
|
||||
let [from = 0, to = this.offset] = range
|
||||
const [from = 0, to = this.offset] = range
|
||||
if (to - from <= 3) {
|
||||
this.stepToFit()
|
||||
return
|
||||
}
|
||||
let target = Math.floor((to + from) / 2)
|
||||
const target = Math.floor((to + from) / 2)
|
||||
this.clampAt(target)
|
||||
if (this.isOverflow()) {
|
||||
this.search(from, target)
|
||||
@@ -209,7 +197,7 @@ export default {
|
||||
}
|
||||
},
|
||||
render (h) {
|
||||
let contents = [
|
||||
const contents = [
|
||||
h(
|
||||
'span',
|
||||
{
|
||||
@@ -222,27 +210,27 @@ export default {
|
||||
)
|
||||
]
|
||||
|
||||
let { expand, collapse, toggle } = this
|
||||
let scope = {
|
||||
const { expand, collapse, toggle } = this
|
||||
const scope = {
|
||||
expand,
|
||||
collapse,
|
||||
toggle,
|
||||
clamped: this.isClamped,
|
||||
expanded: this.localExpanded
|
||||
}
|
||||
let before = this.$scopedSlots.before
|
||||
const before = this.$scopedSlots.before
|
||||
? this.$scopedSlots.before(scope)
|
||||
: this.$slots.before
|
||||
if (before) {
|
||||
contents.unshift(...(Array.isArray(before) ? before : [before]))
|
||||
}
|
||||
let after = this.$scopedSlots.after
|
||||
const after = this.$scopedSlots.after
|
||||
? this.$scopedSlots.after(scope)
|
||||
: this.$slots.after
|
||||
if (after) {
|
||||
contents.push(...(Array.isArray(after) ? after : [after]))
|
||||
}
|
||||
let lines = [
|
||||
const lines = [
|
||||
h(
|
||||
'span',
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user