@leafer-ui/text 1.0.0-rc.3 → 1.0.0-rc.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leafer-ui/text",
3
- "version": "1.0.0-rc.3",
3
+ "version": "1.0.0-rc.30",
4
4
  "description": "@leafer-ui/text",
5
5
  "author": "Chao (Leafer) Wan",
6
6
  "license": "MIT",
@@ -15,17 +15,17 @@
15
15
  "type": "git",
16
16
  "url": "https://github.com/leaferjs/ui.git"
17
17
  },
18
- "homepage": "https://github.com/leaferjs/ui/tree/main/packages/text",
18
+ "homepage": "https://github.com/leaferjs/ui/tree/main/packages/partner/text",
19
19
  "bugs": "https://github.com/leaferjs/ui/issues",
20
20
  "keywords": [
21
21
  "leafer-ui",
22
22
  "leaferjs"
23
23
  ],
24
24
  "dependencies": {
25
- "@leafer-ui/core": "1.0.0-rc.3"
25
+ "@leafer/core": "1.0.0-rc.30"
26
26
  },
27
27
  "devDependencies": {
28
- "@leafer/interface": "1.0.0-rc.3",
29
- "@leafer-ui/interface": "1.0.0-rc.3"
28
+ "@leafer/interface": "1.0.0-rc.30",
29
+ "@leafer-ui/interface": "1.0.0-rc.30"
30
30
  }
31
31
  }
package/src/CharLayout.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { ITextCharData, ITextData, ITextDrawData } from '@leafer-ui/interface'
1
+ import { ITextCharData, ITextData, ITextDrawData, ITextRowData } from '@leafer-ui/interface'
2
2
 
3
3
 
4
4
  const CharMode = 0 // data: [{char:'a', x: 0}, {char:'b', x: 5}, {char:'d', x:20}]
5
5
  const WordMode = 1 // data: [{ char:'ab', x: 0}, { char:'d', x:20}]
6
- const RowMode = 2 // text: 'ab c'
6
+ const TextMode = 2 // text: 'ab c'
7
7
 
