sculp-js 1.0.0 → 1.0.1

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/lib/cjs/array.js CHANGED
@@ -25,26 +25,32 @@ function arrayLike(any) {
25
25
  return object.objectHas(any, 'length');
26
26
  }
27
27
  /**
28
- * 遍历数组,返回 false 中断遍历
28
+ * 遍历数组,返回 false 中断遍历(支持continue和break操作)
29
29
  *
30
30
  * @param {ArrayLike<V>} array
31
- * @param {(val: V, idx: number) => any} iterator
32
- * @param reverse {boolean} 是否倒序
31
+ * @param {(val: V, idx: number) => any} iterator 迭代函数, 返回值为true时continue, 返回值为false时break
32
+ * @param {boolean} reverse 是否倒序
33
33
  * @returns {*}
34
34
  */
35
35
  function arrayEach(array, iterator, reverse = false) {
36
36
  if (reverse) {
37
37
  for (let idx = array.length - 1; idx >= 0; idx--) {
38
38
  const val = array[idx];
39
- if (iterator(val, idx, array) === false)
39
+ const re = iterator(val, idx, array);
40
+ if (re === false)
40
41
  break;
42
+ else if (re === true)
43
+ continue;
41
44
  }
42
45
  }
43
46
  else {
44
47
  for (let idx = 0; idx < array.length; idx++) {
45
48
  const val = array[idx];
46
- if (iterator(val, idx, array) === false)
49
+ const re = iterator(val, idx, array);
50
+ if (re === false)
47
51
  break;
52
+ else if (re === true)
53
+ continue;
48
54
  }
49
55
  }
50
56
  }
