@fast-china/utils 2.1.5 → 2.1.6

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/dist/index.mjs CHANGED
@@ -13,12 +13,18 @@ import { camelCase, copy, decodeURIComponentRepeatedly, escapeHtml, generateUuid
13
13
  import { configureInstallationIdentity, getOrCreateInstallationId, installationIdentity } from "./identity/index.mjs";
14
14
  import { configureLogger, createLogger, logger } from "./logger/index.mjs";
15
15
  import { cloneDeep, hasOwn, isEqual, isPlainObject, mapValues, omit, omitBy, pick, pickBy, shallowEqual, toQueryString } from "./object/index.mjs";
16
+ import { useEventListener } from "./vue/event-listener.mjs";
17
+ import { useBreakpoints } from "./vue/breakpoints.mjs";
18
+ import { useResizeObserver } from "./vue/resize-observer.mjs";
19
+ import { useElementSize } from "./vue/element-size.mjs";
16
20
  import { useEmits } from "./vue/emits.mjs";
17
21
  import { useExpose } from "./vue/expose.mjs";
18
22
  import { callOptionalFunction } from "./vue/func.mjs";
19
23
  import { withInstall, withInstallDirective, withNoopInstall } from "./vue/install.mjs";
24
+ import { useNow } from "./vue/now.mjs";
20
25
  import { definePropType, useProps } from "./vue/props.mjs";
21
26
  import { useRender } from "./vue/render.mjs";
22
27
  import { makeSlots } from "./vue/slots.mjs";
28
+ import { useWindowSize } from "./vue/window-size.mjs";
23
29
  import { withDefineType } from "./vue/with.mjs";
24
- export { AESDecrypt, AESDecryptAuthenticated, AESDecryptWithPassword, AESEncrypt, AESEncryptAuthenticated, AESEncryptWithPassword, DeriveECDHKeySHA256, DeriveECDHSecret, ECDSASign, ECDSAVerify, FixedTimeEquals, GenerateECDHKeyPair, GenerateECDSAKeyPair, GenerateRSAKeyPair, GenerateRandomBytes, HKDFSHA256, HMACSHA256Encrypt, HMACSHA384Encrypt, HMACSHA512Encrypt, HashPasswordPBKDF2SHA256, Local, MD5Encrypt, PBKDF2SHA256, RSADecryptOAEP, RSAEncryptOAEP, RSASignPSS, RSAVerifyPSS, SHA1Encrypt, SHA256Bytes, SHA256Encrypt, SHA384Bytes, SHA384Encrypt, SHA512Bytes, SHA512Encrypt, Session, VerifyPasswordPBKDF2SHA256, addCssUnit, addDays, addMonths, addYears, allEqualBy, average, base64StorageCodec, callOptionalFunction, camelCase, chunk, clamp, cloneDeep, configureInstallationIdentity, configureLogger, configureStorage, contrastRatio, copy, createDateRangeShortcuts, createDateShortcuts, createLogger, createOneMonthRangeFromToday, debounce, decodeBase64, decodeBase64Bytes, decodeBase64Url, decodeBase64UrlBytes, decodeLatin1Base64, decodeSecureBase64, decodeURIComponentRepeatedly, definePropType, detectRuntime, difference, encodeBase64, encodeBase64Bytes, encodeBase64Url, encodeBase64UrlBytes, encodeLatin1Base64, encodeSecureBase64, endOfDay, escapeHtml, formatBytes, formatChineseRelativeTime, formatHexColor, formatRelativeTime, generateUuidV4, getLocalDayBounds, getLocalTimeGreeting, getOrCreateInstallationId, getStartOfToday, groupBy, hasDuplicatesBy, hasOwn, hasWebCrypto, inRange, installationIdentity, intersection, isBrowser, isDateAfterNow, isEqual, isFuture, isMobileUserAgent, isNode, isPlainObject, isSameDay, isStorageConfigured, isTabletUserAgent, isUniApp, isUuidV4, isValidDate, isValidJson, isWebWorker, isWithinInterval, kebabCase, lerp, logger, lowerFirst, makeSlots, mapConcurrent, mapValues, mixHexColorWithBlack, mixHexColorWithWhite, mixHexColors, normalizeWhitespace, omit, omitBy, once, parseHexColor, parseQueryString, partition, pascalCase, pick, pickBy, pickHigherContrastColor, randomInt, randomString, relativeLuminance, removeNullishValues, retry, roundTo, serializeStyle, shallowEqual, sleep, splitWords, startOfDay, sum, symmetricDifference, throttle, toDate, toQueryString, truncateGraphemes, unique, uniqueBy, upperFirst, useEmits, useExpose, useProps, useRender, withDefineType, withInstall, withInstallDirective, withNoopInstall, withTimeout };
30
+ export { AESDecrypt, AESDecryptAuthenticated, AESDecryptWithPassword, AESEncrypt, AESEncryptAuthenticated, AESEncryptWithPassword, DeriveECDHKeySHA256, DeriveECDHSecret, ECDSASign, ECDSAVerify, FixedTimeEquals, GenerateECDHKeyPair, GenerateECDSAKeyPair, GenerateRSAKeyPair, GenerateRandomBytes, HKDFSHA256, HMACSHA256Encrypt, HMACSHA384Encrypt, HMACSHA512Encrypt, HashPasswordPBKDF2SHA256, Local, MD5Encrypt, PBKDF2SHA256, RSADecryptOAEP, RSAEncryptOAEP, RSASignPSS, RSAVerifyPSS, SHA1Encrypt, SHA256Bytes, SHA256Encrypt, SHA384Bytes, SHA384Encrypt, SHA512Bytes, SHA512Encrypt, Session, VerifyPasswordPBKDF2SHA256, addCssUnit, addDays, addMonths, addYears, allEqualBy, average, base64StorageCodec, callOptionalFunction, camelCase, chunk, clamp, cloneDeep, configureInstallationIdentity, configureLogger, configureStorage, contrastRatio, copy, createDateRangeShortcuts, createDateShortcuts, createLogger, createOneMonthRangeFromToday, debounce, decodeBase64, decodeBase64Bytes, decodeBase64Url, decodeBase64UrlBytes, decodeLatin1Base64, decodeSecureBase64, decodeURIComponentRepeatedly, definePropType, detectRuntime, difference, encodeBase64, encodeBase64Bytes, encodeBase64Url, encodeBase64UrlBytes, encodeLatin1Base64, encodeSecureBase64, endOfDay, escapeHtml, formatBytes, formatChineseRelativeTime, formatHexColor, formatRelativeTime, generateUuidV4, getLocalDayBounds, getLocalTimeGreeting, getOrCreateInstallationId, getStartOfToday, groupBy, hasDuplicatesBy, hasOwn, hasWebCrypto, inRange, installationIdentity, intersection, isBrowser, isDateAfterNow, isEqual, isFuture, isMobileUserAgent, isNode, isPlainObject, isSameDay, isStorageConfigured, isTabletUserAgent, isUniApp, isUuidV4, isValidDate, isValidJson, isWebWorker, isWithinInterval, kebabCase, lerp, logger, lowerFirst, makeSlots, mapConcurrent, mapValues, mixHexColorWithBlack, mixHexColorWithWhite, mixHexColors, normalizeWhitespace, omit, omitBy, once, parseHexColor, parseQueryString, partition, pascalCase, pick, pickBy, pickHigherContrastColor, randomInt, randomString, relativeLuminance, removeNullishValues, retry, roundTo, serializeStyle, shallowEqual, sleep, splitWords, startOfDay, sum, symmetricDifference, throttle, toDate, toQueryString, truncateGraphemes, unique, uniqueBy, upperFirst, useBreakpoints, useElementSize, useEmits, useEventListener, useExpose, useNow, useProps, useRender, useResizeObserver, useWindowSize, withDefineType, withInstall, withInstallDirective, withNoopInstall, withTimeout };
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.mjs","names":[],"sources":["../../src/internal/runtime.ts"],"sourcesContent":["/** Web、Node、WebView 与 uni-app 宿主可能按需提供的运行时全局能力。 */\ninterface RuntimeGlobals {\n\treadonly Intl?: {\n\t\treadonly Segmenter?: typeof Intl.Segmenter;\n\t};\n\treadonly crypto?: Omit<Partial<Crypto>, \"subtle\"> & {\n\t\treadonly subtle?: Partial<SubtleCrypto>;\n\t};\n\treadonly document?: Partial<Document>;\n\treadonly importScripts?: unknown;\n\treadonly isSecureContext?: boolean;\n\treadonly localStorage?: Storage;\n\treadonly navigator?: Partial<Navigator>;\n\treadonly plus?: unknown;\n\treadonly process?: unknown;\n\treadonly sessionStorage?: Storage;\n\treadonly uni?: unknown;\n\treadonly window?: Partial<Window>;\n}\n\n/**\n * 以可选能力视图读取全局对象。\n *\n * @remarks TypeScript 的 DOM 声明假定浏览器全局始终存在,但本包也会在 Node、WebView\n * 和 uni-app 中运行。这里只放宽能力是否存在,不改变标准 API 的属性与方法类型。\n */\nexport const runtimeGlobals = globalThis as RuntimeGlobals;\n"],"mappings":";;;;;;;AA0BA,MAAa,iBAAiB"}
1
+ {"version":3,"file":"runtime.mjs","names":[],"sources":["../../src/internal/runtime.ts"],"sourcesContent":["/** Web、Node、WebView 与 uni-app 宿主可能按需提供的运行时全局能力。 */\ninterface RuntimeGlobals {\n\treadonly Intl?: {\n\t\treadonly Segmenter?: typeof Intl.Segmenter;\n\t};\n\treadonly crypto?: Omit<Partial<Crypto>, \"subtle\"> & {\n\t\treadonly subtle?: Partial<SubtleCrypto>;\n\t};\n\treadonly document?: Partial<Document>;\n\treadonly importScripts?: unknown;\n\treadonly isSecureContext?: boolean;\n\treadonly localStorage?: Storage;\n\treadonly navigator?: Partial<Navigator>;\n\treadonly plus?: unknown;\n\treadonly process?: unknown;\n\treadonly ResizeObserver?: typeof ResizeObserver;\n\treadonly sessionStorage?: Storage;\n\treadonly uni?: unknown;\n\treadonly window?: Window;\n}\n\n/**\n * 以可选能力视图读取全局对象。\n *\n * @remarks TypeScript 的 DOM 声明假定浏览器全局始终存在,但本包也会在 Node、WebView\n * 和 uni-app 中运行。这里只放宽能力是否存在,不改变标准 API 的属性与方法类型。\n */\nexport const runtimeGlobals = globalThis as RuntimeGlobals;\n"],"mappings":";;;;;;;AA2BA,MAAa,iBAAiB"}
@@ -0,0 +1,21 @@
1
+ import { ComputedRef, ShallowRef } from "vue";
2
+ //#region src/vue/breakpoints.d.ts
3
+ /** 断点名称与最小视口宽度的映射。 */
4
+ export type Breakpoints<Key extends string = string> = Readonly<Record<Key, number>>;
5
+ /** `useBreakpoints` 返回的断点状态。 */
6
+ export type UseBreakpointsReturn<Key extends string> = Readonly<Record<Key, Readonly<ShallowRef<boolean>>>> & {
7
+ /** 返回当前命中的最大断点名称。 */
8
+ active: () => ComputedRef<Key | "">;
9
+ };
10
+ /**
11
+ * 使用原生 Media Query 创建响应式最小宽度断点。
12
+ *
13
+ * @param breakpoints - 断点名称与非负像素宽度的映射。
14
+ * @returns 每个断点的只读状态和当前最大命中断点。
15
+ * @throws `Error` 当浏览器环境中不存在可用于自动清理的 Vue 响应式作用域。
16
+ * @throws `TypeError` 当断点使用保留名称 `active`。
17
+ * @throws `RangeError` 当断点宽度不是非负有限数值。
18
+ */
19
+ export declare function useBreakpoints<Key extends string>(breakpoints: Breakpoints<Key>): UseBreakpointsReturn<Key>;
20
+ //#endregion
21
+ //# sourceMappingURL=breakpoints.d.mts.map
@@ -0,0 +1,46 @@
1
+ import { runtimeGlobals } from "../internal/runtime.mjs";
2
+ import { useEventListener } from "./event-listener.mjs";
3
+ import { computed, getCurrentScope, readonly, shallowRef } from "vue";
4
+ //#region src/vue/breakpoints.ts
5
+ /**
6
+ * 使用原生 Media Query 创建响应式最小宽度断点。
7
+ *
8
+ * @param breakpoints - 断点名称与非负像素宽度的映射。
9
+ * @returns 每个断点的只读状态和当前最大命中断点。
10
+ * @throws `Error` 当浏览器环境中不存在可用于自动清理的 Vue 响应式作用域。
11
+ * @throws `TypeError` 当断点使用保留名称 `active`。
12
+ * @throws `RangeError` 当断点宽度不是非负有限数值。
13
+ */
14
+ function useBreakpoints(breakpoints) {
15
+ const entries = Object.entries(breakpoints);
16
+ entries.sort((left, right) => left[1] - right[1]);
17
+ for (const [name, minimumWidth] of entries) {
18
+ if (name === "active") throw new TypeError("断点名称不能使用保留名称“active”。");
19
+ if (!Number.isFinite(minimumWidth) || minimumWidth < 0) throw new RangeError(`断点“${name}”必须是非负有限数值。`);
20
+ }
21
+ const states = Object.create(null);
22
+ const window = runtimeGlobals.window;
23
+ if (window !== void 0 && getCurrentScope() === void 0) throw new Error("`useBreakpoints` 必须在 Vue 响应式作用域内调用。");
24
+ for (const [name, minimumWidth] of entries) {
25
+ const state = shallowRef(false);
26
+ if (window !== void 0 && typeof window.matchMedia === "function") {
27
+ const mediaQuery = window.matchMedia(`(min-width: ${minimumWidth}px)`);
28
+ const update = () => {
29
+ state.value = mediaQuery.matches;
30
+ };
31
+ update();
32
+ useEventListener(mediaQuery, "change", update);
33
+ }
34
+ states[name] = readonly(state);
35
+ }
36
+ const active = computed(() => {
37
+ let current = "";
38
+ for (const [name] of entries) if (states[name].value) current = name;
39
+ return current;
40
+ });
41
+ return Object.assign(states, { active: () => active });
42
+ }
43
+ //#endregion
44
+ export { useBreakpoints };
45
+
46
+ //# sourceMappingURL=breakpoints.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"breakpoints.mjs","names":[],"sources":["../../src/vue/breakpoints.ts"],"sourcesContent":["import { computed, getCurrentScope, readonly, shallowRef } from \"vue\";\nimport { runtimeGlobals } from \"../internal/runtime\";\nimport { useEventListener } from \"./event-listener\";\nimport type { ComputedRef, ShallowRef } from \"vue\";\n\n/** 断点名称与最小视口宽度的映射。 */\nexport type Breakpoints<Key extends string = string> = Readonly<Record<Key, number>>;\n\n/** `useBreakpoints` 返回的断点状态。 */\nexport type UseBreakpointsReturn<Key extends string> = Readonly<Record<Key, Readonly<ShallowRef<boolean>>>> & {\n\t/** 返回当前命中的最大断点名称。 */\n\tactive: () => ComputedRef<Key | \"\">;\n};\n\n/**\n * 使用原生 Media Query 创建响应式最小宽度断点。\n *\n * @param breakpoints - 断点名称与非负像素宽度的映射。\n * @returns 每个断点的只读状态和当前最大命中断点。\n * @throws `Error` 当浏览器环境中不存在可用于自动清理的 Vue 响应式作用域。\n * @throws `TypeError` 当断点使用保留名称 `active`。\n * @throws `RangeError` 当断点宽度不是非负有限数值。\n */\nexport function useBreakpoints<Key extends string>(breakpoints: Breakpoints<Key>): UseBreakpointsReturn<Key> {\n\tconst entries = Object.entries(breakpoints) as [Key, number][];\n\tentries.sort((left, right) => left[1] - right[1]);\n\tfor (const [name, minimumWidth] of entries) {\n\t\tif (name === \"active\") throw new TypeError(\"断点名称不能使用保留名称“active”。\");\n\t\tif (!Number.isFinite(minimumWidth) || minimumWidth < 0) throw new RangeError(`断点“${name}”必须是非负有限数值。`);\n\t}\n\tconst states = Object.create(null) as Record<Key, Readonly<ShallowRef<boolean>>>;\n\tconst window = runtimeGlobals.window;\n\tif (window !== undefined && getCurrentScope() === undefined) {\n\t\tthrow new Error(\"`useBreakpoints` 必须在 Vue 响应式作用域内调用。\");\n\t}\n\tfor (const [name, minimumWidth] of entries) {\n\t\tconst state = shallowRef(false);\n\t\tif (window !== undefined && typeof window.matchMedia === \"function\") {\n\t\t\tconst mediaQuery = window.matchMedia(`(min-width: ${minimumWidth}px)`);\n\t\t\tconst update = () => {\n\t\t\t\tstate.value = mediaQuery.matches;\n\t\t\t};\n\t\t\tupdate();\n\t\t\tuseEventListener(mediaQuery, \"change\", update);\n\t\t}\n\t\tstates[name] = readonly(state);\n\t}\n\tconst active = computed<Key | \"\">(() => {\n\t\tlet current: Key | \"\" = \"\";\n\t\tfor (const [name] of entries) {\n\t\t\tif (states[name].value) current = name;\n\t\t}\n\t\treturn current;\n\t});\n\treturn Object.assign(states, { active: () => active });\n}\n"],"mappings":";;;;;;;;;;;;;AAuBA,SAAgB,eAAmC,aAA0D;CAC5G,MAAM,UAAU,OAAO,QAAQ,WAAW;CAC1C,QAAQ,MAAM,MAAM,UAAU,KAAK,KAAK,MAAM,EAAE;CAChD,KAAK,MAAM,CAAC,MAAM,iBAAiB,SAAS;EAC3C,IAAI,SAAS,UAAU,MAAM,IAAI,UAAU,uBAAuB;EAClE,IAAI,CAAC,OAAO,SAAS,YAAY,KAAK,eAAe,GAAG,MAAM,IAAI,WAAW,MAAM,KAAK,YAAY;CACrG;CACA,MAAM,SAAS,OAAO,OAAO,IAAI;CACjC,MAAM,SAAS,eAAe;CAC9B,IAAI,WAAW,KAAA,KAAa,gBAAgB,MAAM,KAAA,GACjD,MAAM,IAAI,MAAM,qCAAqC;CAEtD,KAAK,MAAM,CAAC,MAAM,iBAAiB,SAAS;EAC3C,MAAM,QAAQ,WAAW,KAAK;EAC9B,IAAI,WAAW,KAAA,KAAa,OAAO,OAAO,eAAe,YAAY;GACpE,MAAM,aAAa,OAAO,WAAW,eAAe,aAAa,IAAI;GACrE,MAAM,eAAe;IACpB,MAAM,QAAQ,WAAW;GAC1B;GACA,OAAO;GACP,iBAAiB,YAAY,UAAU,MAAM;EAC9C;EACA,OAAO,QAAQ,SAAS,KAAK;CAC9B;CACA,MAAM,SAAS,eAAyB;EACvC,IAAI,UAAoB;EACxB,KAAK,MAAM,CAAC,SAAS,SACpB,IAAI,OAAO,KAAK,CAAC,OAAO,UAAU;EAEnC,OAAO;CACR,CAAC;CACD,OAAO,OAAO,OAAO,QAAQ,EAAE,cAAc,OAAO,CAAC;AACtD"}
@@ -0,0 +1,25 @@
1
+ import { ResizeObserverTarget } from "./resize-observer.mjs";
2
+ import { ShallowRef } from "vue";
3
+ //#region src/vue/element-size.d.ts
4
+ /** 元素的二维尺寸。 */
5
+ export interface ElementSize {
6
+ readonly width: number;
7
+ readonly height: number;
8
+ }
9
+ /** `useElementSize` 返回的响应式尺寸和停止函数。 */
10
+ export interface UseElementSizeReturn {
11
+ readonly width: Readonly<ShallowRef<number>>;
12
+ readonly height: Readonly<ShallowRef<number>>;
13
+ readonly stop: () => void;
14
+ }
15
+ /**
16
+ * 响应式读取元素 Content Rect 尺寸。
17
+ *
18
+ * @param target - 原生元素、Ref 或 Getter。
19
+ * @param initialSize - 收到首次观察结果前的尺寸,默认均为 `0`。
20
+ * @param options - 原生元素观察选项。
21
+ * @returns 只读宽度、高度和手动停止函数。
22
+ */
23
+ export declare function useElementSize(target: ResizeObserverTarget, initialSize?: ElementSize, options?: ResizeObserverOptions): UseElementSizeReturn;
24
+ //#endregion
25
+ //# sourceMappingURL=element-size.d.mts.map
@@ -0,0 +1,33 @@
1
+ import { useResizeObserver } from "./resize-observer.mjs";
2
+ import { readonly, shallowRef } from "vue";
3
+ //#region src/vue/element-size.ts
4
+ /**
5
+ * 响应式读取元素 Content Rect 尺寸。
6
+ *
7
+ * @param target - 原生元素、Ref 或 Getter。
8
+ * @param initialSize - 收到首次观察结果前的尺寸,默认均为 `0`。
9
+ * @param options - 原生元素观察选项。
10
+ * @returns 只读宽度、高度和手动停止函数。
11
+ */
12
+ function useElementSize(target, initialSize = {
13
+ height: 0,
14
+ width: 0
15
+ }, options) {
16
+ const width = shallowRef(initialSize.width);
17
+ const height = shallowRef(initialSize.height);
18
+ const stop = useResizeObserver(target, (entries) => {
19
+ const entry = entries[0];
20
+ if (entry === void 0) return;
21
+ width.value = entry.contentRect.width;
22
+ height.value = entry.contentRect.height;
23
+ }, options);
24
+ return {
25
+ height: readonly(height),
26
+ stop,
27
+ width: readonly(width)
28
+ };
29
+ }
30
+ //#endregion
31
+ export { useElementSize };
32
+
33
+ //# sourceMappingURL=element-size.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"element-size.mjs","names":[],"sources":["../../src/vue/element-size.ts"],"sourcesContent":["import { readonly, shallowRef } from \"vue\";\nimport { useResizeObserver } from \"./resize-observer\";\nimport type { ShallowRef } from \"vue\";\nimport type { ResizeObserverTarget } from \"./resize-observer\";\n\n/** 元素的二维尺寸。 */\nexport interface ElementSize {\n\treadonly width: number;\n\treadonly height: number;\n}\n\n/** `useElementSize` 返回的响应式尺寸和停止函数。 */\nexport interface UseElementSizeReturn {\n\treadonly width: Readonly<ShallowRef<number>>;\n\treadonly height: Readonly<ShallowRef<number>>;\n\treadonly stop: () => void;\n}\n\n/**\n * 响应式读取元素 Content Rect 尺寸。\n *\n * @param target - 原生元素、Ref 或 Getter。\n * @param initialSize - 收到首次观察结果前的尺寸,默认均为 `0`。\n * @param options - 原生元素观察选项。\n * @returns 只读宽度、高度和手动停止函数。\n */\nexport function useElementSize(\n\ttarget: ResizeObserverTarget,\n\tinitialSize: ElementSize = { height: 0, width: 0 },\n\toptions?: ResizeObserverOptions\n): UseElementSizeReturn {\n\tconst width = shallowRef(initialSize.width);\n\tconst height = shallowRef(initialSize.height);\n\tconst stop = useResizeObserver(\n\t\ttarget,\n\t\t(entries) => {\n\t\t\tconst entry = entries[0];\n\t\t\tif (entry === undefined) return;\n\t\t\twidth.value = entry.contentRect.width;\n\t\t\theight.value = entry.contentRect.height;\n\t\t},\n\t\toptions\n\t);\n\treturn { height: readonly(height), stop, width: readonly(width) };\n}\n"],"mappings":";;;;;;;;;;;AA0BA,SAAgB,eACf,QACA,cAA2B;CAAE,QAAQ;CAAG,OAAO;AAAE,GACjD,SACuB;CACvB,MAAM,QAAQ,WAAW,YAAY,KAAK;CAC1C,MAAM,SAAS,WAAW,YAAY,MAAM;CAC5C,MAAM,OAAO,kBACZ,SACC,YAAY;EACZ,MAAM,QAAQ,QAAQ;EACtB,IAAI,UAAU,KAAA,GAAW;EACzB,MAAM,QAAQ,MAAM,YAAY;EAChC,OAAO,QAAQ,MAAM,YAAY;CAClC,GACA,OACD;CACA,OAAO;EAAE,QAAQ,SAAS,MAAM;EAAG;EAAM,OAAO,SAAS,KAAK;CAAE;AACjE"}
@@ -0,0 +1,16 @@
1
+ import { MaybeRefOrGetter } from "vue";
2
+ //#region src/vue/event-listener.d.ts
3
+ /** `useEventListener` 接受的原生事件目标或响应式事件目标。 */
4
+ export type EventTargetSource = MaybeRefOrGetter<EventTarget | null | undefined>;
5
+ /**
6
+ * 注册原生事件监听器,并在目标变化或 Vue 作用域销毁时自动移除。
7
+ *
8
+ * @param target - 原生事件目标、Ref 或 Getter。
9
+ * @param event - 原生事件名称。
10
+ * @param listener - 事件回调。
11
+ * @param options - 原生事件监听选项。
12
+ * @returns 可提前移除监听器的停止函数。
13
+ */
14
+ export declare function useEventListener<EventType extends Event = Event>(target: EventTargetSource, event: string, listener: (event: EventType) => void, options?: boolean | AddEventListenerOptions): () => void;
15
+ //#endregion
16
+ //# sourceMappingURL=event-listener.d.mts.map
@@ -0,0 +1,30 @@
1
+ import { onScopeDispose, toValue, watch } from "vue";
2
+ //#region src/vue/event-listener.ts
3
+ /**
4
+ * 注册原生事件监听器,并在目标变化或 Vue 作用域销毁时自动移除。
5
+ *
6
+ * @param target - 原生事件目标、Ref 或 Getter。
7
+ * @param event - 原生事件名称。
8
+ * @param listener - 事件回调。
9
+ * @param options - 原生事件监听选项。
10
+ * @returns 可提前移除监听器的停止函数。
11
+ */
12
+ function useEventListener(target, event, listener, options) {
13
+ const eventListener = listener;
14
+ const stop = watch(() => toValue(target), (currentTarget, _previousTarget, onCleanup) => {
15
+ if (currentTarget === null || currentTarget === void 0) return;
16
+ currentTarget.addEventListener(event, eventListener, options);
17
+ onCleanup(() => {
18
+ currentTarget.removeEventListener(event, eventListener, options);
19
+ });
20
+ }, {
21
+ flush: "sync",
22
+ immediate: true
23
+ });
24
+ onScopeDispose(stop, true);
25
+ return stop;
26
+ }
27
+ //#endregion
28
+ export { useEventListener };
29
+
30
+ //# sourceMappingURL=event-listener.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-listener.mjs","names":[],"sources":["../../src/vue/event-listener.ts"],"sourcesContent":["import { onScopeDispose, toValue, watch } from \"vue\";\nimport type { MaybeRefOrGetter } from \"vue\";\n\n/** `useEventListener` 接受的原生事件目标或响应式事件目标。 */\nexport type EventTargetSource = MaybeRefOrGetter<EventTarget | null | undefined>;\n\n/**\n * 注册原生事件监听器,并在目标变化或 Vue 作用域销毁时自动移除。\n *\n * @param target - 原生事件目标、Ref 或 Getter。\n * @param event - 原生事件名称。\n * @param listener - 事件回调。\n * @param options - 原生事件监听选项。\n * @returns 可提前移除监听器的停止函数。\n */\nexport function useEventListener<EventType extends Event = Event>(\n\ttarget: EventTargetSource,\n\tevent: string,\n\tlistener: (event: EventType) => void,\n\toptions?: boolean | AddEventListenerOptions\n): () => void {\n\tconst eventListener = listener as EventListener;\n\tconst stop = watch(\n\t\t() => toValue(target),\n\t\t(currentTarget, _previousTarget, onCleanup) => {\n\t\t\tif (currentTarget === null || currentTarget === undefined) return;\n\t\t\tcurrentTarget.addEventListener(event, eventListener, options);\n\t\t\tonCleanup(() => {\n\t\t\t\tcurrentTarget.removeEventListener(event, eventListener, options);\n\t\t\t});\n\t\t},\n\t\t{ flush: \"sync\", immediate: true }\n\t);\n\tonScopeDispose(stop, true);\n\treturn stop;\n}\n"],"mappings":";;;;;;;;;;;AAeA,SAAgB,iBACf,QACA,OACA,UACA,SACa;CACb,MAAM,gBAAgB;CACtB,MAAM,OAAO,YACN,QAAQ,MAAM,IACnB,eAAe,iBAAiB,cAAc;EAC9C,IAAI,kBAAkB,QAAQ,kBAAkB,KAAA,GAAW;EAC3D,cAAc,iBAAiB,OAAO,eAAe,OAAO;EAC5D,gBAAgB;GACf,cAAc,oBAAoB,OAAO,eAAe,OAAO;EAChE,CAAC;CACF,GACA;EAAE,OAAO;EAAQ,WAAW;CAAK,CAClC;CACA,eAAe,MAAM,IAAI;CACzB,OAAO;AACR"}
@@ -1,9 +1,15 @@
1
+ import { Breakpoints, UseBreakpointsReturn, useBreakpoints } from "./breakpoints.mjs";
2
+ import { ResizeObserverTarget, useResizeObserver } from "./resize-observer.mjs";
3
+ import { ElementSize, UseElementSizeReturn, useElementSize } from "./element-size.mjs";
1
4
  import { EmitHandlers, useEmits } from "./emits.mjs";