8
8
  export function layoutChar(drawData: ITextDrawData, style: ITextData, width: number, _height: number): void {
9
9
 
@@ -16,18 +16,13 @@ export function layoutChar(drawData: ITextDrawData, style: ITextData, width: num
16
16
 
17
17
  indentWidth = paraIndent && row.paraStart ? paraIndent : 0
18
18
  addWordWidth = (width && textAlign === 'justify' && row.words.length > 1) ? (width - row.width - indentWidth) / (row.words.length - 1) : 0
19
- mode = (letterSpacing || row.isOverflow) ? CharMode : (addWordWidth > 0.01 ? WordMode : RowMode)
19
+ mode = (letterSpacing || row.isOverflow) ? CharMode : (addWordWidth > 0.01 ? WordMode : TextMode)
20
+ if (row.isOverflow && !letterSpacing) row.textMode = true
20
21
 
21
- if (mode === RowMode) {
22
+ if (mode === TextMode) {
22
23
 
23
- row.text = ''
24
24
  row.x += indentWidth
25
-
26
- row.words.forEach(word => {
27
- word.data.forEach(char => {
28
- row.text += char.char
29
- })
30
- })
25
+ toTextChar(row)
31
26
 
32
27
  } else {
33
28
 
@@ -41,11 +36,11 @@ export function layoutChar(drawData: ITextDrawData, style: ITextData, width: num
41
36
 
42
37
  wordChar = { char: '', x: charX }
43
38
  charX = toWordChar(word.data, charX, wordChar)
44
- if (wordChar.char !== ' ') row.data.push(wordChar)
39
+ if (row.isOverflow || wordChar.char !== ' ') row.data.push(wordChar)
45
40
 
46
41
  } else {
47
42
 
48
- charX = toChar(word.data, charX, row.data)
43
+ charX = toChar(word.data, charX, row.data, row.isOverflow)
49
44
 
50
45
  }
51
46
 
@@ -63,6 +58,15 @@ export function layoutChar(drawData: ITextDrawData, style: ITextData, width: num
63
58
 
64
59
  }
65
60
 
61
+ function toTextChar(row: ITextRowData): void {
62
+ row.text = ''
63
+ row.words.forEach(word => {
64
+ word.data.forEach(char => {
65
+ row.text += char.char
66
+ })
67
+ })
68
+ }
69
+
66
70
  function toWordChar(data: ITextCharData[], charX: number, wordChar: ITextCharData): number {
67
71
  data.forEach(char => {
68
72
  wordChar.char += char.char
@@ -71,9 +75,9 @@ function toWordChar(data: ITextCharData[], charX: number, wordChar: ITextCharDat
71
75
  return charX
72
76
  }
73
77
 
74
- function toChar(data: ITextCharData[], charX: number, rowData: ITextCharData[]): number {
78
+ function toChar(data: ITextCharData[], charX: number, rowData: ITextCharData[], isOverflow?: boolean): number {
75
79
  data.forEach(char => {
76
- if (char.char !== ' ') {
80
+ if (isOverflow || char.char !== ' ') {
77
81
  char.x = charX
78
82
  rowData.push(char)
79
83
  }
package/src/TextClip.ts CHANGED
@@ -1,39 +1,60 @@
1
1
  import { Platform } from '@leafer/core'
2
2
 
3
- import { IOverflow, ITextCharData, ITextDrawData } from '@leafer-ui/interface'
3
+ import { ITextCharData, ITextData, ITextDrawData, ITextRowData } from '@leafer-ui/interface'
4
4
 
5
5
 
6
- export function clipText(drawData: ITextDrawData, textOverflow: IOverflow | string): void {
6
+ export function clipText(drawData: ITextDrawData, style: ITextData, x: number, width: number): void {
7
+ if (!width) return
7
8
 
8
9
  const { rows, overflow } = drawData
10
+ let { textOverflow } = style
9
11
  rows.splice(overflow)
10
12
 
11
- if (textOverflow !== 'hide') {
12
- if (textOverflow === 'ellipsis') textOverflow = '...'
13
+ if (textOverflow && textOverflow !== 'show') {
14
+ if (textOverflow === 'hide') textOverflow = ''
15
+ else if (textOverflow === 'ellipsis') textOverflow = '...'
13
16
 
14
- const ellipsisWidth = Platform.canvas.measureText(textOverflow).width
15
- const row = rows[overflow - 1]
17
+ let char: ITextCharData, charRight: number
18
+ const ellipsisWidth = textOverflow ? Platform.canvas.measureText(textOverflow).width : 0
19
+ const right = x + width - ellipsisWidth
20
+ const list = style.textWrap === 'none' ? rows : [rows[overflow - 1]]
16
21
 
17
- let char: ITextCharData, end = row.data.length - 1, charRight: number
22
+ list.forEach(row => {
18
23
 
19
- const { x, width } = drawData.bounds
20
- const right = x + width - ellipsisWidth
24
+ if (row.isOverflow && row.data) {
25
+
26
+ let end = row.data.length - 1
27
+
28
+ for (let i = end; i > -1; i--) {
29
+ char = row.data[i]
30
+ charRight = char.x + char.width
31
+ if (i === end && charRight < right) {
32
+ break
33
+ } else if (charRight < right && char.char !== ' ') {
34
+ row.data.splice(i + 1)
35
+ row.width -= char.width
36
+ break
37
+ }
38
+ row.width -= char.width
39
+ }
21
40
 
22
- for (let i = end; i > -1; i--) {
23
- char = row.data[i]
24
- charRight = char.x + char.width
25
- if (i === end && charRight < right) {
26
- break
27
- } else if (charRight < right && char.char !== ' ') {
28
- row.data.splice(i + 1)
29
- row.width -= char.width
30
- break
41
+ row.width += ellipsisWidth
42
+ row.data.push({ char: textOverflow, x: charRight })
43
+
44
+ if (row.textMode) toTextChar(row)
31
45
  }
32
- row.width -= char.width
33
- }
34
46
 
35
- row.width += ellipsisWidth
36
- row.data.push({ char: textOverflow, x: charRight })
47
+
48
+ })
49
+
37
50
  }
38
51
 
52
+ }
53
+
54
+ function toTextChar(row: ITextRowData): void {
55
+ row.text = ''
56
+ row.data.forEach(char => {
57
+ row.text += char.char
58
+ })
59
+ row.data = null
39
60
  }
@@ -1,6 +1,6 @@
1
- import { MathHelper, Platform } from '@leafer/core'
1
+ import { Platform, Direction4 } from '@leafer/core'
2
2
 
3
- import { ITextConvertModule, ITextData, ITextDrawData } from '@leafer-ui/interface'
3
+ import { ITextData, ITextDrawData } from '@leafer-ui/interface'
4
4
 
5
5
  import { createRows } from './TextRows'
6
6
  import { layoutChar } from './CharLayout'
@@ -9,50 +9,79 @@ import { clipText } from './TextClip'
9
9
  import { decorationText } from './TextDecoration'
10
10
 
11
11
 
12
- export const TextConvert: ITextConvertModule = {
12
+ const { top, right, bottom, left } = Direction4
13
13
 
14
- getDrawData(content: string, style: ITextData): ITextDrawData {
14
+ export function getDrawData(content: string, style: ITextData): ITextDrawData {
15
15
 
16
- if (typeof content !== 'string') content = String(content)
16
+ if (typeof content !== 'string') content = String(content)
17
17
 
18
- let x = 0, y = 0
18
+ let x = 0, y = 0
19
19
 
20
- let width = style.__getInput('width') || 0
21
- let height = style.__getInput('height') || 0
20
+ let width = style.__getInput('width') || 0
21
+ let height = style.__getInput('height') || 0
22
22
 
23
- const { textDecoration, textOverflow, __font, padding } = style
23
+ const { textDecoration, __font, __padding: padding } = style
24
24
 
25
- if (padding) {
26
- const [top, right, bottom, left] = MathHelper.fourNumber(padding)
27
- if (width) {
28
- x = left
29
- width -= (right + left)
30
- }
31
- if (height) {
32
- y = top
33
- height -= (top + bottom)
34
- }
25
+ if (padding) {
26
+ if (width) {
27
+ x = padding[left]
28
+ width -= (padding[right] + padding[left])
35
29
  }
36
-
37
- const drawData: ITextDrawData = {
38
- bounds: { x, y, width, height },
39
- rows: [],
40
- paraNumber: 0,
41
- font: Platform.canvas.font = __font
30
+ if (height) {
31
+ y = padding[top]
32
+ height -= (padding[top] + padding[bottom])
42
33
  }
34
+ }
35
+
36
+ const drawData: ITextDrawData = {
37
+ bounds: { x, y, width, height },
38
+ rows: [],
39
+ paraNumber: 0,
40
+ font: Platform.canvas.font = __font
41
+ }
42
+
43
+ createRows(drawData, content, style) // set rows, paraNumber
44
+
45
+ if (padding) padAutoText(padding, drawData, style, width, height)
43
46
 
44
- createRows(drawData, content, style) // set rows, paraNumber
47
+ layoutText(drawData, style) // set bounds
45
48
 
46
- layoutText(drawData, style) // set bounds
49
+ layoutChar(drawData, style, width, height) // set char.x
47
50
 
48
- layoutChar(drawData, style, width, height) // set char.x
51
+ if (drawData.overflow) clipText(drawData, style, x, width)
49
52
 
50
- if (drawData.overflow) clipText(drawData, textOverflow)
53
+ if (textDecoration !== 'none') decorationText(drawData, style)
51
54
 
52
- if (textDecoration !== 'none') decorationText(drawData, style)
55
+ return drawData
53
56
 
54
- return drawData
57
+ }
55
58
 
59
+
60
+ function padAutoText(padding: number[], drawData: ITextDrawData, style: ITextData, width: number, height: number): void {
61
+ if (!width) {
62
+ switch (style.textAlign) {
63
+ case 'left':
64
+ offsetText(drawData, 'x', padding[left])
65
+ break
66
+ case 'right':
67
+ offsetText(drawData, 'x', -padding[right])
68
+ }
69
+ }
70
+
71
+ if (!height) {
72
+ switch (style.verticalAlign) {
73
+ case 'top':
74
+ offsetText(drawData, 'y', padding[top])
75
+ break
76
+ case 'bottom':
77
+ offsetText(drawData, 'y', -padding[bottom])
78
+ }
56
79
  }
80
+ }
81
+
57
82
 
83
+ function offsetText(drawData: ITextDrawData, attrName: 'x' | 'y', value: number): void {
84
+ const { bounds, rows } = drawData
85
+ bounds[attrName] += value
86
+ for (let i = 0; i < rows.length; i++) rows[i][attrName] += value
58
87
  }
package/src/TextLayout.ts CHANGED
@@ -4,14 +4,14 @@ import { ITextData, ITextDrawData, ITextRowData } from '@leafer-ui/interface'
4
4
  export function layoutText(drawData: ITextDrawData, style: ITextData): void {
5
5
 
6
6
  const { rows, bounds } = drawData
7
- const { __lineHeight, __baseLine, __letterSpacing, textAlign, verticalAlign, paraSpacing, textOverflow } = style
7
+ const { __lineHeight, __baseLine, __letterSpacing, __clipText, textAlign, verticalAlign, paraSpacing } = style
8
8
 
9
9
  let { x, y, width, height } = bounds, realHeight = __lineHeight * rows.length + (paraSpacing ? paraSpacing * (drawData.paraNumber - 1) : 0)
10
10
  let starY: number = __baseLine
11
11
 
12
12
  // verticalAlign
13
13
 
14
- if (textOverflow !== 'show' && realHeight > height) {
14
+ if (__clipText && realHeight > height) {
15
15
  realHeight = Math.max(height, __lineHeight)
16
16
  drawData.overflow = rows.length
17
17
  } else {
@@ -33,12 +33,14 @@ export function layoutText(drawData: ITextDrawData, style: ITextData): void {
33
33
  row = rows[i]
34
34
  row.x = x
35
35
 
36
- switch (textAlign) {
37
- case 'center':
38
- row.x += (width - row.width) / 2
39
- break
40
- case 'right':
41
- row.x += width - row.width
36
+ if (row.width < width || (row.width > width && !__clipText)) {
37
+ switch (textAlign) {
38
+ case 'center':
39
+ row.x += (width - row.width) / 2
40
+ break
41
+ case 'right':
42
+ row.x += width - row.width
43
+ }
42
44
  }
43
45
 
44
46
  if (row.paraStart && paraSpacing && i > 0) starY += paraSpacing
@@ -68,6 +70,11 @@ export function layoutText(drawData: ITextDrawData, style: ITextData): void {
68
70
  if (rowX < bounds.x) bounds.x = rowX
69
71
  if (rowWidth > bounds.width) bounds.width = rowWidth
70
72
 
73
+ // clip nowrap
74
+ if (__clipText && width && width < rowWidth) {
75
+ row.isOverflow = true
76
+ if (!drawData.overflow) drawData.overflow = rows.length
77
+ }
71
78
  }
72
79
 
73
80
  bounds.y = y
package/src/TextRows.ts CHANGED
@@ -27,6 +27,9 @@ export function createRows(drawData: ITextDrawData, content: string, style: ITex
27
27
 
28
28
  if (charMode) {
29
29
 
30
+ const wrap = style.textWrap !== 'none'
31
+ const breakAll = style.textWrap === 'break'
32
+
30
33
  paraStart = true
31
34
  lastCharType = null
32
35
  startCharSize = charWidth = charSize = wordWidth = rowWidth = 0
@@ -61,18 +64,25 @@ export function createRows(drawData: ITextDrawData, content: string, style: ITex
61
64
 
62
65
  realWidth = paraStart && paraIndent ? width - paraIndent : width
63
66
 
64
- if (width && rowWidth + wordWidth + charWidth > realWidth) { // wrap
65
-
66
- if (!afterBreak) afterBreak = charType === Letter && lastCharType == After // split ,S
67
+ if (wrap && (width && rowWidth + wordWidth + charWidth > realWidth)) { // wrap
67
68
 
68
- if (langBreak || afterBreak || charType === Break || charType === Before || charType === Single || (wordWidth + charWidth > realWidth)) {
69
+ if (breakAll) {
69
70
 
70
71
  if (wordWidth) addWord() // break
71
- addRow()
72
+ if (rowWidth) addRow()
72
73
 
73
74
  } else {
75
+ if (!afterBreak) afterBreak = charType === Letter && lastCharType == After // split ,S
76
+
77
+ if (langBreak || afterBreak || charType === Break || charType === Before || charType === Single || (wordWidth + charWidth > realWidth)) {
78
+
79
+ if (wordWidth) addWord() // break
80
+ if (rowWidth) addRow()
81
+
82
+ } else {
74
83
 
75
- addRow()
84
+ if (rowWidth) addRow()
85
+ }
76
86
  }
77
87
 
78
88
  }
package/src/index.ts CHANGED
@@ -1 +1,7 @@
1
- export { TextConvert } from './TextConvert'
1
+ import { ITextConvertModule } from '@leafer-ui/interface'
2
+
3
+ import { getDrawData } from './TextConvert'
4
+
5
+ export const TextConvertModule: ITextConvertModule = {
6
+ getDrawData
7
+ }
package/types/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ITextConvertModule } from '@leafer-ui/interface';
2
2
 
3
- declare const TextConvert: ITextConvertModule;
3
+ declare const TextConvertModule: ITextConvertModule;
4
4
 
5
- export { TextConvert };
5
+ export { TextConvertModule };