@@ -106,21 +112,25 @@ function arrayRemove(array, expect) {
106
112
  /**
107
113
  * 自定义深度优先遍历函数(支持continue和break操作)
108
114
  * @param {ArrayLike<V>} tree 树形数据
109
- * @param {Function} iterator 迭代函数
115
+ * @param {Function} iterator 迭代函数, 返回值为true时continue, 返回值为false时break
110
116
  * @param {string} children 定制子元素的key
111
117
  * @param {boolean} isReverse 是否反向遍历
112
118
  * @returns {*}
113
119
  */
114
- function deepTraversal(tree, iterator, children = 'children', isReverse = false) {
115
- let level = 0;
120
+ function forEachDeep(tree, iterator, children = 'children', isReverse = false) {
121
+ let level = 0, isBreak = false;
116
122
  const walk = (arr, parent) => {
117
123
  if (isReverse) {
118
124
  for (let i = arr.length - 1; i >= 0; i--) {
125
+ if (isBreak) {
126
+ break;
127
+ }
119
128
  const re = iterator(arr[i], i, tree, parent, level);
120
- if (re === 'break') {
129
+ if (re === false) {
130
+ isBreak = true;
121
131
  break;
122
132
  }
123
- else if (re === 'continue') {
133
+ else if (re === true) {
124
134
  continue;
125
135
  }
126
136
  // @ts-ignore
@@ -133,11 +143,15 @@ function deepTraversal(tree, iterator, children = 'children', isReverse = false)
133
143
  }
134
144
  else {
135
145
  for (let i = 0; i < arr.length; i++) {
146
+ if (isBreak) {
147
+ break;
148
+ }
136
149
  const re = iterator(arr[i], i, tree, parent, level);
137
- if (re === 'break') {
150
+ if (re === false) {
151
+ isBreak = true;
138
152
  break;
139
153
  }
140
- else if (re === 'continue') {
154
+ else if (re === true) {
141
155
  continue;
142
156
  }
143
157
  // @ts-ignore
@@ -159,7 +173,7 @@ function deepTraversal(tree, iterator, children = 'children', isReverse = false)
159
173
  * @param {ITreeConf} config - 迭代配置项
160
174
  * @returns {[IdLike[], ITreeItem<V>[]]} - 由parentId...childId, parentObject-childObject组成的二维数组
161
175
  */
162
- function getTreeIds(tree, nodeId, config) {
176
+ function searchTreeById(tree, nodeId, config) {
163
177
  const { children = 'children', id = 'id' } = config || {};
164
178
  const toFlatArray = (tree, parentId, parent) => {
165
179
  return tree.reduce((t, _) => {
@@ -190,5 +204,5 @@ exports.arrayEachAsync = arrayEachAsync;
190
204
  exports.arrayInsertBefore = arrayInsertBefore;
191
205
  exports.arrayLike = arrayLike;
192
206
  exports.arrayRemove = arrayRemove;
193
- exports.deepTraversal = deepTraversal;
194
- exports.getTreeIds = getTreeIds;
207
+ exports.forEachDeep = forEachDeep;
208
+ exports.searchTreeById = searchTreeById;
package/lib/cjs/index.js CHANGED
@@ -25,6 +25,7 @@ var func = require('./func.js');
25
25
  var random = require('./random.js');
26
26
  var number = require('./number.js');
27
27
  var unique = require('./unique.js');
28
+ var tooltip = require('./tooltip.js');
28
29
 
29
30
 
30
31
 
@@ -33,8 +34,8 @@ exports.arrayEachAsync = array.arrayEachAsync;
33
34
  exports.arrayInsertBefore = array.arrayInsertBefore;
34
35
  exports.arrayLike = array.arrayLike;
35
36
  exports.arrayRemove = array.arrayRemove;
36
- exports.deepTraversal = array.deepTraversal;
37
- exports.getTreeIds = array.getTreeIds;
37
+ exports.forEachDeep = array.forEachDeep;
38
+ exports.searchTreeById = array.searchTreeById;
38
39
  exports.copyText = clipboard.copyText;
39
40
  exports.cookieDel = cookie.cookieDel;
40
41
  exports.cookieGet = cookie.cookieGet;
@@ -125,3 +126,4 @@ exports.numberToHex = number.numberToHex;
125
126
  exports.UNIQUE_NUMBER_SAFE_LENGTH = unique.UNIQUE_NUMBER_SAFE_LENGTH;
126
127
  exports.uniqueNumber = unique.uniqueNumber;
127
128
  exports.uniqueString = unique.uniqueString;
129
+ exports.tooltipEvent = tooltip.tooltipEvent;
@@ -0,0 +1,118 @@
1
+ /*!
2
+ * sculp-js v1.0.0
3
+ * (c) 2023-2023 chandq
4
+ * Released under the MIT License.
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ var string = require('./string.js');
10
+
11
+ /**
12
+ * @title tooltip
13
+ * @Desc 自定义的tooltip方法, 支持拖动悬浮提示
14
+ * Created by chendeqiao on 2017/5/8.
15
+ * @example
16
+ * <span onmouseleave="handleMouseLeave('#root')" onmousemove="handleMouseEnter({rootElId: '#root', title: 'title content', event: event})"
17
+ * onmouseenter="handleMouseEnter({'#root', title: 'title content', event: event})">title content </span>
18
+ */
19
+ /**
20
+ * 自定义title提示功能的mouseenter事件句柄
21
+ * @param {ITooltipParams} param1
22
+ * @returns {*}
23
+ */
24
+ function handleMouseEnter({ rootElId = '#root', title, event }) {
25
+ try {
26
+ const $rootEl = document.querySelector(rootElId);
27
+ console.assert($rootEl !== null, `未找到id为 ${rootElId} 的dom元素`);
28
+ let $customTitle = null;
29
+ // 动态创建class样式,并加入到head中
30
+ if (!document.querySelector('.tooltip-inner1494304949567')) {
31
+ const tooltipWrapperClass = document.createElement('style');
32
+ tooltipWrapperClass.type = 'text/css';
33
+ tooltipWrapperClass.innerHTML = `
34
+ .tooltip-inner1494304949567 {
35
+ max-width: 250px;
36
+ padding: 3px 8px;
37
+ color: #fff;
38
+ text-decoration: none;
39
+ border-radius: 4px;
40
+ text-align: left;
41
+ }
42
+ `;
43
+ document.querySelector('head').appendChild(tooltipWrapperClass);
44
+ }
45
+ if (document.querySelector('#customTitle1494304949567')) {
46
+ $customTitle = document.querySelector('#customTitle1494304949567');
47
+ mouseenter($customTitle, title, event);
48
+ }
49
+ else {
50
+ const $contentContainer = document.createElement('div');
51
+ $contentContainer.className = 'customTitle';
52
+ $contentContainer.id = 'customTitle1494304949567';
53
+ $contentContainer.className = 'tooltip';
54
+ $contentContainer.style.cssText = 'z-index: 99999999; visibility: hidden;';
55
+ $contentContainer.innerHTML =
56
+ '<div class="tooltip-inner1494304949567" style="word-wrap: break-word; max-width: 44px;">皮肤</div>';
57
+ $rootEl.appendChild($contentContainer);
58
+ $customTitle = document.querySelector('#customTitle1494304949567');
59
+ if (title) {
60
+ //判断div显示的内容是否为空
61
+ mouseenter($customTitle, title, event);
62
+ $customTitle.style.visibility = 'visible';
63
+ }
64
+ }
65
+ }
66
+ catch (e) {
67
+ console.error(e.message);
68
+ }
69
+ }
70
+ /**
71
+ * 提示文案dom渲染的处理函数
72
+ * @param {HTMLDivElement} customTitle
73
+ * @param {string} title 提示的字符串
74
+ * @param {PointerEvent} e 事件对象
75
+ * @returns {*}
76
+ */
77
+ function mouseenter($customTitle, title, e) {
78
+ let diffValueX = 200 + 50; //默认设置弹出div的宽度为250px
79
+ let x = 13;
80
+ const y = 23;
81
+ const $contentEle = $customTitle.children[0];
82
+ if (string.getStrWidthPx(title, 12) < 180 + 50) {
83
+ //【弹出div自适应字符串宽度】若显示的字符串占用宽度小于180,则设置弹出div的宽度为“符串占用宽度”+20
84
+ $contentEle.style.maxWidth = string.getStrWidthPx(title, 12) + 20 + 50 + 'px';
85
+ diffValueX = e.clientX + (string.getStrWidthPx(title, 12) + 50) - document.body.offsetWidth;
86
+ }
87
+ else {
88
+ $contentEle.style.maxWidth = '250px';
89
+ diffValueX = e.clientX + 230 - document.body.offsetWidth; //计算div水平方向显示的内容超出屏幕多少宽度
90
+ }
91
+ $contentEle.innerHTML = title; //html方法可解析内容中换行标签,text方法不能
92
+ if (diffValueX > 0) {
93
+ //水平方向超出可见区域时
94
+ x -= diffValueX;
95
+ }
96
+ $customTitle.style.top = e.clientY + y + 'px';
97
+ $customTitle.style.left = e.clientX + x + 'px';
98
+ $customTitle.style.maxWidth = '250px';
99
+ const diffValueY = $customTitle.getBoundingClientRect().top + $contentEle.offsetHeight - document.body.offsetHeight;
100
+ if (diffValueY > 0) {
101
+ //垂直方向超出可见区域时
102
+ $customTitle.style.top = e.clientY - diffValueY + 'px';
103
+ }
104
+ }
105
+ /**
106
+ * 移除提示文案dom的事件句柄
107
+ * @param {string} rootElId
108
+ * @returns {*}
109
+ */
110
+ function handleMouseLeave(rootElId = '#root') {
111
+ const rootEl = document.querySelector(rootElId), titleEl = document.querySelector('#customTitle1494304949567');
112
+ if (rootEl && titleEl) {
113
+ rootEl.removeChild(titleEl);
114
+ }
115
+ }
116
+ const tooltipEvent = { handleMouseEnter, handleMouseLeave };
117
+
118
+ exports.tooltipEvent = tooltipEvent;
package/lib/es/array.js CHANGED
@@ -23,26 +23,32 @@ function arrayLike(any) {
23
23
  return objectHas(any, 'length');
24
24
  }
25
25
  /**
26
- * 遍历数组,返回 false 中断遍历
26
+ * 遍历数组,返回 false 中断遍历(支持continue和break操作)
27
27
  *
28
28
  * @param {ArrayLike<V>} array
29
- * @param {(val: V, idx: number) => any} iterator
30
- * @param reverse {boolean} 是否倒序
29
+ * @param {(val: V, idx: number) => any} iterator 迭代函数, 返回值为true时continue, 返回值为false时break
30
+ * @param {boolean} reverse 是否倒序
31
31
  * @returns {*}
32
32
  */
33
33
  function arrayEach(array, iterator, reverse = false) {
34
34
  if (reverse) {
35
35
  for (let idx = array.length - 1; idx >= 0; idx--) {
36
36
  const val = array[idx];
37
- if (iterator(val, idx, array) === false)
37
+ const re = iterator(val, idx, array);
38
+ if (re === false)
38
39
  break;
40
+ else if (re === true)
41
+ continue;
39
42
  }
40
43
  }
41
44
  else {
42
45
  for (let idx = 0; idx < array.length; idx++) {
43
46
  const val = array[idx];
44
- if (iterator(val, idx, array) === false)
47
+ const re = iterator(val, idx, array);
48
+ if (re === false)
45
49
  break;
50
+ else if (re === true)
51
+ continue;
46
52
  }
47
53
  }
48
54
  }
@@ -104,21 +110,25 @@ function arrayRemove(array, expect) {
104
110
  /**
105
111
  * 自定义深度优先遍历函数(支持continue和break操作)
106
112
  * @param {ArrayLike<V>} tree 树形数据
107
- * @param {Function} iterator 迭代函数
113
+ * @param {Function} iterator 迭代函数, 返回值为true时continue, 返回值为false时break
108
114
  * @param {string} children 定制子元素的key
109
115
  * @param {boolean} isReverse 是否反向遍历
110
116
  * @returns {*}
111
117
  */
112
- function deepTraversal(tree, iterator, children = 'children', isReverse = false) {
113
- let level = 0;
118
+ function forEachDeep(tree, iterator, children = 'children', isReverse = false) {
119
+ let level = 0, isBreak = false;
114
120
  const walk = (arr, parent) => {
115
121
  if (isReverse) {
116
122
  for (let i = arr.length - 1; i >= 0; i--) {
123
+ if (isBreak) {
124
+ break;
125
+ }
117
126
  const re = iterator(arr[i], i, tree, parent, level);
118
- if (re === 'break') {
127
+ if (re === false) {
128
+ isBreak = true;
119
129
  break;
120
130
  }
121
- else if (re === 'continue') {
131
+ else if (re === true) {
122
132
  continue;
123
133
  }
124
134
  // @ts-ignore
@@ -131,11 +141,15 @@ function deepTraversal(tree, iterator, children = 'children', isReverse = false)
131
141
  }
132
142
  else {
133
143
  for (let i = 0; i < arr.length; i++) {
144
+ if (isBreak) {
145
+ break;
146
+ }
134
147
  const re = iterator(arr[i], i, tree, parent, level);
135
- if (re === 'break') {
148
+ if (re === false) {
149
+ isBreak = true;
136
150
  break;
137
151
  }
138
- else if (re === 'continue') {
152
+ else if (re === true) {
139
153
  continue;
140
154
  }
141
155
  // @ts-ignore
@@ -157,7 +171,7 @@ function deepTraversal(tree, iterator, children = 'children', isReverse = false)
157
171
  * @param {ITreeConf} config - 迭代配置项
158
172
  * @returns {[IdLike[], ITreeItem<V>[]]} - 由parentId...childId, parentObject-childObject组成的二维数组
159
173
  */
160
- function getTreeIds(tree, nodeId, config) {
174
+ function searchTreeById(tree, nodeId, config) {
161
175
  const { children = 'children', id = 'id' } = config || {};
162
176
  const toFlatArray = (tree, parentId, parent) => {
163
177
  return tree.reduce((t, _) => {
@@ -183,4 +197,4 @@ function getTreeIds(tree, nodeId, config) {
183
197
  return getIds(toFlatArray(tree));
184
198
  }
185
199
 
186
- export { arrayEach, arrayEachAsync, arrayInsertBefore, arrayLike, arrayRemove, deepTraversal, getTreeIds };
200
+ export { arrayEach, arrayEachAsync, arrayInsertBefore, arrayLike, arrayRemove, forEachDeep, searchTreeById };
package/lib/es/index.js CHANGED
@@ -4,7 +4,7 @@
4
4
  * Released under the MIT License.
5
5
  */
6
6
 
7
- export { arrayEach, arrayEachAsync, arrayInsertBefore, arrayLike, arrayRemove, deepTraversal, getTreeIds } from './array.js';
7
+ export { arrayEach, arrayEachAsync, arrayInsertBefore, arrayLike, arrayRemove, forEachDeep, searchTreeById } from './array.js';
8
8
  export { copyText } from './clipboard.js';
9
9
  export { cookieDel, cookieGet, cookieSet } from './cookie.js';
10
10
  export { calculateDate, calculateDateTime, dateParse, dateToEnd, dateToStart, formatDate, isValidDate } from './date.js';
@@ -23,3 +23,4 @@ export { debounce, getGlobal, once, setGlobal, throttle } from './func.js';
23
23
  export { STRING_POOL, randomNumber, randomString, randomUuid } from './random.js';
24
24
  export { HEX_POOL, formatNumber, numberAbbr, numberToHex } from './number.js';
25
25
  export { UNIQUE_NUMBER_SAFE_LENGTH, uniqueNumber, uniqueString } from './unique.js';
26
+ export { tooltipEvent } from './tooltip.js';
@@ -0,0 +1,116 @@
1
+ /*!
2
+ * sculp-js v1.0.0
3
+ * (c) 2023-2023 chandq
4
+ * Released under the MIT License.
5
+ */
6
+
7
+ import { getStrWidthPx } from './string.js';
8
+
9
+ /**
10
+ * @title tooltip
11
+ * @Desc 自定义的tooltip方法, 支持拖动悬浮提示
12
+ * Created by chendeqiao on 2017/5/8.
13
+ * @example
14
+ * <span onmouseleave="handleMouseLeave('#root')" onmousemove="handleMouseEnter({rootElId: '#root', title: 'title content', event: event})"
15
+ * onmouseenter="handleMouseEnter({'#root', title: 'title content', event: event})">title content </span>
16
+ */
17
+ /**
18
+ * 自定义title提示功能的mouseenter事件句柄
19
+ * @param {ITooltipParams} param1
20
+ * @returns {*}
21
+ */
22
+ function handleMouseEnter({ rootElId = '#root', title, event }) {
23
+ try {
24
+ const $rootEl = document.querySelector(rootElId);
25
+ console.assert($rootEl !== null, `未找到id为 ${rootElId} 的dom元素`);
26
+ let $customTitle = null;
27
+ // 动态创建class样式,并加入到head中
28
+ if (!document.querySelector('.tooltip-inner1494304949567')) {
29
+ const tooltipWrapperClass = document.createElement('style');
30
+ tooltipWrapperClass.type = 'text/css';
31
+ tooltipWrapperClass.innerHTML = `
32
+ .tooltip-inner1494304949567 {
33
+ max-width: 250px;
34
+ padding: 3px 8px;
35
+ color: #fff;
36
+ text-decoration: none;
37
+ border-radius: 4px;
38
+ text-align: left;
39
+ }
40
+ `;
41
+ document.querySelector('head').appendChild(tooltipWrapperClass);
42
+ }
43
+ if (document.querySelector('#customTitle1494304949567')) {
44
+ $customTitle = document.querySelector('#customTitle1494304949567');
45
+ mouseenter($customTitle, title, event);
46
+ }
47
+ else {
48
+ const $contentContainer = document.createElement('div');
49
+ $contentContainer.className = 'customTitle';
50
+ $contentContainer.id = 'customTitle1494304949567';
51
+ $contentContainer.className = 'tooltip';
52
+ $contentContainer.style.cssText = 'z-index: 99999999; visibility: hidden;';
53
+ $contentContainer.innerHTML =
54
+ '<div class="tooltip-inner1494304949567" style="word-wrap: break-word; max-width: 44px;">皮肤</div>';
55
+ $rootEl.appendChild($contentContainer);
56
+ $customTitle = document.querySelector('#customTitle1494304949567');
57
+ if (title) {
58
+ //判断div显示的内容是否为空
59
+ mouseenter($customTitle, title, event);
60
+ $customTitle.style.visibility = 'visible';
61
+ }
62
+ }
63
+ }
64
+ catch (e) {
65
+ console.error(e.message);
66
+ }
67
+ }
68
+ /**
69
+ * 提示文案dom渲染的处理函数
70
+ * @param {HTMLDivElement} customTitle
71
+ * @param {string} title 提示的字符串
72
+ * @param {PointerEvent} e 事件对象
73
+ * @returns {*}
74
+ */
75
+ function mouseenter($customTitle, title, e) {
76
+ let diffValueX = 200 + 50; //默认设置弹出div的宽度为250px
77
+ let x = 13;
78
+ const y = 23;
79
+ const $contentEle = $customTitle.children[0];
80
+ if (getStrWidthPx(title, 12) < 180 + 50) {
81
+ //【弹出div自适应字符串宽度】若显示的字符串占用宽度小于180,则设置弹出div的宽度为“符串占用宽度”+20
82
+ $contentEle.style.maxWidth = getStrWidthPx(title, 12) + 20 + 50 + 'px';
83
+ diffValueX = e.clientX + (getStrWidthPx(title, 12) + 50) - document.body.offsetWidth;
84
+ }
85
+ else {
86
+ $contentEle.style.maxWidth = '250px';
87
+ diffValueX = e.clientX + 230 - document.body.offsetWidth; //计算div水平方向显示的内容超出屏幕多少宽度
88
+ }
89
+ $contentEle.innerHTML = title; //html方法可解析内容中换行标签,text方法不能
90
+ if (diffValueX > 0) {
91
+ //水平方向超出可见区域时
92
+ x -= diffValueX;
93
+ }
94
+ $customTitle.style.top = e.clientY + y + 'px';
95
+ $customTitle.style.left = e.clientX + x + 'px';
96
+ $customTitle.style.maxWidth = '250px';
97
+ const diffValueY = $customTitle.getBoundingClientRect().top + $contentEle.offsetHeight - document.body.offsetHeight;
98
+ if (diffValueY > 0) {
99
+ //垂直方向超出可见区域时
100
+ $customTitle.style.top = e.clientY - diffValueY + 'px';
101
+ }
102
+ }
103
+ /**
104
+ * 移除提示文案dom的事件句柄
105
+ * @param {string} rootElId
106
+ * @returns {*}
107
+ */
108
+ function handleMouseLeave(rootElId = '#root') {
109
+ const rootEl = document.querySelector(rootElId), titleEl = document.querySelector('#customTitle1494304949567');
110
+ if (rootEl && titleEl) {
111
+ rootEl.removeChild(titleEl);
112
+ }
113
+ }
114
+ const tooltipEvent = { handleMouseEnter, handleMouseLeave };
115
+
116
+ export { tooltipEvent };
package/lib/index.d.ts CHANGED
@@ -44,14 +44,14 @@ declare const isRegExp: (any: unknown) => any is RegExp;
44
44
  */
45
45
  declare function arrayLike(any: unknown): boolean;
46
46
  /**
47
- * 遍历数组,返回 false 中断遍历
47
+ * 遍历数组,返回 false 中断遍历(支持continue和break操作)
48
48
  *
49
49
  * @param {ArrayLike<V>} array
50
- * @param {(val: V, idx: number) => any} iterator
51
- * @param reverse {boolean} 是否倒序
50
+ * @param {(val: V, idx: number) => any} iterator 迭代函数, 返回值为true时continue, 返回值为false时break
51
+ * @param {boolean} reverse 是否倒序
52
52
  * @returns {*}
53
53
  */
54
- declare function arrayEach<V>(array: ArrayLike<V>, iterator: (val: V, idx: number, arr: ArrayLike<V>) => any, reverse?: boolean): void;
54
+ declare function arrayEach<V>(array: ArrayLike<V>, iterator: (val: V, idx: number, arr: ArrayLike<V>) => boolean | void, reverse?: boolean): void;
55
55
  /**
56
56
  * 异步遍历数组,返回 false 中断遍历
57
57
  * @param {ArrayLike<V>} array 数组
@@ -77,12 +77,12 @@ declare function arrayRemove<V>(array: V[], expect: (val: V, idx: number) => boo
77
77
  /**
78
78
  * 自定义深度优先遍历函数(支持continue和break操作)
79
79
  * @param {ArrayLike<V>} tree 树形数据
80
- * @param {Function} iterator 迭代函数
80
+ * @param {Function} iterator 迭代函数, 返回值为true时continue, 返回值为false时break
81
81
  * @param {string} children 定制子元素的key
82
82
  * @param {boolean} isReverse 是否反向遍历
83
83
  * @returns {*}
84
84
  */
85
- declare function deepTraversal<V>(tree: ArrayLike<V>, iterator: (val: V, i: number, arr: ArrayLike<V>, parent: V | null, level: number) => any, children?: string, isReverse?: boolean): void;
85
+ declare function forEachDeep<V>(tree: ArrayLike<V>, iterator: (val: V, i: number, arr: ArrayLike<V>, parent: V | null, level: number) => boolean | void, children?: string, isReverse?: boolean): void;
86
86
  type IdLike = number | string;
87
87
  interface ITreeConf {
88
88
  id: string | number;
@@ -96,7 +96,7 @@ interface ITreeConf {
96
96
  * @param {ITreeConf} config - 迭代配置项
97
97
  * @returns {[IdLike[], ITreeItem<V>[]]} - 由parentId...childId, parentObject-childObject组成的二维数组
98
98
  */
99
- declare function getTreeIds<V>(tree: ArrayLike<V>, nodeId: IdLike, config?: ITreeConf): [IdLike[], ArrayLike<V>[]];
99
+ declare function searchTreeById<V>(tree: ArrayLike<V>, nodeId: IdLike, config?: ITreeConf): [IdLike[], ArrayLike<V>[]];
100
100
 
101
101
  /**
102
102
  * 复制文本
@@ -676,4 +676,34 @@ interface UniqueString {
676
676
  */
677
677
  declare const uniqueString: UniqueString;
678
678
 
679
- export { type AnyArray, type AnyFunc, type AnyObject, type ArrayElements, type DateObj, type DateValue, type DebounceFunc, type FileType, HEX_POOL, type ICanvasWM, type ITreeConf, type IdLike, type LooseParamValue, type LooseParams, type ObjectAssignItem, type OnceFunc, type Params, type PartialDeep, type RandomString, type ReadyCallback, type Replacer, STRING_ARABIC_NUMERALS, STRING_LOWERCASE_ALPHA, STRING_POOL, STRING_UPPERCASE_ALPHA, type SetStyle, type SmoothScrollOptions, type Style, type ThrottleFunc, UNIQUE_NUMBER_SAFE_LENGTH, type UniqueString, type Url, addClass, arrayEach, arrayEachAsync, arrayInsertBefore, arrayLike, arrayRemove, asyncMap, calculateDate, calculateDateTime, chooseLocalFile, cloneDeep, cookieDel, cookieGet, cookieSet, copyText, dateParse, dateToEnd, dateToStart, debounce, deepTraversal, downloadBlob, downloadData, downloadHref, downloadURL, formatDate, formatNumber, genCanvasWM, getComputedCssVal, getGlobal, getStrWidthPx, getStyle, getTreeIds, hasClass, isArray, isBigInt, isBoolean, isDate, isDomReady, isError, isFunction, isNaN, isNull, isNumber, isObject, isPlainObject, isPrimitive, isRegExp, isString, isSymbol, isUndefined, isValidDate, numberAbbr, numberToHex, objectAssign, objectEach, objectEachAsync, objectFill, objectGet, objectHas, objectMap, objectAssign as objectMerge, objectOmit, objectPick, onDomReady, once, pathJoin, pathNormalize, qsParse, qsStringify, randomNumber, randomString, randomUuid, removeClass, setGlobal, setStyle, smoothScroll, stringAssign, stringCamelCase, stringEscapeHtml, stringFill, stringFormat, stringKebabCase, throttle, typeIs, uniqueNumber, uniqueString, urlDelParams, urlParse, urlSetParams, urlStringify, wait };
679
+ /**
680
+ * @title tooltip
681
+ * @Desc 自定义的tooltip方法, 支持拖动悬浮提示
682
+ * Created by chendeqiao on 2017/5/8.
683
+ * @example
684
+ * <span onmouseleave="handleMouseLeave('#root')" onmousemove="handleMouseEnter({rootElId: '#root', title: 'title content', event: event})"
685
+ * onmouseenter="handleMouseEnter({'#root', title: 'title content', event: event})">title content </span>
686
+ */
687
+ interface ITooltipParams {
688
+ rootElId: string;
689
+ title: string;
690
+ event: PointerEvent;
691
+ }
692
+ /**
693
+ * 自定义title提示功能的mouseenter事件句柄
694
+ * @param {ITooltipParams} param1
695
+ * @returns {*}
696
+ */
697
+ declare function handleMouseEnter({ rootElId, title, event }: ITooltipParams): void;
698
+ /**
699
+ * 移除提示文案dom的事件句柄
700
+ * @param {string} rootElId
701
+ * @returns {*}
702
+ */
703
+ declare function handleMouseLeave(rootElId?: string): void;
704
+ declare const tooltipEvent: {
705
+ handleMouseEnter: typeof handleMouseEnter;
706
+ handleMouseLeave: typeof handleMouseLeave;
707
+ };
708
+
709
+ export { type AnyArray, type AnyFunc, type AnyObject, type ArrayElements, type DateObj, type DateValue, type DebounceFunc, type FileType, HEX_POOL, type ICanvasWM, type ITreeConf, type IdLike, type LooseParamValue, type LooseParams, type ObjectAssignItem, type OnceFunc, type Params, type PartialDeep, type RandomString, type ReadyCallback, type Replacer, STRING_ARABIC_NUMERALS, STRING_LOWERCASE_ALPHA, STRING_POOL, STRING_UPPERCASE_ALPHA, type SetStyle, type SmoothScrollOptions, type Style, type ThrottleFunc, UNIQUE_NUMBER_SAFE_LENGTH, type UniqueString, type Url, addClass, arrayEach, arrayEachAsync, arrayInsertBefore, arrayLike, arrayRemove, asyncMap, calculateDate, calculateDateTime, chooseLocalFile, cloneDeep, cookieDel, cookieGet, cookieSet, copyText, dateParse, dateToEnd, dateToStart, debounce, downloadBlob, downloadData, downloadHref, downloadURL, forEachDeep, formatDate, formatNumber, genCanvasWM, getComputedCssVal, getGlobal, getStrWidthPx, getStyle, hasClass, isArray, isBigInt, isBoolean, isDate, isDomReady, isError, isFunction, isNaN, isNull, isNumber, isObject, isPlainObject, isPrimitive, isRegExp, isString, isSymbol, isUndefined, isValidDate, numberAbbr, numberToHex, objectAssign, objectEach, objectEachAsync, objectFill, objectGet, objectHas, objectMap, objectAssign as objectMerge, objectOmit, objectPick, onDomReady, once, pathJoin, pathNormalize, qsParse, qsStringify, randomNumber, randomString, randomUuid, removeClass, searchTreeById, setGlobal, setStyle, smoothScroll, stringAssign, stringCamelCase, stringEscapeHtml, stringFill, stringFormat, stringKebabCase, throttle, tooltipEvent, typeIs, uniqueNumber, uniqueString, urlDelParams, urlParse, urlSetParams, urlStringify, wait };
@@ -0,0 +1,11 @@
1
+ // This file is read by tools that parse documentation comments conforming to the TSDoc standard.
2
+ // It should be published with your NPM package. It should not be tracked by Git.
3
+ {
4
+ "tsdocVersion": "0.12",
5
+ "toolPackages": [
6
+ {
7
+ "packageName": "@microsoft/api-extractor",
8
+ "packageVersion": "7.38.3"
9
+ }
10
+ ]
11
+ }
package/lib/umd/index.js CHANGED
@@ -277,26 +277,32 @@
277
277
  return objectHas(any, 'length');
278
278
  }
279
279
  /**
280
- * 遍历数组,返回 false 中断遍历
280
+ * 遍历数组,返回 false 中断遍历(支持continue和break操作)
281
281
  *
282
282
  * @param {ArrayLike<V>} array
283
- * @param {(val: V, idx: number) => any} iterator
284
- * @param reverse {boolean} 是否倒序
283
+ * @param {(val: V, idx: number) => any} iterator 迭代函数, 返回值为true时continue, 返回值为false时break
284
+ * @param {boolean} reverse 是否倒序
285
285
  * @returns {*}
286
286
  */
287
287
  function arrayEach(array, iterator, reverse = false) {
288
288
  if (reverse) {
289
289
  for (let idx = array.length - 1; idx >= 0; idx--) {
290
290
  const val = array[idx];
291
- if (iterator(val, idx, array) === false)
291
+ const re = iterator(val, idx, array);
292
+ if (re === false)
292
293
  break;
294
+ else if (re === true)
295
+ continue;
293
296
  }
294
297
  }
295
298
  else {
296
299
  for (let idx = 0; idx < array.length; idx++) {
297
300
  const val = array[idx];
298
- if (iterator(val, idx, array) === false)
301
+ const re = iterator(val, idx, array);
302
+ if (re === false)
299
303
  break;
304
+ else if (re === true)
305
+ continue;
300
306
  }
301
307
  }
302
308
  }
@@ -358,21 +364,25 @@
358
364
  /**
359
365
  * 自定义深度优先遍历函数(支持continue和break操作)
360
366
  * @param {ArrayLike<V>} tree 树形数据
361
- * @param {Function} iterator 迭代函数
367
+ * @param {Function} iterator 迭代函数, 返回值为true时continue, 返回值为false时break
362
368
  * @param {string} children 定制子元素的key
363
369
  * @param {boolean} isReverse 是否反向遍历
364
370
  * @returns {*}
365
371
  */
366
- function deepTraversal(tree, iterator, children = 'children', isReverse = false) {
367
- let level = 0;
372
+ function forEachDeep(tree, iterator, children = 'children', isReverse = false) {
373
+ let level = 0, isBreak = false;
368
374
  const walk = (arr, parent) => {
369
375
  if (isReverse) {
370
376
  for (let i = arr.length - 1; i >= 0; i--) {
377
+ if (isBreak) {
378
+ break;
379
+ }
371
380
  const re = iterator(arr[i], i, tree, parent, level);
372
- if (re === 'break') {
381
+ if (re === false) {
382
+ isBreak = true;
373
383
  break;
374
384
  }
375
- else if (re === 'continue') {
385
+ else if (re === true) {
376
386
  continue;
377
387
  }
378
388
  // @ts-ignore
@@ -385,11 +395,15 @@
385
395
  }
386
396
  else {
387
397
  for (let i = 0; i < arr.length; i++) {
398
+ if (isBreak) {
399
+ break;
400
+ }
388
401
  const re = iterator(arr[i], i, tree, parent, level);
389
- if (re === 'break') {
402
+ if (re === false) {
403
+ isBreak = true;
390
404
  break;
391
405
  }
392
- else if (re === 'continue') {
406
+ else if (re === true) {
393
407
  continue;
394
408
  }
395
409
  // @ts-ignore
@@ -411,7 +425,7 @@
411
425
  * @param {ITreeConf} config - 迭代配置项
412
426
  * @returns {[IdLike[], ITreeItem<V>[]]} - 由parentId...childId, parentObject-childObject组成的二维数组
413
427
  */
414
- function getTreeIds(tree, nodeId, config) {
428
+ function searchTreeById(tree, nodeId, config) {
415
429
  const { children = 'children', id = 'id' } = config || {};
416
430
  const toFlatArray = (tree, parentId, parent) => {
417
431
  return tree.reduce((t, _) => {
@@ -1791,6 +1805,113 @@
1791
1805
  return uniqueString;
1792
1806
  };
1793
1807
 
1808
+ /**
1809
+ * @title tooltip
1810
+ * @Desc 自定义的tooltip方法, 支持拖动悬浮提示
1811
+ * Created by chendeqiao on 2017/5/8.
1812
+ * @example
1813
+ * <span onmouseleave="handleMouseLeave('#root')" onmousemove="handleMouseEnter({rootElId: '#root', title: 'title content', event: event})"
1814
+ * onmouseenter="handleMouseEnter({'#root', title: 'title content', event: event})">title content </span>
1815
+ */
1816
+ /**
1817
+ * 自定义title提示功能的mouseenter事件句柄
1818
+ * @param {ITooltipParams} param1
1819
+ * @returns {*}
1820
+ */
1821
+ function handleMouseEnter({ rootElId = '#root', title, event }) {
1822
+ try {
1823
+ const $rootEl = document.querySelector(rootElId);
1824
+ console.assert($rootEl !== null, `未找到id为 ${rootElId} 的dom元素`);
1825
+ let $customTitle = null;
1826
+ // 动态创建class样式,并加入到head中
1827
+ if (!document.querySelector('.tooltip-inner1494304949567')) {
1828
+ const tooltipWrapperClass = document.createElement('style');
1829
+ tooltipWrapperClass.type = 'text/css';
1830
+ tooltipWrapperClass.innerHTML = `
1831
+ .tooltip-inner1494304949567 {
1832
+ max-width: 250px;
1833
+ padding: 3px 8px;
1834
+ color: #fff;
1835
+ text-decoration: none;
1836
+ border-radius: 4px;
1837
+ text-align: left;
1838
+ }
1839
+ `;
1840
+ document.querySelector('head').appendChild(tooltipWrapperClass);
1841
+ }
1842
+ if (document.querySelector('#customTitle1494304949567')) {
1843
+ $customTitle = document.querySelector('#customTitle1494304949567');
1844
+ mouseenter($customTitle, title, event);
1845
+ }
1846
+ else {
1847
+ const $contentContainer = document.createElement('div');
1848
+ $contentContainer.className = 'customTitle';
1849
+ $contentContainer.id = 'customTitle1494304949567';
1850
+ $contentContainer.className = 'tooltip';
1851
+ $contentContainer.style.cssText = 'z-index: 99999999; visibility: hidden;';
1852
+ $contentContainer.innerHTML =
1853
+ '<div class="tooltip-inner1494304949567" style="word-wrap: break-word; max-width: 44px;">皮肤</div>';
1854
+ $rootEl.appendChild($contentContainer);
1855
+ $customTitle = document.querySelector('#customTitle1494304949567');
1856
+ if (title) {
1857
+ //判断div显示的内容是否为空
1858
+ mouseenter($customTitle, title, event);
1859
+ $customTitle.style.visibility = 'visible';
1860
+ }
1861
+ }
1862
+ }
1863
+ catch (e) {
1864
+ console.error(e.message);
1865
+ }
1866
+ }
1867
+ /**
1868
+ * 提示文案dom渲染的处理函数
1869
+ * @param {HTMLDivElement} customTitle
1870
+ * @param {string} title 提示的字符串
1871
+ * @param {PointerEvent} e 事件对象
1872
+ * @returns {*}
1873
+ */
1874
+ function mouseenter($customTitle, title, e) {
1875
+ let diffValueX = 200 + 50; //默认设置弹出div的宽度为250px
1876
+ let x = 13;
1877
+ const y = 23;
1878
+ const $contentEle = $customTitle.children[0];
1879
+ if (getStrWidthPx(title, 12) < 180 + 50) {
1880
+ //【弹出div自适应字符串宽度】若显示的字符串占用宽度小于180,则设置弹出div的宽度为“符串占用宽度”+20
1881
+ $contentEle.style.maxWidth = getStrWidthPx(title, 12) + 20 + 50 + 'px';
1882
+ diffValueX = e.clientX + (getStrWidthPx(title, 12) + 50) - document.body.offsetWidth;
1883
+ }
1884
+ else {
1885
+ $contentEle.style.maxWidth = '250px';
1886
+ diffValueX = e.clientX + 230 - document.body.offsetWidth; //计算div水平方向显示的内容超出屏幕多少宽度
1887
+ }
1888
+ $contentEle.innerHTML = title; //html方法可解析内容中换行标签,text方法不能
1889
+ if (diffValueX > 0) {
1890
+ //水平方向超出可见区域时
1891
+ x -= diffValueX;
1892
+ }
1893
+ $customTitle.style.top = e.clientY + y + 'px';
1894
+ $customTitle.style.left = e.clientX + x + 'px';
1895
+ $customTitle.style.maxWidth = '250px';
1896
+ const diffValueY = $customTitle.getBoundingClientRect().top + $contentEle.offsetHeight - document.body.offsetHeight;
1897
+ if (diffValueY > 0) {
1898
+ //垂直方向超出可见区域时
1899
+ $customTitle.style.top = e.clientY - diffValueY + 'px';
1900
+ }
1901
+ }
1902
+ /**
1903
+ * 移除提示文案dom的事件句柄
1904
+ * @param {string} rootElId
1905
+ * @returns {*}
1906
+ */
1907
+ function handleMouseLeave(rootElId = '#root') {
1908
+ const rootEl = document.querySelector(rootElId), titleEl = document.querySelector('#customTitle1494304949567');
1909
+ if (rootEl && titleEl) {
1910
+ rootEl.removeChild(titleEl);
1911
+ }
1912
+ }
1913
+ const tooltipEvent = { handleMouseEnter, handleMouseLeave };
1914
+
1794
1915
  exports.HEX_POOL = HEX_POOL;
1795
1916
  exports.STRING_ARABIC_NUMERALS = STRING_ARABIC_NUMERALS;
1796
1917
  exports.STRING_LOWERCASE_ALPHA = STRING_LOWERCASE_ALPHA;
@@ -1816,11 +1937,11 @@
1816
1937
  exports.dateToEnd = dateToEnd;
1817
1938
  exports.dateToStart = dateToStart;
1818
1939
  exports.debounce = debounce;
1819
- exports.deepTraversal = deepTraversal;
1820
1940
  exports.downloadBlob = downloadBlob;
1821
1941
  exports.downloadData = downloadData;
1822
1942
  exports.downloadHref = downloadHref;
1823
1943
  exports.downloadURL = downloadURL;
1944
+ exports.forEachDeep = forEachDeep;
1824
1945
  exports.formatDate = formatDate;
1825
1946
  exports.formatNumber = formatNumber;
1826
1947
  exports.genCanvasWM = genCanvasWM;
@@ -1828,7 +1949,6 @@
1828
1949
  exports.getGlobal = getGlobal;
1829
1950
  exports.getStrWidthPx = getStrWidthPx;
1830
1951
  exports.getStyle = getStyle;
1831
- exports.getTreeIds = getTreeIds;
1832
1952
  exports.hasClass = hasClass;
1833
1953
  exports.isArray = isArray;
1834
1954
  exports.isBigInt = isBigInt;
@@ -1870,6 +1990,7 @@
1870
1990
  exports.randomString = randomString;
1871
1991
  exports.randomUuid = randomUuid;
1872
1992
  exports.removeClass = removeClass;
1993
+ exports.searchTreeById = searchTreeById;
1873
1994
  exports.setGlobal = setGlobal;
1874
1995
  exports.setStyle = setStyle;
1875
1996
  exports.smoothScroll = smoothScroll;
@@ -1880,6 +2001,7 @@
1880
2001
  exports.stringFormat = stringFormat;
1881
2002
  exports.stringKebabCase = stringKebabCase;
1882
2003
  exports.throttle = throttle;
2004
+ exports.tooltipEvent = tooltipEvent;
1883
2005
  exports.typeIs = typeIs;
1884
2006
  exports.uniqueNumber = uniqueNumber;
1885
2007
  exports.uniqueString = uniqueString;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sculp-js",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "private": false,
5
5
  "description": "js工具库",
6
6
  "scripts": {