5
+ import { EventTargetSource, useEventListener } from "./event-listener.mjs";
2
6
  import { useExpose } from "./expose.mjs";
3
7
  import { AwaitableFunction, callOptionalFunction } from "./func.mjs";
4
8
  import { Installable, TSXWithInstall, VueInstallValue, withInstall, withInstallDirective, withNoopInstall } from "./install.mjs";
9
+ import { useNow } from "./now.mjs";
5
10
  import { definePropType, useProps } from "./props.mjs";
6
11
  import { useRender } from "./render.mjs";
7
12
  import { TypedSlots, TypedSlotsDeclaration, makeSlots } from "./slots.mjs";
13
+ import { UseWindowSizeReturn, useWindowSize } from "./window-size.mjs";
8
14
  import { withDefineType } from "./with.mjs";
9
- export { AwaitableFunction, EmitHandlers, Installable, TSXWithInstall, TypedSlots, TypedSlotsDeclaration, VueInstallValue, callOptionalFunction, definePropType, makeSlots, useEmits, useExpose, useProps, useRender, withDefineType, withInstall, withInstallDirective, withNoopInstall };
15
+ export { AwaitableFunction, Breakpoints, ElementSize, EmitHandlers, EventTargetSource, Installable, ResizeObserverTarget, TSXWithInstall, TypedSlots, TypedSlotsDeclaration, UseBreakpointsReturn, UseElementSizeReturn, UseWindowSizeReturn, VueInstallValue, callOptionalFunction, definePropType, makeSlots, useBreakpoints, useElementSize, useEmits, useEventListener, useExpose, useNow, useProps, useRender, useResizeObserver, useWindowSize, withDefineType, withInstall, withInstallDirective, withNoopInstall };
@@ -0,0 +1,13 @@
1
+ import { ShallowRef } from "vue";
2
+ //#region src/vue/now.d.ts
3
+ /**
4
+ * 按固定间隔提供响应式当前时间。
5
+ *
6
+ * @param intervalMilliseconds - 更新时间间隔,默认 `1000` 毫秒。
7
+ * @returns 当前 Date 的只读 ShallowRef;SSR 环境只返回调用时的时间。
8
+ * @throws `Error` 当浏览器或 uni-app 环境中不存在可用于自动清理的 Vue 响应式作用域。
9
+ * @throws `RangeError` 当间隔不是平台计时器支持的非负有限整数。
10
+ */
11
+ export declare function useNow(intervalMilliseconds?: number): Readonly<ShallowRef<Date>>;
12
+ //#endregion
13
+ //# sourceMappingURL=now.d.mts.map
@@ -0,0 +1,29 @@
1
+ import { runtimeGlobals } from "../internal/runtime.mjs";
2
+ import { getCurrentScope, onScopeDispose, readonly, shallowRef } from "vue";
3
+ //#region src/vue/now.ts
4
+ /**
5
+ * 按固定间隔提供响应式当前时间。
6
+ *
7
+ * @param intervalMilliseconds - 更新时间间隔,默认 `1000` 毫秒。
8
+ * @returns 当前 Date 的只读 ShallowRef;SSR 环境只返回调用时的时间。
9
+ * @throws `Error` 当浏览器或 uni-app 环境中不存在可用于自动清理的 Vue 响应式作用域。
10
+ * @throws `RangeError` 当间隔不是平台计时器支持的非负有限整数。
11
+ */
12
+ function useNow(intervalMilliseconds = 1e3) {
13
+ if (!Number.isInteger(intervalMilliseconds) || intervalMilliseconds < 0 || intervalMilliseconds > 2147483647) throw new RangeError("`intervalMilliseconds` 必须是 0 至 2,147,483,647 的整数。");
14
+ const now = shallowRef(/* @__PURE__ */ new Date());
15
+ if (runtimeGlobals.window !== void 0 || runtimeGlobals.uni !== void 0) {
16
+ if (getCurrentScope() === void 0) throw new Error("`useNow` 必须在 Vue 响应式作用域内调用。");
17
+ const timer = setInterval(() => {
18
+ now.value = /* @__PURE__ */ new Date();
19
+ }, intervalMilliseconds);
20
+ onScopeDispose(() => {
21
+ clearInterval(timer);
22
+ });
23
+ }
24
+ return readonly(now);
25
+ }
26
+ //#endregion
27
+ export { useNow };
28
+
29
+ //# sourceMappingURL=now.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"now.mjs","names":[],"sources":["../../src/vue/now.ts"],"sourcesContent":["import { getCurrentScope, onScopeDispose, readonly, shallowRef } from \"vue\";\nimport { runtimeGlobals } from \"../internal/runtime\";\nimport type { ShallowRef } from \"vue\";\n\n/**\n * 按固定间隔提供响应式当前时间。\n *\n * @param intervalMilliseconds - 更新时间间隔,默认 `1000` 毫秒。\n * @returns 当前 Date 的只读 ShallowRef;SSR 环境只返回调用时的时间。\n * @throws `Error` 当浏览器或 uni-app 环境中不存在可用于自动清理的 Vue 响应式作用域。\n * @throws `RangeError` 当间隔不是平台计时器支持的非负有限整数。\n */\nexport function useNow(intervalMilliseconds = 1000): Readonly<ShallowRef<Date>> {\n\tif (!Number.isInteger(intervalMilliseconds) || intervalMilliseconds < 0 || intervalMilliseconds > 2_147_483_647) {\n\t\tthrow new RangeError(\"`intervalMilliseconds` 必须是 0 至 2,147,483,647 的整数。\");\n\t}\n\tconst now = shallowRef(new Date());\n\tif (runtimeGlobals.window !== undefined || runtimeGlobals.uni !== undefined) {\n\t\tif (getCurrentScope() === undefined) throw new Error(\"`useNow` 必须在 Vue 响应式作用域内调用。\");\n\t\tconst timer = setInterval(() => {\n\t\t\tnow.value = new Date();\n\t\t}, intervalMilliseconds);\n\t\tonScopeDispose(() => {\n\t\t\tclearInterval(timer);\n\t\t});\n\t}\n\treturn readonly(now);\n}\n"],"mappings":";;;;;;;;;;;AAYA,SAAgB,OAAO,uBAAuB,KAAkC;CAC/E,IAAI,CAAC,OAAO,UAAU,oBAAoB,KAAK,uBAAuB,KAAK,uBAAuB,YACjG,MAAM,IAAI,WAAW,mDAAmD;CAEzE,MAAM,MAAM,2BAAW,IAAI,KAAK,CAAC;CACjC,IAAI,eAAe,WAAW,KAAA,KAAa,eAAe,QAAQ,KAAA,GAAW;EAC5E,IAAI,gBAAgB,MAAM,KAAA,GAAW,MAAM,IAAI,MAAM,6BAA6B;EAClF,MAAM,QAAQ,kBAAkB;GAC/B,IAAI,wBAAQ,IAAI,KAAK;EACtB,GAAG,oBAAoB;EACvB,qBAAqB;GACpB,cAAc,KAAK;EACpB,CAAC;CACF;CACA,OAAO,SAAS,GAAG;AACpB"}
@@ -0,0 +1,15 @@
1
+ import { MaybeRefOrGetter } from "vue";
2
+ //#region src/vue/resize-observer.d.ts
3
+ /** `useResizeObserver` 接受的元素或响应式元素。 */
4
+ export type ResizeObserverTarget = MaybeRefOrGetter<Element | null | undefined>;
5
+ /**
6
+ * 监听元素尺寸变化,并随响应式目标切换和 Vue 作用域销毁自动断开。
7
+ *
8
+ * @param target - 原生元素、Ref 或 Getter。
9
+ * @param callback - 原生 ResizeObserver 回调。
10
+ * @param options - 原生元素观察选项。
11
+ * @returns 可提前断开观察的停止函数;运行时不支持 ResizeObserver 时为空操作。
12
+ */
13
+ export declare function useResizeObserver(target: ResizeObserverTarget, callback: ResizeObserverCallback, options?: ResizeObserverOptions): () => void;
14
+ //#endregion
15
+ //# sourceMappingURL=resize-observer.d.mts.map
@@ -0,0 +1,31 @@
1
+ import { runtimeGlobals } from "../internal/runtime.mjs";
2
+ import { onScopeDispose, toValue, watch } from "vue";
3
+ //#region src/vue/resize-observer.ts
4
+ /**
5
+ * 监听元素尺寸变化,并随响应式目标切换和 Vue 作用域销毁自动断开。
6
+ *
7
+ * @param target - 原生元素、Ref 或 Getter。
8
+ * @param callback - 原生 ResizeObserver 回调。
9
+ * @param options - 原生元素观察选项。
10
+ * @returns 可提前断开观察的停止函数;运行时不支持 ResizeObserver 时为空操作。
11
+ */
12
+ function useResizeObserver(target, callback, options) {
13
+ const stop = watch(() => toValue(target), (currentTarget, _previousTarget, onCleanup) => {
14
+ const ResizeObserver = runtimeGlobals.ResizeObserver;
15
+ if (currentTarget === null || currentTarget === void 0 || ResizeObserver === void 0) return;
16
+ const observer = new ResizeObserver(callback);
17
+ observer.observe(currentTarget, options);
18
+ onCleanup(() => {
19
+ observer.disconnect();
20
+ });
21
+ }, {
22
+ flush: "sync",
23
+ immediate: true
24
+ });
25
+ onScopeDispose(stop, true);
26
+ return stop;
27
+ }
28
+ //#endregion
29
+ export { useResizeObserver };
30
+
31
+ //# sourceMappingURL=resize-observer.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resize-observer.mjs","names":[],"sources":["../../src/vue/resize-observer.ts"],"sourcesContent":["import { onScopeDispose, toValue, watch } from \"vue\";\nimport { runtimeGlobals } from \"../internal/runtime\";\nimport type { MaybeRefOrGetter } from \"vue\";\n\n/** `useResizeObserver` 接受的元素或响应式元素。 */\nexport type ResizeObserverTarget = MaybeRefOrGetter<Element | null | undefined>;\n\n/**\n * 监听元素尺寸变化,并随响应式目标切换和 Vue 作用域销毁自动断开。\n *\n * @param target - 原生元素、Ref 或 Getter。\n * @param callback - 原生 ResizeObserver 回调。\n * @param options - 原生元素观察选项。\n * @returns 可提前断开观察的停止函数;运行时不支持 ResizeObserver 时为空操作。\n */\nexport function useResizeObserver(target: ResizeObserverTarget, callback: ResizeObserverCallback, options?: ResizeObserverOptions): () => void {\n\tconst stop = watch(\n\t\t() => toValue(target),\n\t\t(currentTarget, _previousTarget, onCleanup) => {\n\t\t\tconst ResizeObserver = runtimeGlobals.ResizeObserver;\n\t\t\tif (currentTarget === null || currentTarget === undefined || ResizeObserver === undefined) return;\n\t\t\tconst observer = new ResizeObserver(callback);\n\t\t\tobserver.observe(currentTarget, options);\n\t\t\tonCleanup(() => {\n\t\t\t\tobserver.disconnect();\n\t\t\t});\n\t\t},\n\t\t{ flush: \"sync\", immediate: true }\n\t);\n\tonScopeDispose(stop, true);\n\treturn stop;\n}\n"],"mappings":";;;;;;;;;;;AAeA,SAAgB,kBAAkB,QAA8B,UAAkC,SAA6C;CAC9I,MAAM,OAAO,YACN,QAAQ,MAAM,IACnB,eAAe,iBAAiB,cAAc;EAC9C,MAAM,iBAAiB,eAAe;EACtC,IAAI,kBAAkB,QAAQ,kBAAkB,KAAA,KAAa,mBAAmB,KAAA,GAAW;EAC3F,MAAM,WAAW,IAAI,eAAe,QAAQ;EAC5C,SAAS,QAAQ,eAAe,OAAO;EACvC,gBAAgB;GACf,SAAS,WAAW;EACrB,CAAC;CACF,GACA;EAAE,OAAO;EAAQ,WAAW;CAAK,CAClC;CACA,eAAe,MAAM,IAAI;CACzB,OAAO;AACR"}
@@ -0,0 +1,16 @@
1
+ import { ShallowRef } from "vue";
2
+ //#region src/vue/window-size.d.ts
3
+ /** `useWindowSize` 返回的只读窗口尺寸。 */
4
+ export interface UseWindowSizeReturn {
5
+ readonly width: Readonly<ShallowRef<number>>;
6
+ readonly height: Readonly<ShallowRef<number>>;
7
+ }
8
+ /**
9
+ * 响应式读取浏览器窗口内部尺寸。
10
+ *
11
+ * @returns 随原生 `resize` 事件更新的只读宽度和高度;非浏览器环境均为 `0`。
12
+ * @throws `Error` 当浏览器环境中不存在可用于自动清理的 Vue 响应式作用域。
13
+ */
14
+ export declare function useWindowSize(): UseWindowSizeReturn;
15
+ //#endregion
16
+ //# sourceMappingURL=window-size.d.mts.map
@@ -0,0 +1,32 @@
1
+ import { runtimeGlobals } from "../internal/runtime.mjs";
2
+ import { useEventListener } from "./event-listener.mjs";
3
+ import { getCurrentScope, readonly, shallowRef } from "vue";
4
+ //#region src/vue/window-size.ts
5
+ /**
6
+ * 响应式读取浏览器窗口内部尺寸。
7
+ *
8
+ * @returns 随原生 `resize` 事件更新的只读宽度和高度;非浏览器环境均为 `0`。
9
+ * @throws `Error` 当浏览器环境中不存在可用于自动清理的 Vue 响应式作用域。
10
+ */
11
+ function useWindowSize() {
12
+ const width = shallowRef(0);
13
+ const height = shallowRef(0);
14
+ const window = runtimeGlobals.window;
15
+ if (window !== void 0) {
16
+ if (getCurrentScope() === void 0) throw new Error("`useWindowSize` 必须在 Vue 响应式作用域内调用。");
17
+ const update = () => {
18
+ width.value = window.innerWidth;
19
+ height.value = window.innerHeight;
20
+ };
21
+ update();
22
+ useEventListener(window, "resize", update, { passive: true });
23
+ }
24
+ return {
25
+ height: readonly(height),
26
+ width: readonly(width)
27
+ };
28
+ }
29
+ //#endregion
30
+ export { useWindowSize };
31
+
32
+ //# sourceMappingURL=window-size.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"window-size.mjs","names":[],"sources":["../../src/vue/window-size.ts"],"sourcesContent":["import { getCurrentScope, readonly, shallowRef } from \"vue\";\nimport { runtimeGlobals } from \"../internal/runtime\";\nimport { useEventListener } from \"./event-listener\";\nimport type { ShallowRef } from \"vue\";\n\n/** `useWindowSize` 返回的只读窗口尺寸。 */\nexport interface UseWindowSizeReturn {\n\treadonly width: Readonly<ShallowRef<number>>;\n\treadonly height: Readonly<ShallowRef<number>>;\n}\n\n/**\n * 响应式读取浏览器窗口内部尺寸。\n *\n * @returns 随原生 `resize` 事件更新的只读宽度和高度;非浏览器环境均为 `0`。\n * @throws `Error` 当浏览器环境中不存在可用于自动清理的 Vue 响应式作用域。\n */\nexport function useWindowSize(): UseWindowSizeReturn {\n\tconst width = shallowRef(0);\n\tconst height = shallowRef(0);\n\tconst window = runtimeGlobals.window;\n\tif (window !== undefined) {\n\t\tif (getCurrentScope() === undefined) throw new Error(\"`useWindowSize` 必须在 Vue 响应式作用域内调用。\");\n\t\tconst update = () => {\n\t\t\twidth.value = window.innerWidth;\n\t\t\theight.value = window.innerHeight;\n\t\t};\n\t\tupdate();\n\t\tuseEventListener(window, \"resize\", update, { passive: true });\n\t}\n\treturn { height: readonly(height), width: readonly(width) };\n}\n"],"mappings":";;;;;;;;;;AAiBA,SAAgB,gBAAqC;CACpD,MAAM,QAAQ,WAAW,CAAC;CAC1B,MAAM,SAAS,WAAW,CAAC;CAC3B,MAAM,SAAS,eAAe;CAC9B,IAAI,WAAW,KAAA,GAAW;EACzB,IAAI,gBAAgB,MAAM,KAAA,GAAW,MAAM,IAAI,MAAM,oCAAoC;EACzF,MAAM,eAAe;GACpB,MAAM,QAAQ,OAAO;GACrB,OAAO,QAAQ,OAAO;EACvB;EACA,OAAO;EACP,iBAAiB,QAAQ,UAAU,QAAQ,EAAE,SAAS,KAAK,CAAC;CAC7D;CACA,OAAO;EAAE,QAAQ,SAAS,MAAM;EAAG,OAAO,SAAS,KAAK;CAAE;AAC3D"}
package/docs/API.md CHANGED
@@ -136,7 +136,7 @@ Store passwords with `HashPasswordPBKDF2SHA256` and `VerifyPasswordPBKDF2SHA256`
136
136
  - `number`: ranges, rounding, aggregation, interpolation, byte formatting, and Web Crypto-preferred `randomInt`.
