@veltra/utils 1.0.0

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.
Files changed (73) hide show
  1. package/dist/dom/class-name.d.ts +10 -0
  2. package/dist/dom/class-name.js +16 -0
  3. package/dist/dom/class-name.js.map +1 -0
  4. package/dist/dom/highlight.d.ts +14 -0
  5. package/dist/dom/highlight.js +19 -0
  6. package/dist/dom/highlight.js.map +1 -0
  7. package/dist/dom/position.d.ts +28 -0
  8. package/dist/dom/position.js +59 -0
  9. package/dist/dom/position.js.map +1 -0
  10. package/dist/dom/style.d.ts +25 -0
  11. package/dist/dom/style.js +38 -0
  12. package/dist/dom/style.js.map +1 -0
  13. package/dist/dom/z-index.d.ts +9 -0
  14. package/dist/dom/z-index.js +11 -0
  15. package/dist/dom/z-index.js.map +1 -0
  16. package/dist/form/validate.d.ts +33 -0
  17. package/dist/form/validate.js +197 -0
  18. package/dist/form/validate.js.map +1 -0
  19. package/dist/helper/create-increase.d.ts +10 -0
  20. package/dist/helper/create-increase.js +17 -0
  21. package/dist/helper/create-increase.js.map +1 -0
  22. package/dist/helper/create-toggle.d.ts +15 -0
  23. package/dist/helper/create-toggle.js +24 -0
  24. package/dist/helper/create-toggle.js.map +1 -0
  25. package/dist/helper/frame.d.ts +9 -0
  26. package/dist/helper/frame.js +14 -0
  27. package/dist/helper/frame.js.map +1 -0
  28. package/dist/helper/make-bem.d.ts +52 -0
  29. package/dist/helper/make-bem.js +39 -0
  30. package/dist/helper/make-bem.js.map +1 -0
  31. package/dist/helper/tween.d.ts +43 -0
  32. package/dist/helper/tween.js +89 -0
  33. package/dist/helper/tween.js.map +1 -0
  34. package/dist/helper/vue.d.ts +44 -0
  35. package/dist/helper/vue.js +62 -0
  36. package/dist/helper/vue.js.map +1 -0
  37. package/dist/index.d.ts +19 -0
  38. package/dist/index.js +15 -0
  39. package/dist/reactive/proxy.d.ts +19 -0
  40. package/dist/reactive/proxy.js +57 -0
  41. package/dist/reactive/proxy.js.map +1 -0
  42. package/dist/shared/constants.d.ts +10 -0
  43. package/dist/shared/constants.js +11 -0
  44. package/dist/shared/constants.js.map +1 -0
  45. package/dist/types/component-common.d.ts +37 -0
  46. package/dist/types/form-context.d.ts +6 -0
  47. package/dist/types/helper.d.ts +22 -0
  48. package/dist/types/index.d.ts +5 -0
  49. package/dist/types/index.js +0 -0
  50. package/dist/types/utils/form/validate.d.ts +34 -0
  51. package/package.json +47 -0
  52. package/src/dom/class-name.ts +20 -0
  53. package/src/dom/highlight.ts +23 -0
  54. package/src/dom/position.ts +96 -0
  55. package/src/dom/style.ts +60 -0
  56. package/src/dom/z-index.ts +7 -0
  57. package/src/env.d.ts +1 -0
  58. package/src/form/validate.ts +278 -0
  59. package/src/helper/create-increase.ts +14 -0
  60. package/src/helper/create-toggle.ts +29 -0
  61. package/src/helper/frame.ts +9 -0
  62. package/src/helper/make-bem.ts +109 -0
  63. package/src/helper/tween.ts +123 -0
  64. package/src/helper/vue.ts +88 -0
  65. package/src/index.ts +28 -0
  66. package/src/reactive/proxy.ts +90 -0
  67. package/src/shared/constants.ts +8 -0
  68. package/src/shared/index.ts +1 -0
  69. package/src/types/component-common.ts +41 -0
  70. package/src/types/form-context.ts +2 -0
  71. package/src/types/helper.ts +31 -0
  72. package/src/types/index.ts +4 -0
  73. package/src/types/utils/form/validate.ts +33 -0
