@allkit/shared 0.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.
Files changed (68) hide show
  1. package/README.md +1 -0
  2. package/dist/README.md +1 -0
  3. package/dist/clipboard/index.d.ts +9 -0
  4. package/dist/cloneDeep/index.d.ts +47 -0
  5. package/dist/constants.d.ts +26 -0
  6. package/dist/cookie/index.d.ts +31 -0
  7. package/dist/date/index.d.ts +133 -0
  8. package/dist/device/index.d.ts +70 -0
  9. package/dist/element/index.d.ts +12 -0
  10. package/dist/index.d.ts +13 -0
  11. package/dist/is/index.d.ts +181 -0
  12. package/dist/lodash/index.d.ts +184 -0
  13. package/dist/number/index.d.ts +84 -0
  14. package/dist/package.json +21 -0
  15. package/dist/shared.es.d.ts +2 -0
  16. package/dist/shared.es.js +1367 -0
  17. package/dist/shared.umd.js +1 -0
  18. package/dist/storage/index.d.ts +144 -0
  19. package/dist/string/index.d.ts +40 -0
  20. package/dist/timer/index.d.ts +9 -0
  21. package/eslint.config.js +10 -0
  22. package/package.json +26 -0
  23. package/scripts/build.mjs +92 -0
  24. package/skill/SKILL.md +240 -0
  25. package/skill/examples/usage.ts +67 -0
  26. package/skill/references/clipboard.md +39 -0
  27. package/skill/references/cloneDeep.md +60 -0
  28. package/skill/references/cookie.md +56 -0
  29. package/skill/references/date.md +466 -0
  30. package/skill/references/device.md +138 -0
  31. package/skill/references/element.md +99 -0
  32. package/skill/references/is.md +415 -0
  33. package/skill/references/lodash.md +472 -0
  34. package/skill/references/number.md +248 -0
  35. package/skill/references/storage.md +113 -0
  36. package/skill/references/string.md +126 -0
  37. package/skill/references/timer.md +78 -0
  38. package/src/clipboard/index.ts +26 -0
  39. package/src/cloneDeep/__test__/cloneDeep.test.ts +92 -0
  40. package/src/cloneDeep/index.ts +168 -0
  41. package/src/constants.ts +27 -0
  42. package/src/cookie/index.ts +44 -0
  43. package/src/date/__test__/date-diff.test.ts +23 -0
  44. package/src/date/__test__/date-duration.test.ts +140 -0
  45. package/src/date/__test__/date-from.test.ts +64 -0
  46. package/src/date/__test__/date.test.ts +67 -0
  47. package/src/date/index.ts +331 -0
  48. package/src/device/__test__/device.test.ts +138 -0
  49. package/src/device/index.ts +125 -0
  50. package/src/element/index.ts +100 -0
  51. package/src/index.ts +14 -0
  52. package/src/is/__test__/is.test.ts +320 -0
  53. package/src/is/index.ts +293 -0
  54. package/src/lodash/__test__/lodash.test.ts +111 -0
  55. package/src/lodash/__test__/obj-string.test.ts +107 -0
  56. package/src/lodash/__test__/uniqueId.test.ts +40 -0
  57. package/src/lodash/index.ts +396 -0
  58. package/src/number/__test__/number.test.ts +137 -0
  59. package/src/number/index.ts +161 -0
  60. package/src/storage/__test__/storage.test.ts +44 -0
  61. package/src/storage/index.ts +185 -0
  62. package/src/string/__test__/string.test.ts +24 -0
  63. package/src/string/index.ts +49 -0
  64. package/src/timer/index.ts +15 -0
  65. package/tsconfig.json +25 -0
  66. package/types/global.d.ts +13 -0
  67. package/vite.config.ts +16 -0
  68. package/vitest.config.ts +28 -0
