Skip to content

Commit

Permalink
feat(useEllipsis): support custom action
Browse files Browse the repository at this point in the history
  • Loading branch information
nemo-shen committed Jan 13, 2024
1 parent b3d53cb commit 5969927
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 23 deletions.
66 changes: 53 additions & 13 deletions packages/core/useEllipsis/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
import { ref, type Ref, VNode, nextTick, computed, ComputedRef } from 'vue'
import {
ref,
type Ref,
render,
type VNode,
nextTick,
computed,
ComputedRef,
} from 'vue'

export enum EllipsisPosition {
Start = 'start',
Expand All @@ -15,7 +23,7 @@ interface UseEllipsisOptions {
rows?: number // 同组件 prop default: 1
ellipsisText?: string // 同组件 prop default: '...'
position?: EllipsisPosition // 同组件 prop default 'end'
action?: boolean | VNode // 操作 false = 不需要 true 表示使用默认的,即 展开 | 折叠,VNode则表示自定义slot 传入之后会被计算到字符中
action?: (payload: { state: Ref<EllipsisState>; toggle: Function }) => VNode // 操作 VNode则表示自定义slot 传入之后会被计算到字符中
}
interface UseEllipsisReturn {
content: ComputedRef<string> // 省略后的内容
Expand Down Expand Up @@ -60,7 +68,8 @@ const calcEllipsisText = (
clone: UseCloneElementReturn,
sourceContent: string,
ellipsisText: string,
position: EllipsisPosition
position: EllipsisPosition,
actionNode: VNode
) => {
const node = clone.dupNode

Expand Down Expand Up @@ -111,19 +120,49 @@ const calcEllipsisText = (
return node.innerText
}

function withAction(content: string) {
node.innerText = content
const dummyNode = document.createElement('div')
render(actionNode, dummyNode)
node.appendChild(dummyNode.firstChild)
if (node.clientHeight > lineHeight) {
let newContent
switch (position) {
case EllipsisPosition.Start:
newContent = ellipsisText + content.slice(1 + ellipsisText.length)
break
case EllipsisPosition.End:
newContent =
content.slice(0, content.length - 1 - ellipsisText.length) +
ellipsisText
break
default:
newContent =
content.slice(0, content.length - 1 - ellipsisText.length) +
ellipsisText
break
}
return withAction(newContent)
}
return content
}

let res = calc(sourceContent)
if (ellipsisText.length !== 0) {
res = withEllipsisText(res)
}
clone.unmount()
if (actionNode) {
res = withAction(res)
}

// clone.unmount()
return res
}

const defaultUseEllipsisOptions = {
rows: 1,
ellipsisText: '...',
position: EllipsisPosition.End,
action: false,
}

export const useEllipsis = (
Expand All @@ -136,23 +175,24 @@ export const useEllipsis = (
const state = ref(EllipsisState.Collapsed)
const clone = ref<UseCloneElementReturn>()

const toggle = () => {
state.value =
state.value === EllipsisState.Collapsed
? EllipsisState.Expanded
: EllipsisState.Collapsed
}

nextTick(() => {
clone.value = useCloneElement(target.value)
ellipsisContent.value = calcEllipsisText(
clone.value,
options.content.value,
options.ellipsisText,
options.position
options.position,
options.action ? options.action({ state, toggle }) : undefined
)
})

const toggle = () => {
state.value =
state.value === EllipsisState.Collapsed
? EllipsisState.Expanded
: EllipsisState.Collapsed
}

const content = computed(() =>
state.value === EllipsisState.Collapsed
? ellipsisContent.value
Expand Down
23 changes: 13 additions & 10 deletions src/demo/UseEllipsis.vue
Original file line number Diff line number Diff line change
@@ -1,39 +1,42 @@
<script setup lang="ts">
import { ref, h } from 'vue'
import { ref, h, VNode } from 'vue'
import { useEllipsis, EllipsisPosition } from '@noi/core'
import { useWindowSize } from '@vueuse/core'
const ellipsisRef = ref<HTMLElement>()
const sourceContent = ref(
'擁有正確的座右銘,可以幫助你改變心態,自信迎接新的一天,比前一天更好。座右銘能改變你的生活。將勵志名言納入內容,作為文案,用這些金句激勵讀者。讓名言成為你的引領,展翅高飛!'
)
const renderButton = () => {
return h(
const renderButton = (_this) =>
h(
'button',
{
on: {
click: toggle,
click: () => {
_this.toggle()
},
},
},
state === 'expanded' ? 'Collapsed' : 'Expanded'
'Expanded'
)
}
const { content, state, toggle } = useEllipsis(ellipsisRef, {
content: sourceContent,
position: EllipsisPosition.Start,
position: EllipsisPosition.End,
ellipsisText: '...',
})
</script>

<template>
<div class="ellipsis" ref="ellipsisRef">{{ content }}</div>
{{ state }}
<span class="ellipsis" ref="ellipsisRef">
{{ content }}
</span>
<button @click="toggle">
{{ state === 'expanded' ? 'Collapsed' : 'Expanded' }}
</button>
</template>

<style>
.ellipsis {
display: inline-block;
width: 200px;
font-size: 22px;
line-height: 32px;
Expand Down

0 comments on commit 5969927

Please sign in to comment.