@@ -0,0 +1,10 @@
1
+ import { BEMFactory } from "../helper/make-bem.js";
2
+ import { CLS_PREFIX } from "../shared/constants.js";
3
+
4
+ //#region src/dom/class-name.d.ts
5
+ declare const bem: BEMFactory<typeof CLS_PREFIX>;
6
+ declare function addClass(el: HTMLElement, className: string | string[]): void;
7
+ declare function removeClass(el: HTMLElement, className: string | string[]): void;
8
+ //#endregion
9
+ export { addClass, bem, removeClass };
10
+ //# sourceMappingURL=class-name.d.ts.map
@@ -0,0 +1,16 @@
1
+ import { makeBEM } from "../helper/make-bem.js";
2
+ import { CLS_PREFIX } from "../shared/constants.js";
3
+ //#region src/dom/class-name.ts
4
+ const bem = makeBEM(CLS_PREFIX);
5
+ function addClass(el, className) {
6
+ if (Array.isArray(className)) className.forEach((c) => el.classList.add(c));
7
+ else el.classList.add(className);
8
+ }
9
+ function removeClass(el, className) {
10
+ if (Array.isArray(className)) className.forEach((c) => el.classList.remove(c));
11
+ else el.classList.remove(className);
12
+ }
13
+ //#endregion
14
+ export { addClass, bem, removeClass };
15
+
16
+ //# sourceMappingURL=class-name.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"class-name.js","names":[],"sources":["../../src/dom/class-name.ts"],"sourcesContent":["import { makeBEM, type BEMFactory } from '../helper/make-bem'\nimport { CLS_PREFIX } from '../shared/constants'\n\nexport const bem: BEMFactory<typeof CLS_PREFIX> = makeBEM(CLS_PREFIX)\n\nexport function addClass(el: HTMLElement, className: string | string[]): void {\n if (Array.isArray(className)) {\n className.forEach((c) => el.classList.add(c))\n } else {\n el.classList.add(className)\n }\n}\n\nexport function removeClass(el: HTMLElement, className: string | string[]): void {\n if (Array.isArray(className)) {\n className.forEach((c) => el.classList.remove(c))\n } else {\n el.classList.remove(className)\n }\n}\n"],"mappings":";;;AAGA,MAAa,MAAqC,QAAQ,WAAW;AAErE,SAAgB,SAAS,IAAiB,WAAoC;AAC5E,KAAI,MAAM,QAAQ,UAAU,CAC1B,WAAU,SAAS,MAAM,GAAG,UAAU,IAAI,EAAE,CAAC;KAE7C,IAAG,UAAU,IAAI,UAAU;;AAI/B,SAAgB,YAAY,IAAiB,WAAoC;AAC/E,KAAI,MAAM,QAAQ,UAAU,CAC1B,WAAU,SAAS,MAAM,GAAG,UAAU,OAAO,EAAE,CAAC;KAEhD,IAAG,UAAU,OAAO,UAAU"}
@@ -0,0 +1,14 @@
1
+ //#region src/dom/highlight.d.ts
2
+ interface HighlightChunk {
3
+ text: string;
4
+ highlight: boolean;
5
+ }
6
+ /**
7
+ * 获取文本高亮片段
8
+ * @param string 字符串
9
+ * @param substrings 需要匹配的字串列表
10
+ */
11
+ declare function getHighlightChunks(str: string, substrings: string[]): HighlightChunk[];
12
+ //#endregion
13
+ export { getHighlightChunks };
14
+ //# sourceMappingURL=highlight.d.ts.map
@@ -0,0 +1,19 @@
1
+ //#region src/dom/highlight.ts
2
+ const escapeRegexp = (term) => term.replace(/[|\\{}()[\]^$+*?.-]/g, (char) => `\\${char}`);
3
+ /**
4
+ * 获取文本高亮片段
5
+ * @param string 字符串
6
+ * @param substrings 需要匹配的字串列表
7
+ */
8
+ function getHighlightChunks(str, substrings) {
9
+ const _substrings = substrings.filter((s) => !!s).map((s) => escapeRegexp(s.trim()));
10
+ const re = new RegExp(`(${_substrings.join("|")})`, "gi");
11
+ return str.split(re).filter(Boolean).map((text) => ({
12
+ text,
13
+ highlight: re.test(text)
14
+ }));
15
+ }
16
+ //#endregion
17
+ export { getHighlightChunks };
18
+
19
+ //# sourceMappingURL=highlight.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"highlight.js","names":[],"sources":["../../src/dom/highlight.ts"],"sourcesContent":["// TODO: 在多种场景下, 比较KMP算法, BM算法, two-way算法是否比正则更快\n\ninterface HighlightChunk {\n text: string\n highlight: boolean\n}\n\nconst escapeRegexp = (term: string): string =>\n term.replace(/[|\\\\{}()[\\]^$+*?.-]/g, (char: string) => `\\\\${char}`)\n\n/**\n * 获取文本高亮片段\n * @param string 字符串\n * @param substrings 需要匹配的字串列表\n */\nexport function getHighlightChunks(str: string, substrings: string[]): HighlightChunk[] {\n const _substrings = substrings.filter((s) => !!s).map((s) => escapeRegexp(s.trim()))\n const re = new RegExp(`(${_substrings.join('|')})`, 'gi')\n return str\n .split(re)\n .filter(Boolean)\n .map((text) => ({ text, highlight: re.test(text) }))\n}\n"],"mappings":";AAOA,MAAM,gBAAgB,SACpB,KAAK,QAAQ,yBAAyB,SAAiB,KAAK,OAAO;;;;;;AAOrE,SAAgB,mBAAmB,KAAa,YAAwC;CACtF,MAAM,cAAc,WAAW,QAAQ,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,aAAa,EAAE,MAAM,CAAC,CAAC;CACpF,MAAM,KAAK,IAAI,OAAO,IAAI,YAAY,KAAK,IAAI,CAAC,IAAI,KAAK;AACzD,QAAO,IACJ,MAAM,GAAG,CACT,OAAO,QAAQ,CACf,KAAK,UAAU;EAAE;EAAM,WAAW,GAAG,KAAK,KAAK;EAAE,EAAE"}
@@ -0,0 +1,28 @@
1
+ //#region src/dom/position.d.ts
2
+ /**
3
+ * 获取可滚动的父级
4
+ * @param el 元素
5
+ * @returns
6
+ */
7
+ declare function getScrollParents(el: HTMLElement): HTMLElement[];
8
+ /**
9
+ * 获取最近的可滚动父级
10
+ * @param el 元素
11
+ * @returns 最近的可滚动父级
12
+ */
13
+ declare function getNearestScrollParent(el: HTMLElement): HTMLElement | null;
14
+ type ScrollViewPosition = 'center' | 'start' | 'end';
15
+ /**
16
+ * 滚动元素到容器视图中
17
+ * @description 用于替代 `el.scrollIntoView` 方法,因为 `el.scrollIntoView` 在某些情况下会导致外部元素滚动
18
+ * @param el 元素
19
+ * @param container 可滚动容器
20
+ * @param options 滚动选项
21
+ */
22
+ declare function scrollIntoContainerView(el: HTMLElement, container: HTMLElement | null, options?: {
23
+ block?: ScrollViewPosition;
24
+ inline?: ScrollViewPosition;
25
+ }): void;
26
+ //#endregion
27
+ export { getNearestScrollParent, getScrollParents, scrollIntoContainerView };
28
+ //# sourceMappingURL=position.d.ts.map
@@ -0,0 +1,59 @@
1
+ //#region src/dom/position.ts
2
+ /**
3
+ * 获取可滚动的父级
4
+ * @param el 元素
5
+ * @returns
6
+ */
7
+ function getScrollParents(el) {
8
+ const parents = [];
9
+ let parent = el.parentElement;
10
+ while (parent) {
11
+ if (parent.scrollHeight > parent.clientHeight) parents.push(parent);
12
+ parent = parent.parentElement;
13
+ }
14
+ return parents;
15
+ }
16
+ /**
17
+ * 获取最近的可滚动父级
18
+ * @param el 元素
19
+ * @returns 最近的可滚动父级
20
+ */
21
+ function getNearestScrollParent(el) {
22
+ let parent = el.parentElement;
23
+ while (parent) {
24
+ if (parent.scrollHeight > parent.clientHeight) return parent;
25
+ parent = parent.parentElement;
26
+ }
27
+ return null;
28
+ }
29
+ /**
30
+ * 滚动元素到容器视图中
31
+ * @description 用于替代 `el.scrollIntoView` 方法,因为 `el.scrollIntoView` 在某些情况下会导致外部元素滚动
32
+ * @param el 元素
33
+ * @param container 可滚动容器
34
+ * @param options 滚动选项
35
+ */
36
+ function scrollIntoContainerView(el, container, options) {
37
+ container = container || getNearestScrollParent(el);
38
+ if (!container) return;
39
+ const { block = "center", inline = "center" } = options || {};
40
+ const { offsetTop: eOffsetTop, offsetLeft: eOffsetLeft, offsetHeight: eOffsetHeight, offsetWidth: eOffsetWidth } = el;
41
+ const { clientHeight: cClientHeight, clientWidth: cClientWidth, scrollTop: cScrollTop, scrollLeft: cScrollLeft } = container;
42
+ const isVerticalInView = cScrollTop + cClientHeight > eOffsetTop + eOffsetHeight && cScrollTop < eOffsetTop;
43
+ const isHorizontalInView = cScrollLeft + cClientWidth > eOffsetLeft + eOffsetWidth && cScrollLeft < eOffsetLeft;
44
+ if (isVerticalInView && isHorizontalInView) return;
45
+ if (!isVerticalInView) {
46
+ if (block === "center") container.scrollTop = eOffsetTop - cClientHeight / 2 + eOffsetHeight / 2;
47
+ else if (block === "start") container.scrollTop = eOffsetTop;
48
+ else if (block === "end") container.scrollTop = eOffsetTop - cClientHeight + eOffsetHeight;
49
+ }
50
+ if (!isHorizontalInView) {
51
+ if (inline === "center") container.scrollLeft = eOffsetLeft - cClientWidth / 2 + eOffsetWidth / 2;
52
+ else if (inline === "start") container.scrollLeft = eOffsetLeft;
53
+ else if (inline === "end") container.scrollLeft = eOffsetLeft - cClientWidth + eOffsetWidth;
54
+ }
55
+ }
56
+ //#endregion
57
+ export { getNearestScrollParent, getScrollParents, scrollIntoContainerView };
58
+
59
+ //# sourceMappingURL=position.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"position.js","names":[],"sources":["../../src/dom/position.ts"],"sourcesContent":["/**\n * 获取可滚动的父级\n * @param el 元素\n * @returns\n */\nexport function getScrollParents(el: HTMLElement): HTMLElement[] {\n const parents: HTMLElement[] = []\n let parent = el.parentElement\n while (parent) {\n if (parent.scrollHeight > parent.clientHeight) {\n parents.push(parent)\n }\n\n parent = parent.parentElement\n }\n return parents\n}\n\n/**\n * 获取最近的可滚动父级\n * @param el 元素\n * @returns 最近的可滚动父级\n */\nexport function getNearestScrollParent(el: HTMLElement): HTMLElement | null {\n let parent = el.parentElement\n while (parent) {\n if (parent.scrollHeight > parent.clientHeight) {\n return parent\n }\n parent = parent.parentElement\n }\n return null\n}\n\ntype ScrollViewPosition = 'center' | 'start' | 'end'\n\n/**\n * 滚动元素到容器视图中\n * @description 用于替代 `el.scrollIntoView` 方法,因为 `el.scrollIntoView` 在某些情况下会导致外部元素滚动\n * @param el 元素\n * @param container 可滚动容器\n * @param options 滚动选项\n */\nexport function scrollIntoContainerView(\n el: HTMLElement,\n container: HTMLElement | null,\n options?: { block?: ScrollViewPosition; inline?: ScrollViewPosition }\n): void {\n container = container || getNearestScrollParent(el)\n if (!container) return\n\n const { block = 'center', inline = 'center' } = options || {}\n\n const {\n offsetTop: eOffsetTop,\n offsetLeft: eOffsetLeft,\n offsetHeight: eOffsetHeight,\n offsetWidth: eOffsetWidth\n } = el\n\n const {\n clientHeight: cClientHeight,\n clientWidth: cClientWidth,\n scrollTop: cScrollTop,\n scrollLeft: cScrollLeft\n } = container\n\n const isVerticalInView =\n cScrollTop + cClientHeight > eOffsetTop + eOffsetHeight && cScrollTop < eOffsetTop\n\n const isHorizontalInView =\n cScrollLeft + cClientWidth > eOffsetLeft + eOffsetWidth && cScrollLeft < eOffsetLeft\n\n // 垂直方向和水平方向都已经在视图中,则不进行滚动\n if (isVerticalInView && isHorizontalInView) return\n\n if (!isVerticalInView) {\n if (block === 'center') {\n container.scrollTop = eOffsetTop - cClientHeight / 2 + eOffsetHeight / 2\n } else if (block === 'start') {\n container.scrollTop = eOffsetTop\n } else if (block === 'end') {\n container.scrollTop = eOffsetTop - cClientHeight + eOffsetHeight\n }\n }\n\n if (!isHorizontalInView) {\n if (inline === 'center') {\n container.scrollLeft = eOffsetLeft - cClientWidth / 2 + eOffsetWidth / 2\n } else if (inline === 'start') {\n container.scrollLeft = eOffsetLeft\n } else if (inline === 'end') {\n container.scrollLeft = eOffsetLeft - cClientWidth + eOffsetWidth\n }\n }\n}\n"],"mappings":";;;;;;AAKA,SAAgB,iBAAiB,IAAgC;CAC/D,MAAM,UAAyB,EAAE;CACjC,IAAI,SAAS,GAAG;AAChB,QAAO,QAAQ;AACb,MAAI,OAAO,eAAe,OAAO,aAC/B,SAAQ,KAAK,OAAO;AAGtB,WAAS,OAAO;;AAElB,QAAO;;;;;;;AAQT,SAAgB,uBAAuB,IAAqC;CAC1E,IAAI,SAAS,GAAG;AAChB,QAAO,QAAQ;AACb,MAAI,OAAO,eAAe,OAAO,aAC/B,QAAO;AAET,WAAS,OAAO;;AAElB,QAAO;;;;;;;;;AAYT,SAAgB,wBACd,IACA,WACA,SACM;AACN,aAAY,aAAa,uBAAuB,GAAG;AACnD,KAAI,CAAC,UAAW;CAEhB,MAAM,EAAE,QAAQ,UAAU,SAAS,aAAa,WAAW,EAAE;CAE7D,MAAM,EACJ,WAAW,YACX,YAAY,aACZ,cAAc,eACd,aAAa,iBACX;CAEJ,MAAM,EACJ,cAAc,eACd,aAAa,cACb,WAAW,YACX,YAAY,gBACV;CAEJ,MAAM,mBACJ,aAAa,gBAAgB,aAAa,iBAAiB,aAAa;CAE1E,MAAM,qBACJ,cAAc,eAAe,cAAc,gBAAgB,cAAc;AAG3E,KAAI,oBAAoB,mBAAoB;AAE5C,KAAI,CAAC;MACC,UAAU,SACZ,WAAU,YAAY,aAAa,gBAAgB,IAAI,gBAAgB;WAC9D,UAAU,QACnB,WAAU,YAAY;WACb,UAAU,MACnB,WAAU,YAAY,aAAa,gBAAgB;;AAIvD,KAAI,CAAC;MACC,WAAW,SACb,WAAU,aAAa,cAAc,eAAe,IAAI,eAAe;WAC9D,WAAW,QACpB,WAAU,aAAa;WACd,WAAW,MACpB,WAAU,aAAa,cAAc,eAAe"}
@@ -0,0 +1,25 @@
1
+ import { CSSProperties } from "vue";
2
+
3
+ //#region src/dom/style.d.ts
4
+ /**
5
+ * 给数值加上单位
6
+ * @param value 数值
7
+ * @param unit 单位
8
+ * @returns
9
+ */
10
+ declare function withUnit(value: number | string | undefined, unit: string): string | undefined;
11
+ /**
12
+ * 设置元素样式,优先使用高性能的方式
13
+ * @param el 元素
14
+ * @param styles 样式
15
+ */
16
+ declare function setStyles(el: HTMLElement, styles: CSSProperties): void;
17
+ /**
18
+ * 移除样式
19
+ * @param el dom元素
20
+ * @param props 要移除的样式属性
21
+ */
22
+ declare function removeStyles(el: HTMLElement, props: string[]): void;
23
+ //#endregion
24
+ export { removeStyles, setStyles, withUnit };
25
+ //# sourceMappingURL=style.d.ts.map
@@ -0,0 +1,38 @@
1
+ import { str } from "@cat-kit/core";
2
+ //#region src/dom/style.ts
3
+ /**
4
+ * 给数值加上单位
5
+ * @param value 数值
6
+ * @param unit 单位
7
+ * @returns
8
+ */
9
+ function withUnit(value, unit) {
10
+ return value === void 0 ? void 0 : typeof value === "number" || !isNaN(+value) ? String(value) + unit : value;
11
+ }
12
+ /**
13
+ * 设置元素样式,优先使用高性能的方式
14
+ * @param el 元素
15
+ * @param styles 样式
16
+ */
17
+ function setStyles(el, styles) {
18
+ Object.keys(styles).forEach((key) => {
19
+ el.style[key] = styles[key];
20
+ });
21
+ }
22
+ /**
23
+ * 移除样式
24
+ * @param el dom元素
25
+ * @param props 要移除的样式属性
26
+ */
27
+ function removeStyles(el, props) {
28
+ if (el.attributeStyleMap) props.forEach((key) => {
29
+ el.attributeStyleMap.delete(str(key).kebabCase());
30
+ });
31
+ else props.forEach((key) => {
32
+ el.style.removeProperty(key);
33
+ });
34
+ }
35
+ //#endregion
36
+ export { removeStyles, setStyles, withUnit };
37
+
38
+ //# sourceMappingURL=style.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"style.js","names":[],"sources":["../../src/dom/style.ts"],"sourcesContent":["import { str } from '@cat-kit/core'\nimport type { CSSProperties } from 'vue'\n\n/**\n * 给数值加上单位\n * @param value 数值\n * @param unit 单位\n * @returns\n */\nexport function withUnit(value: number | string | undefined, unit: string): string | undefined {\n return value === undefined\n ? undefined\n : typeof value === 'number' || !isNaN(+value)\n ? String(value) + unit\n : value\n}\n\n/**\n * 设置元素样式,优先使用高性能的方式\n * @param el 元素\n * @param styles 样式\n */\nexport function setStyles(el: HTMLElement, styles: CSSProperties): void {\n Object.keys(styles).forEach((key) => {\n el.style[key] = styles[key]\n })\n // TODO: 此处有问题,在某些情况下会导致样式设置失效\n // 例如在 Tabs 组件中无法设置overflow属性\n // if (el.attributeStyleMap) {\n // Object.keys(styles).forEach(key => {\n // const value = styles[key]\n // if (!value && value !== 0) {\n // el.attributeStyleMap.delete(kebabCase(key))\n // } else {\n // el.attributeStyleMap.set(kebabCase(key), value)\n // }\n // })\n // } else {\n // Object.keys(styles).forEach(key => {\n // el.style[key] = styles[key]\n // })\n // }\n}\n\n/**\n * 移除样式\n * @param el dom元素\n * @param props 要移除的样式属性\n */\nexport function removeStyles(el: HTMLElement, props: string[]): void {\n if (el.attributeStyleMap) {\n props.forEach((key) => {\n el.attributeStyleMap.delete(str(key).kebabCase())\n })\n } else {\n props.forEach((key) => {\n el.style.removeProperty(key)\n })\n }\n}\n"],"mappings":";;;;;;;;AASA,SAAgB,SAAS,OAAoC,MAAkC;AAC7F,QAAO,UAAU,KAAA,IACb,KAAA,IACA,OAAO,UAAU,YAAY,CAAC,MAAM,CAAC,MAAM,GACzC,OAAO,MAAM,GAAG,OAChB;;;;;;;AAQR,SAAgB,UAAU,IAAiB,QAA6B;AACtE,QAAO,KAAK,OAAO,CAAC,SAAS,QAAQ;AACnC,KAAG,MAAM,OAAO,OAAO;GACvB;;;;;;;AAwBJ,SAAgB,aAAa,IAAiB,OAAuB;AACnE,KAAI,GAAG,kBACL,OAAM,SAAS,QAAQ;AACrB,KAAG,kBAAkB,OAAO,IAAI,IAAI,CAAC,WAAW,CAAC;GACjD;KAEF,OAAM,SAAS,QAAQ;AACrB,KAAG,MAAM,eAAe,IAAI;GAC5B"}
@@ -0,0 +1,9 @@
1
+ //#region src/dom/z-index.d.ts
2
+ /**
3
+ * z轴层级
4
+ * 保证每个新打开的弹框的位置都处于上层
5
+ */
6
+ declare const zIndex: () => number;
7
+ //#endregion
8
+ export { zIndex };
9
+ //# sourceMappingURL=z-index.d.ts.map
@@ -0,0 +1,11 @@
1
+ import { createIncrease } from "../helper/create-increase.js";
2
+ //#region src/dom/z-index.ts
3
+ /**
4
+ * z轴层级
5
+ * 保证每个新打开的弹框的位置都处于上层
6
+ */
7
+ const zIndex = createIncrease(1e3);
8
+ //#endregion
9
+ export { zIndex };
10
+
11
+ //# sourceMappingURL=z-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"z-index.js","names":[],"sources":["../../src/dom/z-index.ts"],"sourcesContent":["import { createIncrease } from '../helper/create-increase'\n\n/**\n * z轴层级\n * 保证每个新打开的弹框的位置都处于上层\n */\nexport const zIndex: () => number = createIncrease(1000)\n"],"mappings":";;;;;;AAMA,MAAa,SAAuB,eAAe,IAAK"}
@@ -0,0 +1,33 @@
1
+ import { Data, ValidateRule, ValidatorConfig } from "../types/utils/form/validate.js";
2
+
3
+ //#region src/form/validate.d.ts
4
+ /** */
5
+ declare class Validator<Rules extends Record<string, ValidateRule> = Record<string, ValidateRule>, Field extends keyof Rules = keyof Rules> {
6
+ protected rules: Rules;
7
+ private config?;
8
+ constructor(rules: Rules, config?: ValidatorConfig);
9
+ /** 是否存在规则 */
10
+ private get existRules();
11
+ /**
12
+ * 校验单条数据
13
+ * @param data 数据
14
+ */
15
+ private validateSingleData;
16
+ private validateValue;
17
+ private validateValueLazy;
18
+ /**
19
+ * 校验多条数据
20
+ * @param field 需要校验的字段
21
+ */
22
+ private validateManyData;
23
+ /**
24
+ * 校验
25
+ * @param data 数据
26
+ * @param fields 字段
27
+ * @returns
28
+ */
29
+ validate(data: Data, fields?: Field | Field[]): Promise<{ [key in Field]?: string[] }>;
30
+ }
31
+ //#endregion
32
+ export { Validator };
33
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1,197 @@
1
+ import { o } from "@cat-kit/core";
2
+ //#region src/form/validate.ts
3
+ const isEmpty = (value) => {
4
+ return value === null || value === void 0;
5
+ };
6
+ const presetRules = {
7
+ email(v) {
8
+ if (!/^([\w_-]+)@([\w-]+[.]?)*[\w]+\.[a-zA-Z]{2,10}$/.test(v)) return "邮箱格式不正确";
9
+ },
10
+ phone(v) {
11
+ if (!/^\d{11}$/.test(v)) return "手机号格式不正确";
12
+ },
13
+ num(v) {
14
+ if (!/^\d+$/.test(v)) return "数字格式不正确";
15
+ },
16
+ url(v) {
17
+ if (!/^(ftp|https?):\/\/([\w_-]+)\.([\w-]+[.]?)*[\w]+\.[a-zA-Z]{2,10}(.*)/.test(v)) return "链接格式不正确";
18
+ },
19
+ idCard(v) {
20
+ if (!/^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$/.test(v)) return "身份证格式不正确";
21
+ }
22
+ };
23
+ /** 预设规则 */
24
+ const ruleTypes = {
25
+ required(value, required) {
26
+ if (required === false) return;
27
+ const errMsg = typeof required === "string" ? required : "该项不能为空";
28
+ if (isEmpty(value)) return errMsg;
29
+ if (Array.isArray(value) && !value.length) return errMsg;
30
+ if (typeof value === "string" && !value) return errMsg;
31
+ },
32
+ min(value, rule) {
33
+ if (isEmpty(value)) return;
34
+ let _rule = Array.isArray(rule) ? rule[0] : rule;
35
+ let errMsg = Array.isArray(rule) ? rule[1] : `该项必须大于等于${_rule}`;
36
+ if (typeof value !== "number") return `${value}不是一个数字`;
37
+ if (value < _rule) return errMsg;
38
+ },
39
+ max(value, rule) {
40
+ if (isEmpty(value)) return;
41
+ let _rule = Array.isArray(rule) ? rule[0] : rule;
42
+ let errMsg = Array.isArray(rule) ? rule[1] : `该项必须小于等于${_rule}`;
43
+ if (typeof value !== "number") return `${value}不是一个数字`;
44
+ if (value > _rule) return errMsg;
45
+ },
46
+ minLen(value, rule) {
47
+ if (isEmpty(value)) return;
48
+ let _rule = Array.isArray(rule) ? rule[0] : rule;
49
+ let errMsg = Array.isArray(rule) ? rule[1] : `该项长度必须大于等于${_rule}`;
50
+ if (!Array.isArray(value) && typeof value !== "string") return `${value}不是一个字符串或数组`;
51
+ if (value.length < _rule) return errMsg;
52
+ },
53
+ maxLen(value, rule) {
54
+ if (isEmpty(value)) return;
55
+ let _rule = Array.isArray(rule) ? rule[0] : rule;
56
+ let errMsg = Array.isArray(rule) ? rule[1] : `该项长度必须小于等于:${_rule}`;
57
+ if (!Array.isArray(value) && typeof value !== "string") return `${value}不是一个字符串或数组`;
58
+ if (value.length > _rule) return errMsg;
59
+ },
60
+ match(value, rule) {
61
+ if (isEmpty(value) || value === "") return;
62
+ if (typeof rule === "string") {
63
+ if (!rule) return;
64
+ rule = new RegExp(rule);
65
+ }
66
+ let _rule = Array.isArray(rule) ? rule[0] : rule;
67
+ let errMsg = Array.isArray(rule) ? rule[1] : `该项不匹配正则:${_rule}`;
68
+ if (typeof value !== "string") return `${value}不是一个字符串`;
69
+ if (!_rule.test(value)) return errMsg;
70
+ },
71
+ preset(value, rule) {
72
+ if (isEmpty(value) || value === "" || !rule) return;
73
+ if (typeof value !== "string") return `${value}不是一个字符串`;
74
+ const ruleValidator = presetRules[rule];
75
+ return ruleValidator(value);
76
+ }
77
+ };
78
+ /** */
79
+ var Validator = class {
80
+ rules;
81
+ config;
82
+ constructor(rules, config) {
83
+ this.rules = rules;
84
+ if (config) this.config = config;
85
+ }
86
+ /** 是否存在规则 */
87
+ get existRules() {
88
+ for (const _ in this.rules) return true;
89
+ return false;
90
+ }
91
+ /**
92
+ * 校验单条数据
93
+ * @param data 数据
94
+ */
95
+ async validateSingleData(data, fields) {
96
+ const fieldErrors = {};
97
+ if (!this.existRules) return fieldErrors;
98
+ const lazy = this.config?.lazy ?? true;
99
+ fields = fields ? Array.isArray(fields) ? fields : [fields] : Object.keys(this.rules);
100
+ if (lazy) {
101
+ for (let i = 0; i < fields.length; i++) {
102
+ const field = fields[i];
103
+ const errors = await this.validateValueLazy(data, field);
104
+ if (errors.length === 0) continue;
105
+ fieldErrors[field] = errors;
106
+ }
107
+ return fieldErrors;
108
+ } else {
109
+ for (let i = 0; i < fields.length; i++) {
110
+ const field = fields[i];
111
+ const errors = await this.validateValue(data, field);
112
+ if (errors.length === 0) continue;
113
+ fieldErrors[field] = errors;
114
+ }
115
+ return fieldErrors;
116
+ }
117
+ }
118
+ async validateValue(data, field) {
119
+ const rules = this.rules[field];
120
+ const value = o(data).get(field);
121
+ const { validator, required, ...normalRules } = rules;
122
+ let errors = [];
123
+ if (required) {
124
+ const err = ruleTypes.required(value, required);
125
+ err && errors.push(err);
126
+ }
127
+ for (const ruleKey in normalRules) {
128
+ const validate = ruleTypes[ruleKey];
129
+ if (!validate) continue;
130
+ const err = validate(value, normalRules[ruleKey]);
131
+ err && errors.push(err);
132
+ }
133
+ if (validator) {
134
+ const err = await validator(value, data);
135
+ err && errors.push(err);
136
+ }
137
+ return errors;
138
+ }
139
+ async validateValueLazy(data, field) {
140
+ const rules = this.rules[field];
141
+ const value = o(data).get(field);
142
+ let errors = [];
143
+ if (!rules) return errors;
144
+ const { validator, required, ...normalRules } = rules;
145
+ if (required) {
146
+ const err = ruleTypes.required(value, required);
147
+ if (err) {
148
+ errors.push(err);
149
+ return errors;
150
+ }
151
+ }
152
+ for (const ruleKey in normalRules) {
153
+ const validate = ruleTypes[ruleKey];
154
+ if (!validate) continue;
155
+ const err = validate(value, normalRules[ruleKey]);
156
+ if (err) {
157
+ errors.push(err);
158
+ return errors;
159
+ }
160
+ }
161
+ if (validator) {
162
+ const err = await validator(value, data);
163
+ if (err) {
164
+ errors.push(err);
165
+ return errors;
166
+ }
167
+ }
168
+ return errors;
169
+ }
170
+ /**
171
+ * 校验多条数据
172
+ * @param field 需要校验的字段
173
+ */
174
+ async validateManyData(data, field) {
175
+ let i = 0;
176
+ while (i < data.length) {
177
+ const item = data[i];
178
+ const fieldErrors = await this.validateSingleData(item, field);
179
+ if (Object.keys(fieldErrors).length > 0) return fieldErrors;
180
+ i++;
181
+ }
182
+ return {};
183
+ }
184
+ /**
185
+ * 校验
186
+ * @param data 数据
187
+ * @param fields 字段
188
+ * @returns
189
+ */
190
+ async validate(data, fields) {
191
+ return Array.isArray(data) ? this.validateManyData(data, fields) : this.validateSingleData(data, fields);
192
+ }
193
+ };
194
+ //#endregion
195
+ export { Validator };
196
+
197
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","names":[],"sources":["../../src/form/validate.ts"],"sourcesContent":["import { o } from '@cat-kit/core'\n\nimport type { Undef } from '../types/helper'\nimport type { ValidateRule, Data, ValidatorConfig, PresetRule } from '../types/utils/form/validate'\n\nconst isEmpty = (value: any): value is null | undefined => {\n return value === null || value === undefined\n}\n\nconst presetRules: Record<PresetRule, (value: string) => string | undefined> = {\n email(v) {\n const re = /^([\\w_-]+)@([\\w-]+[.]?)*[\\w]+\\.[a-zA-Z]{2,10}$/\n if (!re.test(v)) {\n return '邮箱格式不正确'\n }\n },\n phone(v) {\n const re = /^\\d{11}$/\n if (!re.test(v)) {\n return '手机号格式不正确'\n }\n },\n num(v) {\n const re = /^\\d+$/\n if (!re.test(v)) {\n return '数字格式不正确'\n }\n },\n url(v) {\n const re = /^(ftp|https?):\\/\\/([\\w_-]+)\\.([\\w-]+[.]?)*[\\w]+\\.[a-zA-Z]{2,10}(.*)/\n if (!re.test(v)) {\n return '链接格式不正确'\n }\n },\n\n idCard(v) {\n const re = /^(\\d{6})(\\d{4})(\\d{2})(\\d{2})(\\d{3})([0-9]|X)$/\n if (!re.test(v)) {\n return '身份证格式不正确'\n }\n }\n}\n\n/** 预设规则 */\nconst ruleTypes = {\n required(value: any, required: ValidateRule['required']): Undef<string> {\n if (required === false) return\n\n const errMsg = typeof required === 'string' ? required : '该项不能为空'\n if (isEmpty(value)) return errMsg\n\n if (Array.isArray(value) && !value.length) return errMsg\n if (typeof value === 'string' && !value) return errMsg\n },\n min(value: any, rule: ValidateRule['min']): Undef<string> {\n if (isEmpty(value)) return\n let _rule = Array.isArray(rule) ? rule[0] : rule!\n let errMsg = Array.isArray(rule) ? rule[1] : `该项必须大于等于${_rule}`\n if (typeof value !== 'number') return `${value}不是一个数字`\n if (value < _rule) return errMsg\n },\n max(value: any, rule: ValidateRule['max']): Undef<string> {\n if (isEmpty(value)) return\n let _rule = Array.isArray(rule) ? rule[0] : rule!\n let errMsg = Array.isArray(rule) ? rule[1] : `该项必须小于等于${_rule}`\n if (typeof value !== 'number') return `${value}不是一个数字`\n if (value > _rule) return errMsg\n },\n\n minLen(value: any, rule: ValidateRule['minLen']): Undef<string> {\n if (isEmpty(value)) return\n let _rule = Array.isArray(rule) ? rule[0] : rule!\n let errMsg = Array.isArray(rule) ? rule[1] : `该项长度必须大于等于${_rule}`\n if (!Array.isArray(value) && typeof value !== 'string') return `${value}不是一个字符串或数组`\n if (value.length < _rule) return errMsg\n },\n maxLen(value: any, rule: ValidateRule['maxLen']): Undef<string> {\n if (isEmpty(value)) return\n let _rule = Array.isArray(rule) ? rule[0] : rule!\n let errMsg = Array.isArray(rule) ? rule[1] : `该项长度必须小于等于:${_rule}`\n if (!Array.isArray(value) && typeof value !== 'string') return `${value}不是一个字符串或数组`\n if (value.length > _rule) return errMsg\n },\n match(value: any, rule: ValidateRule['match']): Undef<string> {\n if (isEmpty(value) || value === '') return\n if (typeof rule === 'string') {\n if (!rule) return\n rule = new RegExp(rule)\n }\n let _rule = Array.isArray(rule) ? rule[0] : rule!\n let errMsg = Array.isArray(rule) ? rule[1] : `该项不匹配正则:${_rule}`\n if (typeof value !== 'string') return `${value}不是一个字符串`\n if (!_rule.test(value)) return errMsg\n },\n preset(value: any, rule: ValidateRule['preset']): Undef<string> {\n if (isEmpty(value) || value === '' || !rule) return\n if (typeof value !== 'string') return `${value}不是一个字符串`\n const ruleValidator = presetRules[rule]\n return ruleValidator(value)\n }\n}\n/** */\nexport class Validator<\n Rules extends Record<string, ValidateRule> = Record<string, ValidateRule>,\n Field extends keyof Rules = keyof Rules\n> {\n protected rules: Rules\n\n private config?: ValidatorConfig\n\n constructor(rules: Rules, config?: ValidatorConfig) {\n this.rules = rules\n if (config) {\n this.config = config\n }\n }\n\n /** 是否存在规则 */\n private get existRules() {\n for (const _ in this.rules) {\n return true\n }\n return false\n }\n\n /**\n * 校验单条数据\n * @param data 数据\n */\n private async validateSingleData(\n data: Record<any, any>,\n fields?: Field | Field[]\n ): Promise<{ [key in Field]?: string[] }> {\n const fieldErrors: { [key in Field]?: string[] } = {}\n\n if (!this.existRules) return fieldErrors\n\n const lazy = this.config?.lazy ?? true\n\n fields = fields\n ? Array.isArray(fields)\n ? fields\n : [fields]\n : (Object.keys(this.rules) as Field[])\n\n // 懒校验,当有一个规则不通过,剩下的规则不再校验\n if (lazy) {\n // 校验字段\n for (let i = 0; i < fields.length; i++) {\n const field = fields[i]!\n // oxlint-disable-next-line eslint(no-await-in-loop)\n const errors = await this.validateValueLazy(data, field)\n if (errors.length === 0) continue\n fieldErrors[field] = errors\n }\n return fieldErrors\n } else {\n // 校验字段\n for (let i = 0; i < fields.length; i++) {\n const field = fields[i]!\n // oxlint-disable-next-line eslint(no-await-in-loop)\n const errors = await this.validateValue(data, field)\n if (errors.length === 0) continue\n fieldErrors[field] = errors\n }\n\n return fieldErrors\n }\n }\n\n private async validateValue(data: Record<any, any>, field: Field) {\n const rules = this.rules[field]!\n const value = o(data).get(field as string)\n\n const { validator, required, ...normalRules } = rules\n\n let errors: string[] = []\n\n // 必填要先去校验\n if (required) {\n const err = ruleTypes.required(value, required)\n err && errors.push(err)\n }\n\n // 校验规则\n for (const ruleKey in normalRules) {\n const validate = ruleTypes[ruleKey]\n if (!validate) continue\n const err = validate(value, normalRules[ruleKey])\n err && errors.push(err)\n }\n\n // 自定义校验\n if (validator) {\n const err = await validator(value, data)\n err && errors.push(err)\n }\n\n return errors\n }\n\n private async validateValueLazy(data: Record<any, any>, field: Field): Promise<string[]> {\n const rules = this.rules[field]\n const value = o(data).get(field as string)\n let errors: string[] = []\n\n if (!rules) return errors\n\n const { validator, required, ...normalRules } = rules\n\n // 必填要先去校验\n if (required) {\n const err = ruleTypes.required(value, required)\n if (err) {\n errors.push(err)\n return errors\n }\n }\n\n // 校验规则\n for (const ruleKey in normalRules) {\n const validate = ruleTypes[ruleKey]\n if (!validate) continue\n\n const err = validate(value, normalRules[ruleKey])\n\n if (err) {\n errors.push(err)\n return errors\n }\n }\n\n // 自定义校验最火校验\n if (validator) {\n const err = await validator(value, data)\n if (err) {\n errors.push(err)\n return errors\n }\n }\n\n return errors\n }\n\n /**\n * 校验多条数据\n * @param field 需要校验的字段\n */\n private async validateManyData(\n data: Data,\n field?: Field | Field[]\n ): Promise<{ [key in Field]?: string[] }> {\n let i = 0\n while (i < data.length) {\n const item = data[i]!\n // oxlint-disable-next-line eslint(no-await-in-loop)\n const fieldErrors = await this.validateSingleData(item, field)\n if (Object.keys(fieldErrors).length > 0) {\n return fieldErrors\n }\n i++\n }\n\n return {}\n }\n\n /**\n * 校验\n * @param data 数据\n * @param fields 字段\n * @returns\n */\n async validate(data: Data, fields?: Field | Field[]): Promise<{ [key in Field]?: string[] }> {\n return Array.isArray(data)\n ? this.validateManyData(data, fields)\n : this.validateSingleData(data, fields)\n }\n}\n"],"mappings":";;AAKA,MAAM,WAAW,UAA0C;AACzD,QAAO,UAAU,QAAQ,UAAU,KAAA;;AAGrC,MAAM,cAAyE;CAC7E,MAAM,GAAG;AAEP,MAAI,CADO,iDACH,KAAK,EAAE,CACb,QAAO;;CAGX,MAAM,GAAG;AAEP,MAAI,CADO,WACH,KAAK,EAAE,CACb,QAAO;;CAGX,IAAI,GAAG;AAEL,MAAI,CADO,QACH,KAAK,EAAE,CACb,QAAO;;CAGX,IAAI,GAAG;AAEL,MAAI,CADO,sEACH,KAAK,EAAE,CACb,QAAO;;CAIX,OAAO,GAAG;AAER,MAAI,CADO,iDACH,KAAK,EAAE,CACb,QAAO;;CAGZ;;AAGD,MAAM,YAAY;CAChB,SAAS,OAAY,UAAmD;AACtE,MAAI,aAAa,MAAO;EAExB,MAAM,SAAS,OAAO,aAAa,WAAW,WAAW;AACzD,MAAI,QAAQ,MAAM,CAAE,QAAO;AAE3B,MAAI,MAAM,QAAQ,MAAM,IAAI,CAAC,MAAM,OAAQ,QAAO;AAClD,MAAI,OAAO,UAAU,YAAY,CAAC,MAAO,QAAO;;CAElD,IAAI,OAAY,MAA0C;AACxD,MAAI,QAAQ,MAAM,CAAE;EACpB,IAAI,QAAQ,MAAM,QAAQ,KAAK,GAAG,KAAK,KAAK;EAC5C,IAAI,SAAS,MAAM,QAAQ,KAAK,GAAG,KAAK,KAAK,WAAW;AACxD,MAAI,OAAO,UAAU,SAAU,QAAO,GAAG,MAAM;AAC/C,MAAI,QAAQ,MAAO,QAAO;;CAE5B,IAAI,OAAY,MAA0C;AACxD,MAAI,QAAQ,MAAM,CAAE;EACpB,IAAI,QAAQ,MAAM,QAAQ,KAAK,GAAG,KAAK,KAAK;EAC5C,IAAI,SAAS,MAAM,QAAQ,KAAK,GAAG,KAAK,KAAK,WAAW;AACxD,MAAI,OAAO,UAAU,SAAU,QAAO,GAAG,MAAM;AAC/C,MAAI,QAAQ,MAAO,QAAO;;CAG5B,OAAO,OAAY,MAA6C;AAC9D,MAAI,QAAQ,MAAM,CAAE;EACpB,IAAI,QAAQ,MAAM,QAAQ,KAAK,GAAG,KAAK,KAAK;EAC5C,IAAI,SAAS,MAAM,QAAQ,KAAK,GAAG,KAAK,KAAK,aAAa;AAC1D,MAAI,CAAC,MAAM,QAAQ,MAAM,IAAI,OAAO,UAAU,SAAU,QAAO,GAAG,MAAM;AACxE,MAAI,MAAM,SAAS,MAAO,QAAO;;CAEnC,OAAO,OAAY,MAA6C;AAC9D,MAAI,QAAQ,MAAM,CAAE;EACpB,IAAI,QAAQ,MAAM,QAAQ,KAAK,GAAG,KAAK,KAAK;EAC5C,IAAI,SAAS,MAAM,QAAQ,KAAK,GAAG,KAAK,KAAK,cAAc;AAC3D,MAAI,CAAC,MAAM,QAAQ,MAAM,IAAI,OAAO,UAAU,SAAU,QAAO,GAAG,MAAM;AACxE,MAAI,MAAM,SAAS,MAAO,QAAO;;CAEnC,MAAM,OAAY,MAA4C;AAC5D,MAAI,QAAQ,MAAM,IAAI,UAAU,GAAI;AACpC,MAAI,OAAO,SAAS,UAAU;AAC5B,OAAI,CAAC,KAAM;AACX,UAAO,IAAI,OAAO,KAAK;;EAEzB,IAAI,QAAQ,MAAM,QAAQ,KAAK,GAAG,KAAK,KAAK;EAC5C,IAAI,SAAS,MAAM,QAAQ,KAAK,GAAG,KAAK,KAAK,WAAW;AACxD,MAAI,OAAO,UAAU,SAAU,QAAO,GAAG,MAAM;AAC/C,MAAI,CAAC,MAAM,KAAK,MAAM,CAAE,QAAO;;CAEjC,OAAO,OAAY,MAA6C;AAC9D,MAAI,QAAQ,MAAM,IAAI,UAAU,MAAM,CAAC,KAAM;AAC7C,MAAI,OAAO,UAAU,SAAU,QAAO,GAAG,MAAM;EAC/C,MAAM,gBAAgB,YAAY;AAClC,SAAO,cAAc,MAAM;;CAE9B;;AAED,IAAa,YAAb,MAGE;CACA;CAEA;CAEA,YAAY,OAAc,QAA0B;AAClD,OAAK,QAAQ;AACb,MAAI,OACF,MAAK,SAAS;;;CAKlB,IAAY,aAAa;AACvB,OAAK,MAAM,KAAK,KAAK,MACnB,QAAO;AAET,SAAO;;;;;;CAOT,MAAc,mBACZ,MACA,QACwC;EACxC,MAAM,cAA6C,EAAE;AAErD,MAAI,CAAC,KAAK,WAAY,QAAO;EAE7B,MAAM,OAAO,KAAK,QAAQ,QAAQ;AAElC,WAAS,SACL,MAAM,QAAQ,OAAO,GACnB,SACA,CAAC,OAAO,GACT,OAAO,KAAK,KAAK,MAAM;AAG5B,MAAI,MAAM;AAER,QAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;IACtC,MAAM,QAAQ,OAAO;IAErB,MAAM,SAAS,MAAM,KAAK,kBAAkB,MAAM,MAAM;AACxD,QAAI,OAAO,WAAW,EAAG;AACzB,gBAAY,SAAS;;AAEvB,UAAO;SACF;AAEL,QAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;IACtC,MAAM,QAAQ,OAAO;IAErB,MAAM,SAAS,MAAM,KAAK,cAAc,MAAM,MAAM;AACpD,QAAI,OAAO,WAAW,EAAG;AACzB,gBAAY,SAAS;;AAGvB,UAAO;;;CAIX,MAAc,cAAc,MAAwB,OAAc;EAChE,MAAM,QAAQ,KAAK,MAAM;EACzB,MAAM,QAAQ,EAAE,KAAK,CAAC,IAAI,MAAgB;EAE1C,MAAM,EAAE,WAAW,UAAU,GAAG,gBAAgB;EAEhD,IAAI,SAAmB,EAAE;AAGzB,MAAI,UAAU;GACZ,MAAM,MAAM,UAAU,SAAS,OAAO,SAAS;AAC/C,UAAO,OAAO,KAAK,IAAI;;AAIzB,OAAK,MAAM,WAAW,aAAa;GACjC,MAAM,WAAW,UAAU;AAC3B,OAAI,CAAC,SAAU;GACf,MAAM,MAAM,SAAS,OAAO,YAAY,SAAS;AACjD,UAAO,OAAO,KAAK,IAAI;;AAIzB,MAAI,WAAW;GACb,MAAM,MAAM,MAAM,UAAU,OAAO,KAAK;AACxC,UAAO,OAAO,KAAK,IAAI;;AAGzB,SAAO;;CAGT,MAAc,kBAAkB,MAAwB,OAAiC;EACvF,MAAM,QAAQ,KAAK,MAAM;EACzB,MAAM,QAAQ,EAAE,KAAK,CAAC,IAAI,MAAgB;EAC1C,IAAI,SAAmB,EAAE;AAEzB,MAAI,CAAC,MAAO,QAAO;EAEnB,MAAM,EAAE,WAAW,UAAU,GAAG,gBAAgB;AAGhD,MAAI,UAAU;GACZ,MAAM,MAAM,UAAU,SAAS,OAAO,SAAS;AAC/C,OAAI,KAAK;AACP,WAAO,KAAK,IAAI;AAChB,WAAO;;;AAKX,OAAK,MAAM,WAAW,aAAa;GACjC,MAAM,WAAW,UAAU;AAC3B,OAAI,CAAC,SAAU;GAEf,MAAM,MAAM,SAAS,OAAO,YAAY,SAAS;AAEjD,OAAI,KAAK;AACP,WAAO,KAAK,IAAI;AAChB,WAAO;;;AAKX,MAAI,WAAW;GACb,MAAM,MAAM,MAAM,UAAU,OAAO,KAAK;AACxC,OAAI,KAAK;AACP,WAAO,KAAK,IAAI;AAChB,WAAO;;;AAIX,SAAO;;;;;;CAOT,MAAc,iBACZ,MACA,OACwC;EACxC,IAAI,IAAI;AACR,SAAO,IAAI,KAAK,QAAQ;GACtB,MAAM,OAAO,KAAK;GAElB,MAAM,cAAc,MAAM,KAAK,mBAAmB,MAAM,MAAM;AAC9D,OAAI,OAAO,KAAK,YAAY,CAAC,SAAS,EACpC,QAAO;AAET;;AAGF,SAAO,EAAE;;;;;;;;CASX,MAAM,SAAS,MAAY,QAAkE;AAC3F,SAAO,MAAM,QAAQ,KAAK,GACtB,KAAK,iBAAiB,MAAM,OAAO,GACnC,KAAK,mBAAmB,MAAM,OAAO"}
@@ -0,0 +1,10 @@
1
+ //#region src/helper/create-increase.d.ts
2
+ /**
3
+ * 创建一个自增函数
4
+ * @param initial 初始值
5
+ * @returns
6
+ */
7
+ declare function createIncrease(initial?: number): () => number;
8
+ //#endregion
9
+ export { createIncrease };
10
+ //# sourceMappingURL=create-increase.d.ts.map
@@ -0,0 +1,17 @@
1
+ //#region src/helper/create-increase.ts
2
+ /**
3
+ * 创建一个自增函数
4
+ * @param initial 初始值
5
+ * @returns
6
+ */
7
+ function createIncrease(initial = 1e3) {
8
+ let value = initial;
9
+ const increase = () => {
10
+ return value++;
11
+ };
12
+ return increase;
13
+ }
14
+ //#endregion
15
+ export { createIncrease };
16
+
17
+ //# sourceMappingURL=create-increase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-increase.js","names":[],"sources":["../../src/helper/create-increase.ts"],"sourcesContent":["/**\n * 创建一个自增函数\n * @param initial 初始值\n * @returns\n */\nexport function createIncrease(initial = 1000): () => number {\n let value = initial\n\n const increase = () => {\n return value++\n }\n\n return increase\n}\n"],"mappings":";;;;;;AAKA,SAAgB,eAAe,UAAU,KAAoB;CAC3D,IAAI,QAAQ;CAEZ,MAAM,iBAAiB;AACrB,SAAO;;AAGT,QAAO"}
@@ -0,0 +1,15 @@
1
+ //#region src/helper/create-toggle.d.ts
2
+ type Active = boolean | ((active: boolean) => boolean) | ((active: boolean) => Promise<boolean>);
3
+ type ToggleReturn = [{
4
+ value: boolean;
5
+ }, (active: Active) => void];
6
+ /**
7
+ * 创建一个toggle函数
8
+ * @param initial 初始值
9
+ * @param onChange 值变化时的回调
10
+ * @returns
11
+ */
12
+ declare function createToggle(initial?: boolean, onChange?: (active: boolean) => void): ToggleReturn;
13
+ //#endregion
14
+ export { createToggle };
15
+ //# sourceMappingURL=create-toggle.d.ts.map
@@ -0,0 +1,24 @@
1
+ //#region src/helper/create-toggle.ts
2
+ /**
3
+ * 创建一个toggle函数
4
+ * @param initial 初始值
5
+ * @param onChange 值变化时的回调
6
+ * @returns
7
+ */
8
+ function createToggle(initial = false, onChange) {
9
+ const state = { value: initial };
10
+ function toggle(active) {
11
+ if (typeof active === "boolean") {
12
+ state.value = active;
13
+ return onChange?.(state.value);
14
+ }
15
+ const result = active(state.value);
16
+ if (result instanceof Promise) result.then(toggle);
17
+ else toggle(result);
18
+ }
19
+ return [state, toggle];
20
+ }
21
+ //#endregion
22
+ export { createToggle };
23
+
24
+ //# sourceMappingURL=create-toggle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-toggle.js","names":[],"sources":["../../src/helper/create-toggle.ts"],"sourcesContent":["type Active = boolean | ((active: boolean) => boolean) | ((active: boolean) => Promise<boolean>)\n\ntype ToggleReturn = [{ value: boolean }, (active: Active) => void]\n/**\n * 创建一个toggle函数\n * @param initial 初始值\n * @param onChange 值变化时的回调\n * @returns\n */\nexport function createToggle(initial = false, onChange?: (active: boolean) => void): ToggleReturn {\n const state = { value: initial }\n\n function toggle(active: Active) {\n if (typeof active === 'boolean') {\n state.value = active\n return onChange?.(state.value)\n }\n\n const result = active(state.value)\n\n if (result instanceof Promise) {\n result.then(toggle)\n } else {\n toggle(result)\n }\n }\n\n return [state, toggle]\n}\n"],"mappings":";;;;;;;AASA,SAAgB,aAAa,UAAU,OAAO,UAAoD;CAChG,MAAM,QAAQ,EAAE,OAAO,SAAS;CAEhC,SAAS,OAAO,QAAgB;AAC9B,MAAI,OAAO,WAAW,WAAW;AAC/B,SAAM,QAAQ;AACd,UAAO,WAAW,MAAM,MAAM;;EAGhC,MAAM,SAAS,OAAO,MAAM,MAAM;AAElC,MAAI,kBAAkB,QACpB,QAAO,KAAK,OAAO;MAEnB,QAAO,OAAO;;AAIlB,QAAO,CAAC,OAAO,OAAO"}
@@ -0,0 +1,9 @@
1
+ //#region src/helper/frame.d.ts
2
+ /**
3
+ * 下一帧运行
4
+ * @param cb 回调
5
+ */
6
+ declare function nextFrame(cb: () => void): void;
7
+ //#endregion
8
+ export { nextFrame };
9
+ //# sourceMappingURL=frame.d.ts.map
@@ -0,0 +1,14 @@
1
+ //#region src/helper/frame.ts
2
+ /**
3
+ * 下一帧运行
4
+ * @param cb 回调
5
+ */
6
+ function nextFrame(cb) {
7
+ requestAnimationFrame(() => {
8
+ requestAnimationFrame(cb);
9
+ });
10
+ }
11
+ //#endregion
12
+ export { nextFrame };
13
+
14
+ //# sourceMappingURL=frame.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frame.js","names":[],"sources":["../../src/helper/frame.ts"],"sourcesContent":["/**\n * 下一帧运行\n * @param cb 回调\n */\nexport function nextFrame(cb: () => void): void {\n requestAnimationFrame(() => {\n requestAnimationFrame(cb)\n })\n}\n"],"mappings":";;;;;AAIA,SAAgB,UAAU,IAAsB;AAC9C,6BAA4B;AAC1B,wBAAsB,GAAG;GACzB"}