137
137
  - `object`: deep cloning and equality, prototype-safe key and predicate selection, mapping, and query serialization. Style serialization is provided by the `dom` module.
138
138
  - `string`: query parsing, casing, grapheme-aware truncation, clipboard copying, UUID, Web Crypto-preferred `randomString`, escaping, and whitespace normalization.
139
- - `vue`: Composition API, type, render, and `app.use()` registration helpers for Vue 3.
139
+ - `vue`: Vue 3 helpers plus native-backed `useEventListener`, `useWindowSize`, `useResizeObserver`, `useElementSize`, `useNow`, and `useBreakpoints` composables. They intentionally cover common browser use rather than the full VueUse option surface.
140
140
 
141
141
  ## Security and limits
142
142
 
package/docs/API.zh-CN.md CHANGED
@@ -135,7 +135,7 @@ const result = plaintext.parseJson<{ id: number }>();
135
135
  - `number`:范围、舍入、聚合、插值、字节格式化,以及优先使用 Web Crypto 的 `randomInt`。
136
136
  - `object`:深复制、深度比较、防原型污染的键和条件筛选、映射及 Query 序列化;Style 序列化由 `dom` 模块提供。
137
137
  - `string`:Query 解析、大小写、字素截断、剪贴板复制、UUID、优先使用 Web Crypto 的 `randomString`、转义和空白规范化。
