Skip to content

Commit

Permalink
feat(useEllipsis): support position
Browse files Browse the repository at this point in the history
  • Loading branch information
nemo-shen committed Jan 13, 2024
1 parent eb6dfd6 commit b3d53cb
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 9 deletions.
57 changes: 49 additions & 8 deletions packages/core/useEllipsis/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { ref, type Ref, VNode, nextTick, computed, ComputedRef } from 'vue'

export enum EllipsisPosition {
Start = 'start',
Middle = 'middle',
End = 'end',
}

Expand Down Expand Up @@ -31,7 +30,7 @@ interface UseCloneElementReturn {

/**
* 存放省略内容的容器需要是一个没有其他元素的干净容器,如果需要在内部增加action,可以通过action option 增加
* 如果需要控制省略位置可以通过 postion option 控制 'left' | 'center' | 'right'(default)
* 如果需要控制省略位置可以通过 position option 控制 'left' | 'center' | 'right'(default)
* 如果需要控制省略符号可以通过 ellipsisText: '...' default
* @param source
*/
Expand Down Expand Up @@ -59,16 +58,19 @@ const useCloneElement = (source: HTMLElement): UseCloneElementReturn => {

const calcEllipsisText = (
clone: UseCloneElementReturn,
sourceContent: string
sourceContent: string,
ellipsisText: string,
position: EllipsisPosition
) => {
const node = clone.dupNode

const style = window.getComputedStyle(node)
const lineHeight = parseFloat(style.lineHeight)
// 先把 ellipsisText 放到node中进行试算,那么我们就能知道我们至少要留多少空间给ellipsisText,也就是说

function calc(content: string, res = '', tail = '') {
if (content.length === 0) return res

const style = window.getComputedStyle(node)
const lineHeight = parseFloat(style.lineHeight)

if (content.length === 1) {
node.innerText = `${res}${content}`
if (node.clientHeight > lineHeight) {
Expand All @@ -88,22 +90,60 @@ const calcEllipsisText = (
}
return calc(remain + tail, res + half, '')
}
const res = calc(sourceContent)

function withEllipsisText(content: string) {
node.innerText = ''
const newContent = content.slice(0, content.length - 1)
switch (position) {
case EllipsisPosition.Start:
node.innerText = ellipsisText + content
break
case EllipsisPosition.End:
node.innerText = content + ellipsisText
break
default:
node.innerText = content + ellipsisText
break
}
if (node.clientHeight > lineHeight) {
return withEllipsisText(newContent)
}
return node.innerText
}

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

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

export const useEllipsis = (
target: Ref<HTMLElement>,
options: UseEllipsisOptions
): UseEllipsisReturn => {
// eslint-disable-next-line no-param-reassign
options = { ...defaultUseEllipsisOptions, ...options }
const ellipsisContent = ref('')
const state = ref(EllipsisState.Collapsed)
const clone = ref<UseCloneElementReturn>()

nextTick(() => {
clone.value = useCloneElement(target.value)
ellipsisContent.value = calcEllipsisText(clone.value, options.content.value)
ellipsisContent.value = calcEllipsisText(
clone.value,
options.content.value,
options.ellipsisText,
options.position
)
})

const toggle = () => {
Expand All @@ -118,6 +158,7 @@ export const useEllipsis = (
? ellipsisContent.value
: options.content.value
)

return {
content,
state: EllipsisState.Collapsed,
Expand Down
2 changes: 1 addition & 1 deletion src/demo/UseEllipsis.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const renderButton = () => {
}
const { content, state, toggle } = useEllipsis(ellipsisRef, {
content: sourceContent,
position: EllipsisPosition.End,
position: EllipsisPosition.Start,
ellipsisText: '...',
})
</script>
Expand Down

0 comments on commit b3d53cb

Please sign in to comment.