@@ -0,0 +1,113 @@
1
+ # storage
2
+
3
+ 本地存储工具函数,自动处理 JSON 序列化,支持 TypeScript 类型推断
4
+
5
+ ## Functions
6
+
7
+ ### setLocal
8
+
9
+ 设置 LocalStorage
10
+
11
+ ```ts
12
+ function setLocal<T>(key: string, content: T): void
13
+ ```
14
+
15
+ ### getLocal
16
+
17
+ 获取 LocalStorage
18
+
19
+ ```ts
20
+ function getLocal<T>(key: string): T
21
+ ```
22
+
23
+ ### removeLocal
24
+
25
+ 删除 LocalStorage
26
+
27
+ ```ts
28
+ function removeLocal(key: string): void
29
+ ```
30
+
31
+ ### clearLocal
32
+
33
+ 清空 LocalStorage
34
+
35
+ ```ts
36
+ function clearLocal(): void
37
+ ```
38
+
39
+ ### setSession
40
+
41
+ 设置 SessionStorage
42
+
43
+ ```ts
44
+ function setSession<T>(key: string, content: T): void
45
+ ```
46
+
47
+ ### getSession
48
+
49
+ 获取 SessionStorage
50
+
51
+ ```ts
52
+ function getSession<T>(key: string): T
53
+ ```
54
+
55
+ ### removeSession
56
+
57
+ 删除 SessionStorage
58
+
59
+ ```ts
60
+ function removeSession(key: string): void
61
+ ```
62
+
63
+ ### clearSession
64
+
65
+ 清空 SessionStorage
66
+
67
+ ```ts
68
+ function clearSession(): void
69
+ ```
70
+
71
+ ### setStore
72
+
73
+ 设置本地存储
74
+
75
+ ```ts
76
+ function setStore<T>(key: string, value: T, type?: 'local' | 'session'): void
77
+ ```
78
+
79
+ ### getStore
80
+
81
+ 获取本地存储
82
+
83
+ ```ts
84
+ function getStore<T>(key: string, type?: 'local' | 'session'): T
85
+ ```
86
+
87
+ ### removeStore
88
+
89
+ 删除本地存储
90
+
91
+ ```ts
92
+ function removeStore(key: string, type?: 'local' | 'session'): void
93
+ ```
94
+
95
+ ## Example
96
+
97
+ ```ts
98
+ import { setLocal, getLocal, setSession, getSession } from '@allkit/shared'
99
+
100
+ // LocalStorage
101
+ setLocal('token', '123')
102
+ const token = getLocal<string>('token') // '123'
103
+ removeLocal('token')
104
+
105
+ // SessionStorage
106
+ setSession('userInfo', { name: '张三', age: 18 })
107
+ const userInfo = getSession<{ name: string; age: number }>('userInfo')
108
+ removeSession('userInfo')
109
+
110
+ // 通用方法
111
+ setStore('token', '123', 'local')
112
+ const token2 = getStore<string>('token', 'local')
113
+ ```
@@ -0,0 +1,126 @@
1
+ # string
2
+
3
+ 字符串操作工具函数
4
+
5
+ ## Functions
6
+
7
+ ### camelize
8
+
9
+ 中划线转小驼峰
10
+
11
+ ```ts
12
+ function camelize(str: string): string
13
+ ```
14
+
15
+ **Example**
16
+
17
+ ```ts
18
+ camelize('user-info') // 'userInfo'
19
+ camelize('hello-world-test') // 'helloWorldTest'
20
+ ```
21
+
22
+ ### kebabCase
23
+
24
+ 驼峰转中划线
25
+
26
+ ```ts
27
+ function kebabCase(str: string): string
28
+ ```
29
+
30
+ **Example**
31
+
32
+ ```ts
33
+ kebabCase('userInfo') // 'user-info'
34
+ kebabCase('helloWorldTest') // 'hello-world-test'
35
+ ```
36
+
37
+ ### snakeCase
38
+
39
+ 驼峰转下划线
40
+
41
+ ```ts
42
+ function snakeCase(str: string): string
43
+ ```
44
+
45
+ **Example**
46
+
47
+ ```ts
48
+ snakeCase('userInfo') // 'user_info'
49
+ snakeCase('helloWorldTest') // 'hello_world_test'
50
+ ```
51
+
52
+ ### lowerFirst
53
+
54
+ 首字母转小写
55
+
56
+ ```ts
57
+ function lowerFirst(str: string): string
58
+ ```
59
+
60
+ **Example**
61
+
62
+ ```ts
63
+ lowerFirst('UserInfo') // 'userInfo'
64
+ lowerFirst('Hello') // 'hello'
65
+ ```
66
+
67
+ ### upperFirst
68
+
69
+ 首字母转大写
70
+
71
+ ```ts
72
+ function upperFirst(str: string): string
73
+ ```
74
+
75
+ **Example**
76
+
77
+ ```ts
78
+ upperFirst('userInfo') // 'UserInfo'
79
+ upperFirst('hello') // 'Hello'
80
+ ```
81
+
82
+ ### trim
83
+
84
+ 去除字符串首尾空白
85
+
86
+ ```ts
87
+ function trim(str: string, chars?: string): string
88
+ ```
89
+
90
+ **Example**
91
+
92
+ ```ts
93
+ trim(' hello ') // 'hello'
94
+ trim('--hello--', '-') // 'hello'
95
+ ```
96
+
97
+ ### repeat
98
+
99
+ 重复字符串
100
+
101
+ ```ts
102
+ function repeat(str: string, count: number): string
103
+ ```
104
+
105
+ **Example**
106
+
107
+ ```ts
108
+ repeat('a', 3) // 'aaa'
109
+ repeat('ab', 2) // 'abab'
110
+ ```
111
+
112
+ ### padStart / padEnd
113
+
114
+ 字符串补全
115
+
116
+ ```ts
117
+ function padStart(str: string, length: number, chars?: string): string
118
+ function padEnd(str: string, length: number, chars?: string): string
119
+ ```
120
+
121
+ **Example**
122
+
123
+ ```ts
124
+ padStart('5', 2, '0') // '05'
125
+ padEnd('hi', 4, '!') // 'hi!!'
126
+ ```
@@ -0,0 +1,78 @@
1
+ # timer
2
+
3
+ 定时器工具函数
4
+
5
+ ## Functions
6
+
7
+ ### sleep
8
+
9
+ 睡眠函数
10
+
11
+ ```ts
12
+ function sleep(timer: number): Promise<void>
13
+ ```
14
+
15
+ **Example**
16
+
17
+ ```ts
18
+ await sleep(1000) // 等待 1 秒
19
+ ```
20
+
21
+ ### raf
22
+
23
+ 监听下一动画帧(Promise)
24
+
25
+ ```ts
26
+ function raf(): Promise<void>
27
+ ```
28
+
29
+ **Example**
30
+
31
+ ```ts
32
+ raf().then(() => {
33
+ console.log('执行下一帧')
34
+ })
35
+ ```
36
+
37
+ ### doubleRaf
38
+
39
+ 监听双帧动画帧(Promise)
40
+
41
+ ```ts
42
+ function doubleRaf(): Promise<void>
43
+ ```
44
+
45
+ **Example**
46
+
47
+ ```ts
48
+ doubleRaf().then(() => {
49
+ console.log('执行双帧后')
50
+ })
51
+ ```
52
+
53
+ ### clearTimer
54
+
55
+ 清除定时器
56
+
57
+ ```ts
58
+ function clearTimer(timerId: number | undefined): void
59
+ ```
60
+
61
+ ## Usage
62
+
63
+ ```ts
64
+ import { sleep, raf, doubleRaf } from '@allkit/shared'
65
+
66
+ // 睡眠
67
+ await sleep(100)
68
+
69
+ // 下一帧
70
+ raf().then(() => {
71
+ console.log('执行下一帧')
72
+ })
73
+
74
+ // 双帧
75
+ doubleRaf().then(() => {
76
+ console.log('执行双帧后')
77
+ })
78
+ ```
@@ -0,0 +1,26 @@
1
+ /**
2
+ * 复制文本到剪贴板
3
+ * @param value - 文本内容
4
+ * @example
5
+ * ```ts
6
+ * let isResult= copyTextToClipboard('test')
7
+ * ```
8
+ */
9
+ export function copyTextToClipboard(value: string = '') {
10
+ // 动态创建 textarea 标签
11
+ const textarea = document.createElement('textarea')
12
+ // 将该 textarea 设为 readonly 防止 iOS 下自动唤起键盘,同时将 textarea 移出可视区域
13
+ textarea.readOnly = true
14
+ textarea.style.position = 'absolute'
15
+ textarea.style.left = '-9999px'
16
+ // 将要 copy 的值赋给 textarea 标签的 value 属性
17
+ textarea.value = value
18
+ // 将 textarea 插入到 body 中
19
+ document.body.appendChild(textarea)
20
+ // 选中值并复制
21
+ textarea.select()
22
+ textarea.setSelectionRange(0, textarea.value.length)
23
+ const result = document.execCommand('Copy')
24
+ document.body.removeChild(textarea)
25
+ return result
26
+ }
@@ -0,0 +1,92 @@
1
+ import { describe, expect, test } from 'vitest'
2
+ import { cloneDeep } from '../'
3
+ describe('cloneDeep', () => {
4
+ test('simple object with no nested objects', () => {
5
+ const source = { a: 1, b: 'test' }
6
+ const result = cloneDeep(source)
7
+ expect(result).toEqual(source)
8
+ expect(result).not.toBe(source)
9
+ })
10
+
11
+ test('object with nested objects', () => {
12
+ const source = { a: 1, b: { c: 2 } }
13
+ const result = cloneDeep(source)
14
+ expect(result).toEqual(source)
15
+ expect(result.b).not.toBe(source.b)
16
+ })
17
+
18
+ test('object with multiple levels of nested objects', () => {
19
+ const source = { a: 1, b: { c: { d: 2 } } }
20
+ const result = cloneDeep(source)
21
+ expect(result).toEqual(source)
22
+ expect(result.b).not.toBe(source.b)
23
+ expect(result.b.c).not.toBe(source.b.c)
24
+ })
25
+
26
+ test('object with arrays and nested arrays', () => {
27
+ const source = { a: [1, [2]], b: { c: [3, 4] } }
28
+ const result = cloneDeep(source)
29
+ expect(result).toEqual(source)
30
+ expect(result.a).not.toBe(source.a)
31
+ expect(result.a[1]).not.toBe(source.a[1])
32
+ expect(result.b.c).not.toBe(source.b.c)
33
+ })
34
+
35
+ test('object with complex types of nested objects', () => {
36
+ const source = { a: { b: new Date(), c: /test/g, d: () => {} } }
37
+ const result = cloneDeep(source)
38
+ expect(result).toEqual(source)
39
+ expect(result).not.toBe(source)
40
+ expect(result.a).not.toBe(source.a)
41
+ expect(result.a.b).toBe(source.a.b)
42
+ expect(result.a.c).toBe(source.a.c)
43
+ expect(result.a.d).toBe(source.a.d)
44
+ })
45
+
46
+ test('object with non-enumerable properties', () => {
47
+ const source = { a: 1 }
48
+ Object.defineProperty(source, 'b', { value: 2, enumerable: false })
49
+ const result = cloneDeep(source)
50
+ expect(result).toEqual(source)
51
+ })
52
+
53
+ test('object containing Set and Map instances', () => {
54
+ const source = {
55
+ a: new Set([{ a: 1 }, { a: 2 }]),
56
+ b: new Map([[{ b: 1 }, { b: 2 }]]),
57
+ }
58
+
59
+ const result = cloneDeep(source)
60
+ expect(result).toEqual(source)
61
+
62
+ expect(result.a).not.toBe(source.a)
63
+ expect(result.b).not.toBe(source.b)
64
+
65
+ // Objects inside sets are cloned.
66
+ expect([...result.a].every((item) => !source.a.has(item))).toBe(true)
67
+
68
+ // Object keys in maps are *not* cloned.
69
+ // Object values in maps are cloned.
70
+ expect(
71
+ [...result.b].every(([key, value]) => source.b.has(key) && source.b.get(key) !== value),
72
+ ).toBe(true)
73
+ })
74
+
75
+ test('handle circular references', () => {
76
+ const source: any = { a: 1 }
77
+ source.b = source
78
+ const result = cloneDeep(source)
79
+ expect(result).not.toBe(source)
80
+ expect(result).toEqual(source)
81
+ expect(result.b).toBe(result)
82
+ })
83
+
84
+ test('avoid cloning an object more than once', () => {
85
+ const source: any = { a1: { b: 1 } }
86
+ source.a2 = source.a1
87
+ const result = cloneDeep(source)
88
+ expect(result).toEqual(source)
89
+ expect(result.a1).toBe(result.a2)
90
+ expect(result.a1).not.toBe(source.a1)
91
+ })
92
+ })
@@ -0,0 +1,168 @@
1
+ import { isArray, isMap, isPlainObject, isSet, isUnDef } from '../is'
2
+
3
+ /**
4
+ * A strategy for cloning objects with `cloneDeep`.
5
+ *
6
+ * Methods **must** call the `track` function with the new parent
7
+ * object **before** looping over the input object's
8
+ * properties/elements for cloning purposes. This protects against
9
+ * circular references.
10
+ *
11
+ * Methods may return the input object to indicate that cloning should
12
+ * be skipped.
13
+ *
14
+ * Methods may return null to indicate that the default cloning logic
15
+ * should be used.
16
+ */
17
+ export interface CloningStrategy {
18
+ cloneMap: <K, V>(
19
+ parent: Map<K, V>,
20
+ track: (newParent: Map<K, V>) => Map<K, V>,
21
+ clone: <T>(value: T) => T,
22
+ ) => Map<K, V> | null
23
+ cloneSet: <T>(
24
+ parent: Set<T>,
25
+ track: (newParent: Set<T>) => Set<T>,
26
+ clone: <T>(value: T) => T,
27
+ ) => Set<T> | null
28
+ cloneArray: <T>(
29
+ parent: readonly T[],
30
+ track: (newParent: T[]) => T[],
31
+ clone: <T>(value: T) => T,
32
+ ) => T[] | null
33
+ cloneObject: <T extends object>(
34
+ parent: T,
35
+ track: (newParent: T) => T,
36
+ clone: <T>(value: T) => T,
37
+ ) => T | null
38
+ cloneOther: <T>(parent: T, track: (newParent: T) => T, clone: <T>(value: T) => T) => T | null
39
+ }
40
+
41
+ export const DefaultCloningStrategy: CloningStrategy = {
42
+ cloneMap<K, V>(
43
+ input: Map<K, V>,
44
+ track: (newParent: Map<K, V>) => Map<K, V>,
45
+ clone: <T>(value: T) => T,
46
+ ): Map<K, V> {
47
+ const output = track(new Map())
48
+ for (const [key, value] of input) {
49
+ output.set(key, clone(value))
50
+ }
51
+ return output
52
+ },
53
+ cloneSet<T>(
54
+ input: Set<T>,
55
+ track: (newParent: Set<T>) => Set<T>,
56
+ clone: <T>(value: T) => T,
57
+ ): Set<T> {
58
+ const output = track(new Set())
59
+ for (const value of input) {
60
+ output.add(clone(value))
61
+ }
62
+ return output
63
+ },
64
+ cloneArray<T>(
65
+ input: readonly T[],
66
+ track: (newParent: T[]) => T[],
67
+ clone: <T>(value: T) => T,
68
+ ): T[] {
69
+ // Use .forEach for correct handling of sparse arrays
70
+ const output = track(new Array(input.length))
71
+ input.forEach((value, index) => {
72
+ output[index] = clone(value)
73
+ })
74
+ return output
75
+ },
76
+ cloneObject<T extends object>(
77
+ input: T,
78
+ track: (newParent: T) => T,
79
+ clone: <T>(value: T) => T,
80
+ ): T {
81
+ const output = track(Object.create(Object.getPrototypeOf(input)))
82
+ for (const key of Reflect.ownKeys(input)) {
83
+ // By copying the property descriptors, we preserve computed
84
+ // properties and non-enumerable properties.
85
+ const descriptor = Object.getOwnPropertyDescriptor(input, key)!
86
+ if ('value' in descriptor) {
87
+ descriptor.value = clone(descriptor.value)
88
+ }
89
+ Object.defineProperty(output, key, descriptor)
90
+ }
91
+ return output
92
+ },
93
+ cloneOther<T>(input: T, track: (newParent: T) => T): T {
94
+ return track(input)
95
+ },
96
+ }
97
+
98
+ /**
99
+ * 深拷贝
100
+ *
101
+ * 默认情况下,唯一被克隆的对象是普通对象、类实例、数组、`Set`实例和`Map`,`Date`
102
+ * 其他的场景,通过第二个参数自定义Strategy,实现拷贝逻辑(copy Radashi)
103
+ *
104
+ * ```ts
105
+ * const obj = { a: 1, b: { c: 2 } }
106
+ * const clone = cloneDeep(obj)
107
+ * ```
108
+ */
109
+ export function cloneDeep<T extends object>(root: T, customStrategy?: Partial<CloningStrategy>): T {
110
+ if (isUnDef(root)) {
111
+ return root
112
+ }
113
+ const strategy = { ...DefaultCloningStrategy, ...customStrategy }
114
+
115
+ const tracked = new Map<unknown, unknown>()
116
+ const track = (parent: unknown, newParent: unknown) => {
117
+ tracked.set(parent, newParent)
118
+ return newParent
119
+ }
120
+
121
+ const clone = <T>(value: T): T =>
122
+ value && typeof value === 'object'
123
+ ? ((tracked.get(value) ?? cloneDeep(value, strategy)) as T)
124
+ : value
125
+
126
+ const cloneDeep = (parent: unknown, strategy: CloningStrategy): unknown => {
127
+ const cloneParent = (
128
+ isPlainObject(parent)
129
+ ? strategy.cloneObject
130
+ : isArray(parent)
131
+ ? strategy.cloneArray
132
+ : isMap(parent)
133
+ ? strategy.cloneMap
134
+ : isSet(parent)
135
+ ? strategy.cloneSet
136
+ : strategy.cloneOther
137
+ ) as (
138
+ newParent: unknown,
139
+ track: (newParent: unknown) => unknown,
140
+ clone: (value: unknown) => unknown,
141
+ ) => unknown
142
+
143
+ const newParent = cloneParent(parent, track.bind(null, parent), clone)
144
+ if (!newParent) {
145
+ // Use the default strategy if null is returned.
146
+ return cloneDeep(parent, DefaultCloningStrategy)
147
+ }
148
+
149
+ tracked.set(parent, newParent)
150
+ return newParent
151
+ }
152
+
153
+ return cloneDeep(root, strategy) as T
154
+ }
155
+
156
+ /**
157
+ * @deprecated - 请使用cloneDeep
158
+ *
159
+ * 深拷贝(与cloneDeep完成相同,历史原因2个名字)
160
+ * 默认情况下,唯一被克隆的对象是普通对象、类实例、数组、`Set`实例和`Map`,`Date`
161
+ * 其他的场景,通过第二个参数自定义Strategy,实现拷贝逻辑
162
+ *
163
+ * ```ts
164
+ * const obj = { a: 1, b: { c: 2 } }
165
+ * const clone = deepClone(obj)
166
+ * ```
167
+ */
168
+ export const deepClone = cloneDeep
@@ -0,0 +1,27 @@
1
+ /**
2
+ * 普通是与否枚举
3
+ */
4
+ export enum EnumYesNo {
5
+ /**
6
+ * 是('1')
7
+ */
8
+ YES = 1,
9
+ /**
10
+ * 否('0')
11
+ */
12
+ NO = 0,
13
+ }
14
+
15
+ /**
16
+ * 普通是与否枚举(10,20)
17
+ */
18
+ export enum EnumYesNoPlus {
19
+ /**
20
+ * 是('10')
21
+ */
22
+ YES = '10',
23
+ /**
24
+ * 否('20')
25
+ */
26
+ NO = '20',
27
+ }
@@ -0,0 +1,44 @@
1
+ import Cookies from 'js-cookie'
2
+
3
+ /**
4
+ * 设置cookie
5
+ * @param name - cookie的key
6
+ * @param value - cookie的内容
7
+ * @param options - cookie的配置
8
+ * @example
9
+ * ```ts
10
+ * setCookie('name', 'value')
11
+ * setCookie('name', 'value', { expires: 30 })
12
+ * ```
13
+ */
14
+ export function setCookie(
15
+ name: string,
16
+ value: string,
17
+ options: Parameters<typeof Cookies.set>[2] = { expires: 30 },
18
+ ) {
19
+ Cookies.set(name, value, options)
20
+ }
21
+
22
+ /**
23
+ * 获取指定name的cookie值
24
+ * @param name - cookie的key
25
+ * @example
26
+ * ```ts
27
+ * getCookie('name')
28
+ * ```
29
+ */
30
+ export function getCookie(name: string) {
31
+ return Cookies.get(name)
32
+ }
33
+
34
+ /**
35
+ * 删除指定name的cookie
36
+ * @param name - cookie的key
37
+ * @example
38
+ * ```ts
39
+ * removeCookie('name')
40
+ * ```
41
+ */
42
+ export function removeCookie(name: string) {
43
+ Cookies.remove(name)
44
+ }
@@ -0,0 +1,23 @@
1
+ import { describe, expect, test } from 'vitest'
2
+ import { dateDiffFormat } from '../'
3
+
4
+ describe('date.ts', () => {
5
+ test('dateDiffFormat - YY年MM个月DD天', () => {
6
+ const start = '2024-12-18'
7
+ const _date = dateDiffFormat(start, 1743762046095)
8
+ expect(_date).toEqual('0年3个月17天')
9
+ })
10
+
11
+ test('dateFormat - param is Date', () => {
12
+ const start = '2024-12-18'
13
+ const _date = dateDiffFormat(start, 1743762046095, 'MM个月DD天')
14
+
15
+ expect(_date).toEqual('3个月17天')
16
+ })
17
+
18
+ test('dateFormat - param is Date', () => {
19
+ const start = '2023-12-18'
20
+ const _date = dateDiffFormat(start, '2026-12-18', 'MM个月DD天')
21
+ expect(_date).toEqual('36个月0天')
22
+ })
23
+ })