138
- - `vue`:Vue 3 的 Composition API、类型、Render 和 `app.use()` 注册 Helper。
138
+ - `vue`:Vue 3 Helper,以及基于原生能力的 `useEventListener`、`useWindowSize`、`useResizeObserver`、`useElementSize`、`useNow` 和 `useBreakpoints`。这些 Composable 面向常用浏览器场景,不提供 VueUse 的完整选项面。
139
139
 
140
140
  ## 安全与限制
141
141
 
@@ -4,7 +4,8 @@
4
4
 
5
5
  - Runtime platforms: ES2022 modern browsers, WebViews, Vue 3 applications, and uni-app.
6
6
  - Package format: one public named-export ESM entry for package managers and one separately minified IIFE entry for CDN use; CommonJS and UMD are not shipped.
7
- - Framework boundary: Vue remains external to the package-manager build and is a required peer in `^3.3.0`.
7
+ - Framework boundary: Vue remains external to the package-manager build and is a required peer in `^3.5.11`.
8
+ - Vue browser composables: event and observer helpers use native platform APIs, return manual stop handles where exposed, and clean up automatically with the current Vue scope. Window size and breakpoints use `0`/`false` outside browsers; `useNow` returns a non-updating initial Date during SSR.
8
9
  - uni-app boundary: the first Storage operation, or an earlier `configureStorage({ prefix })` call, detects global `uni` and uses its synchronous Storage API.
