ph-utils 0.15.0 → 0.15.3

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/README.md CHANGED
@@ -1,7 +1,7 @@
1
- ## ph-utils
2
-
3
- 整理了 js 前后端开发(web + nodejs)时常用的一些工具;[详细文档](https://gitee.com/towardly/ph/wikis/Home?sort_id=4035190)
4
-
5
- ### 包含如下工具文件
6
-
7
- `index` 基础工具类、`date` 跟日期相关的工具类、`file` 文件操作相关工具类[**服务端**]、`server` 服务端工具类、`validator` 数据验证、`dom` 浏览器节点操作相关[**前端**]、`web` 一些只适用于前端相关的工具、`color` 颜色相关工具
1
+ ## ph-utils
2
+
3
+ 整理了 js 前后端开发(web + nodejs)时常用的一些工具;[详细文档](https://gitee.com/towardly/ph/wikis/Home?sort_id=4035190)
4
+
5
+ ### 包含如下工具文件
6
+
7
+ `index` 基础工具类、`date` 跟日期相关的工具类、`file` 文件操作相关工具类[**服务端**]、`server` 服务端工具类、`validator` 数据验证、`dom` 浏览器节点操作相关[**前端**]、`web` 一些只适用于前端相关的工具、`color` 颜色相关工具
package/lib/array.d.ts CHANGED
@@ -59,14 +59,14 @@ export declare function symmetricDifference<T>(...arrs: T[][]): T[];
59
59
  * @param a2
60
60
  * @returns
61
61
  */
62
- export declare function isSubsetOf<T>(a1: T[] | Set<T>, a2: T[] | Set<T>): boolean;
62
+ export declare function isSubsetOf<T>(a1: T[] | Set<T>, a2: T[] | Set<T>): any;
63
63
  /**
64
64
  * 返回一个布尔值,指示给定集合中的所有元素是否都在此集合中。
65
65
  * @param arr1
66
66
  * @param arr2
67
67
  * @returns
68
68
  */
69
- export declare function isSupersetOf<T>(arr1: T[] | Set<T>, arr2: T[] | Set<T>): boolean;
69
+ export declare function isSupersetOf<T>(arr1: T[] | Set<T>, arr2: T[] | Set<T>): any;
70
70
  /**
71
71
  * 返回一个布尔值,指示此集合是否与给定集合没有公共元素。
72
72
  *
@@ -76,4 +76,4 @@ export declare function isSupersetOf<T>(arr1: T[] | Set<T>, arr2: T[] | Set<T>):
76
76
  * @param arr2
77
77
  * @returns
78
78
  */
79
- export declare function isDisjointFrom<T>(arr1: T[] | Set<T>, arr2: T[] | Set<T>): boolean;
79
+ export declare function isDisjointFrom<T>(arr1: T[] | Set<T>, arr2: T[] | Set<T>): any;
package/lib/dom.d.ts CHANGED
@@ -82,7 +82,7 @@ export declare function toggleClass(el: HTMLElement, clazz: string): void;
82
82
  * @param {function} event 事件处理函数
83
83
  * @param {boolean} onceOrConfig 是否是只运行一次的处理函数或者配置,其中 eventFlag 为 string,如果配置该项,则表明为委托事件
84
84
  */
85
- export declare function on(element: HTMLElement | ShadowRoot | Document, listener: string, fn: EventListener, option?: boolean | (AddEventListenerOptions & {
85
+ export declare function on(element: HTMLElement | ShadowRoot | Document | HTMLCollection | NodeListOf<HTMLElement> | HTMLElement[], listener: string, fn: EventListener, option?: boolean | (AddEventListenerOptions & {
86
86
  eventFlag?: string;
87
87
  })): void;
88
88
  /**
@@ -91,7 +91,7 @@ export declare function on(element: HTMLElement | ShadowRoot | Document, listene
91
91
  * @param listener - 事件名称。
92
92
  * @param fn - 要移除的事件监听器函数。
93
93
  */
94
- export declare function off(el: HTMLElement | ShadowRoot | Document, listener: string, fn: EventListener, option?: boolean | EventListenerOptions): void;
94
+ export declare function off(el: HTMLElement | ShadowRoot | Document | HTMLCollection | NodeListOf<HTMLElement> | HTMLElement[], listener: string, fn: EventListener, option?: boolean | EventListenerOptions): void;
95
95
  /**
96
96
  * 判断事件是否应该继续传递。
97
97
  * 从事件目标开始向上遍历DOM树,检查每个节点上是否存在指定的属性。
@@ -119,12 +119,8 @@ export declare function html(element: HTMLElement, htmlstr?: string): string | u
119
119
  * @returns
120
120
  */
121
121
  export declare function text(element: HTMLElement, textstr?: string): string | null | undefined;
122
- /**
123
- * 节点列表遍历
124
- * @param elems
125
- * @param fn 遍历到节点时的回调,回调第一个参数为遍历到的节点,第2个参数为 index;如果回调函数返回 true,则会终止遍历(break)
126
- */
127
- export declare function iterate(elems: NodeList | HTMLElement[], fn: (el: HTMLElement, index: number) => any): void;
122
+ export declare function iterate<T>(elems: T[], fn: (el: T, index: number) => any): void;
123
+ export declare function iterate(elems: NodeList | HTMLCollection, fn: (el: HTMLElement, index: number) => any): void;
128
124
  /**
129
125
  * 设置或获取节点 data-* 属性
130
126
  * @param elem
package/lib/dom.js CHANGED
@@ -128,12 +128,20 @@ export function toggleClass(el, clazz) {
128
128
  * @param {boolean} onceOrConfig 是否是只运行一次的处理函数或者配置,其中 eventFlag 为 string,如果配置该项,则表明为委托事件
129
129
  */
130
130
  export function on(element, listener, fn, option) {
131
- if (typeof option === "object" && option.eventFlag) {
132
- if (element.setAttribute) {
131
+ if (element.length != null) {
132
+ iterate(element, (elem) => {
133
+ if (typeof option === "object" && option.eventFlag) {
134
+ elem.setAttribute(option.eventFlag, "__stop__");
135
+ }
136
+ elem.addEventListener(listener, fn, option);
137
+ });
138
+ }
139
+ else if (element) {
140
+ if (typeof option === "object" && option.eventFlag) {
133
141
  element.setAttribute(option.eventFlag, "__stop__");
134
142
  }
143
+ element.addEventListener(listener, fn, option);
135
144
  }
136
- element.addEventListener(listener, fn, option);
137
145
  }
138
146
  /**
139
147
  * 移除指定元素的事件监听器。
@@ -142,7 +150,14 @@ export function on(element, listener, fn, option) {
142
150
  * @param fn - 要移除的事件监听器函数。
143
151
  */
144
152
  export function off(el, listener, fn, option) {
145
- el.removeEventListener(listener, fn, option);
153
+ if (el.length != null) {
154
+ iterate(el, (elem) => {
155
+ elem.removeEventListener(listener, fn, option);
156
+ });
157
+ }
158
+ else if (el) {
159
+ el.removeEventListener(listener, fn, option);
160
+ }
146
161
  }
147
162
  /**
148
163
  * 判断事件是否应该继续传递。
@@ -439,6 +454,8 @@ function toggleCssProperty(el, properties, method = "set") {
439
454
  export function transition(el, nameOrProperties, dir = "enter", finish) {
440
455
  const p = dir === "enter" ? "from" : "to";
441
456
  let nameClass = "", activeClass = "";
457
+ /** 动画状态, -1 - 准备, 0 - 进行中, 1 - 完成 */
458
+ let status = -1;
442
459
  const trans = [];
443
460
  if (typeof nameOrProperties === "string") {
444
461
  nameClass = `${nameOrProperties}-${dir}-${p}`;
@@ -452,6 +469,7 @@ export function transition(el, nameOrProperties, dir = "enter", finish) {
452
469
  }
453
470
  }
454
471
  }
472
+ status = 0;
455
473
  if (dir === "enter") {
456
474
  if (nameClass) {
457
475
  el.classList.add(nameClass);
@@ -490,25 +508,26 @@ export function transition(el, nameOrProperties, dir = "enter", finish) {
490
508
  });
491
509
  }
492
510
  }
493
- el.addEventListener("transitionend", () => {
494
- if (nameClass) {
495
- el.classList.remove(activeClass);
496
- requestAnimationFrame(() => {
497
- el.classList.remove(nameClass);
498
- });
499
- }
500
- else {
501
- if (trans) {
502
- el.style.removeProperty("transition");
511
+ el.addEventListener("transitionend", (_e) => {
512
+ if (status === 0) {
513
+ status = 1;
514
+ if (nameClass) {
515
+ el.classList.remove(activeClass);
516
+ requestAnimationFrame(() => {
517
+ el.classList.remove(nameClass);
518
+ });
503
519
  }
504
- requestAnimationFrame(() => {
520
+ else {
521
+ if (trans) {
522
+ el.style.removeProperty("transition");
523
+ }
505
524
  requestAnimationFrame(() => {
506
525
  toggleCssProperty(el, nameOrProperties, "remove");
507
526
  });
508
- });
509
- }
510
- if (finish) {
511
- finish();
527
+ }
528
+ if (finish) {
529
+ finish();
530
+ }
512
531
  }
513
532
  }, { once: true });
514
533
  }
package/lib/server.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ /// <reference types="node" />
1
2
  import type { SpawnOptions } from "node:child_process";
2
3
  /**
3
4
  * 执行命令
package/lib/theme.js CHANGED
@@ -19,10 +19,10 @@ export async function initTheme() {
19
19
  if ($themeStyle == null) {
20
20
  $themeStyle = document.createElement("style");
21
21
  $themeStyle.id = "theme-style";
22
- $themeStyle.innerHTML = `
23
- :root{color-scheme:light dark;}
24
- html.light{color-scheme: light;}
25
- html.dark {color-scheme: dark;}
22
+ $themeStyle.innerHTML = `
23
+ :root{color-scheme:light dark;}
24
+ html.light{color-scheme: light;}
25
+ html.dark {color-scheme: dark;}
26
26
  `;
27
27
  document.head.appendChild($themeStyle);
28
28
  }
package/package.json CHANGED
@@ -68,7 +68,7 @@
68
68
  },
69
69
  "./*": "./lib/*"
70
70
  },
71
- "version": "0.15.0",
71
+ "version": "0.15.3",
72
72
  "type": "module",
73
73
  "repository": {
74
74
  "type": "git",
@@ -1,11 +0,0 @@
1
- /**
2
- * 复制数据, 可以从多种类型的数据
3
- * 1. 直接复制文本: await copy("待复制的文本")
4
- * 2. 复制节点上的 data-copy-text:
5
- * <button data-copy-text="这是待复制的文本">复制</button>
6
- * await copy(e.target) // or await copy("#a") or await copy(document.querySelector('#a'))
7
- * 3. 直接复制节点本身数据: await copy('#a')
8
- * @param {string | HTMLElement} source 复制源, 从中解析待复制的数据
9
- * @returns {Promise<boolean>} 是否复制成功
10
- */
11
- export declare function copy(source: string | HTMLElement): Promise<boolean>;
package/lib/clipboard.js DELETED
@@ -1,101 +0,0 @@
1
- /**
2
- * 创建一个临时节点缓存待复制数据
3
- * @param {String} value - 待复制文本
4
- * @return {HTMLElement}
5
- */
6
- function createFakeElement(value) {
7
- const fakeElement = document.createElement("textarea");
8
- fakeElement.style.border = "0";
9
- fakeElement.style.padding = "0";
10
- fakeElement.style.margin = "0";
11
- fakeElement.style.position = "absolute";
12
- fakeElement.style.left = "-9999px";
13
- fakeElement.style.top = "-9999";
14
- fakeElement.setAttribute("readonly", "");
15
- fakeElement.value = value;
16
- return fakeElement;
17
- }
18
- /** 通过执行 execCommand 来执行复制 */
19
- function copyFromCommand(text) {
20
- // 添加节点
21
- const fakeEl = createFakeElement(text);
22
- document.body.append(fakeEl);
23
- fakeEl.focus();
24
- fakeEl.select();
25
- // 执行复制
26
- const res = document.execCommand("copy");
27
- fakeEl.remove(); // 删除节点
28
- return Promise.resolve(res);
29
- }
30
- /** 使用 navigator.clipboard 复制 */
31
- function copyFromClipboard(text) {
32
- const theClipboard = navigator.clipboard;
33
- if (theClipboard != null) {
34
- return theClipboard
35
- .writeText(text)
36
- .then(() => {
37
- Promise.resolve(true);
38
- })
39
- .catch(() => Promise.resolve(false));
40
- }
41
- return Promise.resolve(false);
42
- }
43
- /** 解析待复制的文本 */
44
- function parseCopyText(source) {
45
- let copyText = null; // 待复制文本
46
- let sourceEl = null;
47
- // 获取待复制数据
48
- if (typeof source === "string") {
49
- // 从节点拿数据
50
- if (source.startsWith("#") || source.startsWith(".")) {
51
- sourceEl = document.querySelector(source);
52
- if (sourceEl == null) {
53
- copyText = source;
54
- }
55
- }
56
- else {
57
- copyText = source;
58
- }
59
- }
60
- if (source instanceof HTMLElement) {
61
- sourceEl = source;
62
- }
63
- // 从节点获取待复制数据
64
- if (sourceEl != null) {
65
- if (sourceEl.hasAttribute("data-copy-text")) {
66
- copyText = sourceEl.getAttribute("data-copy-text");
67
- }
68
- else {
69
- const tagName = sourceEl.tagName;
70
- if (tagName === "INPUT" || tagName === "TEXTAREA") {
71
- copyText = sourceEl.value;
72
- }
73
- else {
74
- copyText = sourceEl.textContent;
75
- }
76
- }
77
- }
78
- return copyText;
79
- }
80
- /**
81
- * 复制数据, 可以从多种类型的数据
82
- * 1. 直接复制文本: await copy("待复制的文本")
83
- * 2. 复制节点上的 data-copy-text:
84
- * <button data-copy-text="这是待复制的文本">复制</button>
85
- * await copy(e.target) // or await copy("#a") or await copy(document.querySelector('#a'))
86
- * 3. 直接复制节点本身数据: await copy('#a')
87
- * @param {string | HTMLElement} source 复制源, 从中解析待复制的数据
88
- * @returns {Promise<boolean>} 是否复制成功
89
- */
90
- export async function copy(source) {
91
- // 待复制文本
92
- const copyText = parseCopyText(source);
93
- if (copyText == null) {
94
- return Promise.resolve(false);
95
- }
96
- const v = await copyFromClipboard(copyText);
97
- if (v === false) {
98
- return copyFromCommand(copyText);
99
- }
100
- return Promise.resolve(true);
101
- }