@cloudcome/utils-browser 1.2.17 → 1.3.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.
package/README.md CHANGED
@@ -9,15 +9,15 @@
9
9
 
10
10
  ## 包列表
11
11
 
12
- | 名称 | 版本 | 描述 |
13
- | --- | --- | --- |
14
- | [@cloudcome/utils-core](./packages/utils-core) | [![npm version](https://badge.fury.io/js/@cloudcome%2Futils-core.svg)](https://npmjs.com/package/@cloudcome/utils-core) | 核心工具库,与运行环境无关的通用工具 |
12
+ | 名称 | 版本 | 描述 |
13
+ | ---------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------- |
14
+ | [@cloudcome/utils-core](./packages/utils-core) | [![npm version](https://badge.fury.io/js/@cloudcome%2Futils-core.svg)](https://npmjs.com/package/@cloudcome/utils-core) | 核心工具库,与运行环境无关的通用工具 |
15
15
  | [@cloudcome/utils-browser](./packages/utils-browser) | [![npm version](https://badge.fury.io/js/@cloudcome%2Futils-browser.svg)](https://npmjs.com/package/@cloudcome/utils-browser) | 浏览器端工具(DOM、Canvas、Cookie、剪贴板等) |
16
- | [@cloudcome/utils-node](./packages/utils-node) | [![npm version](https://badge.fury.io/js/@cloudcome%2Futils-node.svg)](https://npmjs.com/package/@cloudcome/utils-node) | Node.js 端工具(Base64、加密等) |
17
- | [@cloudcome/utils-vue](./packages/utils-vue) | [![npm version](https://badge.fury.io/js/@cloudcome%2Futils-vue.svg)](https://npmjs.com/package/@cloudcome/utils-vue) | Vue 3 工具库(组合式函数、组件、请求等) |
18
- | [@cloudcome/utils-react](./packages/utils-react) | [![npm version](https://badge.fury.io/js/@cloudcome%2Futils-react.svg)](https://npmjs.com/package/@cloudcome/utils-react) | React 工具库 |
19
- | [@cloudcome/utils-uni](./packages/utils-uni) | [![npm version](https://badge.fury.io/js/@cloudcome%2Futils-uni.svg)](https://npmjs.com/package/@cloudcome/utils-uni) | UniApp 工具库(云函数、数据库、页面等) |
20
- | [@cloudcome/docs](./packages/docs) | - | VitePress 文档站点 |
16
+ | [@cloudcome/utils-node](./packages/utils-node) | [![npm version](https://badge.fury.io/js/@cloudcome%2Futils-node.svg)](https://npmjs.com/package/@cloudcome/utils-node) | Node.js 端工具(Base64、加密、JSONL 等) |
17
+ | [@cloudcome/utils-vue](./packages/utils-vue) | [![npm version](https://badge.fury.io/js/@cloudcome%2Futils-vue.svg)](https://npmjs.com/package/@cloudcome/utils-vue) | Vue 3 工具库(组合式函数、组件、请求等) |
18
+ | [@cloudcome/utils-react](./packages/utils-react) | [![npm version](https://badge.fury.io/js/@cloudcome%2Futils-react.svg)](https://npmjs.com/package/@cloudcome/utils-react) | React 工具库 |
19
+ | [@cloudcome/utils-uni](./packages/utils-uni) | [![npm version](https://badge.fury.io/js/@cloudcome%2Futils-uni.svg)](https://npmjs.com/package/@cloudcome/utils-uni) | UniApp 工具库(云函数、数据库、页面等) |
20
+ | [@cloudcome/docs](./packages/docs) | - | VitePress 文档站点 |
21
21
 
22
22
  ## 功能概览
23
23
 
@@ -25,79 +25,80 @@
25
25
 
26
26
  核心工具库,提供以下子模块:
27
27
 
28
- | 子模块 | 导入路径 | 功能 |
29
- | --- | --- | --- |
30
- | array | `@cloudcome/utils-core/array` | 数组操作 |
31
- | async | `@cloudcome/utils-core/async` | 异步工具 |
32
- | base64 | `@cloudcome/utils-core/base64` | Base64 编解码 |
33
- | cache | `@cloudcome/utils-core/cache` | 缓存工具 |
34
- | color | `@cloudcome/utils-core/color` | 颜色转换(RGB/HSL/HSV/HWB/LAB/XYZ)、对比度、亮度、混合 |
35
- | crypto | `@cloudcome/utils-core/crypto` | 加密(MD5、SHA1、SHA256、SHA512) |
36
- | date | `@cloudcome/utils-core/date` | 日期解析、格式化、时区、相对时间、周/天计算 |
37
- | dict | `@cloudcome/utils-core/dict` | 字典/映射工具 |
38
- | easing | `@cloudcome/utils-core/easing` | 缓动函数 |
39
- | emitter | `@cloudcome/utils-core/emitter` | 事件发射器 |
40
- | env | `@cloudcome/utils-core/env` | 环境检测 |
41
- | error | `@cloudcome/utils-core/error` | 错误处理 |
42
- | exception | `@cloudcome/utils-core/exception` | 异常处理 |
43
- | function | `@cloudcome/utils-core/function` | 函数工具 |
44
- | number | `@cloudcome/utils-core/number` | 数字工具 |
45
- | object | `@cloudcome/utils-core/object` | 对象遍历、深层 get/set、合并、类型判断 |
46
- | path | `@cloudcome/utils-core/path` | 路径工具 |
47
- | promise | `@cloudcome/utils-core/promise` | Promise 工具 |
48
- | qs | `@cloudcome/utils-core/qs` | 查询字符串解析与序列化 |
49
- | regexp | `@cloudcome/utils-core/regexp` | 正则表达式工具 |
50
- | string | `@cloudcome/utils-core/string` | 字符串工具 |
51
- | time | `@cloudcome/utils-core/time` | 时间单位转换 |
52
- | timer | `@cloudcome/utils-core/timer` | 定时器工具 |
53
- | tree | `@cloudcome/utils-core/tree` | 树结构操作 |
54
- | try | `@cloudcome/utils-core/try` | 安全调用(try-catch 包装,支持同步/异步/柯里化) |
55
- | type | `@cloudcome/utils-core/type` | 类型判断 |
56
- | types | `@cloudcome/utils-core/types` | 公共类型定义 |
57
- | unique | `@cloudcome/utils-core/unique` | 唯一 ID 生成 |
58
- | url | `@cloudcome/utils-core/url` | URL 解析与构建 |
59
- | version | `@cloudcome/utils-core/version` | 版本号比较 |
28
+ | 子模块 | 导入路径 | 功能 |
29
+ | --------- | --------------------------------- | ------------------------------------------------------- |
30
+ | array | `@cloudcome/utils-core/array` | 数组操作 |
31
+ | async | `@cloudcome/utils-core/async` | 异步工具 |
32
+ | base64 | `@cloudcome/utils-core/base64` | Base64 编解码 |
33
+ | cache | `@cloudcome/utils-core/cache` | 缓存工具 |
34
+ | color | `@cloudcome/utils-core/color` | 颜色转换(RGB/HSL/HSV/HWB/LAB/XYZ)、对比度、亮度、混合 |
35
+ | crypto | `@cloudcome/utils-core/crypto` | 加密(MD5、SHA1、SHA256、SHA512) |
36
+ | date | `@cloudcome/utils-core/date` | 日期解析、格式化、时区、相对时间、周/天计算 |
37
+ | dict | `@cloudcome/utils-core/dict` | 字典/映射工具 |
38
+ | easing | `@cloudcome/utils-core/easing` | 缓动函数 |
39
+ | emitter | `@cloudcome/utils-core/emitter` | 事件发射器 |
40
+ | env | `@cloudcome/utils-core/env` | 环境检测 |
41
+ | error | `@cloudcome/utils-core/error` | 错误处理 |
42
+ | exception | `@cloudcome/utils-core/exception` | 异常处理 |
43
+ | function | `@cloudcome/utils-core/function` | 函数工具 |
44
+ | number | `@cloudcome/utils-core/number` | 数字工具 |
45
+ | object | `@cloudcome/utils-core/object` | 对象遍历、深层 get/set、合并、类型判断 |
46
+ | path | `@cloudcome/utils-core/path` | 路径工具 |
47
+ | promise | `@cloudcome/utils-core/promise` | Promise 工具 |
48
+ | qs | `@cloudcome/utils-core/qs` | 查询字符串解析与序列化 |
49
+ | regexp | `@cloudcome/utils-core/regexp` | 正则表达式工具 |
50
+ | string | `@cloudcome/utils-core/string` | 字符串工具 |
51
+ | time | `@cloudcome/utils-core/time` | 时间单位转换 |
52
+ | timer | `@cloudcome/utils-core/timer` | 定时器工具 |
53
+ | tree | `@cloudcome/utils-core/tree` | 树结构操作 |
54
+ | try | `@cloudcome/utils-core/try` | 安全调用(try-catch 包装,支持同步/异步/柯里化) |
55
+ | type | `@cloudcome/utils-core/type` | 类型判断 |
56
+ | types | `@cloudcome/utils-core/types` | 公共类型定义 |
57
+ | unique | `@cloudcome/utils-core/unique` | 唯一 ID 生成 |
58
+ | url | `@cloudcome/utils-core/url` | URL 解析与构建 |
59
+ | version | `@cloudcome/utils-core/version` | 版本号比较 |
60
60
 
61
61
  ### @cloudcome/utils-browser
62
62
 
63
63
  浏览器端工具库,依赖 `@cloudcome/utils-core`:
64
64
 
65
- | 子模块 | 导入路径 | 功能 |
66
- | --- | --- | --- |
67
- | base64 | `@cloudcome/utils-browser/base64` | 浏览器端 Base64 编解码 |
68
- | cache | `@cloudcome/utils-browser/cache` | 浏览器缓存(localStorage/sessionStorage) |
69
- | canvas | `@cloudcome/utils-browser/canvas` | Canvas 操作 |
70
- | clipboard | `@cloudcome/utils-browser/clipboard` | 剪贴板读写 |
71
- | cookie | `@cloudcome/utils-browser/cookie` | Cookie 读写 |
72
- | dom | `@cloudcome/utils-browser/dom` | DOM 操作 |
73
- | download | `@cloudcome/utils-browser/download` | 文件下载 |
74
- | image | `@cloudcome/utils-browser/image` | 图片处理 |
75
- | timer | `@cloudcome/utils-browser/timer` | 浏览器端定时器 |
76
- | video | `@cloudcome/utils-browser/video` | 视频处理 |
65
+ | 子模块 | 导入路径 | 功能 |
66
+ | --------- | ------------------------------------ | ----------------------------------------- |
67
+ | base64 | `@cloudcome/utils-browser/base64` | 浏览器端 Base64 编解码 |
68
+ | cache | `@cloudcome/utils-browser/cache` | 浏览器缓存(localStorage/sessionStorage) |
69
+ | canvas | `@cloudcome/utils-browser/canvas` | Canvas 操作 |
70
+ | clipboard | `@cloudcome/utils-browser/clipboard` | 剪贴板读写 |
71
+ | cookie | `@cloudcome/utils-browser/cookie` | Cookie 读写 |
72
+ | dom | `@cloudcome/utils-browser/dom` | DOM 操作 |
73
+ | download | `@cloudcome/utils-browser/download` | 文件下载 |
74
+ | image | `@cloudcome/utils-browser/image` | 图片处理 |
75
+ | timer | `@cloudcome/utils-browser/timer` | 浏览器端定时器 |
76
+ | video | `@cloudcome/utils-browser/video` | 视频处理 |
77
77
 
78
78
  ### @cloudcome/utils-node
79
79
 
80
80
  Node.js 端工具库:
81
81
 
82
- | 子模块 | 导入路径 | 功能 |
83
- | --- | --- | --- |
82
+ | 子模块 | 导入路径 | 功能 |
83
+ | ------ | ------------------------------ | ------------------------ |
84
84
  | base64 | `@cloudcome/utils-node/base64` | Node.js 端 Base64 编解码 |
85
- | crypto | `@cloudcome/utils-node/crypto` | Node.js 端加密工具 |
85
+ | crypto | `@cloudcome/utils-node/crypto` | Node.js 端加密工具 |
86
+ | jsonl | `@cloudcome/utils-node/jsonl` | JSONL 文件读写 |
86
87
 
87
88
  ### @cloudcome/utils-vue
88
89
 
89
90
  Vue 3 工具库,依赖 `@cloudcome/utils-core` 和 `vue`:
90
91
 
91
- | 子模块 | 导入路径 | 功能 |
92
- | --- | --- | --- |
93
- | async | `@cloudcome/utils-vue/async` | Vue 异步组合式函数 |
94
- | component | `@cloudcome/utils-vue/component` | 组件工具(生命周期等) |
95
- | event | `@cloudcome/utils-vue/event` | 事件工具 |
96
- | request | `@cloudcome/utils-vue/request` | 请求组合式函数(useRequest) |
97
- | shared | `@cloudcome/utils-vue/shared` | 共享工具 |
98
- | state | `@cloudcome/utils-vue/state` | 状态管理工具 |
99
- | time | `@cloudcome/utils-vue/time` | 时间相关组合式函数 |
100
- | types | `@cloudcome/utils-vue/types` | 类型定义 |
92
+ | 子模块 | 导入路径 | 功能 |
93
+ | --------- | -------------------------------- | ---------------------------- |
94
+ | async | `@cloudcome/utils-vue/async` | Vue 异步组合式函数 |
95
+ | component | `@cloudcome/utils-vue/component` | 组件工具(生命周期等) |
96
+ | event | `@cloudcome/utils-vue/event` | 事件工具 |
97
+ | request | `@cloudcome/utils-vue/request` | 请求组合式函数(useRequest) |
98
+ | shared | `@cloudcome/utils-vue/shared` | 共享工具 |
99
+ | state | `@cloudcome/utils-vue/state` | 状态管理工具 |
100
+ | time | `@cloudcome/utils-vue/time` | 时间相关组合式函数 |
101
+ | types | `@cloudcome/utils-vue/types` | 类型定义 |
101
102
 
102
103
  ### @cloudcome/utils-react
103
104
 
@@ -107,13 +108,11 @@ React 工具库。
107
108
 
108
109
  UniApp 工具库,依赖 `@cloudcome/utils-core`、`@cloudcome/utils-vue`:
109
110
 
110
- | 子模块 | 导入路径 | 功能 |
111
- | --- | --- | --- |
112
- | app | `@cloudcome/utils-uni/app` | App 相关工具 |
113
- | client | `@cloudcome/utils-uni/client` | 客户端工具 |
114
- | cloud | `@cloudcome/utils-uni/cloud` | 云函数工具(调用、错误处理、uni-id 等) |
115
- | database | `@cloudcome/utils-uni/database` | 数据库操作(CRUD、事务、分页、upsert 等) |
116
- | page | `@cloudcome/utils-uni/page` | 页面相关工具 |
111
+ | 子模块 | 导入路径 | 功能 |
112
+ | -------- | ------------------------------- | ---------------------------------------------------- |
113
+ | client | `@cloudcome/utils-uni/client` | 客户端工具(App/页面生命周期、消息提示、异步工具等) |
114
+ | cloud | `@cloudcome/utils-uni/cloud` | 云函数工具(调用、错误处理、uni-id 等) |
115
+ | database | `@cloudcome/utils-uni/database` | 数据库操作(CRUD、事务、分页、upsert 等) |
117
116
 
118
117
  ## 开发
119
118
 
package/dist/cache.cjs CHANGED
@@ -33,7 +33,7 @@ var StorageCache = class extends _cloudcome_utils_core_cache.AbstractCache {
33
33
  return null;
34
34
  }
35
35
  return cached;
36
- } catch (_e) {
36
+ } catch {
37
37
  return null;
38
38
  }
39
39
  }
@@ -54,7 +54,7 @@ var StorageCache = class extends _cloudcome_utils_core_cache.AbstractCache {
54
54
  createdAt: Date.now(),
55
55
  maxAge: options?.maxAge || 0
56
56
  }));
57
- } catch (_cause) {}
57
+ } catch {}
58
58
  }
59
59
  /**
60
60
  * 通过ID删除缓存数据
@@ -65,12 +65,12 @@ var StorageCache = class extends _cloudcome_utils_core_cache.AbstractCache {
65
65
  const fullId = namespace ? `${namespace}:${id}` : id;
66
66
  try {
67
67
  storage.removeItem(fullId);
68
- } catch (_cause) {}
68
+ } catch {}
69
69
  }
70
70
  clear() {
71
71
  try {
72
72
  this.storage.clear();
73
- } catch (_err) {}
73
+ } catch {}
74
74
  }
75
75
  };
76
76
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"cache.cjs","names":[],"sources":["../src/cache.ts"],"sourcesContent":["import {\n AbstractCache,\n type Cached,\n type CacheOptions,\n} from '@cloudcome/utils-core/cache';\n\n/**\n * 使用浏览器存储(localStorage 或 sessionStorage)实现的缓存类\n * @template T - 缓存数据的类型\n */\nexport class StorageCache<T> extends AbstractCache<T> {\n /**\n * 创建一个新的 StorageCache 实例\n * @param storage - 使用的存储实现(localStorage 或 sessionStorage)\n * @param namespace - 可选,用于为缓存键添加前缀的命名空间\n */\n constructor(\n readonly storage: Storage,\n readonly namespace = '',\n ) {\n super();\n }\n\n /**\n * 通过ID获取缓存数据\n * @param id - 要获取的缓存键\n * @returns 如果找到且未过期则返回缓存数据,否则返回null\n */\n get(id: string): Cached<T> | null {\n const { storage, namespace } = this;\n const fullId = namespace ? `${namespace}:${id}` : id;\n\n try {\n const cachedString = storage.getItem(fullId);\n if (!cachedString) return null;\n\n const cached = JSON.parse(cachedString);\n\n if (cached.createdAt + cached.maxAge < Date.now()) {\n this.del(id);\n return null;\n }\n\n return cached;\n } catch (_e) {\n return null;\n }\n }\n\n /**\n * 将数据存储到缓存中\n * @param id - 存储数据使用的缓存键\n * @param data - 要缓存的数据\n * @param options - 可选的缓存配置\n * @returns 成功返回true,存储失败返回false\n */\n set(id: string, data: T, options?: CacheOptions) {\n const { storage, namespace } = this;\n const fullId = namespace ? `${namespace}:${id}` : id;\n\n try {\n storage.setItem(\n fullId,\n JSON.stringify({\n id,\n data,\n createdAt: Date.now(),\n maxAge: options?.maxAge || 0,\n }),\n );\n } catch (_cause) {\n //\n }\n }\n\n /**\n * 通过ID删除缓存数据\n * @param id - 要删除的缓存键\n */\n del(id: string) {\n const { storage, namespace } = this;\n const fullId = namespace ? `${namespace}:${id}` : id;\n\n try {\n storage.removeItem(fullId);\n } catch (_cause) {\n //\n }\n }\n\n clear() {\n try {\n this.storage.clear();\n } catch (_err) {\n //\n }\n }\n}\n\n/**\n * 创建一个使用 localStorage 的缓存实例\n * @template T - 缓存数据的类型\n * @param namespace - 可选,用于为缓存键添加前缀的命名空间\n * @returns 使用 localStorage 的新 StorageCache 实例\n */\nexport function createLocalCache<T>(namespace?: string): AbstractCache<T> {\n return new StorageCache<T>(localStorage, namespace);\n}\n\n/**\n * 创建一个使用 sessionStorage 的缓存实例\n * @template T - 缓存数据的类型\n * @param namespace - 可选,用于为缓存键添加前缀的命名空间\n * @returns 使用 sessionStorage 的新 StorageCache 实例\n */\nexport function createSessionCache<T>(namespace?: string): AbstractCache<T> {\n return new StorageCache<T>(sessionStorage, namespace);\n}\n"],"mappings":";;;;;;;AAUA,IAAa,eAAb,cAAqC,4BAAA,cAAiB;;;;;;CAMpD,YACE,SACA,YAAqB,IACrB;EACA,OAAO;EAHE,KAAA,UAAA;EACA,KAAA,YAAA;;;;;;;CAUX,IAAI,IAA8B;EAChC,MAAM,EAAE,SAAS,cAAc;EAC/B,MAAM,SAAS,YAAY,GAAG,UAAU,GAAG,OAAO;EAElD,IAAI;GACF,MAAM,eAAe,QAAQ,QAAQ,OAAO;GAC5C,IAAI,CAAC,cAAc,OAAO;GAE1B,MAAM,SAAS,KAAK,MAAM,aAAa;GAEvC,IAAI,OAAO,YAAY,OAAO,SAAS,KAAK,KAAK,EAAE;IACjD,KAAK,IAAI,GAAG;IACZ,OAAO;;GAGT,OAAO;WACA,IAAI;GACX,OAAO;;;;;;;;;;CAWX,IAAI,IAAY,MAAS,SAAwB;EAC/C,MAAM,EAAE,SAAS,cAAc;EAC/B,MAAM,SAAS,YAAY,GAAG,UAAU,GAAG,OAAO;EAElD,IAAI;GACF,QAAQ,QACN,QACA,KAAK,UAAU;IACb;IACA;IACA,WAAW,KAAK,KAAK;IACrB,QAAQ,SAAS,UAAU;IAC5B,CAAC,CACH;WACM,QAAQ;;;;;;CASnB,IAAI,IAAY;EACd,MAAM,EAAE,SAAS,cAAc;EAC/B,MAAM,SAAS,YAAY,GAAG,UAAU,GAAG,OAAO;EAElD,IAAI;GACF,QAAQ,WAAW,OAAO;WACnB,QAAQ;;CAKnB,QAAQ;EACN,IAAI;GACF,KAAK,QAAQ,OAAO;WACb,MAAM;;;;;;;;;AAYnB,SAAgB,iBAAoB,WAAsC;CACxE,OAAO,IAAI,aAAgB,cAAc,UAAU;;;;;;;;AASrD,SAAgB,mBAAsB,WAAsC;CAC1E,OAAO,IAAI,aAAgB,gBAAgB,UAAU"}
1
+ {"version":3,"file":"cache.cjs","names":[],"sources":["../src/cache.ts"],"sourcesContent":["import { AbstractCache, type Cached, type CacheOptions } from '@cloudcome/utils-core/cache';\n\n/**\n * 使用浏览器存储(localStorage 或 sessionStorage)实现的缓存类\n * @template T - 缓存数据的类型\n */\nexport class StorageCache<T> extends AbstractCache<T> {\n /**\n * 创建一个新的 StorageCache 实例\n * @param storage - 使用的存储实现(localStorage 或 sessionStorage)\n * @param namespace - 可选,用于为缓存键添加前缀的命名空间\n */\n constructor(\n readonly storage: Storage,\n readonly namespace = '',\n ) {\n super();\n }\n\n /**\n * 通过ID获取缓存数据\n * @param id - 要获取的缓存键\n * @returns 如果找到且未过期则返回缓存数据,否则返回null\n */\n get(id: string): Cached<T> | null {\n const { storage, namespace } = this;\n const fullId = namespace ? `${namespace}:${id}` : id;\n\n try {\n const cachedString = storage.getItem(fullId);\n if (!cachedString) return null;\n\n const cached = JSON.parse(cachedString);\n\n if (cached.createdAt + cached.maxAge < Date.now()) {\n this.del(id);\n return null;\n }\n\n return cached;\n } catch {\n return null;\n }\n }\n\n /**\n * 将数据存储到缓存中\n * @param id - 存储数据使用的缓存键\n * @param data - 要缓存的数据\n * @param options - 可选的缓存配置\n * @returns 成功返回true,存储失败返回false\n */\n set(id: string, data: T, options?: CacheOptions) {\n const { storage, namespace } = this;\n const fullId = namespace ? `${namespace}:${id}` : id;\n\n try {\n storage.setItem(\n fullId,\n JSON.stringify({\n id,\n data,\n createdAt: Date.now(),\n maxAge: options?.maxAge || 0,\n }),\n );\n } catch {\n //\n }\n }\n\n /**\n * 通过ID删除缓存数据\n * @param id - 要删除的缓存键\n */\n del(id: string) {\n const { storage, namespace } = this;\n const fullId = namespace ? `${namespace}:${id}` : id;\n\n try {\n storage.removeItem(fullId);\n } catch {\n //\n }\n }\n\n clear() {\n try {\n this.storage.clear();\n } catch {\n //\n }\n }\n}\n\n/**\n * 创建一个使用 localStorage 的缓存实例\n * @template T - 缓存数据的类型\n * @param namespace - 可选,用于为缓存键添加前缀的命名空间\n * @returns 使用 localStorage 的新 StorageCache 实例\n */\nexport function createLocalCache<T>(namespace?: string): AbstractCache<T> {\n return new StorageCache<T>(localStorage, namespace);\n}\n\n/**\n * 创建一个使用 sessionStorage 的缓存实例\n * @template T - 缓存数据的类型\n * @param namespace - 可选,用于为缓存键添加前缀的命名空间\n * @returns 使用 sessionStorage 的新 StorageCache 实例\n */\nexport function createSessionCache<T>(namespace?: string): AbstractCache<T> {\n return new StorageCache<T>(sessionStorage, namespace);\n}\n"],"mappings":";;;;;;;AAMA,IAAa,eAAb,cAAqC,4BAAA,cAAiB;;;;;;CAMpD,YACE,SACA,YAAqB,IACrB;EACA,OAAO;EAHE,KAAA,UAAA;EACA,KAAA,YAAA;;;;;;;CAUX,IAAI,IAA8B;EAChC,MAAM,EAAE,SAAS,cAAc;EAC/B,MAAM,SAAS,YAAY,GAAG,UAAU,GAAG,OAAO;EAElD,IAAI;GACF,MAAM,eAAe,QAAQ,QAAQ,OAAO;GAC5C,IAAI,CAAC,cAAc,OAAO;GAE1B,MAAM,SAAS,KAAK,MAAM,aAAa;GAEvC,IAAI,OAAO,YAAY,OAAO,SAAS,KAAK,KAAK,EAAE;IACjD,KAAK,IAAI,GAAG;IACZ,OAAO;;GAGT,OAAO;UACD;GACN,OAAO;;;;;;;;;;CAWX,IAAI,IAAY,MAAS,SAAwB;EAC/C,MAAM,EAAE,SAAS,cAAc;EAC/B,MAAM,SAAS,YAAY,GAAG,UAAU,GAAG,OAAO;EAElD,IAAI;GACF,QAAQ,QACN,QACA,KAAK,UAAU;IACb;IACA;IACA,WAAW,KAAK,KAAK;IACrB,QAAQ,SAAS,UAAU;IAC5B,CAAC,CACH;UACK;;;;;;CASV,IAAI,IAAY;EACd,MAAM,EAAE,SAAS,cAAc;EAC/B,MAAM,SAAS,YAAY,GAAG,UAAU,GAAG,OAAO;EAElD,IAAI;GACF,QAAQ,WAAW,OAAO;UACpB;;CAKV,QAAQ;EACN,IAAI;GACF,KAAK,QAAQ,OAAO;UACd;;;;;;;;;AAYZ,SAAgB,iBAAoB,WAAsC;CACxE,OAAO,IAAI,aAAgB,cAAc,UAAU;;;;;;;;AASrD,SAAgB,mBAAsB,WAAsC;CAC1E,OAAO,IAAI,aAAgB,gBAAgB,UAAU"}
package/dist/cache.mjs CHANGED
@@ -32,7 +32,7 @@ var StorageCache = class extends AbstractCache {
32
32
  return null;
33
33
  }
34
34
  return cached;
35
- } catch (_e) {
35
+ } catch {
36
36
  return null;
37
37
  }
38
38
  }
@@ -53,7 +53,7 @@ var StorageCache = class extends AbstractCache {
53
53
  createdAt: Date.now(),
54
54
  maxAge: options?.maxAge || 0
55
55
  }));
56
- } catch (_cause) {}
56
+ } catch {}
57
57
  }
58
58
  /**
59
59
  * 通过ID删除缓存数据
@@ -64,12 +64,12 @@ var StorageCache = class extends AbstractCache {
64
64
  const fullId = namespace ? `${namespace}:${id}` : id;
65
65
  try {
66
66
  storage.removeItem(fullId);
67
- } catch (_cause) {}
67
+ } catch {}
68
68
  }
69
69
  clear() {
70
70
  try {
71
71
  this.storage.clear();
72
- } catch (_err) {}
72
+ } catch {}
73
73
  }
74
74
  };
75
75
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"cache.mjs","names":[],"sources":["../src/cache.ts"],"sourcesContent":["import {\n AbstractCache,\n type Cached,\n type CacheOptions,\n} from '@cloudcome/utils-core/cache';\n\n/**\n * 使用浏览器存储(localStorage 或 sessionStorage)实现的缓存类\n * @template T - 缓存数据的类型\n */\nexport class StorageCache<T> extends AbstractCache<T> {\n /**\n * 创建一个新的 StorageCache 实例\n * @param storage - 使用的存储实现(localStorage 或 sessionStorage)\n * @param namespace - 可选,用于为缓存键添加前缀的命名空间\n */\n constructor(\n readonly storage: Storage,\n readonly namespace = '',\n ) {\n super();\n }\n\n /**\n * 通过ID获取缓存数据\n * @param id - 要获取的缓存键\n * @returns 如果找到且未过期则返回缓存数据,否则返回null\n */\n get(id: string): Cached<T> | null {\n const { storage, namespace } = this;\n const fullId = namespace ? `${namespace}:${id}` : id;\n\n try {\n const cachedString = storage.getItem(fullId);\n if (!cachedString) return null;\n\n const cached = JSON.parse(cachedString);\n\n if (cached.createdAt + cached.maxAge < Date.now()) {\n this.del(id);\n return null;\n }\n\n return cached;\n } catch (_e) {\n return null;\n }\n }\n\n /**\n * 将数据存储到缓存中\n * @param id - 存储数据使用的缓存键\n * @param data - 要缓存的数据\n * @param options - 可选的缓存配置\n * @returns 成功返回true,存储失败返回false\n */\n set(id: string, data: T, options?: CacheOptions) {\n const { storage, namespace } = this;\n const fullId = namespace ? `${namespace}:${id}` : id;\n\n try {\n storage.setItem(\n fullId,\n JSON.stringify({\n id,\n data,\n createdAt: Date.now(),\n maxAge: options?.maxAge || 0,\n }),\n );\n } catch (_cause) {\n //\n }\n }\n\n /**\n * 通过ID删除缓存数据\n * @param id - 要删除的缓存键\n */\n del(id: string) {\n const { storage, namespace } = this;\n const fullId = namespace ? `${namespace}:${id}` : id;\n\n try {\n storage.removeItem(fullId);\n } catch (_cause) {\n //\n }\n }\n\n clear() {\n try {\n this.storage.clear();\n } catch (_err) {\n //\n }\n }\n}\n\n/**\n * 创建一个使用 localStorage 的缓存实例\n * @template T - 缓存数据的类型\n * @param namespace - 可选,用于为缓存键添加前缀的命名空间\n * @returns 使用 localStorage 的新 StorageCache 实例\n */\nexport function createLocalCache<T>(namespace?: string): AbstractCache<T> {\n return new StorageCache<T>(localStorage, namespace);\n}\n\n/**\n * 创建一个使用 sessionStorage 的缓存实例\n * @template T - 缓存数据的类型\n * @param namespace - 可选,用于为缓存键添加前缀的命名空间\n * @returns 使用 sessionStorage 的新 StorageCache 实例\n */\nexport function createSessionCache<T>(namespace?: string): AbstractCache<T> {\n return new StorageCache<T>(sessionStorage, namespace);\n}\n"],"mappings":";;;;;;AAUA,IAAa,eAAb,cAAqC,cAAiB;;;;;;CAMpD,YACE,SACA,YAAqB,IACrB;EACA,OAAO;EAHE,KAAA,UAAA;EACA,KAAA,YAAA;;;;;;;CAUX,IAAI,IAA8B;EAChC,MAAM,EAAE,SAAS,cAAc;EAC/B,MAAM,SAAS,YAAY,GAAG,UAAU,GAAG,OAAO;EAElD,IAAI;GACF,MAAM,eAAe,QAAQ,QAAQ,OAAO;GAC5C,IAAI,CAAC,cAAc,OAAO;GAE1B,MAAM,SAAS,KAAK,MAAM,aAAa;GAEvC,IAAI,OAAO,YAAY,OAAO,SAAS,KAAK,KAAK,EAAE;IACjD,KAAK,IAAI,GAAG;IACZ,OAAO;;GAGT,OAAO;WACA,IAAI;GACX,OAAO;;;;;;;;;;CAWX,IAAI,IAAY,MAAS,SAAwB;EAC/C,MAAM,EAAE,SAAS,cAAc;EAC/B,MAAM,SAAS,YAAY,GAAG,UAAU,GAAG,OAAO;EAElD,IAAI;GACF,QAAQ,QACN,QACA,KAAK,UAAU;IACb;IACA;IACA,WAAW,KAAK,KAAK;IACrB,QAAQ,SAAS,UAAU;IAC5B,CAAC,CACH;WACM,QAAQ;;;;;;CASnB,IAAI,IAAY;EACd,MAAM,EAAE,SAAS,cAAc;EAC/B,MAAM,SAAS,YAAY,GAAG,UAAU,GAAG,OAAO;EAElD,IAAI;GACF,QAAQ,WAAW,OAAO;WACnB,QAAQ;;CAKnB,QAAQ;EACN,IAAI;GACF,KAAK,QAAQ,OAAO;WACb,MAAM;;;;;;;;;AAYnB,SAAgB,iBAAoB,WAAsC;CACxE,OAAO,IAAI,aAAgB,cAAc,UAAU;;;;;;;;AASrD,SAAgB,mBAAsB,WAAsC;CAC1E,OAAO,IAAI,aAAgB,gBAAgB,UAAU"}
1
+ {"version":3,"file":"cache.mjs","names":[],"sources":["../src/cache.ts"],"sourcesContent":["import { AbstractCache, type Cached, type CacheOptions } from '@cloudcome/utils-core/cache';\n\n/**\n * 使用浏览器存储(localStorage 或 sessionStorage)实现的缓存类\n * @template T - 缓存数据的类型\n */\nexport class StorageCache<T> extends AbstractCache<T> {\n /**\n * 创建一个新的 StorageCache 实例\n * @param storage - 使用的存储实现(localStorage 或 sessionStorage)\n * @param namespace - 可选,用于为缓存键添加前缀的命名空间\n */\n constructor(\n readonly storage: Storage,\n readonly namespace = '',\n ) {\n super();\n }\n\n /**\n * 通过ID获取缓存数据\n * @param id - 要获取的缓存键\n * @returns 如果找到且未过期则返回缓存数据,否则返回null\n */\n get(id: string): Cached<T> | null {\n const { storage, namespace } = this;\n const fullId = namespace ? `${namespace}:${id}` : id;\n\n try {\n const cachedString = storage.getItem(fullId);\n if (!cachedString) return null;\n\n const cached = JSON.parse(cachedString);\n\n if (cached.createdAt + cached.maxAge < Date.now()) {\n this.del(id);\n return null;\n }\n\n return cached;\n } catch {\n return null;\n }\n }\n\n /**\n * 将数据存储到缓存中\n * @param id - 存储数据使用的缓存键\n * @param data - 要缓存的数据\n * @param options - 可选的缓存配置\n * @returns 成功返回true,存储失败返回false\n */\n set(id: string, data: T, options?: CacheOptions) {\n const { storage, namespace } = this;\n const fullId = namespace ? `${namespace}:${id}` : id;\n\n try {\n storage.setItem(\n fullId,\n JSON.stringify({\n id,\n data,\n createdAt: Date.now(),\n maxAge: options?.maxAge || 0,\n }),\n );\n } catch {\n //\n }\n }\n\n /**\n * 通过ID删除缓存数据\n * @param id - 要删除的缓存键\n */\n del(id: string) {\n const { storage, namespace } = this;\n const fullId = namespace ? `${namespace}:${id}` : id;\n\n try {\n storage.removeItem(fullId);\n } catch {\n //\n }\n }\n\n clear() {\n try {\n this.storage.clear();\n } catch {\n //\n }\n }\n}\n\n/**\n * 创建一个使用 localStorage 的缓存实例\n * @template T - 缓存数据的类型\n * @param namespace - 可选,用于为缓存键添加前缀的命名空间\n * @returns 使用 localStorage 的新 StorageCache 实例\n */\nexport function createLocalCache<T>(namespace?: string): AbstractCache<T> {\n return new StorageCache<T>(localStorage, namespace);\n}\n\n/**\n * 创建一个使用 sessionStorage 的缓存实例\n * @template T - 缓存数据的类型\n * @param namespace - 可选,用于为缓存键添加前缀的命名空间\n * @returns 使用 sessionStorage 的新 StorageCache 实例\n */\nexport function createSessionCache<T>(namespace?: string): AbstractCache<T> {\n return new StorageCache<T>(sessionStorage, namespace);\n}\n"],"mappings":";;;;;;AAMA,IAAa,eAAb,cAAqC,cAAiB;;;;;;CAMpD,YACE,SACA,YAAqB,IACrB;EACA,OAAO;EAHE,KAAA,UAAA;EACA,KAAA,YAAA;;;;;;;CAUX,IAAI,IAA8B;EAChC,MAAM,EAAE,SAAS,cAAc;EAC/B,MAAM,SAAS,YAAY,GAAG,UAAU,GAAG,OAAO;EAElD,IAAI;GACF,MAAM,eAAe,QAAQ,QAAQ,OAAO;GAC5C,IAAI,CAAC,cAAc,OAAO;GAE1B,MAAM,SAAS,KAAK,MAAM,aAAa;GAEvC,IAAI,OAAO,YAAY,OAAO,SAAS,KAAK,KAAK,EAAE;IACjD,KAAK,IAAI,GAAG;IACZ,OAAO;;GAGT,OAAO;UACD;GACN,OAAO;;;;;;;;;;CAWX,IAAI,IAAY,MAAS,SAAwB;EAC/C,MAAM,EAAE,SAAS,cAAc;EAC/B,MAAM,SAAS,YAAY,GAAG,UAAU,GAAG,OAAO;EAElD,IAAI;GACF,QAAQ,QACN,QACA,KAAK,UAAU;IACb;IACA;IACA,WAAW,KAAK,KAAK;IACrB,QAAQ,SAAS,UAAU;IAC5B,CAAC,CACH;UACK;;;;;;CASV,IAAI,IAAY;EACd,MAAM,EAAE,SAAS,cAAc;EAC/B,MAAM,SAAS,YAAY,GAAG,UAAU,GAAG,OAAO;EAElD,IAAI;GACF,QAAQ,WAAW,OAAO;UACpB;;CAKV,QAAQ;EACN,IAAI;GACF,KAAK,QAAQ,OAAO;UACd;;;;;;;;;AAYZ,SAAgB,iBAAoB,WAAsC;CACxE,OAAO,IAAI,aAAgB,cAAc,UAAU;;;;;;;;AASrD,SAAgB,mBAAsB,WAAsC;CAC1E,OAAO,IAAI,aAAgB,gBAAgB,UAAU"}
@@ -1 +1 @@
1
- {"version":3,"file":"canvas.cjs","names":[],"sources":["../src/canvas.ts"],"sourcesContent":["import { objectDefaults } from '@cloudcome/utils-core/object';\nimport { imageLoad } from './image';\n\n/**\n * 将 Canvas 转换为 Base64 编码的字符串\n * @param {HTMLCanvasElement} canvas - 需要转换的 Canvas 元素\n * @param {string} [type] - 图片格式,默认为 'image/png'\n * @param {number} [quality] - 图片质量,范围 0 到 1,仅适用于 'image/jpeg' 或 'image/webp'\n * @returns {string} Base64 编码的图片数据\n * @example\n * const base64 = canvasToBase64(canvas, 'image/jpeg', 0.8);\n */\nexport function canvasToBase64(\n canvas: HTMLCanvasElement,\n type?: string,\n quality?: number,\n) {\n return canvas.toDataURL(type, quality);\n}\n\n/**\n * 将 Canvas 转换为 Blob 对象\n * @param {HTMLCanvasElement} canvas - 需要转换的 Canvas 元素\n * @param {string} [type] - 图片格式,默认为 'image/png'\n * @param {number} [quality] - 图片质量,范围 0 到 1,仅适用于 'image/jpeg' 或 'image/webp'\n * @returns {Promise<Blob>} 返回一个包含 Blob 对象的 Promise\n * @example\n * const blob = await canvasToBlob(canvas, 'image/jpeg', 0.8);\n */\nexport async function canvasToBlob(\n canvas: HTMLCanvasElement,\n type?: string,\n quality?: number,\n) {\n return new Promise<Blob>((resolve, reject) => {\n canvas.toBlob(\n (blob) => {\n if (blob) {\n resolve(blob);\n } else {\n reject(new Error('canvas 导出二进制对象失败'));\n }\n },\n type,\n quality,\n );\n });\n}\n\n/**\n * Canvas 绘制图片的配置选项\n */\nexport type CanvasDrawImageOptions = {\n /**\n * 源图片的左上角 x 坐标\n * @type {number}\n * @default 0\n */\n srcLeft?: number;\n /**\n * 源图片的左上角 y 坐标\n * @type {number}\n * @default 0\n */\n srcTop?: number;\n /**\n * 源图片的宽度\n * @type {number}\n * @default 图片的原始宽度\n */\n srcWidth?: number;\n /**\n * 源图片的高度\n * @type {number}\n * @default 图片的原始高度\n */\n srcHeight?: number;\n\n /**\n * 目标 Canvas 的左上角 x 坐标\n * @type {number}\n * @default 0\n */\n destLeft?: number;\n /**\n * 目标 Canvas 的左上角 y 坐标\n * @type {number}\n * @default 0\n */\n destTop?: number;\n /**\n * 目标 Canvas 的宽度\n * @type {number}\n * @default Canvas 的宽度\n */\n destWidth?: number;\n /**\n * 目标 Canvas 的高度\n * @type {number}\n * @default Canvas 的高度\n */\n destHeight?: number;\n};\n\n/**\n * 在 Canvas 上绘制图片\n * @param {HTMLCanvasElement} canvas - 目标 Canvas 元素\n * @param {string} url - 图片的 URL\n * @param {CanvasDrawImageOptions} [options] - 绘制图片的配置选项\n * @returns {Promise<void>} 返回一个 Promise,表示绘制完成\n * @example\n * await canvasDrawImage(canvas, 'https://example.com/image.png', {\n * srcLeft: 10,\n * srcTop: 10,\n * srcWidth: 100,\n * srcHeight: 100,\n * destLeft: 0,\n * destTop: 0,\n * destWidth: 200,\n * destHeight: 200\n * });\n */\nexport async function canvasDrawImage(\n canvas: HTMLCanvasElement,\n url: string,\n options?: CanvasDrawImageOptions,\n) {\n const ctx = canvas.getContext('2d');\n if (!ctx) throw new Error('canvas context is null');\n\n const img = await imageLoad(url);\n const defaults: CanvasDrawImageOptions = {\n srcLeft: 0,\n srcTop: 0,\n srcWidth: img.width,\n srcHeight: img.height,\n destLeft: 0,\n destTop: 0,\n destWidth: canvas.width,\n destHeight: canvas.height,\n };\n const {\n srcLeft,\n srcTop,\n srcWidth,\n srcHeight,\n destLeft,\n destTop,\n destWidth,\n destHeight,\n } = objectDefaults(\n options || {},\n defaults,\n ) as Required<CanvasDrawImageOptions>;\n ctx.drawImage(\n img,\n // source\n srcLeft,\n srcTop,\n srcWidth,\n srcHeight,\n // dest\n destLeft,\n destTop,\n destWidth,\n destHeight,\n );\n}\n"],"mappings":";;;;;;;;;;;;;AAYA,SAAgB,eACd,QACA,MACA,SACA;CACA,OAAO,OAAO,UAAU,MAAM,QAAQ;;;;;;;;;;;AAYxC,eAAsB,aACpB,QACA,MACA,SACA;CACA,OAAO,IAAI,SAAe,SAAS,WAAW;EAC5C,OAAO,QACJ,SAAS;GACR,IAAI,MACF,QAAQ,KAAK;QAEb,uBAAO,IAAI,MAAM,mBAAmB,CAAC;KAGzC,MACA,QACD;GACD;;;;;;;;;;;;;;;;;;;;AA4EJ,eAAsB,gBACpB,QACA,KACA,SACA;CACA,MAAM,MAAM,OAAO,WAAW,KAAK;CACnC,IAAI,CAAC,KAAK,MAAM,IAAI,MAAM,yBAAyB;CAEnD,MAAM,MAAM,MAAM,cAAA,UAAU,IAAI;CAChC,MAAM,WAAmC;EACvC,SAAS;EACT,QAAQ;EACR,UAAU,IAAI;EACd,WAAW,IAAI;EACf,UAAU;EACV,SAAS;EACT,WAAW,OAAO;EAClB,YAAY,OAAO;EACpB;CACD,MAAM,EACJ,SACA,QACA,UACA,WACA,UACA,SACA,WACA,gBAAA,GAAA,6BAAA,gBAEA,WAAW,EAAE,EACb,SACD;CACD,IAAI,UACF,KAEA,SACA,QACA,UACA,WAEA,UACA,SACA,WACA,WACD"}
1
+ {"version":3,"file":"canvas.cjs","names":[],"sources":["../src/canvas.ts"],"sourcesContent":["import { objectDefaults } from '@cloudcome/utils-core/object';\nimport { imageLoad } from './image';\n\n/**\n * 将 Canvas 转换为 Base64 编码的字符串\n * @param {HTMLCanvasElement} canvas - 需要转换的 Canvas 元素\n * @param {string} [type] - 图片格式,默认为 'image/png'\n * @param {number} [quality] - 图片质量,范围 0 到 1,仅适用于 'image/jpeg' 或 'image/webp'\n * @returns {string} Base64 编码的图片数据\n * @example\n * const base64 = canvasToBase64(canvas, 'image/jpeg', 0.8);\n */\nexport function canvasToBase64(canvas: HTMLCanvasElement, type?: string, quality?: number) {\n return canvas.toDataURL(type, quality);\n}\n\n/**\n * 将 Canvas 转换为 Blob 对象\n * @param {HTMLCanvasElement} canvas - 需要转换的 Canvas 元素\n * @param {string} [type] - 图片格式,默认为 'image/png'\n * @param {number} [quality] - 图片质量,范围 0 到 1,仅适用于 'image/jpeg' 或 'image/webp'\n * @returns {Promise<Blob>} 返回一个包含 Blob 对象的 Promise\n * @example\n * const blob = await canvasToBlob(canvas, 'image/jpeg', 0.8);\n */\nexport async function canvasToBlob(canvas: HTMLCanvasElement, type?: string, quality?: number) {\n return new Promise<Blob>((resolve, reject) => {\n canvas.toBlob(\n (blob) => {\n if (blob) {\n resolve(blob);\n } else {\n reject(new Error('canvas 导出二进制对象失败'));\n }\n },\n type,\n quality,\n );\n });\n}\n\n/**\n * Canvas 绘制图片的配置选项\n */\nexport type CanvasDrawImageOptions = {\n /**\n * 源图片的左上角 x 坐标\n * @type {number}\n * @default 0\n */\n srcLeft?: number;\n /**\n * 源图片的左上角 y 坐标\n * @type {number}\n * @default 0\n */\n srcTop?: number;\n /**\n * 源图片的宽度\n * @type {number}\n * @default 图片的原始宽度\n */\n srcWidth?: number;\n /**\n * 源图片的高度\n * @type {number}\n * @default 图片的原始高度\n */\n srcHeight?: number;\n\n /**\n * 目标 Canvas 的左上角 x 坐标\n * @type {number}\n * @default 0\n */\n destLeft?: number;\n /**\n * 目标 Canvas 的左上角 y 坐标\n * @type {number}\n * @default 0\n */\n destTop?: number;\n /**\n * 目标 Canvas 的宽度\n * @type {number}\n * @default Canvas 的宽度\n */\n destWidth?: number;\n /**\n * 目标 Canvas 的高度\n * @type {number}\n * @default Canvas 的高度\n */\n destHeight?: number;\n};\n\n/**\n * 在 Canvas 上绘制图片\n * @param {HTMLCanvasElement} canvas - 目标 Canvas 元素\n * @param {string} url - 图片的 URL\n * @param {CanvasDrawImageOptions} [options] - 绘制图片的配置选项\n * @returns {Promise<void>} 返回一个 Promise,表示绘制完成\n * @example\n * await canvasDrawImage(canvas, 'https://example.com/image.png', {\n * srcLeft: 10,\n * srcTop: 10,\n * srcWidth: 100,\n * srcHeight: 100,\n * destLeft: 0,\n * destTop: 0,\n * destWidth: 200,\n * destHeight: 200\n * });\n */\nexport async function canvasDrawImage(canvas: HTMLCanvasElement, url: string, options?: CanvasDrawImageOptions) {\n const ctx = canvas.getContext('2d');\n if (!ctx) throw new Error('canvas context is null');\n\n const img = await imageLoad(url);\n const defaults: CanvasDrawImageOptions = {\n srcLeft: 0,\n srcTop: 0,\n srcWidth: img.width,\n srcHeight: img.height,\n destLeft: 0,\n destTop: 0,\n destWidth: canvas.width,\n destHeight: canvas.height,\n };\n const { srcLeft, srcTop, srcWidth, srcHeight, destLeft, destTop, destWidth, destHeight } = objectDefaults(\n options || {},\n defaults,\n ) as Required<CanvasDrawImageOptions>;\n ctx.drawImage(\n img,\n // source\n srcLeft,\n srcTop,\n srcWidth,\n srcHeight,\n // dest\n destLeft,\n destTop,\n destWidth,\n destHeight,\n );\n}\n"],"mappings":";;;;;;;;;;;;;AAYA,SAAgB,eAAe,QAA2B,MAAe,SAAkB;CACzF,OAAO,OAAO,UAAU,MAAM,QAAQ;;;;;;;;;;;AAYxC,eAAsB,aAAa,QAA2B,MAAe,SAAkB;CAC7F,OAAO,IAAI,SAAe,SAAS,WAAW;EAC5C,OAAO,QACJ,SAAS;GACR,IAAI,MACF,QAAQ,KAAK;QAEb,uBAAO,IAAI,MAAM,mBAAmB,CAAC;KAGzC,MACA,QACD;GACD;;;;;;;;;;;;;;;;;;;;AA4EJ,eAAsB,gBAAgB,QAA2B,KAAa,SAAkC;CAC9G,MAAM,MAAM,OAAO,WAAW,KAAK;CACnC,IAAI,CAAC,KAAK,MAAM,IAAI,MAAM,yBAAyB;CAEnD,MAAM,MAAM,MAAM,cAAA,UAAU,IAAI;CAChC,MAAM,WAAmC;EACvC,SAAS;EACT,QAAQ;EACR,UAAU,IAAI;EACd,WAAW,IAAI;EACf,UAAU;EACV,SAAS;EACT,WAAW,OAAO;EAClB,YAAY,OAAO;EACpB;CACD,MAAM,EAAE,SAAS,QAAQ,UAAU,WAAW,UAAU,SAAS,WAAW,gBAAA,GAAA,6BAAA,gBAC1E,WAAW,EAAE,EACb,SACD;CACD,IAAI,UACF,KAEA,SACA,QACA,UACA,WAEA,UACA,SACA,WACA,WACD"}
@@ -1 +1 @@
1
- {"version":3,"file":"canvas.mjs","names":[],"sources":["../src/canvas.ts"],"sourcesContent":["import { objectDefaults } from '@cloudcome/utils-core/object';\nimport { imageLoad } from './image';\n\n/**\n * 将 Canvas 转换为 Base64 编码的字符串\n * @param {HTMLCanvasElement} canvas - 需要转换的 Canvas 元素\n * @param {string} [type] - 图片格式,默认为 'image/png'\n * @param {number} [quality] - 图片质量,范围 0 到 1,仅适用于 'image/jpeg' 或 'image/webp'\n * @returns {string} Base64 编码的图片数据\n * @example\n * const base64 = canvasToBase64(canvas, 'image/jpeg', 0.8);\n */\nexport function canvasToBase64(\n canvas: HTMLCanvasElement,\n type?: string,\n quality?: number,\n) {\n return canvas.toDataURL(type, quality);\n}\n\n/**\n * 将 Canvas 转换为 Blob 对象\n * @param {HTMLCanvasElement} canvas - 需要转换的 Canvas 元素\n * @param {string} [type] - 图片格式,默认为 'image/png'\n * @param {number} [quality] - 图片质量,范围 0 到 1,仅适用于 'image/jpeg' 或 'image/webp'\n * @returns {Promise<Blob>} 返回一个包含 Blob 对象的 Promise\n * @example\n * const blob = await canvasToBlob(canvas, 'image/jpeg', 0.8);\n */\nexport async function canvasToBlob(\n canvas: HTMLCanvasElement,\n type?: string,\n quality?: number,\n) {\n return new Promise<Blob>((resolve, reject) => {\n canvas.toBlob(\n (blob) => {\n if (blob) {\n resolve(blob);\n } else {\n reject(new Error('canvas 导出二进制对象失败'));\n }\n },\n type,\n quality,\n );\n });\n}\n\n/**\n * Canvas 绘制图片的配置选项\n */\nexport type CanvasDrawImageOptions = {\n /**\n * 源图片的左上角 x 坐标\n * @type {number}\n * @default 0\n */\n srcLeft?: number;\n /**\n * 源图片的左上角 y 坐标\n * @type {number}\n * @default 0\n */\n srcTop?: number;\n /**\n * 源图片的宽度\n * @type {number}\n * @default 图片的原始宽度\n */\n srcWidth?: number;\n /**\n * 源图片的高度\n * @type {number}\n * @default 图片的原始高度\n */\n srcHeight?: number;\n\n /**\n * 目标 Canvas 的左上角 x 坐标\n * @type {number}\n * @default 0\n */\n destLeft?: number;\n /**\n * 目标 Canvas 的左上角 y 坐标\n * @type {number}\n * @default 0\n */\n destTop?: number;\n /**\n * 目标 Canvas 的宽度\n * @type {number}\n * @default Canvas 的宽度\n */\n destWidth?: number;\n /**\n * 目标 Canvas 的高度\n * @type {number}\n * @default Canvas 的高度\n */\n destHeight?: number;\n};\n\n/**\n * 在 Canvas 上绘制图片\n * @param {HTMLCanvasElement} canvas - 目标 Canvas 元素\n * @param {string} url - 图片的 URL\n * @param {CanvasDrawImageOptions} [options] - 绘制图片的配置选项\n * @returns {Promise<void>} 返回一个 Promise,表示绘制完成\n * @example\n * await canvasDrawImage(canvas, 'https://example.com/image.png', {\n * srcLeft: 10,\n * srcTop: 10,\n * srcWidth: 100,\n * srcHeight: 100,\n * destLeft: 0,\n * destTop: 0,\n * destWidth: 200,\n * destHeight: 200\n * });\n */\nexport async function canvasDrawImage(\n canvas: HTMLCanvasElement,\n url: string,\n options?: CanvasDrawImageOptions,\n) {\n const ctx = canvas.getContext('2d');\n if (!ctx) throw new Error('canvas context is null');\n\n const img = await imageLoad(url);\n const defaults: CanvasDrawImageOptions = {\n srcLeft: 0,\n srcTop: 0,\n srcWidth: img.width,\n srcHeight: img.height,\n destLeft: 0,\n destTop: 0,\n destWidth: canvas.width,\n destHeight: canvas.height,\n };\n const {\n srcLeft,\n srcTop,\n srcWidth,\n srcHeight,\n destLeft,\n destTop,\n destWidth,\n destHeight,\n } = objectDefaults(\n options || {},\n defaults,\n ) as Required<CanvasDrawImageOptions>;\n ctx.drawImage(\n img,\n // source\n srcLeft,\n srcTop,\n srcWidth,\n srcHeight,\n // dest\n destLeft,\n destTop,\n destWidth,\n destHeight,\n );\n}\n"],"mappings":";;;;;;;;;;;;AAYA,SAAgB,eACd,QACA,MACA,SACA;CACA,OAAO,OAAO,UAAU,MAAM,QAAQ;;;;;;;;;;;AAYxC,eAAsB,aACpB,QACA,MACA,SACA;CACA,OAAO,IAAI,SAAe,SAAS,WAAW;EAC5C,OAAO,QACJ,SAAS;GACR,IAAI,MACF,QAAQ,KAAK;QAEb,uBAAO,IAAI,MAAM,mBAAmB,CAAC;KAGzC,MACA,QACD;GACD;;;;;;;;;;;;;;;;;;;;AA4EJ,eAAsB,gBACpB,QACA,KACA,SACA;CACA,MAAM,MAAM,OAAO,WAAW,KAAK;CACnC,IAAI,CAAC,KAAK,MAAM,IAAI,MAAM,yBAAyB;CAEnD,MAAM,MAAM,MAAM,UAAU,IAAI;CAChC,MAAM,WAAmC;EACvC,SAAS;EACT,QAAQ;EACR,UAAU,IAAI;EACd,WAAW,IAAI;EACf,UAAU;EACV,SAAS;EACT,WAAW,OAAO;EAClB,YAAY,OAAO;EACpB;CACD,MAAM,EACJ,SACA,QACA,UACA,WACA,UACA,SACA,WACA,eACE,eACF,WAAW,EAAE,EACb,SACD;CACD,IAAI,UACF,KAEA,SACA,QACA,UACA,WAEA,UACA,SACA,WACA,WACD"}
1
+ {"version":3,"file":"canvas.mjs","names":[],"sources":["../src/canvas.ts"],"sourcesContent":["import { objectDefaults } from '@cloudcome/utils-core/object';\nimport { imageLoad } from './image';\n\n/**\n * 将 Canvas 转换为 Base64 编码的字符串\n * @param {HTMLCanvasElement} canvas - 需要转换的 Canvas 元素\n * @param {string} [type] - 图片格式,默认为 'image/png'\n * @param {number} [quality] - 图片质量,范围 0 到 1,仅适用于 'image/jpeg' 或 'image/webp'\n * @returns {string} Base64 编码的图片数据\n * @example\n * const base64 = canvasToBase64(canvas, 'image/jpeg', 0.8);\n */\nexport function canvasToBase64(canvas: HTMLCanvasElement, type?: string, quality?: number) {\n return canvas.toDataURL(type, quality);\n}\n\n/**\n * 将 Canvas 转换为 Blob 对象\n * @param {HTMLCanvasElement} canvas - 需要转换的 Canvas 元素\n * @param {string} [type] - 图片格式,默认为 'image/png'\n * @param {number} [quality] - 图片质量,范围 0 到 1,仅适用于 'image/jpeg' 或 'image/webp'\n * @returns {Promise<Blob>} 返回一个包含 Blob 对象的 Promise\n * @example\n * const blob = await canvasToBlob(canvas, 'image/jpeg', 0.8);\n */\nexport async function canvasToBlob(canvas: HTMLCanvasElement, type?: string, quality?: number) {\n return new Promise<Blob>((resolve, reject) => {\n canvas.toBlob(\n (blob) => {\n if (blob) {\n resolve(blob);\n } else {\n reject(new Error('canvas 导出二进制对象失败'));\n }\n },\n type,\n quality,\n );\n });\n}\n\n/**\n * Canvas 绘制图片的配置选项\n */\nexport type CanvasDrawImageOptions = {\n /**\n * 源图片的左上角 x 坐标\n * @type {number}\n * @default 0\n */\n srcLeft?: number;\n /**\n * 源图片的左上角 y 坐标\n * @type {number}\n * @default 0\n */\n srcTop?: number;\n /**\n * 源图片的宽度\n * @type {number}\n * @default 图片的原始宽度\n */\n srcWidth?: number;\n /**\n * 源图片的高度\n * @type {number}\n * @default 图片的原始高度\n */\n srcHeight?: number;\n\n /**\n * 目标 Canvas 的左上角 x 坐标\n * @type {number}\n * @default 0\n */\n destLeft?: number;\n /**\n * 目标 Canvas 的左上角 y 坐标\n * @type {number}\n * @default 0\n */\n destTop?: number;\n /**\n * 目标 Canvas 的宽度\n * @type {number}\n * @default Canvas 的宽度\n */\n destWidth?: number;\n /**\n * 目标 Canvas 的高度\n * @type {number}\n * @default Canvas 的高度\n */\n destHeight?: number;\n};\n\n/**\n * 在 Canvas 上绘制图片\n * @param {HTMLCanvasElement} canvas - 目标 Canvas 元素\n * @param {string} url - 图片的 URL\n * @param {CanvasDrawImageOptions} [options] - 绘制图片的配置选项\n * @returns {Promise<void>} 返回一个 Promise,表示绘制完成\n * @example\n * await canvasDrawImage(canvas, 'https://example.com/image.png', {\n * srcLeft: 10,\n * srcTop: 10,\n * srcWidth: 100,\n * srcHeight: 100,\n * destLeft: 0,\n * destTop: 0,\n * destWidth: 200,\n * destHeight: 200\n * });\n */\nexport async function canvasDrawImage(canvas: HTMLCanvasElement, url: string, options?: CanvasDrawImageOptions) {\n const ctx = canvas.getContext('2d');\n if (!ctx) throw new Error('canvas context is null');\n\n const img = await imageLoad(url);\n const defaults: CanvasDrawImageOptions = {\n srcLeft: 0,\n srcTop: 0,\n srcWidth: img.width,\n srcHeight: img.height,\n destLeft: 0,\n destTop: 0,\n destWidth: canvas.width,\n destHeight: canvas.height,\n };\n const { srcLeft, srcTop, srcWidth, srcHeight, destLeft, destTop, destWidth, destHeight } = objectDefaults(\n options || {},\n defaults,\n ) as Required<CanvasDrawImageOptions>;\n ctx.drawImage(\n img,\n // source\n srcLeft,\n srcTop,\n srcWidth,\n srcHeight,\n // dest\n destLeft,\n destTop,\n destWidth,\n destHeight,\n );\n}\n"],"mappings":";;;;;;;;;;;;AAYA,SAAgB,eAAe,QAA2B,MAAe,SAAkB;CACzF,OAAO,OAAO,UAAU,MAAM,QAAQ;;;;;;;;;;;AAYxC,eAAsB,aAAa,QAA2B,MAAe,SAAkB;CAC7F,OAAO,IAAI,SAAe,SAAS,WAAW;EAC5C,OAAO,QACJ,SAAS;GACR,IAAI,MACF,QAAQ,KAAK;QAEb,uBAAO,IAAI,MAAM,mBAAmB,CAAC;KAGzC,MACA,QACD;GACD;;;;;;;;;;;;;;;;;;;;AA4EJ,eAAsB,gBAAgB,QAA2B,KAAa,SAAkC;CAC9G,MAAM,MAAM,OAAO,WAAW,KAAK;CACnC,IAAI,CAAC,KAAK,MAAM,IAAI,MAAM,yBAAyB;CAEnD,MAAM,MAAM,MAAM,UAAU,IAAI;CAChC,MAAM,WAAmC;EACvC,SAAS;EACT,QAAQ;EACR,UAAU,IAAI;EACd,WAAW,IAAI;EACf,UAAU;EACV,SAAS;EACT,WAAW,OAAO;EAClB,YAAY,OAAO;EACpB;CACD,MAAM,EAAE,SAAS,QAAQ,UAAU,WAAW,UAAU,SAAS,WAAW,eAAe,eACzF,WAAW,EAAE,EACb,SACD;CACD,IAAI,UACF,KAEA,SACA,QACA,UACA,WAEA,UACA,SACA,WACA,WACD"}
@@ -1 +1 @@
1
- {"version":3,"file":"cookie.cjs","names":[],"sources":["../src/cookie.ts"],"sourcesContent":["import type { DateValue } from '@cloudcome/utils-core/date';\nimport { dateParse } from '@cloudcome/utils-core/date';\n\n/**\n * 获取指定名称的 Cookie 值。\n * @param {string} name - Cookie 的名称。\n * @returns {string} - 返回对应的 Cookie 值,如果不存在则返回空字符串。\n */\nexport function cookieGet(name: string) {\n const cookies = document.cookie.split(';');\n\n for (let i = 0; i < cookies.length; i++) {\n const cookie = cookies[i].trim();\n\n if (cookie.startsWith(`${name}=`)) {\n try {\n return decodeURIComponent(cookie.slice(name.length + 1));\n } catch {\n return cookie.slice(name.length + 1);\n }\n }\n }\n\n return '';\n}\n\n/**\n * 设置 Cookie。\n * @param {string} name - Cookie 的名称。\n * @param {string} value - Cookie 的值。\n * @param {CookieOptions} [options] - 可选的 Cookie 配置项。\n */\nexport type CookieOptions = {\n /**\n * Cookie 的过期时间,可以是日期字符串、时间戳或 `Date` 对象。\n */\n expires?: DateValue;\n\n /**\n * Cookie 的路径,默认为当前路径。\n */\n path?: string;\n\n /**\n * Cookie 的域名,默认为当前域名。\n */\n domain?: string;\n\n /**\n * 是否启用安全传输(HTTPS)。\n */\n secure?: boolean;\n\n /**\n * SameSite 属性,可选值为 `'strict'`、`'lax'` 或 `'none'`。\n */\n sameSite?: 'strict' | 'lax' | 'none';\n\n /**\n * Cookie 的最大存活时间(秒)。\n */\n maxAge?: number;\n};\n\n/**\n * 设置 Cookie。\n * @param {string} name - Cookie 的名称。\n * @param {string} value - Cookie 的值。\n * @param {CookieOptions} [options] - 可选的 Cookie 配置项。\n */\nexport function cookieSet(\n name: string,\n value: string,\n options?: CookieOptions,\n) {\n const { expires, maxAge, path, domain, sameSite, secure } = options || {};\n let cookie = `${name}=${encodeURIComponent(value)}`;\n\n const expiresAt = expires\n ? dateParse(expires)\n : maxAge\n ? dateParse(Date.now() + maxAge * 1000)\n : null;\n const metas: [string, string][] = [];\n\n if (expiresAt) {\n metas.push(['expires', expiresAt.toISOString()]);\n }\n\n if (path) {\n metas.push(['path', path]);\n }\n\n if (domain) {\n metas.push(['domain', domain]);\n }\n\n if (sameSite) {\n metas.push(['sameSite', sameSite]);\n }\n\n if (secure) {\n metas.push(['secure', 'true']);\n }\n\n for (const [key, value] of metas) {\n cookie += `; ${key}=${value}`;\n }\n\n // biome-ignore lint/suspicious/noDocumentCookie: 暂时方案\n document.cookie = cookie;\n}\n\n/**\n * 删除指定名称的 Cookie。\n * @param {string} name - 要删除的 Cookie 名称。\n */\nexport function cookieDel(name: string) {\n cookieSet(name, '', {\n expires: 0,\n });\n}\n"],"mappings":";;;;;;;;AAQA,SAAgB,UAAU,MAAc;CACtC,MAAM,UAAU,SAAS,OAAO,MAAM,IAAI;CAE1C,KAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;EACvC,MAAM,SAAS,QAAQ,GAAG,MAAM;EAEhC,IAAI,OAAO,WAAW,GAAG,KAAK,GAAG,EAC/B,IAAI;GACF,OAAO,mBAAmB,OAAO,MAAM,KAAK,SAAS,EAAE,CAAC;UAClD;GACN,OAAO,OAAO,MAAM,KAAK,SAAS,EAAE;;;CAK1C,OAAO;;;;;;;;AA+CT,SAAgB,UACd,MACA,OACA,SACA;CACA,MAAM,EAAE,SAAS,QAAQ,MAAM,QAAQ,UAAU,WAAW,WAAW,EAAE;CACzE,IAAI,SAAS,GAAG,KAAK,GAAG,mBAAmB,MAAM;CAEjD,MAAM,YAAY,WAAA,GAAA,2BAAA,WACJ,QAAQ,GAClB,UAAA,GAAA,2BAAA,WACY,KAAK,KAAK,GAAG,SAAS,IAAK,GACrC;CACN,MAAM,QAA4B,EAAE;CAEpC,IAAI,WACF,MAAM,KAAK,CAAC,WAAW,UAAU,aAAa,CAAC,CAAC;CAGlD,IAAI,MACF,MAAM,KAAK,CAAC,QAAQ,KAAK,CAAC;CAG5B,IAAI,QACF,MAAM,KAAK,CAAC,UAAU,OAAO,CAAC;CAGhC,IAAI,UACF,MAAM,KAAK,CAAC,YAAY,SAAS,CAAC;CAGpC,IAAI,QACF,MAAM,KAAK,CAAC,UAAU,OAAO,CAAC;CAGhC,KAAK,MAAM,CAAC,KAAK,UAAU,OACzB,UAAU,KAAK,IAAI,GAAG;CAIxB,SAAS,SAAS;;;;;;AAOpB,SAAgB,UAAU,MAAc;CACtC,UAAU,MAAM,IAAI,EAClB,SAAS,GACV,CAAC"}
1
+ {"version":3,"file":"cookie.cjs","names":[],"sources":["../src/cookie.ts"],"sourcesContent":["import type { DateValue } from '@cloudcome/utils-core/date';\nimport { dateParse } from '@cloudcome/utils-core/date';\n\n/**\n * 获取指定名称的 Cookie 值。\n * @param {string} name - Cookie 的名称。\n * @returns {string} - 返回对应的 Cookie 值,如果不存在则返回空字符串。\n */\nexport function cookieGet(name: string) {\n const cookies = document.cookie.split(';');\n\n for (let i = 0; i < cookies.length; i++) {\n const cookie = cookies[i].trim();\n\n if (cookie.startsWith(`${name}=`)) {\n try {\n return decodeURIComponent(cookie.slice(name.length + 1));\n } catch {\n return cookie.slice(name.length + 1);\n }\n }\n }\n\n return '';\n}\n\n/**\n * 设置 Cookie。\n * @param {string} name - Cookie 的名称。\n * @param {string} value - Cookie 的值。\n * @param {CookieOptions} [options] - 可选的 Cookie 配置项。\n */\nexport type CookieOptions = {\n /**\n * Cookie 的过期时间,可以是日期字符串、时间戳或 `Date` 对象。\n */\n expires?: DateValue;\n\n /**\n * Cookie 的路径,默认为当前路径。\n */\n path?: string;\n\n /**\n * Cookie 的域名,默认为当前域名。\n */\n domain?: string;\n\n /**\n * 是否启用安全传输(HTTPS)。\n */\n secure?: boolean;\n\n /**\n * SameSite 属性,可选值为 `'strict'`、`'lax'` 或 `'none'`。\n */\n sameSite?: 'strict' | 'lax' | 'none';\n\n /**\n * Cookie 的最大存活时间(秒)。\n */\n maxAge?: number;\n};\n\n/**\n * 设置 Cookie。\n * @param {string} name - Cookie 的名称。\n * @param {string} value - Cookie 的值。\n * @param {CookieOptions} [options] - 可选的 Cookie 配置项。\n */\nexport function cookieSet(name: string, value: string, options?: CookieOptions) {\n const { expires, maxAge, path, domain, sameSite, secure } = options || {};\n let cookie = `${name}=${encodeURIComponent(value)}`;\n\n const expiresAt = expires ? dateParse(expires) : maxAge ? dateParse(Date.now() + maxAge * 1000) : null;\n const metas: [string, string][] = [];\n\n if (expiresAt) {\n metas.push(['expires', expiresAt.toISOString()]);\n }\n\n if (path) {\n metas.push(['path', path]);\n }\n\n if (domain) {\n metas.push(['domain', domain]);\n }\n\n if (sameSite) {\n metas.push(['sameSite', sameSite]);\n }\n\n if (secure) {\n metas.push(['secure', 'true']);\n }\n\n for (const [key, value] of metas) {\n cookie += `; ${key}=${value}`;\n }\n\n // biome-ignore lint/suspicious/noDocumentCookie: 暂时方案\n document.cookie = cookie;\n}\n\n/**\n * 删除指定名称的 Cookie。\n * @param {string} name - 要删除的 Cookie 名称。\n */\nexport function cookieDel(name: string) {\n cookieSet(name, '', {\n expires: 0,\n });\n}\n"],"mappings":";;;;;;;;AAQA,SAAgB,UAAU,MAAc;CACtC,MAAM,UAAU,SAAS,OAAO,MAAM,IAAI;CAE1C,KAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;EACvC,MAAM,SAAS,QAAQ,GAAG,MAAM;EAEhC,IAAI,OAAO,WAAW,GAAG,KAAK,GAAG,EAC/B,IAAI;GACF,OAAO,mBAAmB,OAAO,MAAM,KAAK,SAAS,EAAE,CAAC;UAClD;GACN,OAAO,OAAO,MAAM,KAAK,SAAS,EAAE;;;CAK1C,OAAO;;;;;;;;AA+CT,SAAgB,UAAU,MAAc,OAAe,SAAyB;CAC9E,MAAM,EAAE,SAAS,QAAQ,MAAM,QAAQ,UAAU,WAAW,WAAW,EAAE;CACzE,IAAI,SAAS,GAAG,KAAK,GAAG,mBAAmB,MAAM;CAEjD,MAAM,YAAY,WAAA,GAAA,2BAAA,WAAoB,QAAQ,GAAG,UAAA,GAAA,2BAAA,WAAmB,KAAK,KAAK,GAAG,SAAS,IAAK,GAAG;CAClG,MAAM,QAA4B,EAAE;CAEpC,IAAI,WACF,MAAM,KAAK,CAAC,WAAW,UAAU,aAAa,CAAC,CAAC;CAGlD,IAAI,MACF,MAAM,KAAK,CAAC,QAAQ,KAAK,CAAC;CAG5B,IAAI,QACF,MAAM,KAAK,CAAC,UAAU,OAAO,CAAC;CAGhC,IAAI,UACF,MAAM,KAAK,CAAC,YAAY,SAAS,CAAC;CAGpC,IAAI,QACF,MAAM,KAAK,CAAC,UAAU,OAAO,CAAC;CAGhC,KAAK,MAAM,CAAC,KAAK,UAAU,OACzB,UAAU,KAAK,IAAI,GAAG;CAIxB,SAAS,SAAS;;;;;;AAOpB,SAAgB,UAAU,MAAc;CACtC,UAAU,MAAM,IAAI,EAClB,SAAS,GACV,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"cookie.mjs","names":[],"sources":["../src/cookie.ts"],"sourcesContent":["import type { DateValue } from '@cloudcome/utils-core/date';\nimport { dateParse } from '@cloudcome/utils-core/date';\n\n/**\n * 获取指定名称的 Cookie 值。\n * @param {string} name - Cookie 的名称。\n * @returns {string} - 返回对应的 Cookie 值,如果不存在则返回空字符串。\n */\nexport function cookieGet(name: string) {\n const cookies = document.cookie.split(';');\n\n for (let i = 0; i < cookies.length; i++) {\n const cookie = cookies[i].trim();\n\n if (cookie.startsWith(`${name}=`)) {\n try {\n return decodeURIComponent(cookie.slice(name.length + 1));\n } catch {\n return cookie.slice(name.length + 1);\n }\n }\n }\n\n return '';\n}\n\n/**\n * 设置 Cookie。\n * @param {string} name - Cookie 的名称。\n * @param {string} value - Cookie 的值。\n * @param {CookieOptions} [options] - 可选的 Cookie 配置项。\n */\nexport type CookieOptions = {\n /**\n * Cookie 的过期时间,可以是日期字符串、时间戳或 `Date` 对象。\n */\n expires?: DateValue;\n\n /**\n * Cookie 的路径,默认为当前路径。\n */\n path?: string;\n\n /**\n * Cookie 的域名,默认为当前域名。\n */\n domain?: string;\n\n /**\n * 是否启用安全传输(HTTPS)。\n */\n secure?: boolean;\n\n /**\n * SameSite 属性,可选值为 `'strict'`、`'lax'` 或 `'none'`。\n */\n sameSite?: 'strict' | 'lax' | 'none';\n\n /**\n * Cookie 的最大存活时间(秒)。\n */\n maxAge?: number;\n};\n\n/**\n * 设置 Cookie。\n * @param {string} name - Cookie 的名称。\n * @param {string} value - Cookie 的值。\n * @param {CookieOptions} [options] - 可选的 Cookie 配置项。\n */\nexport function cookieSet(\n name: string,\n value: string,\n options?: CookieOptions,\n) {\n const { expires, maxAge, path, domain, sameSite, secure } = options || {};\n let cookie = `${name}=${encodeURIComponent(value)}`;\n\n const expiresAt = expires\n ? dateParse(expires)\n : maxAge\n ? dateParse(Date.now() + maxAge * 1000)\n : null;\n const metas: [string, string][] = [];\n\n if (expiresAt) {\n metas.push(['expires', expiresAt.toISOString()]);\n }\n\n if (path) {\n metas.push(['path', path]);\n }\n\n if (domain) {\n metas.push(['domain', domain]);\n }\n\n if (sameSite) {\n metas.push(['sameSite', sameSite]);\n }\n\n if (secure) {\n metas.push(['secure', 'true']);\n }\n\n for (const [key, value] of metas) {\n cookie += `; ${key}=${value}`;\n }\n\n // biome-ignore lint/suspicious/noDocumentCookie: 暂时方案\n document.cookie = cookie;\n}\n\n/**\n * 删除指定名称的 Cookie。\n * @param {string} name - 要删除的 Cookie 名称。\n */\nexport function cookieDel(name: string) {\n cookieSet(name, '', {\n expires: 0,\n });\n}\n"],"mappings":";;;;;;;AAQA,SAAgB,UAAU,MAAc;CACtC,MAAM,UAAU,SAAS,OAAO,MAAM,IAAI;CAE1C,KAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;EACvC,MAAM,SAAS,QAAQ,GAAG,MAAM;EAEhC,IAAI,OAAO,WAAW,GAAG,KAAK,GAAG,EAC/B,IAAI;GACF,OAAO,mBAAmB,OAAO,MAAM,KAAK,SAAS,EAAE,CAAC;UAClD;GACN,OAAO,OAAO,MAAM,KAAK,SAAS,EAAE;;;CAK1C,OAAO;;;;;;;;AA+CT,SAAgB,UACd,MACA,OACA,SACA;CACA,MAAM,EAAE,SAAS,QAAQ,MAAM,QAAQ,UAAU,WAAW,WAAW,EAAE;CACzE,IAAI,SAAS,GAAG,KAAK,GAAG,mBAAmB,MAAM;CAEjD,MAAM,YAAY,UACd,UAAU,QAAQ,GAClB,SACE,UAAU,KAAK,KAAK,GAAG,SAAS,IAAK,GACrC;CACN,MAAM,QAA4B,EAAE;CAEpC,IAAI,WACF,MAAM,KAAK,CAAC,WAAW,UAAU,aAAa,CAAC,CAAC;CAGlD,IAAI,MACF,MAAM,KAAK,CAAC,QAAQ,KAAK,CAAC;CAG5B,IAAI,QACF,MAAM,KAAK,CAAC,UAAU,OAAO,CAAC;CAGhC,IAAI,UACF,MAAM,KAAK,CAAC,YAAY,SAAS,CAAC;CAGpC,IAAI,QACF,MAAM,KAAK,CAAC,UAAU,OAAO,CAAC;CAGhC,KAAK,MAAM,CAAC,KAAK,UAAU,OACzB,UAAU,KAAK,IAAI,GAAG;CAIxB,SAAS,SAAS;;;;;;AAOpB,SAAgB,UAAU,MAAc;CACtC,UAAU,MAAM,IAAI,EAClB,SAAS,GACV,CAAC"}
1
+ {"version":3,"file":"cookie.mjs","names":[],"sources":["../src/cookie.ts"],"sourcesContent":["import type { DateValue } from '@cloudcome/utils-core/date';\nimport { dateParse } from '@cloudcome/utils-core/date';\n\n/**\n * 获取指定名称的 Cookie 值。\n * @param {string} name - Cookie 的名称。\n * @returns {string} - 返回对应的 Cookie 值,如果不存在则返回空字符串。\n */\nexport function cookieGet(name: string) {\n const cookies = document.cookie.split(';');\n\n for (let i = 0; i < cookies.length; i++) {\n const cookie = cookies[i].trim();\n\n if (cookie.startsWith(`${name}=`)) {\n try {\n return decodeURIComponent(cookie.slice(name.length + 1));\n } catch {\n return cookie.slice(name.length + 1);\n }\n }\n }\n\n return '';\n}\n\n/**\n * 设置 Cookie。\n * @param {string} name - Cookie 的名称。\n * @param {string} value - Cookie 的值。\n * @param {CookieOptions} [options] - 可选的 Cookie 配置项。\n */\nexport type CookieOptions = {\n /**\n * Cookie 的过期时间,可以是日期字符串、时间戳或 `Date` 对象。\n */\n expires?: DateValue;\n\n /**\n * Cookie 的路径,默认为当前路径。\n */\n path?: string;\n\n /**\n * Cookie 的域名,默认为当前域名。\n */\n domain?: string;\n\n /**\n * 是否启用安全传输(HTTPS)。\n */\n secure?: boolean;\n\n /**\n * SameSite 属性,可选值为 `'strict'`、`'lax'` 或 `'none'`。\n */\n sameSite?: 'strict' | 'lax' | 'none';\n\n /**\n * Cookie 的最大存活时间(秒)。\n */\n maxAge?: number;\n};\n\n/**\n * 设置 Cookie。\n * @param {string} name - Cookie 的名称。\n * @param {string} value - Cookie 的值。\n * @param {CookieOptions} [options] - 可选的 Cookie 配置项。\n */\nexport function cookieSet(name: string, value: string, options?: CookieOptions) {\n const { expires, maxAge, path, domain, sameSite, secure } = options || {};\n let cookie = `${name}=${encodeURIComponent(value)}`;\n\n const expiresAt = expires ? dateParse(expires) : maxAge ? dateParse(Date.now() + maxAge * 1000) : null;\n const metas: [string, string][] = [];\n\n if (expiresAt) {\n metas.push(['expires', expiresAt.toISOString()]);\n }\n\n if (path) {\n metas.push(['path', path]);\n }\n\n if (domain) {\n metas.push(['domain', domain]);\n }\n\n if (sameSite) {\n metas.push(['sameSite', sameSite]);\n }\n\n if (secure) {\n metas.push(['secure', 'true']);\n }\n\n for (const [key, value] of metas) {\n cookie += `; ${key}=${value}`;\n }\n\n // biome-ignore lint/suspicious/noDocumentCookie: 暂时方案\n document.cookie = cookie;\n}\n\n/**\n * 删除指定名称的 Cookie。\n * @param {string} name - 要删除的 Cookie 名称。\n */\nexport function cookieDel(name: string) {\n cookieSet(name, '', {\n expires: 0,\n });\n}\n"],"mappings":";;;;;;;AAQA,SAAgB,UAAU,MAAc;CACtC,MAAM,UAAU,SAAS,OAAO,MAAM,IAAI;CAE1C,KAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;EACvC,MAAM,SAAS,QAAQ,GAAG,MAAM;EAEhC,IAAI,OAAO,WAAW,GAAG,KAAK,GAAG,EAC/B,IAAI;GACF,OAAO,mBAAmB,OAAO,MAAM,KAAK,SAAS,EAAE,CAAC;UAClD;GACN,OAAO,OAAO,MAAM,KAAK,SAAS,EAAE;;;CAK1C,OAAO;;;;;;;;AA+CT,SAAgB,UAAU,MAAc,OAAe,SAAyB;CAC9E,MAAM,EAAE,SAAS,QAAQ,MAAM,QAAQ,UAAU,WAAW,WAAW,EAAE;CACzE,IAAI,SAAS,GAAG,KAAK,GAAG,mBAAmB,MAAM;CAEjD,MAAM,YAAY,UAAU,UAAU,QAAQ,GAAG,SAAS,UAAU,KAAK,KAAK,GAAG,SAAS,IAAK,GAAG;CAClG,MAAM,QAA4B,EAAE;CAEpC,IAAI,WACF,MAAM,KAAK,CAAC,WAAW,UAAU,aAAa,CAAC,CAAC;CAGlD,IAAI,MACF,MAAM,KAAK,CAAC,QAAQ,KAAK,CAAC;CAG5B,IAAI,QACF,MAAM,KAAK,CAAC,UAAU,OAAO,CAAC;CAGhC,IAAI,UACF,MAAM,KAAK,CAAC,YAAY,SAAS,CAAC;CAGpC,IAAI,QACF,MAAM,KAAK,CAAC,UAAU,OAAO,CAAC;CAGhC,KAAK,MAAM,CAAC,KAAK,UAAU,OACzB,UAAU,KAAK,IAAI,GAAG;CAIxB,SAAS,SAAS;;;;;;AAOpB,SAAgB,UAAU,MAAc;CACtC,UAAU,MAAM,IAAI,EAClB,SAAS,GACV,CAAC"}
package/dist/dom.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"dom.cjs","names":[],"sources":["../src/dom.ts"],"sourcesContent":["import { objectEach } from '@cloudcome/utils-core/object';\n\n/**\n * 表示 CSS 样式声明的类型,仅包含可用的字符串或数字类型的属性\n * @typedef {Object} Style\n * @property {string | number} [K] - CSS 样式属性,K 为 CSSStyleDeclaration 的键名,且值为字符串或数字类型\n */\nexport type Style = {\n [K in keyof CSSStyleDeclaration as K extends number\n ? never\n : CSSStyleDeclaration[K] extends string | number\n ? K\n : never]: CSSStyleDeclaration[K];\n};\n\n/**\n * 设置元素的样式\n * @param {HTMLElement} el - 需要设置样式的 HTML 元素\n * @param {string | Partial<Style> | Record<string, string>} style - 样式字符串或样式对象\n * @example\n * // 设置 body 元素的颜色为红色,并设置一个自定义变量\n * setStyle(document.body, { color: 'red', '--var': 'value' });\n * @example\n * // 使用字符串设置样式\n * setStyle(document.body, 'color: red; --var: value;');\n */\nexport function setStyle(\n el: HTMLElement,\n style: string | Partial<Style> | Record<string, string>,\n) {\n if (typeof style === 'string') {\n el.style.cssText = style;\n } else {\n objectEach(style, (value, key) => {\n el.style.setProperty(key as string, value as string | null);\n });\n }\n}\n\n/**\n * 获取元素的指定样式值\n * @param {HTMLElement} el - 需要获取样式的 HTML 元素\n * @param {keyof Style} style - 需要获取的样式属性\n * @returns {string} 返回指定样式的值\n * @example\n * // 获取 body 元素的颜色\n * const color = getStyle(document.body, 'color');\n */\nexport function getStyle(el: HTMLElement, style: keyof Style) {\n return window.getComputedStyle(el).getPropertyValue(style);\n}\n"],"mappings":";;;;;;;;;;;;;;AA0BA,SAAgB,SACd,IACA,OACA;CACA,IAAI,OAAO,UAAU,UACnB,GAAG,MAAM,UAAU;MAEnB,CAAA,GAAA,6BAAA,YAAW,QAAQ,OAAO,QAAQ;EAChC,GAAG,MAAM,YAAY,KAAe,MAAuB;GAC3D;;;;;;;;;;;AAaN,SAAgB,SAAS,IAAiB,OAAoB;CAC5D,OAAO,OAAO,iBAAiB,GAAG,CAAC,iBAAiB,MAAM"}
1
+ {"version":3,"file":"dom.cjs","names":[],"sources":["../src/dom.ts"],"sourcesContent":["import { objectEach } from '@cloudcome/utils-core/object';\n\n/**\n * 表示 CSS 样式声明的类型,仅包含可用的字符串或数字类型的属性\n * @typedef {Object} Style\n * @property {string | number} [K] - CSS 样式属性,K 为 CSSStyleDeclaration 的键名,且值为字符串或数字类型\n */\nexport type Style = {\n [K in keyof CSSStyleDeclaration as K extends number\n ? never\n : CSSStyleDeclaration[K] extends string | number\n ? K\n : never]: CSSStyleDeclaration[K];\n};\n\n/**\n * 设置元素的样式\n * @param {HTMLElement} el - 需要设置样式的 HTML 元素\n * @param {string | Partial<Style> | Record<string, string>} style - 样式字符串或样式对象\n * @example\n * // 设置 body 元素的颜色为红色,并设置一个自定义变量\n * setStyle(document.body, { color: 'red', '--var': 'value' });\n * @example\n * // 使用字符串设置样式\n * setStyle(document.body, 'color: red; --var: value;');\n */\nexport function setStyle(el: HTMLElement, style: string | Partial<Style> | Record<string, string>) {\n if (typeof style === 'string') {\n el.style.cssText = style;\n } else {\n objectEach(style, (value, key) => {\n el.style.setProperty(key as string, value as string | null);\n });\n }\n}\n\n/**\n * 获取元素的指定样式值\n * @param {HTMLElement} el - 需要获取样式的 HTML 元素\n * @param {keyof Style} style - 需要获取的样式属性\n * @returns {string} 返回指定样式的值\n * @example\n * // 获取 body 元素的颜色\n * const color = getStyle(document.body, 'color');\n */\nexport function getStyle(el: HTMLElement, style: keyof Style) {\n return window.getComputedStyle(el).getPropertyValue(style);\n}\n"],"mappings":";;;;;;;;;;;;;;AA0BA,SAAgB,SAAS,IAAiB,OAAyD;CACjG,IAAI,OAAO,UAAU,UACnB,GAAG,MAAM,UAAU;MAEnB,CAAA,GAAA,6BAAA,YAAW,QAAQ,OAAO,QAAQ;EAChC,GAAG,MAAM,YAAY,KAAe,MAAuB;GAC3D;;;;;;;;;;;AAaN,SAAgB,SAAS,IAAiB,OAAoB;CAC5D,OAAO,OAAO,iBAAiB,GAAG,CAAC,iBAAiB,MAAM"}
package/dist/dom.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"dom.mjs","names":[],"sources":["../src/dom.ts"],"sourcesContent":["import { objectEach } from '@cloudcome/utils-core/object';\n\n/**\n * 表示 CSS 样式声明的类型,仅包含可用的字符串或数字类型的属性\n * @typedef {Object} Style\n * @property {string | number} [K] - CSS 样式属性,K 为 CSSStyleDeclaration 的键名,且值为字符串或数字类型\n */\nexport type Style = {\n [K in keyof CSSStyleDeclaration as K extends number\n ? never\n : CSSStyleDeclaration[K] extends string | number\n ? K\n : never]: CSSStyleDeclaration[K];\n};\n\n/**\n * 设置元素的样式\n * @param {HTMLElement} el - 需要设置样式的 HTML 元素\n * @param {string | Partial<Style> | Record<string, string>} style - 样式字符串或样式对象\n * @example\n * // 设置 body 元素的颜色为红色,并设置一个自定义变量\n * setStyle(document.body, { color: 'red', '--var': 'value' });\n * @example\n * // 使用字符串设置样式\n * setStyle(document.body, 'color: red; --var: value;');\n */\nexport function setStyle(\n el: HTMLElement,\n style: string | Partial<Style> | Record<string, string>,\n) {\n if (typeof style === 'string') {\n el.style.cssText = style;\n } else {\n objectEach(style, (value, key) => {\n el.style.setProperty(key as string, value as string | null);\n });\n }\n}\n\n/**\n * 获取元素的指定样式值\n * @param {HTMLElement} el - 需要获取样式的 HTML 元素\n * @param {keyof Style} style - 需要获取的样式属性\n * @returns {string} 返回指定样式的值\n * @example\n * // 获取 body 元素的颜色\n * const color = getStyle(document.body, 'color');\n */\nexport function getStyle(el: HTMLElement, style: keyof Style) {\n return window.getComputedStyle(el).getPropertyValue(style);\n}\n"],"mappings":";;;;;;;;;;;;;AA0BA,SAAgB,SACd,IACA,OACA;CACA,IAAI,OAAO,UAAU,UACnB,GAAG,MAAM,UAAU;MAEnB,WAAW,QAAQ,OAAO,QAAQ;EAChC,GAAG,MAAM,YAAY,KAAe,MAAuB;GAC3D;;;;;;;;;;;AAaN,SAAgB,SAAS,IAAiB,OAAoB;CAC5D,OAAO,OAAO,iBAAiB,GAAG,CAAC,iBAAiB,MAAM"}
1
+ {"version":3,"file":"dom.mjs","names":[],"sources":["../src/dom.ts"],"sourcesContent":["import { objectEach } from '@cloudcome/utils-core/object';\n\n/**\n * 表示 CSS 样式声明的类型,仅包含可用的字符串或数字类型的属性\n * @typedef {Object} Style\n * @property {string | number} [K] - CSS 样式属性,K 为 CSSStyleDeclaration 的键名,且值为字符串或数字类型\n */\nexport type Style = {\n [K in keyof CSSStyleDeclaration as K extends number\n ? never\n : CSSStyleDeclaration[K] extends string | number\n ? K\n : never]: CSSStyleDeclaration[K];\n};\n\n/**\n * 设置元素的样式\n * @param {HTMLElement} el - 需要设置样式的 HTML 元素\n * @param {string | Partial<Style> | Record<string, string>} style - 样式字符串或样式对象\n * @example\n * // 设置 body 元素的颜色为红色,并设置一个自定义变量\n * setStyle(document.body, { color: 'red', '--var': 'value' });\n * @example\n * // 使用字符串设置样式\n * setStyle(document.body, 'color: red; --var: value;');\n */\nexport function setStyle(el: HTMLElement, style: string | Partial<Style> | Record<string, string>) {\n if (typeof style === 'string') {\n el.style.cssText = style;\n } else {\n objectEach(style, (value, key) => {\n el.style.setProperty(key as string, value as string | null);\n });\n }\n}\n\n/**\n * 获取元素的指定样式值\n * @param {HTMLElement} el - 需要获取样式的 HTML 元素\n * @param {keyof Style} style - 需要获取的样式属性\n * @returns {string} 返回指定样式的值\n * @example\n * // 获取 body 元素的颜色\n * const color = getStyle(document.body, 'color');\n */\nexport function getStyle(el: HTMLElement, style: keyof Style) {\n return window.getComputedStyle(el).getPropertyValue(style);\n}\n"],"mappings":";;;;;;;;;;;;;AA0BA,SAAgB,SAAS,IAAiB,OAAyD;CACjG,IAAI,OAAO,UAAU,UACnB,GAAG,MAAM,UAAU;MAEnB,WAAW,QAAQ,OAAO,QAAQ;EAChC,GAAG,MAAM,YAAY,KAAe,MAAuB;GAC3D;;;;;;;;;;;AAaN,SAAgB,SAAS,IAAiB,OAAoB;CAC5D,OAAO,OAAO,iBAAiB,GAAG,CAAC,iBAAiB,MAAM"}
package/dist/image.cjs CHANGED
@@ -18,7 +18,8 @@ async function imageLoad(url) {
18
18
  finished = true;
19
19
  image.onload = image.onerror = null;
20
20
  document.body.removeChild(image);
21
- isError ? reject(/* @__PURE__ */ new Error("图片加载失败")) : resolve(image);
21
+ if (isError) reject(/* @__PURE__ */ new Error("图片加载失败"));
22
+ else resolve(image);
22
23
  };
23
24
  image.onload = () => onFinish();
24
25
  image.onerror = () => onFinish(true);
@@ -1 +1 @@
1
- {"version":3,"file":"image.cjs","names":[],"sources":["../src/image.ts"],"sourcesContent":["import { setStyle } from './dom';\n\n/**\n * 加载图片并返回一个包含 HTMLImageElement 的 Promise\n * @param {string} url - 图片的 URL 地址\n * @returns {Promise<HTMLImageElement>} 返回一个包含 HTMLImageElement 的 Promise\n * @example\n * const img = await imageLoad('https://example.com/image.png');\n * @throws {Error} 如果图片加载失败,抛出错误\n */\nexport async function imageLoad(url: string) {\n return new Promise<HTMLImageElement>((resolve, reject) => {\n const image = new Image();\n let finished = false;\n const onFinish = (isError?: boolean) => {\n if (finished) return;\n finished = true;\n image.onload = image.onerror = null;\n document.body.removeChild(image);\n isError ? reject(new Error('图片加载失败')) : resolve(image);\n };\n image.onload = () => onFinish();\n image.onerror = () => onFinish(true);\n image.crossOrigin = 'anonymous';\n image.src = url;\n\n // ios 拍照产生的图片,如果没有插入的 DOM 中获取到的图片尺寸是相反的\n setStyle(image, {\n visibility: 'hidden',\n position: 'absolute',\n top: '-99999%',\n left: '-99999%',\n maxWidth: 'none',\n maxHeight: 'none',\n border: '0',\n width: 'auto',\n height: 'auto',\n margin: '0',\n padding: '0',\n transform: '',\n });\n document.body.appendChild(image);\n\n if (image.complete && image.width > 0) onFinish();\n });\n}\n\n// 图片缩放函数\n"],"mappings":";;;;;;;;;;;AAUA,eAAsB,UAAU,KAAa;CAC3C,OAAO,IAAI,SAA2B,SAAS,WAAW;EACxD,MAAM,QAAQ,IAAI,OAAO;EACzB,IAAI,WAAW;EACf,MAAM,YAAY,YAAsB;GACtC,IAAI,UAAU;GACd,WAAW;GACX,MAAM,SAAS,MAAM,UAAU;GAC/B,SAAS,KAAK,YAAY,MAAM;GAChC,UAAU,uBAAO,IAAI,MAAM,SAAS,CAAC,GAAG,QAAQ,MAAM;;EAExD,MAAM,eAAe,UAAU;EAC/B,MAAM,gBAAgB,SAAS,KAAK;EACpC,MAAM,cAAc;EACpB,MAAM,MAAM;EAGZ,YAAA,SAAS,OAAO;GACd,YAAY;GACZ,UAAU;GACV,KAAK;GACL,MAAM;GACN,UAAU;GACV,WAAW;GACX,QAAQ;GACR,OAAO;GACP,QAAQ;GACR,QAAQ;GACR,SAAS;GACT,WAAW;GACZ,CAAC;EACF,SAAS,KAAK,YAAY,MAAM;EAEhC,IAAI,MAAM,YAAY,MAAM,QAAQ,GAAG,UAAU;GACjD"}
1
+ {"version":3,"file":"image.cjs","names":[],"sources":["../src/image.ts"],"sourcesContent":["import { setStyle } from './dom';\n\n/**\n * 加载图片并返回一个包含 HTMLImageElement 的 Promise\n * @param {string} url - 图片的 URL 地址\n * @returns {Promise<HTMLImageElement>} 返回一个包含 HTMLImageElement 的 Promise\n * @example\n * const img = await imageLoad('https://example.com/image.png');\n * @throws {Error} 如果图片加载失败,抛出错误\n */\nexport async function imageLoad(url: string) {\n return new Promise<HTMLImageElement>((resolve, reject) => {\n const image = new Image();\n let finished = false;\n const onFinish = (isError?: boolean) => {\n if (finished) return;\n finished = true;\n image.onload = image.onerror = null;\n document.body.removeChild(image);\n if (isError) {\n reject(new Error('图片加载失败'));\n } else {\n resolve(image);\n }\n };\n image.onload = () => onFinish();\n image.onerror = () => onFinish(true);\n image.crossOrigin = 'anonymous';\n image.src = url;\n\n // ios 拍照产生的图片,如果没有插入的 DOM 中获取到的图片尺寸是相反的\n setStyle(image, {\n visibility: 'hidden',\n position: 'absolute',\n top: '-99999%',\n left: '-99999%',\n maxWidth: 'none',\n maxHeight: 'none',\n border: '0',\n width: 'auto',\n height: 'auto',\n margin: '0',\n padding: '0',\n transform: '',\n });\n document.body.appendChild(image);\n\n if (image.complete && image.width > 0) onFinish();\n });\n}\n\n// 图片缩放函数\n"],"mappings":";;;;;;;;;;;AAUA,eAAsB,UAAU,KAAa;CAC3C,OAAO,IAAI,SAA2B,SAAS,WAAW;EACxD,MAAM,QAAQ,IAAI,OAAO;EACzB,IAAI,WAAW;EACf,MAAM,YAAY,YAAsB;GACtC,IAAI,UAAU;GACd,WAAW;GACX,MAAM,SAAS,MAAM,UAAU;GAC/B,SAAS,KAAK,YAAY,MAAM;GAChC,IAAI,SACF,uBAAO,IAAI,MAAM,SAAS,CAAC;QAE3B,QAAQ,MAAM;;EAGlB,MAAM,eAAe,UAAU;EAC/B,MAAM,gBAAgB,SAAS,KAAK;EACpC,MAAM,cAAc;EACpB,MAAM,MAAM;EAGZ,YAAA,SAAS,OAAO;GACd,YAAY;GACZ,UAAU;GACV,KAAK;GACL,MAAM;GACN,UAAU;GACV,WAAW;GACX,QAAQ;GACR,OAAO;GACP,QAAQ;GACR,QAAQ;GACR,SAAS;GACT,WAAW;GACZ,CAAC;EACF,SAAS,KAAK,YAAY,MAAM;EAEhC,IAAI,MAAM,YAAY,MAAM,QAAQ,GAAG,UAAU;GACjD"}
package/dist/image.mjs CHANGED
@@ -17,7 +17,8 @@ async function imageLoad(url) {
17
17
  finished = true;
18
18
  image.onload = image.onerror = null;
19
19
  document.body.removeChild(image);
20
- isError ? reject(/* @__PURE__ */ new Error("图片加载失败")) : resolve(image);
20
+ if (isError) reject(/* @__PURE__ */ new Error("图片加载失败"));
21
+ else resolve(image);
21
22
  };
22
23
  image.onload = () => onFinish();
23
24
  image.onerror = () => onFinish(true);
@@ -1 +1 @@
1
- {"version":3,"file":"image.mjs","names":[],"sources":["../src/image.ts"],"sourcesContent":["import { setStyle } from './dom';\n\n/**\n * 加载图片并返回一个包含 HTMLImageElement 的 Promise\n * @param {string} url - 图片的 URL 地址\n * @returns {Promise<HTMLImageElement>} 返回一个包含 HTMLImageElement 的 Promise\n * @example\n * const img = await imageLoad('https://example.com/image.png');\n * @throws {Error} 如果图片加载失败,抛出错误\n */\nexport async function imageLoad(url: string) {\n return new Promise<HTMLImageElement>((resolve, reject) => {\n const image = new Image();\n let finished = false;\n const onFinish = (isError?: boolean) => {\n if (finished) return;\n finished = true;\n image.onload = image.onerror = null;\n document.body.removeChild(image);\n isError ? reject(new Error('图片加载失败')) : resolve(image);\n };\n image.onload = () => onFinish();\n image.onerror = () => onFinish(true);\n image.crossOrigin = 'anonymous';\n image.src = url;\n\n // ios 拍照产生的图片,如果没有插入的 DOM 中获取到的图片尺寸是相反的\n setStyle(image, {\n visibility: 'hidden',\n position: 'absolute',\n top: '-99999%',\n left: '-99999%',\n maxWidth: 'none',\n maxHeight: 'none',\n border: '0',\n width: 'auto',\n height: 'auto',\n margin: '0',\n padding: '0',\n transform: '',\n });\n document.body.appendChild(image);\n\n if (image.complete && image.width > 0) onFinish();\n });\n}\n\n// 图片缩放函数\n"],"mappings":";;;;;;;;;;AAUA,eAAsB,UAAU,KAAa;CAC3C,OAAO,IAAI,SAA2B,SAAS,WAAW;EACxD,MAAM,QAAQ,IAAI,OAAO;EACzB,IAAI,WAAW;EACf,MAAM,YAAY,YAAsB;GACtC,IAAI,UAAU;GACd,WAAW;GACX,MAAM,SAAS,MAAM,UAAU;GAC/B,SAAS,KAAK,YAAY,MAAM;GAChC,UAAU,uBAAO,IAAI,MAAM,SAAS,CAAC,GAAG,QAAQ,MAAM;;EAExD,MAAM,eAAe,UAAU;EAC/B,MAAM,gBAAgB,SAAS,KAAK;EACpC,MAAM,cAAc;EACpB,MAAM,MAAM;EAGZ,SAAS,OAAO;GACd,YAAY;GACZ,UAAU;GACV,KAAK;GACL,MAAM;GACN,UAAU;GACV,WAAW;GACX,QAAQ;GACR,OAAO;GACP,QAAQ;GACR,QAAQ;GACR,SAAS;GACT,WAAW;GACZ,CAAC;EACF,SAAS,KAAK,YAAY,MAAM;EAEhC,IAAI,MAAM,YAAY,MAAM,QAAQ,GAAG,UAAU;GACjD"}
1
+ {"version":3,"file":"image.mjs","names":[],"sources":["../src/image.ts"],"sourcesContent":["import { setStyle } from './dom';\n\n/**\n * 加载图片并返回一个包含 HTMLImageElement 的 Promise\n * @param {string} url - 图片的 URL 地址\n * @returns {Promise<HTMLImageElement>} 返回一个包含 HTMLImageElement 的 Promise\n * @example\n * const img = await imageLoad('https://example.com/image.png');\n * @throws {Error} 如果图片加载失败,抛出错误\n */\nexport async function imageLoad(url: string) {\n return new Promise<HTMLImageElement>((resolve, reject) => {\n const image = new Image();\n let finished = false;\n const onFinish = (isError?: boolean) => {\n if (finished) return;\n finished = true;\n image.onload = image.onerror = null;\n document.body.removeChild(image);\n if (isError) {\n reject(new Error('图片加载失败'));\n } else {\n resolve(image);\n }\n };\n image.onload = () => onFinish();\n image.onerror = () => onFinish(true);\n image.crossOrigin = 'anonymous';\n image.src = url;\n\n // ios 拍照产生的图片,如果没有插入的 DOM 中获取到的图片尺寸是相反的\n setStyle(image, {\n visibility: 'hidden',\n position: 'absolute',\n top: '-99999%',\n left: '-99999%',\n maxWidth: 'none',\n maxHeight: 'none',\n border: '0',\n width: 'auto',\n height: 'auto',\n margin: '0',\n padding: '0',\n transform: '',\n });\n document.body.appendChild(image);\n\n if (image.complete && image.width > 0) onFinish();\n });\n}\n\n// 图片缩放函数\n"],"mappings":";;;;;;;;;;AAUA,eAAsB,UAAU,KAAa;CAC3C,OAAO,IAAI,SAA2B,SAAS,WAAW;EACxD,MAAM,QAAQ,IAAI,OAAO;EACzB,IAAI,WAAW;EACf,MAAM,YAAY,YAAsB;GACtC,IAAI,UAAU;GACd,WAAW;GACX,MAAM,SAAS,MAAM,UAAU;GAC/B,SAAS,KAAK,YAAY,MAAM;GAChC,IAAI,SACF,uBAAO,IAAI,MAAM,SAAS,CAAC;QAE3B,QAAQ,MAAM;;EAGlB,MAAM,eAAe,UAAU;EAC/B,MAAM,gBAAgB,SAAS,KAAK;EACpC,MAAM,cAAc;EACpB,MAAM,MAAM;EAGZ,SAAS,OAAO;GACd,YAAY;GACZ,UAAU;GACV,KAAK;GACL,MAAM;GACN,UAAU;GACV,WAAW;GACX,QAAQ;GACR,OAAO;GACP,QAAQ;GACR,QAAQ;GACR,SAAS;GACT,WAAW;GACZ,CAAC;EACF,SAAS,KAAK,YAAY,MAAM;EAEhC,IAAI,MAAM,YAAY,MAAM,QAAQ,GAAG,UAAU;GACjD"}
package/dist/index.cjs CHANGED
@@ -3,7 +3,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  /**
4
4
  * `@cloudcome/utils-browser` 版本号
5
5
  */
6
- var VERSION = "1.2.17";
6
+ var VERSION = "1.3.0";
7
7
  //#endregion
8
8
  exports.VERSION = VERSION;
9
9
 
package/dist/index.mjs CHANGED
@@ -2,7 +2,7 @@
2
2
  /**
3
3
  * `@cloudcome/utils-browser` 版本号
4
4
  */
5
- var VERSION = "1.2.17";
5
+ var VERSION = "1.3.0";
6
6
  //#endregion
7
7
  export { VERSION };
8
8
 
package/dist/timer.cjs CHANGED
@@ -4,37 +4,58 @@ let _cloudcome_utils_core_timer = require("@cloudcome/utils-core/timer");
4
4
  /**
5
5
  * 创建一个基于 `requestAnimationFrame` 的间隔定时器
6
6
  *
7
- * @param callback - 每次间隔执行的回调函数,接收定时器状态和可选的 `next` 函数
7
+ * @example
8
+ * ```typescript
9
+ * // 无 condition
10
+ * frameInterval({
11
+ * runner: (state) => console.log(state.times),
12
+ * })
13
+ *
14
+ * // 有 condition,T 自动推断为 number
15
+ * frameInterval({
16
+ * condition: (state) => state.times,
17
+ * runner: (state) => state.data.toFixed(2),
18
+ * })
19
+ * ```
20
+ *
8
21
  * @param options - 配置选项
9
22
  * @returns {TimerHandler} 返回包含控制方法的对象
10
23
  */
11
- function frameInterval(callback, options) {
24
+ function frameInterval(options) {
25
+ const { runner, condition, leading, trailing } = options;
12
26
  let rafId;
13
- const { canStart, start, canStop, stop, canPause, pause, canResume, resume, execute } = (0, _cloudcome_utils_core_timer.makeInterval)((call) => {
14
- rafId = requestAnimationFrame(call);
15
- }, callback);
27
+ const { canStart, start, canStop, stop, canPause, pause, canResume, resume, execute } = (0, _cloudcome_utils_core_timer.makeInterval)({
28
+ dispatcher: (call) => {
29
+ rafId = requestAnimationFrame(call);
30
+ },
31
+ runner,
32
+ condition,
33
+ leading: leading ?? false,
34
+ trailing
35
+ });
16
36
  return {
17
37
  start() {
18
38
  if (!canStart()) return;
19
- if (options?.leading) start();
20
- else rafId = requestAnimationFrame(start);
39
+ start();
21
40
  },
22
41
  stop() {
23
42
  if (!canStop()) return;
24
- if (options?.trailing) execute();
25
- cancelAnimationFrame(rafId);
26
43
  stop();
44
+ cancelAnimationFrame(rafId);
27
45
  },
28
46
  pause() {
29
47
  if (!canPause()) return;
30
- if (options?.trailing) execute();
31
- cancelAnimationFrame(rafId);
32
48
  pause();
49
+ cancelAnimationFrame(rafId);
33
50
  },
34
51
  resume(immediate) {
35
52
  if (!canResume()) return;
36
- if (immediate || options?.leading) resume();
37
- else rafId = requestAnimationFrame(resume);
53
+ if (immediate || leading) resume();
54
+ else rafId = requestAnimationFrame(() => resume());
55
+ },
56
+ execute() {
57
+ cancelAnimationFrame(rafId);
58
+ execute();
38
59
  }
39
60
  };
40
61
  }
@@ -1 +1 @@
1
- {"version":3,"file":"timer.cjs","names":[],"sources":["../src/timer.ts"],"sourcesContent":["import {\n makeInterval,\n type TimerHandler,\n type TimerOptions,\n type TimerState,\n} from '@cloudcome/utils-core/timer';\n\n/**\n * 创建一个基于 `requestAnimationFrame` 的间隔定时器\n *\n * @param callback - 每次间隔执行的回调函数,接收定时器状态和可选的 `next` 函数\n * @param options - 配置选项\n * @returns {TimerHandler} 返回包含控制方法的对象\n */\nexport function frameInterval(\n callback: (state: TimerState, next?: () => void) => unknown,\n options?: TimerOptions,\n): TimerHandler {\n let rafId: number;\n const {\n canStart,\n start,\n canStop,\n stop,\n canPause,\n pause,\n canResume,\n resume,\n execute,\n } = makeInterval((call) => {\n rafId = requestAnimationFrame(call);\n }, callback);\n\n return {\n start() {\n if (!canStart()) return;\n\n if (options?.leading) {\n start();\n } else {\n rafId = requestAnimationFrame(start);\n }\n },\n\n stop() {\n if (!canStop()) return;\n if (options?.trailing) execute();\n\n cancelAnimationFrame(rafId);\n stop();\n },\n\n pause() {\n if (!canPause()) return;\n if (options?.trailing) execute();\n\n cancelAnimationFrame(rafId);\n pause();\n },\n\n resume(immediate?: boolean) {\n if (!canResume()) return;\n\n if (immediate || options?.leading) {\n resume();\n } else {\n rafId = requestAnimationFrame(resume);\n }\n },\n };\n}\n"],"mappings":";;;;;;;;;;AAcA,SAAgB,cACd,UACA,SACc;CACd,IAAI;CACJ,MAAM,EACJ,UACA,OACA,SACA,MACA,UACA,OACA,WACA,QACA,aAAA,GAAA,4BAAA,eACgB,SAAS;EACzB,QAAQ,sBAAsB,KAAK;IAClC,SAAS;CAEZ,OAAO;EACL,QAAQ;GACN,IAAI,CAAC,UAAU,EAAE;GAEjB,IAAI,SAAS,SACX,OAAO;QAEP,QAAQ,sBAAsB,MAAM;;EAIxC,OAAO;GACL,IAAI,CAAC,SAAS,EAAE;GAChB,IAAI,SAAS,UAAU,SAAS;GAEhC,qBAAqB,MAAM;GAC3B,MAAM;;EAGR,QAAQ;GACN,IAAI,CAAC,UAAU,EAAE;GACjB,IAAI,SAAS,UAAU,SAAS;GAEhC,qBAAqB,MAAM;GAC3B,OAAO;;EAGT,OAAO,WAAqB;GAC1B,IAAI,CAAC,WAAW,EAAE;GAElB,IAAI,aAAa,SAAS,SACxB,QAAQ;QAER,QAAQ,sBAAsB,OAAO;;EAG1C"}
1
+ {"version":3,"file":"timer.cjs","names":[],"sources":["../src/timer.ts"],"sourcesContent":["import {\n makeInterval,\n type TimerHandler,\n type TimerStateBase,\n type TimerState,\n type MakeIntervalOptions,\n} from '@cloudcome/utils-core/timer';\nimport type { MaybePromise } from '@cloudcome/utils-core/types';\n\n/**\n * frameInterval 配置选项\n * @template T - condition 函数返回值类型\n */\nexport type FrameIntervalOptions<T> = {\n /**\n * 条件函数,每次执行前调用,返回值存入 state.data\n * 支持同步或异步返回值\n * 抛错时跳过本次 runner 执行,继续下一次调度\n */\n condition?: (state: TimerStateBase) => MaybePromise<T>;\n /**\n * 执行函数,每次 requestAnimationFrame 触发时调用,接收完整的定时器状态\n * @param next - 可选的手动触发下一次调度的函数\n */\n runner: (state: TimerState<Awaited<T>>, next?: () => void) => unknown;\n /**\n * 是否在定时器启动时立即执行一次,默认为 false\n */\n leading?: boolean;\n /**\n * 是否在定时器停止或暂停时额外执行一次(trailing edge)\n */\n trailing?: boolean;\n};\n\n/**\n * 创建一个基于 `requestAnimationFrame` 的间隔定时器\n *\n * @example\n * ```typescript\n * // 无 condition\n * frameInterval({\n * runner: (state) => console.log(state.times),\n * })\n *\n * // 有 condition,T 自动推断为 number\n * frameInterval({\n * condition: (state) => state.times,\n * runner: (state) => state.data.toFixed(2),\n * })\n * ```\n *\n * @param options - 配置选项\n * @returns {TimerHandler} 返回包含控制方法的对象\n */\nexport function frameInterval<T = null>(options: FrameIntervalOptions<T>): TimerHandler {\n const { runner, condition, leading, trailing } = options;\n let rafId: number;\n const { canStart, start, canStop, stop, canPause, pause, canResume, resume, execute } = makeInterval({\n dispatcher: (call) => {\n rafId = requestAnimationFrame(call);\n },\n runner: runner as MakeIntervalOptions<T>['runner'],\n condition,\n leading: leading ?? false,\n trailing,\n });\n\n return {\n start() {\n if (!canStart()) return;\n start();\n },\n\n stop() {\n if (!canStop()) return;\n stop();\n cancelAnimationFrame(rafId);\n },\n\n pause() {\n if (!canPause()) return;\n pause();\n cancelAnimationFrame(rafId);\n },\n\n resume(immediate?: boolean) {\n if (!canResume()) return;\n if (immediate || leading) {\n resume();\n } else {\n rafId = requestAnimationFrame(() => resume());\n }\n },\n\n execute() {\n cancelAnimationFrame(rafId);\n execute();\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAuDA,SAAgB,cAAwB,SAAgD;CACtF,MAAM,EAAE,QAAQ,WAAW,SAAS,aAAa;CACjD,IAAI;CACJ,MAAM,EAAE,UAAU,OAAO,SAAS,MAAM,UAAU,OAAO,WAAW,QAAQ,aAAA,GAAA,4BAAA,cAAyB;EACnG,aAAa,SAAS;GACpB,QAAQ,sBAAsB,KAAK;;EAE7B;EACR;EACA,SAAS,WAAW;EACpB;EACD,CAAC;CAEF,OAAO;EACL,QAAQ;GACN,IAAI,CAAC,UAAU,EAAE;GACjB,OAAO;;EAGT,OAAO;GACL,IAAI,CAAC,SAAS,EAAE;GAChB,MAAM;GACN,qBAAqB,MAAM;;EAG7B,QAAQ;GACN,IAAI,CAAC,UAAU,EAAE;GACjB,OAAO;GACP,qBAAqB,MAAM;;EAG7B,OAAO,WAAqB;GAC1B,IAAI,CAAC,WAAW,EAAE;GAClB,IAAI,aAAa,SACf,QAAQ;QAER,QAAQ,4BAA4B,QAAQ,CAAC;;EAIjD,UAAU;GACR,qBAAqB,MAAM;GAC3B,SAAS;;EAEZ"}
package/dist/timer.d.ts CHANGED
@@ -1,9 +1,48 @@
1
- import { TimerHandler, TimerOptions, TimerState } from '@cloudcome/utils-core/timer';
1
+ import { TimerHandler, TimerStateBase, TimerState } from '@cloudcome/utils-core/timer';
2
+ import { MaybePromise } from '@cloudcome/utils-core/types';
3
+ /**
4
+ * frameInterval 配置选项
5
+ * @template T - condition 函数返回值类型
6
+ */
7
+ export type FrameIntervalOptions<T> = {
8
+ /**
9
+ * 条件函数,每次执行前调用,返回值存入 state.data
10
+ * 支持同步或异步返回值
11
+ * 抛错时跳过本次 runner 执行,继续下一次调度
12
+ */
13
+ condition?: (state: TimerStateBase) => MaybePromise<T>;
14
+ /**
15
+ * 执行函数,每次 requestAnimationFrame 触发时调用,接收完整的定时器状态
16
+ * @param next - 可选的手动触发下一次调度的函数
17
+ */
18
+ runner: (state: TimerState<Awaited<T>>, next?: () => void) => unknown;
19
+ /**
20
+ * 是否在定时器启动时立即执行一次,默认为 false
21
+ */
22
+ leading?: boolean;
23
+ /**
24
+ * 是否在定时器停止或暂停时额外执行一次(trailing edge)
25
+ */
26
+ trailing?: boolean;
27
+ };
2
28
  /**
3
29
  * 创建一个基于 `requestAnimationFrame` 的间隔定时器
4
30
  *
5
- * @param callback - 每次间隔执行的回调函数,接收定时器状态和可选的 `next` 函数
31
+ * @example
32
+ * ```typescript
33
+ * // 无 condition
34
+ * frameInterval({
35
+ * runner: (state) => console.log(state.times),
36
+ * })
37
+ *
38
+ * // 有 condition,T 自动推断为 number
39
+ * frameInterval({
40
+ * condition: (state) => state.times,
41
+ * runner: (state) => state.data.toFixed(2),
42
+ * })
43
+ * ```
44
+ *
6
45
  * @param options - 配置选项
7
46
  * @returns {TimerHandler} 返回包含控制方法的对象
8
47
  */
9
- export declare function frameInterval(callback: (state: TimerState, next?: () => void) => unknown, options?: TimerOptions): TimerHandler;
48
+ export declare function frameInterval<T = null>(options: FrameIntervalOptions<T>): TimerHandler;
package/dist/timer.mjs CHANGED
@@ -3,37 +3,58 @@ import { makeInterval } from "@cloudcome/utils-core/timer";
3
3
  /**
4
4
  * 创建一个基于 `requestAnimationFrame` 的间隔定时器
5
5
  *
6
- * @param callback - 每次间隔执行的回调函数,接收定时器状态和可选的 `next` 函数
6
+ * @example
7
+ * ```typescript
8
+ * // 无 condition
9
+ * frameInterval({
10
+ * runner: (state) => console.log(state.times),
11
+ * })
12
+ *
13
+ * // 有 condition,T 自动推断为 number
14
+ * frameInterval({
15
+ * condition: (state) => state.times,
16
+ * runner: (state) => state.data.toFixed(2),
17
+ * })
18
+ * ```
19
+ *
7
20
  * @param options - 配置选项
8
21
  * @returns {TimerHandler} 返回包含控制方法的对象
9
22
  */
10
- function frameInterval(callback, options) {
23
+ function frameInterval(options) {
24
+ const { runner, condition, leading, trailing } = options;
11
25
  let rafId;
12
- const { canStart, start, canStop, stop, canPause, pause, canResume, resume, execute } = makeInterval((call) => {
13
- rafId = requestAnimationFrame(call);
14
- }, callback);
26
+ const { canStart, start, canStop, stop, canPause, pause, canResume, resume, execute } = makeInterval({
27
+ dispatcher: (call) => {
28
+ rafId = requestAnimationFrame(call);
29
+ },
30
+ runner,
31
+ condition,
32
+ leading: leading ?? false,
33
+ trailing
34
+ });
15
35
  return {
16
36
  start() {
17
37
  if (!canStart()) return;
18
- if (options?.leading) start();
19
- else rafId = requestAnimationFrame(start);
38
+ start();
20
39
  },
21
40
  stop() {
22
41
  if (!canStop()) return;
23
- if (options?.trailing) execute();
24
- cancelAnimationFrame(rafId);
25
42
  stop();
43
+ cancelAnimationFrame(rafId);
26
44
  },
27
45
  pause() {
28
46
  if (!canPause()) return;
29
- if (options?.trailing) execute();
30
- cancelAnimationFrame(rafId);
31
47
  pause();
48
+ cancelAnimationFrame(rafId);
32
49
  },
33
50
  resume(immediate) {
34
51
  if (!canResume()) return;
35
- if (immediate || options?.leading) resume();
36
- else rafId = requestAnimationFrame(resume);
52
+ if (immediate || leading) resume();
53
+ else rafId = requestAnimationFrame(() => resume());
54
+ },
55
+ execute() {
56
+ cancelAnimationFrame(rafId);
57
+ execute();
37
58
  }
38
59
  };
39
60
  }
@@ -1 +1 @@
1
- {"version":3,"file":"timer.mjs","names":[],"sources":["../src/timer.ts"],"sourcesContent":["import {\n makeInterval,\n type TimerHandler,\n type TimerOptions,\n type TimerState,\n} from '@cloudcome/utils-core/timer';\n\n/**\n * 创建一个基于 `requestAnimationFrame` 的间隔定时器\n *\n * @param callback - 每次间隔执行的回调函数,接收定时器状态和可选的 `next` 函数\n * @param options - 配置选项\n * @returns {TimerHandler} 返回包含控制方法的对象\n */\nexport function frameInterval(\n callback: (state: TimerState, next?: () => void) => unknown,\n options?: TimerOptions,\n): TimerHandler {\n let rafId: number;\n const {\n canStart,\n start,\n canStop,\n stop,\n canPause,\n pause,\n canResume,\n resume,\n execute,\n } = makeInterval((call) => {\n rafId = requestAnimationFrame(call);\n }, callback);\n\n return {\n start() {\n if (!canStart()) return;\n\n if (options?.leading) {\n start();\n } else {\n rafId = requestAnimationFrame(start);\n }\n },\n\n stop() {\n if (!canStop()) return;\n if (options?.trailing) execute();\n\n cancelAnimationFrame(rafId);\n stop();\n },\n\n pause() {\n if (!canPause()) return;\n if (options?.trailing) execute();\n\n cancelAnimationFrame(rafId);\n pause();\n },\n\n resume(immediate?: boolean) {\n if (!canResume()) return;\n\n if (immediate || options?.leading) {\n resume();\n } else {\n rafId = requestAnimationFrame(resume);\n }\n },\n };\n}\n"],"mappings":";;;;;;;;;AAcA,SAAgB,cACd,UACA,SACc;CACd,IAAI;CACJ,MAAM,EACJ,UACA,OACA,SACA,MACA,UACA,OACA,WACA,QACA,YACE,cAAc,SAAS;EACzB,QAAQ,sBAAsB,KAAK;IAClC,SAAS;CAEZ,OAAO;EACL,QAAQ;GACN,IAAI,CAAC,UAAU,EAAE;GAEjB,IAAI,SAAS,SACX,OAAO;QAEP,QAAQ,sBAAsB,MAAM;;EAIxC,OAAO;GACL,IAAI,CAAC,SAAS,EAAE;GAChB,IAAI,SAAS,UAAU,SAAS;GAEhC,qBAAqB,MAAM;GAC3B,MAAM;;EAGR,QAAQ;GACN,IAAI,CAAC,UAAU,EAAE;GACjB,IAAI,SAAS,UAAU,SAAS;GAEhC,qBAAqB,MAAM;GAC3B,OAAO;;EAGT,OAAO,WAAqB;GAC1B,IAAI,CAAC,WAAW,EAAE;GAElB,IAAI,aAAa,SAAS,SACxB,QAAQ;QAER,QAAQ,sBAAsB,OAAO;;EAG1C"}
1
+ {"version":3,"file":"timer.mjs","names":[],"sources":["../src/timer.ts"],"sourcesContent":["import {\n makeInterval,\n type TimerHandler,\n type TimerStateBase,\n type TimerState,\n type MakeIntervalOptions,\n} from '@cloudcome/utils-core/timer';\nimport type { MaybePromise } from '@cloudcome/utils-core/types';\n\n/**\n * frameInterval 配置选项\n * @template T - condition 函数返回值类型\n */\nexport type FrameIntervalOptions<T> = {\n /**\n * 条件函数,每次执行前调用,返回值存入 state.data\n * 支持同步或异步返回值\n * 抛错时跳过本次 runner 执行,继续下一次调度\n */\n condition?: (state: TimerStateBase) => MaybePromise<T>;\n /**\n * 执行函数,每次 requestAnimationFrame 触发时调用,接收完整的定时器状态\n * @param next - 可选的手动触发下一次调度的函数\n */\n runner: (state: TimerState<Awaited<T>>, next?: () => void) => unknown;\n /**\n * 是否在定时器启动时立即执行一次,默认为 false\n */\n leading?: boolean;\n /**\n * 是否在定时器停止或暂停时额外执行一次(trailing edge)\n */\n trailing?: boolean;\n};\n\n/**\n * 创建一个基于 `requestAnimationFrame` 的间隔定时器\n *\n * @example\n * ```typescript\n * // 无 condition\n * frameInterval({\n * runner: (state) => console.log(state.times),\n * })\n *\n * // 有 condition,T 自动推断为 number\n * frameInterval({\n * condition: (state) => state.times,\n * runner: (state) => state.data.toFixed(2),\n * })\n * ```\n *\n * @param options - 配置选项\n * @returns {TimerHandler} 返回包含控制方法的对象\n */\nexport function frameInterval<T = null>(options: FrameIntervalOptions<T>): TimerHandler {\n const { runner, condition, leading, trailing } = options;\n let rafId: number;\n const { canStart, start, canStop, stop, canPause, pause, canResume, resume, execute } = makeInterval({\n dispatcher: (call) => {\n rafId = requestAnimationFrame(call);\n },\n runner: runner as MakeIntervalOptions<T>['runner'],\n condition,\n leading: leading ?? false,\n trailing,\n });\n\n return {\n start() {\n if (!canStart()) return;\n start();\n },\n\n stop() {\n if (!canStop()) return;\n stop();\n cancelAnimationFrame(rafId);\n },\n\n pause() {\n if (!canPause()) return;\n pause();\n cancelAnimationFrame(rafId);\n },\n\n resume(immediate?: boolean) {\n if (!canResume()) return;\n if (immediate || leading) {\n resume();\n } else {\n rafId = requestAnimationFrame(() => resume());\n }\n },\n\n execute() {\n cancelAnimationFrame(rafId);\n execute();\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAuDA,SAAgB,cAAwB,SAAgD;CACtF,MAAM,EAAE,QAAQ,WAAW,SAAS,aAAa;CACjD,IAAI;CACJ,MAAM,EAAE,UAAU,OAAO,SAAS,MAAM,UAAU,OAAO,WAAW,QAAQ,YAAY,aAAa;EACnG,aAAa,SAAS;GACpB,QAAQ,sBAAsB,KAAK;;EAE7B;EACR;EACA,SAAS,WAAW;EACpB;EACD,CAAC;CAEF,OAAO;EACL,QAAQ;GACN,IAAI,CAAC,UAAU,EAAE;GACjB,OAAO;;EAGT,OAAO;GACL,IAAI,CAAC,SAAS,EAAE;GAChB,MAAM;GACN,qBAAqB,MAAM;;EAG7B,QAAQ;GACN,IAAI,CAAC,UAAU,EAAE;GACjB,OAAO;GACP,qBAAqB,MAAM;;EAG7B,OAAO,WAAqB;GAC1B,IAAI,CAAC,WAAW,EAAE;GAClB,IAAI,aAAa,SACf,QAAQ;QAER,QAAQ,4BAA4B,QAAQ,CAAC;;EAIjD,UAAU;GACR,qBAAqB,MAAM;GAC3B,SAAS;;EAEZ"}
package/dist/video.cjs CHANGED
@@ -13,7 +13,8 @@ async function videoLoad(url) {
13
13
  const video = document.createElement("video");
14
14
  const onFinish = (isError) => {
15
15
  video.onload = video.onerror = null;
16
- isError ? reject(/* @__PURE__ */ new Error("视频加载失败")) : resolve(video);
16
+ if (isError) reject(/* @__PURE__ */ new Error("视频加载失败"));
17
+ else resolve(video);
17
18
  };
18
19
  video.src = url;
19
20
  video.crossOrigin = "anonymous";
@@ -1 +1 @@
1
- {"version":3,"file":"video.cjs","names":[],"sources":["../src/video.ts"],"sourcesContent":["/**\n * 加载视频并返回一个包含 HTMLVideoElement 的 Promise\n * @param {string} url - 视频的 URL 地址\n * @returns {Promise<HTMLVideoElement>} 返回一个包含 HTMLVideoElement 的 Promise\n * @example\n * const video = await videoLoad('https://example.com/video.mp4');\n * @throws {Error} 如果视频加载失败,抛出错误\n */\nexport async function videoLoad(url: string) {\n return new Promise<HTMLVideoElement>((resolve, reject) => {\n const video = document.createElement('video');\n const onFinish = (isError?: boolean) => {\n video.onload = video.onerror = null;\n isError ? reject(new Error('视频加载失败')) : resolve(video);\n };\n\n video.src = url;\n video.crossOrigin = 'anonymous';\n video.currentTime = 1;\n video.onloadedmetadata = () => onFinish();\n video.onerror = () => onFinish(true);\n });\n}\n"],"mappings":";;;;;;;;;;AAQA,eAAsB,UAAU,KAAa;CAC3C,OAAO,IAAI,SAA2B,SAAS,WAAW;EACxD,MAAM,QAAQ,SAAS,cAAc,QAAQ;EAC7C,MAAM,YAAY,YAAsB;GACtC,MAAM,SAAS,MAAM,UAAU;GAC/B,UAAU,uBAAO,IAAI,MAAM,SAAS,CAAC,GAAG,QAAQ,MAAM;;EAGxD,MAAM,MAAM;EACZ,MAAM,cAAc;EACpB,MAAM,cAAc;EACpB,MAAM,yBAAyB,UAAU;EACzC,MAAM,gBAAgB,SAAS,KAAK;GACpC"}
1
+ {"version":3,"file":"video.cjs","names":[],"sources":["../src/video.ts"],"sourcesContent":["/**\n * 加载视频并返回一个包含 HTMLVideoElement 的 Promise\n * @param {string} url - 视频的 URL 地址\n * @returns {Promise<HTMLVideoElement>} 返回一个包含 HTMLVideoElement 的 Promise\n * @example\n * const video = await videoLoad('https://example.com/video.mp4');\n * @throws {Error} 如果视频加载失败,抛出错误\n */\nexport async function videoLoad(url: string) {\n return new Promise<HTMLVideoElement>((resolve, reject) => {\n const video = document.createElement('video');\n const onFinish = (isError?: boolean) => {\n video.onload = video.onerror = null;\n if (isError) {\n reject(new Error('视频加载失败'));\n } else {\n resolve(video);\n }\n };\n\n video.src = url;\n video.crossOrigin = 'anonymous';\n video.currentTime = 1;\n video.onloadedmetadata = () => onFinish();\n video.onerror = () => onFinish(true);\n });\n}\n"],"mappings":";;;;;;;;;;AAQA,eAAsB,UAAU,KAAa;CAC3C,OAAO,IAAI,SAA2B,SAAS,WAAW;EACxD,MAAM,QAAQ,SAAS,cAAc,QAAQ;EAC7C,MAAM,YAAY,YAAsB;GACtC,MAAM,SAAS,MAAM,UAAU;GAC/B,IAAI,SACF,uBAAO,IAAI,MAAM,SAAS,CAAC;QAE3B,QAAQ,MAAM;;EAIlB,MAAM,MAAM;EACZ,MAAM,cAAc;EACpB,MAAM,cAAc;EACpB,MAAM,yBAAyB,UAAU;EACzC,MAAM,gBAAgB,SAAS,KAAK;GACpC"}
package/dist/video.mjs CHANGED
@@ -12,7 +12,8 @@ async function videoLoad(url) {
12
12
  const video = document.createElement("video");
13
13
  const onFinish = (isError) => {
14
14
  video.onload = video.onerror = null;
15
- isError ? reject(/* @__PURE__ */ new Error("视频加载失败")) : resolve(video);
15
+ if (isError) reject(/* @__PURE__ */ new Error("视频加载失败"));
16
+ else resolve(video);
16
17
  };
17
18
  video.src = url;
18
19
  video.crossOrigin = "anonymous";
@@ -1 +1 @@
1
- {"version":3,"file":"video.mjs","names":[],"sources":["../src/video.ts"],"sourcesContent":["/**\n * 加载视频并返回一个包含 HTMLVideoElement 的 Promise\n * @param {string} url - 视频的 URL 地址\n * @returns {Promise<HTMLVideoElement>} 返回一个包含 HTMLVideoElement 的 Promise\n * @example\n * const video = await videoLoad('https://example.com/video.mp4');\n * @throws {Error} 如果视频加载失败,抛出错误\n */\nexport async function videoLoad(url: string) {\n return new Promise<HTMLVideoElement>((resolve, reject) => {\n const video = document.createElement('video');\n const onFinish = (isError?: boolean) => {\n video.onload = video.onerror = null;\n isError ? reject(new Error('视频加载失败')) : resolve(video);\n };\n\n video.src = url;\n video.crossOrigin = 'anonymous';\n video.currentTime = 1;\n video.onloadedmetadata = () => onFinish();\n video.onerror = () => onFinish(true);\n });\n}\n"],"mappings":";;;;;;;;;AAQA,eAAsB,UAAU,KAAa;CAC3C,OAAO,IAAI,SAA2B,SAAS,WAAW;EACxD,MAAM,QAAQ,SAAS,cAAc,QAAQ;EAC7C,MAAM,YAAY,YAAsB;GACtC,MAAM,SAAS,MAAM,UAAU;GAC/B,UAAU,uBAAO,IAAI,MAAM,SAAS,CAAC,GAAG,QAAQ,MAAM;;EAGxD,MAAM,MAAM;EACZ,MAAM,cAAc;EACpB,MAAM,cAAc;EACpB,MAAM,yBAAyB,UAAU;EACzC,MAAM,gBAAgB,SAAS,KAAK;GACpC"}
1
+ {"version":3,"file":"video.mjs","names":[],"sources":["../src/video.ts"],"sourcesContent":["/**\n * 加载视频并返回一个包含 HTMLVideoElement 的 Promise\n * @param {string} url - 视频的 URL 地址\n * @returns {Promise<HTMLVideoElement>} 返回一个包含 HTMLVideoElement 的 Promise\n * @example\n * const video = await videoLoad('https://example.com/video.mp4');\n * @throws {Error} 如果视频加载失败,抛出错误\n */\nexport async function videoLoad(url: string) {\n return new Promise<HTMLVideoElement>((resolve, reject) => {\n const video = document.createElement('video');\n const onFinish = (isError?: boolean) => {\n video.onload = video.onerror = null;\n if (isError) {\n reject(new Error('视频加载失败'));\n } else {\n resolve(video);\n }\n };\n\n video.src = url;\n video.crossOrigin = 'anonymous';\n video.currentTime = 1;\n video.onloadedmetadata = () => onFinish();\n video.onerror = () => onFinish(true);\n });\n}\n"],"mappings":";;;;;;;;;AAQA,eAAsB,UAAU,KAAa;CAC3C,OAAO,IAAI,SAA2B,SAAS,WAAW;EACxD,MAAM,QAAQ,SAAS,cAAc,QAAQ;EAC7C,MAAM,YAAY,YAAsB;GACtC,MAAM,SAAS,MAAM,UAAU;GAC/B,IAAI,SACF,uBAAO,IAAI,MAAM,SAAS,CAAC;QAE3B,QAAQ,MAAM;;EAIlB,MAAM,MAAM;EACZ,MAAM,cAAc;EACpB,MAAM,cAAc;EACpB,MAAM,yBAAyB,UAAU;EACzC,MAAM,gBAAgB,SAAS,KAAK;GACpC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudcome/utils-browser",
3
- "version": "1.2.17",
3
+ "version": "1.3.0",
4
4
  "description": "cloudcome utils for browser",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",
@@ -105,19 +105,19 @@
105
105
  "node": ">=22"
106
106
  },
107
107
  "dependencies": {
108
- "@cloudcome/utils-core": "~1.20.0"
108
+ "@cloudcome/utils-core": "~1.21.0"
109
109
  },
110
110
  "keywords": [
111
- "utils",
112
111
  "cloudcome",
112
+ "utils",
113
+ "utils-browser",
113
114
  "utils-core",
114
- "utils-vue",
115
+ "utils-node",
115
116
  "utils-react",
116
117
  "utils-uni",
117
- "utils-node",
118
- "utils-browser"
118
+ "utils-vue"
119
119
  ],
120
- "homepage": "https://github.com/cloudcome/utils",
120
+ "homepage": "https://cloudcome.github.io/utils/",
121
121
  "license": "MIT",
122
122
  "author": "云淡然 <hi@ydr.me> (https://ydr.me/)",
123
123
  "repository": {