9
10
  - Browser storage: applications import `Local` and `Session` directly; `configureStorage()` is needed only to override defaults before the first operation.
10
11
  - Storage operation overrides: `set/get({ crypto })` select JSON or Base64 for one operation without mutating global configuration. The v3 envelope does not identify its codec, so callers must use matching options for the same entry.
@@ -28,7 +29,8 @@ Importing a module does not itself read `window`, browser Storage, or `uni`, so
28
29
 
29
30
  - 运行平台:ES2022 现代浏览器、WebView、Vue 3 应用和 uni-app。
30
31
  - 包格式:包管理器使用单一公开具名导出 ESM 入口,CDN 使用单独压缩的 IIFE;不发布 CommonJS 或 UMD。
31
- - Vue 边界:Vue 不会打进包管理器使用的构建产物,是 `^3.3.0` 的必需 Peer。
32
+ - Vue 边界:Vue 不会打进包管理器使用的构建产物,是 `^3.5.11` 的必需 Peer。
33
+ - Vue 浏览器 Composable:事件和观察器 Helper 直接使用原生平台 API,在公开停止函数时支持手动清理,并随当前 Vue 作用域自动清理。非浏览器环境下窗口尺寸和断点状态分别使用 `0` 与 `false`,`useNow` 在 SSR 时只返回调用时的静态 Date。
32
34
  - uni-app:首次 Storage 操作或更早的 `configureStorage({ prefix })` 调用会检测全局 `uni`,并使用其同步 Storage API。
33
35
  - Storage:直接从包导入 `Local` 和 `Session` 即可;只有覆盖默认值时才需在首次操作前调用 `configureStorage()`。
34
36
  - Storage 单次覆盖:`set/get({ crypto })` 只为当前操作选择 JSON 或 Base64,不修改全局配置。v3 包络不记录 Codec,调用方必须对同一条目使用匹配的读写选项。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fast-china/utils",
3
- "version": "2.1.5",
3
+ "version": "2.1.6",
4
4
  "description": "Typed utilities for modern browsers, WebViews, Vue 3, and uni-app applications.",
5
5
  "type": "module",
6
6
  "keywords": [