fast-element-plus 2.0.20 → 2.0.22
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/CHANGELOG.md +20 -0
- package/dist/component.d.ts +15 -15
- package/dist/components/avatar/index.d.ts +3 -3
- package/dist/components/avatar/index.mjs.map +1 -1
- package/dist/components/button/index.d.ts +3 -3
- package/dist/components/button/index.mjs.map +1 -1
- package/dist/components/button/src/button.d.ts +1 -1
- package/dist/components/carNumber/index.d.ts +1 -1
- package/dist/components/carNumber/index.mjs.map +1 -1
- package/dist/components/contextMenu/index.d.ts +1 -1
- package/dist/components/contextMenu/index.mjs.map +1 -1
- package/dist/components/contextMenu/src/contextMenu.type.d.ts +1 -1
- package/dist/components/dialog/index.d.ts +3 -3
- package/dist/components/dialog/index.mjs.map +1 -1
- package/dist/components/dialog/src/dialog.d.ts +3 -3
- package/dist/components/drawer/index.d.ts +3 -3
- package/dist/components/drawer/index.mjs.map +1 -1
- package/dist/components/drawer/src/drawer.d.ts +3 -3
- package/dist/components/form/index.d.ts +4 -4
- package/dist/components/form/index.mjs.map +1 -1
- package/dist/components/form/utils/form.d.ts +2 -2
- package/dist/components/form/utils/form.mjs +2 -2
- package/dist/components/form/utils/form.mjs.map +1 -1
- package/dist/components/formItemTip/index.d.ts +2 -2
- package/dist/components/formItemTip/index.mjs.map +1 -1
- package/dist/components/icon/index.d.ts +2 -2
- package/dist/components/icon/index.mjs.map +1 -1
- package/dist/components/iconSelector/index.d.ts +1 -1
- package/dist/components/iconSelector/index.mjs.map +1 -1
- package/dist/components/image/index.d.ts +2 -2
- package/dist/components/image/index.mjs.map +1 -1
- package/dist/components/image/src/image.d.ts +1 -1
- package/dist/components/inputDialogPage/index.d.ts +3 -3
- package/dist/components/inputDialogPage/index.mjs.map +1 -1
- package/dist/components/layoutGrid/index.d.ts +2 -2
- package/dist/components/layoutGrid/index.mjs.map +1 -1
- package/dist/components/select/index.d.ts +4 -4
- package/dist/components/select/index.mjs.map +1 -1
- package/dist/components/select/src/select.d.ts +1 -1
- package/dist/components/select/src/select.type.d.ts +2 -2
- package/dist/components/selectPage/index.d.ts +3 -3
- package/dist/components/selectPage/index.mjs.map +1 -1
- package/dist/components/selectPage/src/selectPage.d.ts +1 -1
- package/dist/components/selectV2/index.d.ts +3 -3
- package/dist/components/selectV2/index.mjs.map +1 -1
- package/dist/components/selectV2/src/selectV2.d.ts +1 -1
- package/dist/components/table/index.d.ts +4 -4
- package/dist/components/table/index.mjs.map +1 -1
- package/dist/components/table/src/page.type.d.ts +2 -2
- package/dist/components/table/src/table.mjs +20 -20
- package/dist/components/table/src/table.mjs.map +1 -1
- package/dist/components/table/src/table.type.d.ts +5 -5
- package/dist/components/table/src/table.type.mjs.map +1 -1
- package/dist/components/table/src/tableColumn.d.ts +2 -2
- package/dist/components/table/src/tableColumn.mjs +34 -28
- package/dist/components/table/src/tableColumn.mjs.map +1 -1
- package/dist/components/table/utils/table.d.ts +18 -15
- package/dist/components/table/utils/table.mjs +20 -17
- package/dist/components/table/utils/table.mjs.map +1 -1
- package/dist/components/tree/index.d.ts +3 -3
- package/dist/components/tree/index.mjs.map +1 -1
- package/dist/components/tree/src/tree.props.d.ts +2 -2
- package/dist/components/tree/src/tree.type.d.ts +2 -2
- package/dist/components/treeSelect/index.d.ts +3 -3
- package/dist/components/treeSelect/index.mjs.map +1 -1
- package/dist/components/treeSelect/src/treeSelect.d.ts +1 -1
- package/dist/components/upload/index.d.ts +3 -3
- package/dist/components/upload/index.mjs.map +1 -1
- package/dist/components/upload/utils/upload.d.ts +15 -10
- package/dist/components/upload/utils/upload.mjs +15 -10
- package/dist/components/upload/utils/upload.mjs.map +1 -1
- package/dist/components/uploadImage/index.d.ts +3 -3
- package/dist/components/uploadImage/index.mjs.map +1 -1
- package/dist/components/uploadImages/index.d.ts +3 -3
- package/dist/components/uploadImages/index.mjs.map +1 -1
- package/dist/index.global.min.js +4 -4
- package/dist/index.global.min.js.map +1 -1
- package/dist/internal/props.d.ts +1 -1
- package/dist/internal/props.mjs.map +1 -1
- package/dist/utils/async/index.d.ts +4 -4
- package/dist/utils/async/index.mjs +9 -9
- package/dist/utils/async/index.mjs.map +1 -1
- package/dist/utils/date/index.d.ts +8 -8
- package/dist/utils/date/index.mjs +16 -16
- package/dist/utils/date/index.mjs.map +1 -1
- package/dist/utils/dom/index.d.ts +1 -1
- package/dist/utils/dom/index.mjs +4 -4
- package/dist/utils/dom/index.mjs.map +1 -1
- package/dist/utils/object/index.d.ts +10 -10
- package/dist/utils/object/index.mjs +6 -6
- package/dist/utils/object/index.mjs.map +1 -1
- package/dist/utils/string/index.d.ts +4 -4
- package/dist/utils/string/index.mjs +14 -40
- package/dist/utils/string/index.mjs.map +1 -1
- package/dist/utils/vue/emits.d.ts +8 -8
- package/dist/utils/vue/emits.mjs +7 -7
- package/dist/utils/vue/emits.mjs.map +1 -1
- package/dist/utils/vue/expose.d.ts +3 -3
- package/dist/utils/vue/expose.mjs +3 -3
- package/dist/utils/vue/expose.mjs.map +1 -1
- package/dist/utils/vue/func.d.ts +2 -2
- package/dist/utils/vue/func.mjs +2 -2
- package/dist/utils/vue/func.mjs.map +1 -1
- package/dist/utils/vue/install.d.ts +9 -9
- package/dist/utils/vue/install.mjs +24 -24
- package/dist/utils/vue/install.mjs.map +1 -1
- package/dist/utils/vue/props.d.ts +4 -4
- package/dist/utils/vue/props.mjs +5 -5
- package/dist/utils/vue/props.mjs.map +1 -1
- package/dist/utils/vue/render.d.ts +1 -1
- package/dist/utils/vue/render.mjs +2 -2
- package/dist/utils/vue/render.mjs.map +1 -1
- package/dist/utils/vue/slots.d.ts +4 -4
- package/dist/utils/vue/slots.mjs.map +1 -1
- package/dist/utils/vue/with.d.ts +1 -1
- package/dist/utils/vue/with.mjs +1 -1
- package/dist/utils/vue/with.mjs.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.mjs +1 -1
- package/dist/version.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../../src/utils/object/index.ts"],"sourcesContent":["/**\n * 安全写入结果对象的自有可枚举属性。\n *\n * @remarks 使用 `defineProperty` 避免 `__proto__` 触发 Setter,并统一创建可写、可配置的自有可枚举数据属性。\n * @param target - 要写入的结果对象。\n * @param key - 自有属性键。\n * @param value - 属性值。\n */\nconst defineEnumerableProperty = (target: object, key: PropertyKey, value: unknown): void => {\n\tObject.defineProperty(target, key, { configurable: true, enumerable: true, value, writable: true });\n};\n\nconst typedArrayTags = new Set([\n\t\"[object BigInt64Array]\",\n\t\"[object BigUint64Array]\",\n\t\"[object Float32Array]\",\n\t\"[object Float64Array]\",\n\t\"[object Int8Array]\",\n\t\"[object Int16Array]\",\n\t\"[object Int32Array]\",\n\t\"[object Uint8Array]\",\n\t\"[object Uint8ClampedArray]\",\n\t\"[object Uint16Array]\",\n\t\"[object Uint32Array]\",\n]);\n\n/** 深度比较过程中用于识别循环引用的双向对象映射。 */\ninterface EqualityState {\n\treadonly leftObjects: WeakMap<object, object>;\n\treadonly rightObjects: WeakMap<object, object>;\n}\n\n/** 判断两个值是否满足 SameValueZero 相等。 */\nconst sameValueZero = (left: unknown, right: unknown): boolean =>\n\tleft === right || (typeof left === \"number\" && typeof right === \"number\" && Number.isNaN(left) && Number.isNaN(right));\n\n/** 返回对象的自有可枚举字符串与 Symbol 键。 */\nconst getEnumerableOwnKeys = (value: object): PropertyKey[] =>\n\tReflect.ownKeys(value).filter((key) => Object.prototype.propertyIsEnumerable.call(value, key));\n\n/** 在一次递归分支内记录对象对应关系。 */\nconst compareTrackedPair = (left: object, right: object, state: EqualityState, compare: () => boolean): boolean => {\n\tconst existingRight = state.leftObjects.get(left);\n\tconst existingLeft = state.rightObjects.get(right);\n\tif (existingRight !== undefined || existingLeft !== undefined) return existingRight === right && existingLeft === left;\n\tstate.leftObjects.set(left, right);\n\tstate.rightObjects.set(right, left);\n\ttry {\n\t\treturn compare();\n\t} finally {\n\t\tstate.leftObjects.delete(left);\n\t\tstate.rightObjects.delete(right);\n\t}\n};\n\n/** 按字节比较两个 ArrayBufferLike。 */\nconst equalArrayBuffers = (left: ArrayBufferLike, right: ArrayBufferLike): boolean => {\n\tif (left.byteLength !== right.byteLength) return false;\n\tconst leftBytes = new Uint8Array(left);\n\tconst rightBytes = new Uint8Array(right);\n\tfor (let index = 0; index < leftBytes.length; index += 1) {\n\t\tif (leftBytes[index] !== rightBytes[index]) return false;\n\t}\n\treturn true;\n};\n\n/** 按顺序比较数组或 TypedArray 的元素。 */\nconst equalIndexedValues = (\n\tleft: { readonly [index: number]: unknown; readonly length: number },\n\tright: { readonly [index: number]: unknown; readonly length: number },\n\tstate: EqualityState\n): boolean => {\n\tif (left.length !== right.length) return false;\n\treturn compareTrackedPair(left, right, state, () => {\n\t\tfor (let index = 0; index < left.length; index += 1) {\n\t\t\tif (!isEqualValue(left[index], right[index], state)) return false;\n\t\t}\n\t\treturn true;\n\t});\n};\n\n/** 无序比较 Map 条目或 Set 元素。 */\nconst equalUnorderedValues = (left: readonly unknown[], right: readonly unknown[], state: EqualityState): boolean => {\n\tif (left.length !== right.length) return false;\n\tconst matchedIndexes = new Set<number>();\n\tfor (const leftValue of left) {\n\t\tlet matchedIndex = -1;\n\t\tfor (let index = 0; index < right.length; index += 1) {\n\t\t\tif (matchedIndexes.has(index) || !isEqualValue(leftValue, right[index], state)) continue;\n\t\t\tmatchedIndex = index;\n\t\t\tbreak;\n\t\t}\n\t\tif (matchedIndex < 0) return false;\n\t\tmatchedIndexes.add(matchedIndex);\n\t}\n\treturn true;\n};\n\n/** 比较普通对象或 Arguments 的自有可枚举属性与构造器。 */\nconst equalObjects = (left: object, right: object, state: EqualityState): boolean => {\n\tconst leftKeys = getEnumerableOwnKeys(left);\n\tconst rightKeys = getEnumerableOwnKeys(right);\n\tif (leftKeys.length !== rightKeys.length) return false;\n\tfor (const key of leftKeys) {\n\t\tif (!Object.hasOwn(right, key)) return false;\n\t}\n\n\treturn compareTrackedPair(left, right, state, () => {\n\t\tlet compareConstructors = true;\n\t\tfor (const key of leftKeys) {\n\t\t\tif (!isEqualValue(Reflect.get(left, key), Reflect.get(right, key), state)) return false;\n\t\t\tif (key === \"constructor\") compareConstructors = false;\n\t\t}\n\t\tif (!compareConstructors) return true;\n\t\tconst leftConstructor: unknown = Reflect.get(left, \"constructor\");\n\t\tconst rightConstructor: unknown = Reflect.get(right, \"constructor\");\n\t\tif (leftConstructor === rightConstructor || !(\"constructor\" in left && \"constructor\" in right)) return true;\n\t\treturn (\n\t\t\ttypeof leftConstructor === \"function\" &&\n\t\t\ttypeof rightConstructor === \"function\" &&\n\t\t\tleftConstructor instanceof leftConstructor &&\n\t\t\trightConstructor instanceof rightConstructor\n\t\t);\n\t});\n};\n\n/** 递归比较两个值。 */\nfunction isEqualValue(left: unknown, right: unknown, state: EqualityState): boolean {\n\tif (sameValueZero(left, right)) return true;\n\tif (left === null || left === undefined || right === null || right === undefined) return false;\n\n\tconst leftTag = Object.prototype.toString.call(left);\n\tconst rightTag = Object.prototype.toString.call(right);\n\tconst normalizedLeftTag = leftTag === \"[object Arguments]\" ? \"[object Object]\" : leftTag;\n\tconst normalizedRightTag = rightTag === \"[object Arguments]\" ? \"[object Object]\" : rightTag;\n\tif (normalizedLeftTag !== normalizedRightTag) return false;\n\n\tswitch (normalizedLeftTag) {\n\t\tcase \"[object Boolean]\":\n\t\tcase \"[object Date]\":\n\t\tcase \"[object Number]\":\n\t\t\treturn sameValueZero(Number(left), Number(right));\n\t\tcase \"[object Error]\":\n\t\t\treturn (left as Error).name === (right as Error).name && (left as Error).message === (right as Error).message;\n\t\tcase \"[object RegExp]\":\n\t\t\treturn RegExp.prototype.toString.call(left) === RegExp.prototype.toString.call(right);\n\t\tcase \"[object String]\":\n\t\t\treturn String.prototype.valueOf.call(left) === String.prototype.valueOf.call(right);\n\t\tcase \"[object Symbol]\":\n\t\t\treturn Symbol.prototype.valueOf.call(left) === Symbol.prototype.valueOf.call(right);\n\t}\n\n\tif (typeof left !== \"object\" || typeof right !== \"object\") return false;\n\tif (Array.isArray(left) && Array.isArray(right)) return equalIndexedValues(left, right, state);\n\tif (normalizedLeftTag === \"[object ArrayBuffer]\" || normalizedLeftTag === \"[object SharedArrayBuffer]\") {\n\t\treturn equalArrayBuffers(left as ArrayBufferLike, right as ArrayBufferLike);\n\t}\n\tif (normalizedLeftTag === \"[object DataView]\") {\n\t\tconst leftView = left as DataView;\n\t\tconst rightView = right as DataView;\n\t\treturn (\n\t\t\tleftView.byteLength === rightView.byteLength &&\n\t\t\tleftView.byteOffset === rightView.byteOffset &&\n\t\t\tequalArrayBuffers(leftView.buffer, rightView.buffer)\n\t\t);\n\t}\n\tif (typedArrayTags.has(normalizedLeftTag)) {\n\t\treturn equalIndexedValues(\n\t\t\tleft as ArrayBufferView & { readonly [index: number]: unknown; readonly length: number },\n\t\t\tright as ArrayBufferView & { readonly [index: number]: unknown; readonly length: number },\n\t\t\tstate\n\t\t);\n\t}\n\tif (normalizedLeftTag === \"[object Map]\") {\n\t\treturn compareTrackedPair(left, right, state, () =>\n\t\t\tequalUnorderedValues([...(left as Map<unknown, unknown>)], [...(right as Map<unknown, unknown>)], state)\n\t\t);\n\t}\n\tif (normalizedLeftTag === \"[object Set]\") {\n\t\treturn compareTrackedPair(left, right, state, () => equalUnorderedValues([...(left as Set<unknown>)], [...(right as Set<unknown>)], state));\n\t}\n\tif (normalizedLeftTag === \"[object Object]\") return equalObjects(left, right, state);\n\treturn false;\n}\n\n/**\n * 深度比较两个值是否等价。\n *\n * @remarks 原始值使用 SameValueZero 语义;支持循环引用、数组、对象、ArrayBuffer、DataView、Date、Error、Map、RegExp、Set、Symbol 和 TypedArray。\n * 对象只比较自有可枚举字符串与 Symbol 属性,函数及其他不支持的宿主对象仅在引用相同时相等。\n * @param left - 第一待比较值。\n * @param right - 第二待比较值。\n * @returns 两个值深度等价时返回 `true`。\n */\nexport function isEqual(left: unknown, right: unknown): boolean {\n\treturn isEqualValue(left, right, { leftObjects: new WeakMap(), rightObjects: new WeakMap() });\n}\n\n/**\n * 从对象中选择指定自有可枚举属性。\n *\n * @remarks 字面量键数组保留精确返回类型;普通 `string[]` 等动态键数组返回 `Partial<Source>`。\n * @param source - 不会被修改的源对象。\n * @param keys - 需要保留的键;不存在的键被忽略。\n * @returns 新对象,保持 `keys` 的遍历顺序。\n */\nexport function pick<Source extends object, const Keys extends readonly (keyof Source)[]>(source: Source, keys: Keys): Pick<Source, Keys[number]>;\nexport function pick<Source extends object>(source: Source, keys: readonly PropertyKey[]): Partial<Source>;\nexport function pick<Source extends object>(source: Source, keys: readonly PropertyKey[]): Partial<Source> {\n\tconst result: Partial<Source> = {};\n\tfor (const key of keys) {\n\t\tif (Object.prototype.propertyIsEnumerable.call(source, key)) defineEnumerableProperty(result, key, Reflect.get(source, key));\n\t}\n\treturn result;\n}\n\n/**\n * 浅复制对象并删除指定属性。\n *\n * @remarks 字面量键数组保留精确返回类型;普通 `string[]` 等动态键数组返回 `Partial<Source>`。\n * @param source - 不会被修改的源对象。\n * @param keys - 需要排除的键。\n * @returns 包含其余自有可枚举字符串与 Symbol 属性的新对象。\n */\nexport function omit<Source extends object, const Keys extends readonly (keyof Source)[]>(source: Source, keys: Keys): Omit<Source, Keys[number]>;\nexport function omit<Source extends object>(source: Source, keys: readonly PropertyKey[]): Partial<Source>;\nexport function omit<Source extends object>(source: Source, keys: readonly PropertyKey[]): Partial<Source> {\n\tconst result = { ...source };\n\tfor (const key of keys) Reflect.deleteProperty(result, key);\n\treturn result;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../../src/utils/object/index.ts"],"sourcesContent":["/**\n * 安全写入结果对象的自有可枚举属性。\n *\n * @remarks 使用 `defineProperty` 避免 `__proto__` 触发 Setter,并统一创建可写、可配置的自有可枚举数据属性。\n * @param target - 要写入的结果对象\n * @param key - 自有属性键\n * @param value - 属性值\n */\nconst defineEnumerableProperty = (target: object, key: PropertyKey, value: unknown): void => {\n\tObject.defineProperty(target, key, { configurable: true, enumerable: true, value, writable: true });\n};\n\nconst typedArrayTags = new Set([\n\t\"[object BigInt64Array]\",\n\t\"[object BigUint64Array]\",\n\t\"[object Float32Array]\",\n\t\"[object Float64Array]\",\n\t\"[object Int8Array]\",\n\t\"[object Int16Array]\",\n\t\"[object Int32Array]\",\n\t\"[object Uint8Array]\",\n\t\"[object Uint8ClampedArray]\",\n\t\"[object Uint16Array]\",\n\t\"[object Uint32Array]\",\n]);\n\n/** 深度比较过程中用于识别循环引用的双向对象映射 */\ninterface EqualityState {\n\treadonly leftObjects: WeakMap<object, object>;\n\treadonly rightObjects: WeakMap<object, object>;\n}\n\n/** 判断两个值是否满足 SameValueZero 相等。 */\nconst sameValueZero = (left: unknown, right: unknown): boolean =>\n\tleft === right || (typeof left === \"number\" && typeof right === \"number\" && Number.isNaN(left) && Number.isNaN(right));\n\n/** 返回对象的自有可枚举字符串与 Symbol 键。 */\nconst getEnumerableOwnKeys = (value: object): PropertyKey[] =>\n\tReflect.ownKeys(value).filter((key) => Object.prototype.propertyIsEnumerable.call(value, key));\n\n/** 在一次递归分支内记录对象对应关系。 */\nconst compareTrackedPair = (left: object, right: object, state: EqualityState, compare: () => boolean): boolean => {\n\tconst existingRight = state.leftObjects.get(left);\n\tconst existingLeft = state.rightObjects.get(right);\n\tif (existingRight !== undefined || existingLeft !== undefined) return existingRight === right && existingLeft === left;\n\tstate.leftObjects.set(left, right);\n\tstate.rightObjects.set(right, left);\n\ttry {\n\t\treturn compare();\n\t} finally {\n\t\tstate.leftObjects.delete(left);\n\t\tstate.rightObjects.delete(right);\n\t}\n};\n\n/** 按字节比较两个 ArrayBufferLike。 */\nconst equalArrayBuffers = (left: ArrayBufferLike, right: ArrayBufferLike): boolean => {\n\tif (left.byteLength !== right.byteLength) return false;\n\tconst leftBytes = new Uint8Array(left);\n\tconst rightBytes = new Uint8Array(right);\n\tfor (let index = 0; index < leftBytes.length; index += 1) {\n\t\tif (leftBytes[index] !== rightBytes[index]) return false;\n\t}\n\treturn true;\n};\n\n/** 按顺序比较数组或 TypedArray 的元素。 */\nconst equalIndexedValues = (\n\tleft: { readonly [index: number]: unknown; readonly length: number },\n\tright: { readonly [index: number]: unknown; readonly length: number },\n\tstate: EqualityState\n): boolean => {\n\tif (left.length !== right.length) return false;\n\treturn compareTrackedPair(left, right, state, () => {\n\t\tfor (let index = 0; index < left.length; index += 1) {\n\t\t\tif (!isEqualValue(left[index], right[index], state)) return false;\n\t\t}\n\t\treturn true;\n\t});\n};\n\n/** 无序比较 Map 条目或 Set 元素。 */\nconst equalUnorderedValues = (left: readonly unknown[], right: readonly unknown[], state: EqualityState): boolean => {\n\tif (left.length !== right.length) return false;\n\tconst matchedIndexes = new Set<number>();\n\tfor (const leftValue of left) {\n\t\tlet matchedIndex = -1;\n\t\tfor (let index = 0; index < right.length; index += 1) {\n\t\t\tif (matchedIndexes.has(index) || !isEqualValue(leftValue, right[index], state)) continue;\n\t\t\tmatchedIndex = index;\n\t\t\tbreak;\n\t\t}\n\t\tif (matchedIndex < 0) return false;\n\t\tmatchedIndexes.add(matchedIndex);\n\t}\n\treturn true;\n};\n\n/** 比较普通对象或 Arguments 的自有可枚举属性与构造器。 */\nconst equalObjects = (left: object, right: object, state: EqualityState): boolean => {\n\tconst leftKeys = getEnumerableOwnKeys(left);\n\tconst rightKeys = getEnumerableOwnKeys(right);\n\tif (leftKeys.length !== rightKeys.length) return false;\n\tfor (const key of leftKeys) {\n\t\tif (!Object.prototype.hasOwnProperty.call(right, key)) return false;\n\t}\n\n\treturn compareTrackedPair(left, right, state, () => {\n\t\tlet compareConstructors = true;\n\t\tfor (const key of leftKeys) {\n\t\t\tif (!isEqualValue(Reflect.get(left, key), Reflect.get(right, key), state)) return false;\n\t\t\tif (key === \"constructor\") compareConstructors = false;\n\t\t}\n\t\tif (!compareConstructors) return true;\n\t\tconst leftConstructor: unknown = Reflect.get(left, \"constructor\");\n\t\tconst rightConstructor: unknown = Reflect.get(right, \"constructor\");\n\t\tif (leftConstructor === rightConstructor || !(\"constructor\" in left && \"constructor\" in right)) return true;\n\t\treturn (\n\t\t\ttypeof leftConstructor === \"function\" &&\n\t\t\ttypeof rightConstructor === \"function\" &&\n\t\t\tleftConstructor instanceof leftConstructor &&\n\t\t\trightConstructor instanceof rightConstructor\n\t\t);\n\t});\n};\n\n/** 递归比较两个值。 */\nfunction isEqualValue(left: unknown, right: unknown, state: EqualityState): boolean {\n\tif (sameValueZero(left, right)) return true;\n\tif (left === null || left === undefined || right === null || right === undefined) return false;\n\n\tconst leftTag = Object.prototype.toString.call(left);\n\tconst rightTag = Object.prototype.toString.call(right);\n\tconst normalizedLeftTag = leftTag === \"[object Arguments]\" ? \"[object Object]\" : leftTag;\n\tconst normalizedRightTag = rightTag === \"[object Arguments]\" ? \"[object Object]\" : rightTag;\n\tif (normalizedLeftTag !== normalizedRightTag) return false;\n\n\tswitch (normalizedLeftTag) {\n\t\tcase \"[object Boolean]\":\n\t\tcase \"[object Date]\":\n\t\tcase \"[object Number]\":\n\t\t\treturn sameValueZero(Number(left), Number(right));\n\t\tcase \"[object Error]\":\n\t\t\treturn (left as Error).name === (right as Error).name && (left as Error).message === (right as Error).message;\n\t\tcase \"[object RegExp]\":\n\t\t\treturn RegExp.prototype.toString.call(left) === RegExp.prototype.toString.call(right);\n\t\tcase \"[object String]\":\n\t\t\treturn String.prototype.valueOf.call(left) === String.prototype.valueOf.call(right);\n\t\tcase \"[object Symbol]\":\n\t\t\treturn Symbol.prototype.valueOf.call(left) === Symbol.prototype.valueOf.call(right);\n\t}\n\n\tif (typeof left !== \"object\" || typeof right !== \"object\") return false;\n\tif (Array.isArray(left) && Array.isArray(right)) return equalIndexedValues(left, right, state);\n\tif (normalizedLeftTag === \"[object ArrayBuffer]\" || normalizedLeftTag === \"[object SharedArrayBuffer]\") {\n\t\treturn equalArrayBuffers(left as ArrayBufferLike, right as ArrayBufferLike);\n\t}\n\tif (normalizedLeftTag === \"[object DataView]\") {\n\t\tconst leftView = left as DataView;\n\t\tconst rightView = right as DataView;\n\t\treturn (\n\t\t\tleftView.byteLength === rightView.byteLength &&\n\t\t\tleftView.byteOffset === rightView.byteOffset &&\n\t\t\tequalArrayBuffers(leftView.buffer, rightView.buffer)\n\t\t);\n\t}\n\tif (typedArrayTags.has(normalizedLeftTag)) {\n\t\treturn equalIndexedValues(\n\t\t\tleft as ArrayBufferView & { readonly [index: number]: unknown; readonly length: number },\n\t\t\tright as ArrayBufferView & { readonly [index: number]: unknown; readonly length: number },\n\t\t\tstate\n\t\t);\n\t}\n\tif (normalizedLeftTag === \"[object Map]\") {\n\t\treturn compareTrackedPair(left, right, state, () =>\n\t\t\tequalUnorderedValues([...(left as Map<unknown, unknown>)], [...(right as Map<unknown, unknown>)], state)\n\t\t);\n\t}\n\tif (normalizedLeftTag === \"[object Set]\") {\n\t\treturn compareTrackedPair(left, right, state, () => equalUnorderedValues([...(left as Set<unknown>)], [...(right as Set<unknown>)], state));\n\t}\n\tif (normalizedLeftTag === \"[object Object]\") return equalObjects(left, right, state);\n\treturn false;\n}\n\n/**\n * 深度比较两个值是否等价。\n *\n * @remarks 原始值使用 SameValueZero 语义;支持循环引用、数组、对象、ArrayBuffer、DataView、Date、Error、Map、RegExp、Set、Symbol 和 TypedArray。\n * 对象只比较自有可枚举字符串与 Symbol 属性,函数及其他不支持的宿主对象仅在引用相同时相等。\n * @param left - 第一待比较值\n * @param right - 第二待比较值\n * @returns 两个值深度等价时返回 `true`。\n */\nexport function isEqual(left: unknown, right: unknown): boolean {\n\treturn isEqualValue(left, right, { leftObjects: new WeakMap(), rightObjects: new WeakMap() });\n}\n\n/**\n * 从对象中选择指定自有可枚举属性。\n *\n * @remarks 固定键元组保留精确返回类型;动态数组中可能被选择或排除的键在返回类型中保持可选。\n * @param source - 不会被修改的源对象\n * @param keys - 需要保留的键;不存在的键被忽略。\n * @returns 新对象,保持 `keys` 的遍历顺序。\n */\nexport function pick<Source extends object, const Keys extends readonly (keyof Source)[]>(\n\tsource: Source,\n\tkeys: Keys\n): number extends Keys[\"length\"] ? Partial<Pick<Source, Keys[number]>> : Pick<Source, Keys[number]>;\nexport function pick<Source extends object>(source: Source, keys: readonly PropertyKey[]): Partial<Source>;\nexport function pick<Source extends object>(source: Source, keys: readonly PropertyKey[]): Partial<Source> {\n\tconst result: Partial<Source> = {};\n\tfor (const key of keys) {\n\t\tif (Object.prototype.propertyIsEnumerable.call(source, key)) defineEnumerableProperty(result, key, Reflect.get(source, key));\n\t}\n\treturn result;\n}\n\n/**\n * 浅复制对象并删除指定属性。\n *\n * @remarks 固定键元组保留精确返回类型;动态数组中可能被选择或排除的键在返回类型中保持可选。\n * @param source - 不会被修改的源对象\n * @param keys - 需要排除的键\n * @returns 包含其余自有可枚举字符串与 Symbol 属性的新对象\n */\nexport function omit<Source extends object, const Keys extends readonly (keyof Source)[]>(\n\tsource: Source,\n\tkeys: Keys\n): number extends Keys[\"length\"] ? Omit<Source, Keys[number]> & Partial<Pick<Source, Keys[number]>> : Omit<Source, Keys[number]>;\nexport function omit<Source extends object>(source: Source, keys: readonly PropertyKey[]): Partial<Source>;\nexport function omit<Source extends object>(source: Source, keys: readonly PropertyKey[]): Partial<Source> {\n\tconst result = { ...source };\n\tfor (const key of keys) Reflect.deleteProperty(result, key);\n\treturn result;\n}\n"],"mappings":"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"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 把文本复制到系统剪贴板。
|
|
3
3
|
*
|
|
4
|
-
* @remarks
|
|
4
|
+
* @remarks 浏览器优先使用 Clipboard API,并在该 API 不可用时
|
|
5
5
|
* 回退到 `document.execCommand("copy")`。平台拒绝访问剪贴板时不会静默忽略错误。
|
|
6
|
-
* @param value -
|
|
7
|
-
* @returns 复制完成后兑现的 Promise
|
|
6
|
+
* @param value - 要复制的文本
|
|
7
|
+
* @returns 复制完成后兑现的 Promise
|
|
8
8
|
* @throws `Error` 当运行时没有可用的剪贴板能力或复制失败。
|
|
9
9
|
*/
|
|
10
10
|
export declare function copy(value: string): Promise<void>;
|
|
@@ -14,7 +14,7 @@ export declare function copy(value: string): Promise<void>;
|
|
|
14
14
|
* @remarks 优先使用 Web Crypto;平台缺少安全随机能力时回退到 `Math.random()`。
|
|
15
15
|
* @param length - 字符数量,必须是 0 至 1,000,000 的安全整数。
|
|
16
16
|
* @param alphabet - 不得为空、包含重复字符或超过 2^32 个 Unicode 码点。
|
|
17
|
-
* @returns 由 `alphabet` 中 Unicode
|
|
17
|
+
* @returns 由 `alphabet` 中 Unicode 码点组成的随机文本
|
|
18
18
|
* @throws `RangeError` 当长度或字母表非法。
|
|
19
19
|
*/
|
|
20
20
|
export declare function randomString(length: number, alphabet?: string): string;
|
|
@@ -1,19 +1,11 @@
|
|
|
1
1
|
//#region src/utils/string/index.ts
|
|
2
|
-
/**
|
|
3
|
-
* 以可选能力视图读取全局对象。
|
|
4
|
-
*
|
|
5
|
-
* @remarks TypeScript 的 DOM 声明假定浏览器全局始终存在,但本包也会在 Node、WebView
|
|
6
|
-
* 和 uni-app 中运行。这里只放宽能力是否存在,不改变标准 API 的属性与方法类型。
|
|
7
|
-
*/
|
|
8
|
-
const runtimeGlobals = globalThis;
|
|
9
2
|
const defaultRandomAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
10
3
|
const maximumRandomStringLength = 1e6;
|
|
11
4
|
const maximumRandomValuesPerBatch = 16384;
|
|
12
5
|
const uint32Range = 4294967296;
|
|
13
6
|
/** 使用 Web Crypto 填充随机值,能力缺失时回退到 `Math.random()`。 */
|
|
14
7
|
const fillRandomValues = (values) => {
|
|
15
|
-
|
|
16
|
-
if (typeof crypto?.getRandomValues === "function") {
|
|
8
|
+
if (typeof crypto !== "undefined" && typeof crypto?.getRandomValues === "function") {
|
|
17
9
|
crypto.getRandomValues(values);
|
|
18
10
|
return;
|
|
19
11
|
}
|
|
@@ -23,37 +15,19 @@ const fillRandomValues = (values) => {
|
|
|
23
15
|
/**
|
|
24
16
|
* 把文本复制到系统剪贴板。
|
|
25
17
|
*
|
|
26
|
-
* @remarks
|
|
18
|
+
* @remarks 浏览器优先使用 Clipboard API,并在该 API 不可用时
|
|
27
19
|
* 回退到 `document.execCommand("copy")`。平台拒绝访问剪贴板时不会静默忽略错误。
|
|
28
|
-
* @param value -
|
|
29
|
-
* @returns 复制完成后兑现的 Promise
|
|
20
|
+
* @param value - 要复制的文本
|
|
21
|
+
* @returns 复制完成后兑现的 Promise
|
|
30
22
|
* @throws `Error` 当运行时没有可用的剪贴板能力或复制失败。
|
|
31
23
|
*/
|
|
32
24
|
async function copy(value) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
if (typeof uni !== "object" && typeof uni !== "function" || uni === null) throw new TypeError("全局 uni 对象未提供 `setClipboardData`。");
|
|
36
|
-
const clipboard = uni;
|
|
37
|
-
const setClipboardData = clipboard.setClipboardData?.bind(clipboard);
|
|
38
|
-
if (setClipboardData === void 0) throw new TypeError("全局 uni 对象未提供 `setClipboardData`。");
|
|
39
|
-
await new Promise((resolve, reject) => {
|
|
40
|
-
setClipboardData({
|
|
41
|
-
data: value,
|
|
42
|
-
fail: (error) => {
|
|
43
|
-
reject(error instanceof Error ? error : new Error("文本复制到剪贴板失败。", { cause: error }));
|
|
44
|
-
},
|
|
45
|
-
success: resolve
|
|
46
|
-
});
|
|
47
|
-
});
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
const browserClipboard = runtimeGlobals.navigator?.clipboard;
|
|
51
|
-
if (runtimeGlobals.isSecureContext === true && typeof browserClipboard?.writeText === "function") {
|
|
52
|
-
await browserClipboard.writeText(value);
|
|
25
|
+
if (typeof isSecureContext !== "undefined" && isSecureContext && typeof navigator !== "undefined" && typeof navigator.clipboard?.writeText === "function") {
|
|
26
|
+
await navigator.clipboard.writeText(value);
|
|
53
27
|
return;
|
|
54
28
|
}
|
|
55
|
-
|
|
56
|
-
if (typeof document
|
|
29
|
+
if (typeof document === "undefined" || document === null) throw new Error("The current runtime does not support clipboard access.");
|
|
30
|
+
if (typeof document.createElement !== "function" || document.body == null || typeof document.execCommand !== "function") throw new Error("The current runtime does not support clipboard access.");
|
|
57
31
|
const textarea = document.createElement("textarea");
|
|
58
32
|
textarea.value = value;
|
|
59
33
|
textarea.style.left = "-999999px";
|
|
@@ -69,7 +43,7 @@ async function copy(value) {
|
|
|
69
43
|
} finally {
|
|
70
44
|
textarea.remove();
|
|
71
45
|
}
|
|
72
|
-
if (!copied) throw new Error("
|
|
46
|
+
if (!copied) throw new Error("Failed to copy text to the clipboard.");
|
|
73
47
|
}
|
|
74
48
|
/**
|
|
75
49
|
* 生成随机字符串。
|
|
@@ -77,15 +51,15 @@ async function copy(value) {
|
|
|
77
51
|
* @remarks 优先使用 Web Crypto;平台缺少安全随机能力时回退到 `Math.random()`。
|
|
78
52
|
* @param length - 字符数量,必须是 0 至 1,000,000 的安全整数。
|
|
79
53
|
* @param alphabet - 不得为空、包含重复字符或超过 2^32 个 Unicode 码点。
|
|
80
|
-
* @returns 由 `alphabet` 中 Unicode
|
|
54
|
+
* @returns 由 `alphabet` 中 Unicode 码点组成的随机文本
|
|
81
55
|
* @throws `RangeError` 当长度或字母表非法。
|
|
82
56
|
*/
|
|
83
57
|
function randomString(length, alphabet = defaultRandomAlphabet) {
|
|
84
|
-
if (!Number.isSafeInteger(length) || length < 0 || length > maximumRandomStringLength) throw new RangeError(`\`length\`
|
|
58
|
+
if (!Number.isSafeInteger(length) || length < 0 || length > maximumRandomStringLength) throw new RangeError(`\`length\` must be a safe integer between 0 and ${maximumRandomStringLength}.`);
|
|
85
59
|
const characters = Array.from(alphabet);
|
|
86
|
-
if (characters.length === 0) throw new RangeError("`alphabet`
|
|
87
|
-
if (new Set(characters).size !== characters.length) throw new RangeError("`alphabet`
|
|
88
|
-
if (characters.length > 4294967296) throw new RangeError("`alphabet`
|
|
60
|
+
if (characters.length === 0) throw new RangeError("`alphabet` must not be empty.");
|
|
61
|
+
if (new Set(characters).size !== characters.length) throw new RangeError("`alphabet` must not contain duplicate characters.");
|
|
62
|
+
if (characters.length > 4294967296) throw new RangeError("`alphabet` must not contain more than 2^32 characters.");
|
|
89
63
|
if (length === 0) return "";
|
|
90
64
|
const acceptanceLimit = Math.floor(uint32Range / characters.length) * characters.length;
|
|
91
65
|
const result = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../../src/utils/string/index.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../../src/utils/string/index.ts"],"sourcesContent":["const defaultRandomAlphabet = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\nconst maximumRandomStringLength = 1_000_000;\nconst maximumRandomValuesPerBatch = 16_384;\nconst uint32Range = 0x1_0000_0000;\n\n/** 使用 Web Crypto 填充随机值,能力缺失时回退到 `Math.random()`。 */\nconst fillRandomValues = (values: Uint8Array<ArrayBuffer> | Uint32Array<ArrayBuffer>): void => {\n\tif (typeof crypto !== \"undefined\" && typeof crypto?.getRandomValues === \"function\") {\n\t\tcrypto.getRandomValues(values);\n\t\treturn;\n\t}\n\tconst range = values.BYTES_PER_ELEMENT === Uint8Array.BYTES_PER_ELEMENT ? 0x100 : uint32Range;\n\tfor (let index = 0; index < values.length; index += 1) values[index] = Math.floor(Math.random() * range);\n};\n\n/**\n * 把文本复制到系统剪贴板。\n *\n * @remarks 浏览器优先使用 Clipboard API,并在该 API 不可用时\n * 回退到 `document.execCommand(\"copy\")`。平台拒绝访问剪贴板时不会静默忽略错误。\n * @param value - 要复制的文本\n * @returns 复制完成后兑现的 Promise\n * @throws `Error` 当运行时没有可用的剪贴板能力或复制失败。\n */\nexport async function copy(value: string): Promise<void> {\n\tif (\n\t\ttypeof isSecureContext !== \"undefined\" &&\n\t\tisSecureContext &&\n\t\ttypeof navigator !== \"undefined\" &&\n\t\ttypeof navigator.clipboard?.writeText === \"function\"\n\t) {\n\t\tawait navigator.clipboard.writeText(value);\n\t\treturn;\n\t}\n\n\tif (typeof document === \"undefined\" || document === null) {\n\t\tthrow new Error(\"The current runtime does not support clipboard access.\");\n\t}\n\t// eslint-disable-next-line @typescript-eslint/no-deprecated -- 兼容不支持 Clipboard API 的旧 WebView。\n\tif (typeof document.createElement !== \"function\" || document.body == null || typeof document.execCommand !== \"function\") {\n\t\tthrow new Error(\"The current runtime does not support clipboard access.\");\n\t}\n\tconst textarea = document.createElement(\"textarea\");\n\ttextarea.value = value;\n\ttextarea.style.left = \"-999999px\";\n\ttextarea.style.opacity = \"0\";\n\ttextarea.style.position = \"fixed\";\n\ttextarea.style.top = \"-999999px\";\n\tdocument.body.appendChild(textarea);\n\tlet copied: boolean;\n\ttry {\n\t\ttextarea.focus();\n\t\ttextarea.select();\n\t\t// eslint-disable-next-line @typescript-eslint/no-deprecated -- 兼容不支持 Clipboard API 的旧 WebView。\n\t\tcopied = document.execCommand(\"copy\");\n\t} finally {\n\t\ttextarea.remove();\n\t}\n\tif (!copied) throw new Error(\"Failed to copy text to the clipboard.\");\n}\n\n/**\n * 生成随机字符串。\n *\n * @remarks 优先使用 Web Crypto;平台缺少安全随机能力时回退到 `Math.random()`。\n * @param length - 字符数量,必须是 0 至 1,000,000 的安全整数。\n * @param alphabet - 不得为空、包含重复字符或超过 2^32 个 Unicode 码点。\n * @returns 由 `alphabet` 中 Unicode 码点组成的随机文本\n * @throws `RangeError` 当长度或字母表非法。\n */\nexport function randomString(length: number, alphabet: string = defaultRandomAlphabet): string {\n\tif (!Number.isSafeInteger(length) || length < 0 || length > maximumRandomStringLength) {\n\t\tthrow new RangeError(`\\`length\\` must be a safe integer between 0 and ${maximumRandomStringLength}.`);\n\t}\n\tconst characters = Array.from(alphabet);\n\tif (characters.length === 0) throw new RangeError(\"`alphabet` must not be empty.\");\n\tif (new Set(characters).size !== characters.length) throw new RangeError(\"`alphabet` must not contain duplicate characters.\");\n\tif (characters.length > 0x1_0000_0000) throw new RangeError(\"`alphabet` must not contain more than 2^32 characters.\");\n\tif (length === 0) return \"\";\n\n\t// 丢弃不能平均映射到字母表的尾部区间,避免 `%` 造成前部字符概率偏高。\n\tconst acceptanceLimit = Math.floor(uint32Range / characters.length) * characters.length;\n\tconst result: string[] = [];\n\twhile (result.length < length) {\n\t\tconst remaining = length - result.length;\n\t\t// 分批填充可控制临时内存,并避开 Web Crypto 单次随机数组大小限制。\n\t\tconst samples = new Uint32Array(Math.min(remaining, maximumRandomValuesPerBatch));\n\t\tfillRandomValues(samples);\n\t\tfor (const sample of samples) {\n\t\t\tif (sample >= acceptanceLimit) continue;\n\t\t\tconst character = characters[sample % characters.length];\n\t\t\tif (character === undefined) continue;\n\t\t\tresult.push(character);\n\t\t\tif (result.length === length) break;\n\t\t}\n\t}\n\treturn result.join(\"\");\n}\n"],"mappings":";AAAA,MAAM,wBAAwB;AAC9B,MAAM,4BAA4B;AAClC,MAAM,8BAA8B;AACpC,MAAM,cAAc;;AAGpB,MAAM,oBAAoB,WAAqE;CAC9F,IAAI,OAAO,WAAW,eAAe,OAAO,QAAQ,oBAAoB,YAAY;EACnF,OAAO,gBAAgB,MAAM;EAC7B;CACD;CACA,MAAM,QAAQ,OAAO,sBAAsB,WAAW,oBAAoB,MAAQ;CAClF,KAAK,IAAI,QAAQ,GAAG,QAAQ,OAAO,QAAQ,SAAS,GAAG,OAAO,SAAS,KAAK,MAAM,KAAK,OAAO,IAAI,KAAK;AACxG;;;;;;;;;;AAWA,eAAsB,KAAK,OAA8B;CACxD,IACC,OAAO,oBAAoB,eAC3B,mBACA,OAAO,cAAc,eACrB,OAAO,UAAU,WAAW,cAAc,YACzC;EACD,MAAM,UAAU,UAAU,UAAU,KAAK;EACzC;CACD;CAEA,IAAI,OAAO,aAAa,eAAe,aAAa,MACnD,MAAM,IAAI,MAAM,wDAAwD;CAGzE,IAAI,OAAO,SAAS,kBAAkB,cAAc,SAAS,QAAQ,QAAQ,OAAO,SAAS,gBAAgB,YAC5G,MAAM,IAAI,MAAM,wDAAwD;CAEzE,MAAM,WAAW,SAAS,cAAc,UAAU;CAClD,SAAS,QAAQ;CACjB,SAAS,MAAM,OAAO;CACtB,SAAS,MAAM,UAAU;CACzB,SAAS,MAAM,WAAW;CAC1B,SAAS,MAAM,MAAM;CACrB,SAAS,KAAK,YAAY,QAAQ;CAClC,IAAI;CACJ,IAAI;EACH,SAAS,MAAM;EACf,SAAS,OAAO;EAEhB,SAAS,SAAS,YAAY,MAAM;CACrC,UAAU;EACT,SAAS,OAAO;CACjB;CACA,IAAI,CAAC,QAAQ,MAAM,IAAI,MAAM,uCAAuC;AACrE;;;;;;;;;;AAWA,SAAgB,aAAa,QAAgB,WAAmB,uBAA+B;CAC9F,IAAI,CAAC,OAAO,cAAc,MAAM,KAAK,SAAS,KAAK,SAAS,2BAC3D,MAAM,IAAI,WAAW,mDAAmD,0BAA0B,EAAE;CAErG,MAAM,aAAa,MAAM,KAAK,QAAQ;CACtC,IAAI,WAAW,WAAW,GAAG,MAAM,IAAI,WAAW,+BAA+B;CACjF,IAAI,IAAI,IAAI,UAAU,CAAC,CAAC,SAAS,WAAW,QAAQ,MAAM,IAAI,WAAW,mDAAmD;CAC5H,IAAI,WAAW,SAAS,YAAe,MAAM,IAAI,WAAW,wDAAwD;CACpH,IAAI,WAAW,GAAG,OAAO;CAGzB,MAAM,kBAAkB,KAAK,MAAM,cAAc,WAAW,MAAM,IAAI,WAAW;CACjF,MAAM,SAAmB,CAAC;CAC1B,OAAO,OAAO,SAAS,QAAQ;EAC9B,MAAM,YAAY,SAAS,OAAO;EAElC,MAAM,UAAU,IAAI,YAAY,KAAK,IAAI,WAAW,2BAA2B,CAAC;EAChF,iBAAiB,OAAO;EACxB,KAAK,MAAM,UAAU,SAAS;GAC7B,IAAI,UAAU,iBAAiB;GAC/B,MAAM,YAAY,WAAW,SAAS,WAAW;GACjD,IAAI,cAAc,KAAA,GAAW;GAC7B,OAAO,KAAK,SAAS;GACrB,IAAI,OAAO,WAAW,QAAQ;EAC/B;CACD;CACA,OAAO,OAAO,KAAK,EAAE;AACtB"}
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import type { ComputedRef } from "vue";
|
|
2
|
-
/** Vue Emits
|
|
2
|
+
/** Vue Emits 对象中允许的校验器形状 */
|
|
3
3
|
type EmitValidator = ((...arguments_: never[]) => unknown) | null;
|
|
4
|
-
/**
|
|
4
|
+
/** 事件名到可选参数校验器的内部映射 */
|
|
5
5
|
type EmitsOptions = Record<string, EmitValidator>;
|
|
6
6
|
/** 从校验器中提取事件参数;无校验器时保留未知参数。 */
|
|
7
7
|
type EventArguments<Validator> = Validator extends (...arguments_: infer Arguments) => unknown ? Arguments : unknown[];
|
|
8
|
-
/** 在类型层递归把 kebab-case 事件名转换为 PascalCase
|
|
8
|
+
/** 在类型层递归把 kebab-case 事件名转换为 PascalCase */
|
|
9
9
|
type PascalEventName<Value extends string> = Value extends `${infer Head}-${infer Tail}` ? `${Capitalize<Head>}${PascalEventName<Tail>}` : Capitalize<Value>;
|
|
10
|
-
/** 把事件配置映射为 Vue `onXxx`
|
|
10
|
+
/** 把事件配置映射为 Vue `onXxx` 属性 */
|
|
11
11
|
export type EmitHandlers<Emits extends EmitsOptions> = {
|
|
12
12
|
[Name in keyof Emits as Name extends string ? `on${PascalEventName<Name>}` : never]: (...arguments_: EventArguments<Emits[Name]>) => void;
|
|
13
13
|
};
|
|
14
14
|
/**
|
|
15
15
|
* 构建响应式 Vue 事件处理器。
|
|
16
16
|
*
|
|
17
|
-
* @param emits - Vue emits
|
|
18
|
-
* @param emit - `setup` 上下文提供的 emit
|
|
19
|
-
* @param ignoredEvents -
|
|
20
|
-
* @returns
|
|
17
|
+
* @param emits - Vue emits 配置对象
|
|
18
|
+
* @param emit - `setup` 上下文提供的 emit 函数
|
|
19
|
+
* @param ignoredEvents - 不需要向子组件透传的事件名
|
|
20
|
+
* @returns 随配置重新计算的事件处理器对象
|
|
21
21
|
*/
|
|
22
22
|
export declare function useEmits<Emits extends EmitsOptions>(emits: Emits, emit: (...arguments_: never[]) => unknown, ignoredEvents?: readonly (keyof Emits)[]): ComputedRef<Partial<EmitHandlers<Emits>>>;
|
|
23
23
|
export {};
|
package/dist/utils/vue/emits.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import { computed } from "vue";
|
|
|
4
4
|
* 把事件名转换为 Vue Handler Prop 名称。
|
|
5
5
|
*
|
|
6
6
|
* @param eventName - Emits 对象中的原始事件名,可使用 kebab-case。
|
|
7
|
-
* @returns `onPascalCase`
|
|
7
|
+
* @returns `onPascalCase` 形式的属性名
|
|
8
8
|
* @throws `TypeError` 当事件名包含空片段或无法生成有效 Handler 名称。
|
|
9
9
|
*/
|
|
10
10
|
const toHandlerName = (eventName) => {
|
|
@@ -13,10 +13,10 @@ const toHandlerName = (eventName) => {
|
|
|
13
13
|
/**
|
|
14
14
|
* 构建响应式 Vue 事件处理器。
|
|
15
15
|
*
|
|
16
|
-
* @param emits - Vue emits
|
|
17
|
-
* @param emit - `setup` 上下文提供的 emit
|
|
18
|
-
* @param ignoredEvents -
|
|
19
|
-
* @returns
|
|
16
|
+
* @param emits - Vue emits 配置对象
|
|
17
|
+
* @param emit - `setup` 上下文提供的 emit 函数
|
|
18
|
+
* @param ignoredEvents - 不需要向子组件透传的事件名
|
|
19
|
+
* @returns 随配置重新计算的事件处理器对象
|
|
20
20
|
*/
|
|
21
21
|
function useEmits(emits, emit, ignoredEvents = []) {
|
|
22
22
|
const ignored = new Set(ignoredEvents);
|
|
@@ -26,9 +26,9 @@ function useEmits(emits, emit, ignoredEvents = []) {
|
|
|
26
26
|
const handlerNames = /* @__PURE__ */ new Set();
|
|
27
27
|
for (const eventName of Object.keys(emits)) {
|
|
28
28
|
if (ignored.has(eventName)) continue;
|
|
29
|
-
if (eventName.length === 0 || /\s/u.test(eventName)) throw new TypeError(
|
|
29
|
+
if (eventName.length === 0 || /\s/u.test(eventName)) throw new TypeError(`Invalid Vue event name: "${eventName}".`);
|
|
30
30
|
const handlerName = toHandlerName(eventName);
|
|
31
|
-
if (handlerNames.has(handlerName)) throw new TypeError(
|
|
31
|
+
if (handlerNames.has(handlerName)) throw new TypeError(`Multiple Vue events map to the same handler property: "${handlerName}".`);
|
|
32
32
|
handlerNames.add(handlerName);
|
|
33
33
|
Object.defineProperty(handlers, handlerName, {
|
|
34
34
|
enumerable: true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emits.mjs","names":[],"sources":["../../../src/utils/vue/emits.ts"],"sourcesContent":["import { computed } from \"vue\";\nimport type { ComputedRef } from \"vue\";\n\n/** Vue Emits
|
|
1
|
+
{"version":3,"file":"emits.mjs","names":[],"sources":["../../../src/utils/vue/emits.ts"],"sourcesContent":["import { computed } from \"vue\";\nimport type { ComputedRef } from \"vue\";\n\n/** Vue Emits 对象中允许的校验器形状 */\ntype EmitValidator = ((...arguments_: never[]) => unknown) | null;\n/** 事件名到可选参数校验器的内部映射 */\ntype EmitsOptions = Record<string, EmitValidator>;\n/** 从校验器中提取事件参数;无校验器时保留未知参数。 */\ntype EventArguments<Validator> = Validator extends (...arguments_: infer Arguments) => unknown ? Arguments : unknown[];\n/** 在类型层递归把 kebab-case 事件名转换为 PascalCase */\ntype PascalEventName<Value extends string> = Value extends `${infer Head}-${infer Tail}`\n\t? `${Capitalize<Head>}${PascalEventName<Tail>}`\n\t: Capitalize<Value>;\n\n/** 把事件配置映射为 Vue `onXxx` 属性 */\nexport type EmitHandlers<Emits extends EmitsOptions> = {\n\t[Name in keyof Emits as Name extends string ? `on${PascalEventName<Name>}` : never]: (...arguments_: EventArguments<Emits[Name]>) => void;\n};\n\n/**\n * 把事件名转换为 Vue Handler Prop 名称。\n *\n * @param eventName - Emits 对象中的原始事件名,可使用 kebab-case。\n * @returns `onPascalCase` 形式的属性名\n * @throws `TypeError` 当事件名包含空片段或无法生成有效 Handler 名称。\n */\nconst toHandlerName = (eventName: string): string => {\n\treturn `on${eventName\n\t\t.split(\"-\")\n\t\t.map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n\t\t.join(\"\")}`;\n};\n\n/**\n * 构建响应式 Vue 事件处理器。\n *\n * @param emits - Vue emits 配置对象\n * @param emit - `setup` 上下文提供的 emit 函数\n * @param ignoredEvents - 不需要向子组件透传的事件名\n * @returns 随配置重新计算的事件处理器对象\n */\nexport function useEmits<Emits extends EmitsOptions>(\n\temits: Emits,\n\temit: (...arguments_: never[]) => unknown,\n\tignoredEvents: readonly (keyof Emits)[] = []\n): ComputedRef<Partial<EmitHandlers<Emits>>> {\n\tconst ignored = new Set<PropertyKey>(ignoredEvents);\n\tconst emitEvent = emit as (eventName: string, ...arguments_: unknown[]) => void;\n\treturn computed<Partial<EmitHandlers<Emits>>>(() => {\n\t\tconst handlers = {} as Partial<EmitHandlers<Emits>>;\n\t\tconst handlerNames = new Set<string>();\n\t\tfor (const eventName of Object.keys(emits)) {\n\t\t\tif (ignored.has(eventName)) continue;\n\t\t\tif (eventName.length === 0 || /\\s/u.test(eventName)) throw new TypeError(`Invalid Vue event name: \"${eventName}\".`);\n\t\t\tconst handlerName = toHandlerName(eventName);\n\t\t\tif (handlerNames.has(handlerName)) {\n\t\t\t\tthrow new TypeError(`Multiple Vue events map to the same handler property: \"${handlerName}\".`);\n\t\t\t}\n\t\t\thandlerNames.add(handlerName);\n\t\t\tObject.defineProperty(handlers, handlerName, {\n\t\t\t\tenumerable: true,\n\t\t\t\tvalue: (...arguments_: unknown[]) => {\n\t\t\t\t\temitEvent(eventName, ...arguments_);\n\t\t\t\t},\n\t\t\t\twritable: true,\n\t\t\t});\n\t\t}\n\t\treturn handlers;\n\t});\n}\n"],"mappings":";;;;;;;;;AA0BA,MAAM,iBAAiB,cAA8B;CACpD,OAAO,KAAK,UACV,MAAM,GAAG,CAAC,CACV,KAAK,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,YAAY,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,CAC3D,KAAK,EAAE;AACV;;;;;;;;;AAUA,SAAgB,SACf,OACA,MACA,gBAA0C,CAAC,GACC;CAC5C,MAAM,UAAU,IAAI,IAAiB,aAAa;CAClD,MAAM,YAAY;CAClB,OAAO,eAA6C;EACnD,MAAM,WAAW,CAAC;EAClB,MAAM,+BAAe,IAAI,IAAY;EACrC,KAAK,MAAM,aAAa,OAAO,KAAK,KAAK,GAAG;GAC3C,IAAI,QAAQ,IAAI,SAAS,GAAG;GAC5B,IAAI,UAAU,WAAW,KAAK,MAAM,KAAK,SAAS,GAAG,MAAM,IAAI,UAAU,4BAA4B,UAAU,GAAG;GAClH,MAAM,cAAc,cAAc,SAAS;GAC3C,IAAI,aAAa,IAAI,WAAW,GAC/B,MAAM,IAAI,UAAU,0DAA0D,YAAY,GAAG;GAE9F,aAAa,IAAI,WAAW;GAC5B,OAAO,eAAe,UAAU,aAAa;IAC5C,YAAY;IACZ,QAAQ,GAAG,eAA0B;KACpC,UAAU,WAAW,GAAG,UAAU;IACnC;IACA,UAAU;GACX,CAAC;EACF;EACA,OAAO;CACR,CAAC;AACF"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 同时暴露组件实例能力并返回同一个对象,便于 `setup` 返回状态供 Vue Devtools 查看。
|
|
3
3
|
*
|
|
4
|
-
* @param expose - `setup` 上下文提供的 expose
|
|
5
|
-
* @param exposed -
|
|
6
|
-
* @returns 原始 exposed
|
|
4
|
+
* @param expose - `setup` 上下文提供的 expose 函数
|
|
5
|
+
* @param exposed - 需要暴露的状态和方法
|
|
6
|
+
* @returns 原始 exposed 对象
|
|
7
7
|
*/
|
|
8
8
|
export declare function useExpose<Exposed extends object>(expose: (exposed?: Exposed) => void, exposed: Exposed): Exposed;
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* 同时暴露组件实例能力并返回同一个对象,便于 `setup` 返回状态供 Vue Devtools 查看。
|
|
4
4
|
*
|
|
5
|
-
* @param expose - `setup` 上下文提供的 expose
|
|
6
|
-
* @param exposed -
|
|
7
|
-
* @returns 原始 exposed
|
|
5
|
+
* @param expose - `setup` 上下文提供的 expose 函数
|
|
6
|
+
* @param exposed - 需要暴露的状态和方法
|
|
7
|
+
* @returns 原始 exposed 对象
|
|
8
8
|
*/
|
|
9
9
|
function useExpose(expose, exposed) {
|
|
10
10
|
expose(exposed);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expose.mjs","names":[],"sources":["../../../src/utils/vue/expose.ts"],"sourcesContent":["/**\n * 同时暴露组件实例能力并返回同一个对象,便于 `setup` 返回状态供 Vue Devtools 查看。\n *\n * @param expose - `setup` 上下文提供的 expose
|
|
1
|
+
{"version":3,"file":"expose.mjs","names":[],"sources":["../../../src/utils/vue/expose.ts"],"sourcesContent":["/**\n * 同时暴露组件实例能力并返回同一个对象,便于 `setup` 返回状态供 Vue Devtools 查看。\n *\n * @param expose - `setup` 上下文提供的 expose 函数\n * @param exposed - 需要暴露的状态和方法\n * @returns 原始 exposed 对象\n */\nexport function useExpose<Exposed extends object>(expose: (exposed?: Exposed) => void, exposed: Exposed): Exposed {\n\texpose(exposed);\n\treturn exposed;\n}\n"],"mappings":";;;;;;;;AAOA,SAAgB,UAAkC,QAAqC,SAA2B;CACjH,OAAO,OAAO;CACd,OAAO;AACR"}
|
package/dist/utils/vue/func.d.ts
CHANGED
|
@@ -3,8 +3,8 @@ export type AwaitableFunction<Arguments extends readonly unknown[], Result> = (.
|
|
|
3
3
|
/**
|
|
4
4
|
* 统一执行同步或异步函数,异常保持原样向调用方传播。
|
|
5
5
|
*
|
|
6
|
-
* @param function_ -
|
|
7
|
-
* @param arguments_ -
|
|
6
|
+
* @param function_ - 可选的待执行函数
|
|
7
|
+
* @param arguments_ - 原样传入函数的参数
|
|
8
8
|
* @returns 函数结果;未传函数时返回 `undefined`。
|
|
9
9
|
*/
|
|
10
10
|
export declare function callOptionalFunction<Arguments extends readonly unknown[], Result>(function_: AwaitableFunction<Arguments, Result> | null | undefined, ...arguments_: Arguments): Promise<Awaited<Result> | undefined>;
|
package/dist/utils/vue/func.mjs
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* 统一执行同步或异步函数,异常保持原样向调用方传播。
|
|
4
4
|
*
|
|
5
|
-
* @param function_ -
|
|
6
|
-
* @param arguments_ -
|
|
5
|
+
* @param function_ - 可选的待执行函数
|
|
6
|
+
* @param arguments_ - 原样传入函数的参数
|
|
7
7
|
* @returns 函数结果;未传函数时返回 `undefined`。
|
|
8
8
|
*/
|
|
9
9
|
async function callOptionalFunction(function_, ...arguments_) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"func.mjs","names":[],"sources":["../../../src/utils/vue/func.ts"],"sourcesContent":["/** 可同步或异步返回结果的函数。 */\nexport type AwaitableFunction<Arguments extends readonly unknown[], Result> = (...arguments_: Arguments) => Result | PromiseLike<Result>;\n\n/**\n * 统一执行同步或异步函数,异常保持原样向调用方传播。\n *\n * @param function_ -
|
|
1
|
+
{"version":3,"file":"func.mjs","names":[],"sources":["../../../src/utils/vue/func.ts"],"sourcesContent":["/** 可同步或异步返回结果的函数。 */\nexport type AwaitableFunction<Arguments extends readonly unknown[], Result> = (...arguments_: Arguments) => Result | PromiseLike<Result>;\n\n/**\n * 统一执行同步或异步函数,异常保持原样向调用方传播。\n *\n * @param function_ - 可选的待执行函数\n * @param arguments_ - 原样传入函数的参数\n * @returns 函数结果;未传函数时返回 `undefined`。\n */\nexport async function callOptionalFunction<Arguments extends readonly unknown[], Result>(\n\tfunction_: AwaitableFunction<Arguments, Result> | null | undefined,\n\t...arguments_: Arguments\n): Promise<Awaited<Result> | undefined> {\n\tif (function_ === null || function_ === undefined) return undefined;\n\treturn Promise.resolve(function_(...arguments_));\n}\n"],"mappings":";;;;;;;;AAUA,eAAsB,qBACrB,WACA,GAAG,YACoC;CACvC,IAAI,cAAc,QAAQ,cAAc,KAAA,GAAW,OAAO,KAAA;CAC1D,OAAO,QAAQ,QAAQ,UAAU,GAAG,UAAU,CAAC;AAChD"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { App } from "vue";
|
|
2
|
-
/** Vue
|
|
2
|
+
/** Vue 组件对象、函数组件或指令对象可接受的最小结构类型 */
|
|
3
3
|
export type VueInstallValue = object | ((...arguments_: never[]) => unknown);
|
|
4
|
-
/** 为 Vue 组件或指令附加供 Vue 3 `app.use()`
|
|
4
|
+
/** 为 Vue 组件或指令附加供 Vue 3 `app.use()` 调用的安装能力 */
|
|
5
5
|
export type Installable<Value> = Value & {
|
|
6
6
|
/**
|
|
7
7
|
* 把当前组件或指令安装到 Vue 3 App。
|
|
8
|
-
* @param app - Vue 3 App
|
|
8
|
+
* @param app - Vue 3 App 实例
|
|
9
9
|
*/
|
|
10
10
|
install: (app: App) => void;
|
|
11
11
|
};
|
|
@@ -16,8 +16,8 @@ export type TSXWithInstall<Value> = Installable<Value>;
|
|
|
16
16
|
*
|
|
17
17
|
* @remarks 函数会直接为 `main` 定义附属组件属性和 `install`。所有组件名称、附属属性
|
|
18
18
|
* 冲突会在修改 `main` 前完成校验;安装到 App 时也会先预检全部全局名称,再统一注册。
|
|
19
|
-
* @param main - 具有非空 `name`
|
|
20
|
-
* @param extras -
|
|
19
|
+
* @param main - 具有非空 `name` 的组件
|
|
20
|
+
* @param extras - 同时注册并以可枚举属性挂到主组件的附属组件映射
|
|
21
21
|
* @returns 原始 `main` 引用,并附加类型化的 `install` 与 `extras` 属性。
|
|
22
22
|
* @throws `TypeError` 当组件缺少合法名称、已有 `install`、附属键或名称发生冲突。
|
|
23
23
|
* @throws `Error` 当 App 中同名位置已经注册其他组件。
|
|
@@ -28,8 +28,8 @@ export declare function withInstall<Main extends VueInstallValue, Extras extends
|
|
|
28
28
|
*
|
|
29
29
|
* @remarks 适用于只能作为主组件附属属性使用、但仍需满足 Vue Plugin 类型的组件。
|
|
30
30
|
* 函数直接修改并返回传入组件,不会向 Vue 3 App 注册内容。
|
|
31
|
-
* @param component - 尚未定义或继承 `install`
|
|
32
|
-
* @returns 原组件引用及无副作用的 `install`
|
|
31
|
+
* @param component - 尚未定义或继承 `install` 属性的组件
|
|
32
|
+
* @returns 原组件引用及无副作用的 `install` 方法
|
|
33
33
|
* @throws `TypeError` 当组件自身或原型链已经存在 `install`。
|
|
34
34
|
*/
|
|
35
35
|
export declare function withNoopInstall<Value extends VueInstallValue>(component: Value): TSXWithInstall<Value>;
|
|
@@ -38,8 +38,8 @@ export declare function withNoopInstall<Value extends VueInstallValue>(component
|
|
|
38
38
|
*
|
|
39
39
|
* @remarks 函数直接修改并返回指令。安装时重复注册同一引用保持幂等,不会覆盖同名的
|
|
40
40
|
* 其他指令。名称只传给 `directive()`,不得包含 `v-` 前缀。
|
|
41
|
-
* @param directive - 尚未定义或继承 `install` 属性的 Vue
|
|
42
|
-
* @param name - 非空、无空白且不以 `v-`
|
|
41
|
+
* @param directive - 尚未定义或继承 `install` 属性的 Vue 指令对象
|
|
42
|
+
* @param name - 非空、无空白且不以 `v-` 开头的全局指令名
|
|
43
43
|
* @returns 原指令引用及 Vue Plugin `install` 方法。
|
|
44
44
|
* @throws `TypeError` 当名称非法、指令已有 `install`,或安装目标无效。
|
|
45
45
|
* @throws `Error` 当 App 中同名位置已经注册其他指令。
|
|
@@ -2,41 +2,41 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* 校验 Vue 3 插件安装目标。
|
|
4
4
|
*
|
|
5
|
-
* @param value - Vue 3 App
|
|
6
|
-
* @returns 只包含组件和指令注册能力的 App
|
|
5
|
+
* @param value - Vue 3 App 实例
|
|
6
|
+
* @returns 只包含组件和指令注册能力的 App
|
|
7
7
|
* @throws `TypeError` 当目标不是对象或缺少 `component`、`directive` 方法。
|
|
8
8
|
*/
|
|
9
9
|
const assertApp = (value) => {
|
|
10
|
-
if (typeof value !== "object" || value === null) throw new TypeError("
|
|
10
|
+
if (typeof value !== "object" || value === null) throw new TypeError("Installing a Vue plugin requires a Vue 3 App instance.");
|
|
11
11
|
const app = value;
|
|
12
|
-
if (typeof app.component !== "function" || typeof app.directive !== "function") throw new TypeError("
|
|
12
|
+
if (typeof app.component !== "function" || typeof app.directive !== "function") throw new TypeError("Installing a Vue plugin requires `component()` and `directive()` registration methods.");
|
|
13
13
|
return app;
|
|
14
14
|
};
|
|
15
15
|
/**
|
|
16
16
|
* 提取组件的全局注册名称。
|
|
17
17
|
*
|
|
18
|
-
* @param component -
|
|
19
|
-
* @returns
|
|
18
|
+
* @param component - 待注册组件
|
|
19
|
+
* @returns 经过校验的显式名称
|
|
20
20
|
* @throws `TypeError` 当组件没有非空字符串名称,或名称包含空白。
|
|
21
21
|
*/
|
|
22
22
|
const getComponentName = (component) => {
|
|
23
23
|
const name = component.name;
|
|
24
|
-
if (typeof name !== "string" || name.length === 0 || /\s/u.test(name)) throw new TypeError("
|
|
24
|
+
if (typeof name !== "string" || name.length === 0 || /\s/u.test(name)) throw new TypeError("An installable Vue component must expose a nonempty name without whitespace.");
|
|
25
25
|
return name;
|
|
26
26
|
};
|
|
27
27
|
/**
|
|
28
28
|
* 预检单个组件注册。
|
|
29
29
|
*
|
|
30
30
|
* @remarks 先读取同名组件并完成冲突判断,再返回延迟执行动作;调用方可以在所有组件预检通过后统一提交。
|
|
31
|
-
* @param app - 已校验的 Vue 3 App
|
|
32
|
-
* @param component -
|
|
31
|
+
* @param app - 已校验的 Vue 3 App 注册目标
|
|
32
|
+
* @param component - 待注册组件
|
|
33
33
|
* @returns 已校验的组件引用、名称和目标中是否已经存在同一引用。
|
|
34
34
|
* @throws `Error` 当同名位置已由其他组件占用。
|
|
35
35
|
*/
|
|
36
36
|
const prepareComponentRegistration = (app, component) => {
|
|
37
37
|
const name = getComponentName(component);
|
|
38
38
|
const existing = app.component(name);
|
|
39
|
-
if (existing !== void 0 && existing !== component) throw new Error(`Vue
|
|
39
|
+
if (existing !== void 0 && existing !== component) throw new Error(`The Vue component name "${name}" is already registered to another component.`);
|
|
40
40
|
return {
|
|
41
41
|
component,
|
|
42
42
|
name,
|
|
@@ -48,22 +48,22 @@ const prepareComponentRegistration = (app, component) => {
|
|
|
48
48
|
*
|
|
49
49
|
* @remarks 函数会直接为 `main` 定义附属组件属性和 `install`。所有组件名称、附属属性
|
|
50
50
|
* 冲突会在修改 `main` 前完成校验;安装到 App 时也会先预检全部全局名称,再统一注册。
|
|
51
|
-
* @param main - 具有非空 `name`
|
|
52
|
-
* @param extras -
|
|
51
|
+
* @param main - 具有非空 `name` 的组件
|
|
52
|
+
* @param extras - 同时注册并以可枚举属性挂到主组件的附属组件映射
|
|
53
53
|
* @returns 原始 `main` 引用,并附加类型化的 `install` 与 `extras` 属性。
|
|
54
54
|
* @throws `TypeError` 当组件缺少合法名称、已有 `install`、附属键或名称发生冲突。
|
|
55
55
|
* @throws `Error` 当 App 中同名位置已经注册其他组件。
|
|
56
56
|
*/
|
|
57
57
|
function withInstall(main, extras) {
|
|
58
58
|
const componentNames = /* @__PURE__ */ new Set([getComponentName(main)]);
|
|
59
|
-
if ("install" in Object(main)) throw new TypeError("Vue
|
|
59
|
+
if ("install" in Object(main)) throw new TypeError("The Vue component already defines an `install` property.");
|
|
60
60
|
const extraEntries = Object.entries(extras ?? {});
|
|
61
|
-
if (extras !== void 0 && Object.getOwnPropertySymbols(extras).some((key) => Object.prototype.propertyIsEnumerable.call(extras, key))) throw new TypeError("Vue
|
|
61
|
+
if (extras !== void 0 && Object.getOwnPropertySymbols(extras).some((key) => Object.prototype.propertyIsEnumerable.call(extras, key))) throw new TypeError("Vue component extras must use string property names.");
|
|
62
62
|
for (const [key, component] of extraEntries) {
|
|
63
63
|
const componentName = getComponentName(component);
|
|
64
|
-
if (componentNames.has(componentName)) throw new TypeError(`Vue
|
|
64
|
+
if (componentNames.has(componentName)) throw new TypeError(`The Vue component name "${componentName}" is registered more than once.`);
|
|
65
65
|
componentNames.add(componentName);
|
|
66
|
-
if (key === "install" || key in Object(main)) throw new TypeError(`Vue
|
|
66
|
+
if (key === "install" || key in Object(main)) throw new TypeError(`The Vue component extra "${key}" would overwrite a property on the main component.`);
|
|
67
67
|
}
|
|
68
68
|
const installable = main;
|
|
69
69
|
for (const [key, component] of extraEntries) Object.defineProperty(installable, key, {
|
|
@@ -84,12 +84,12 @@ function withInstall(main, extras) {
|
|
|
84
84
|
*
|
|
85
85
|
* @remarks 适用于只能作为主组件附属属性使用、但仍需满足 Vue Plugin 类型的组件。
|
|
86
86
|
* 函数直接修改并返回传入组件,不会向 Vue 3 App 注册内容。
|
|
87
|
-
* @param component - 尚未定义或继承 `install`
|
|
88
|
-
* @returns 原组件引用及无副作用的 `install`
|
|
87
|
+
* @param component - 尚未定义或继承 `install` 属性的组件
|
|
88
|
+
* @returns 原组件引用及无副作用的 `install` 方法
|
|
89
89
|
* @throws `TypeError` 当组件自身或原型链已经存在 `install`。
|
|
90
90
|
*/
|
|
91
91
|
function withNoopInstall(component) {
|
|
92
|
-
if ("install" in Object(component)) throw new TypeError("Vue
|
|
92
|
+
if ("install" in Object(component)) throw new TypeError("The Vue component already defines an `install` property.");
|
|
93
93
|
const installable = component;
|
|
94
94
|
installable.install = () => void 0;
|
|
95
95
|
return installable;
|
|
@@ -99,20 +99,20 @@ function withNoopInstall(component) {
|
|
|
99
99
|
*
|
|
100
100
|
* @remarks 函数直接修改并返回指令。安装时重复注册同一引用保持幂等,不会覆盖同名的
|
|
101
101
|
* 其他指令。名称只传给 `directive()`,不得包含 `v-` 前缀。
|
|
102
|
-
* @param directive - 尚未定义或继承 `install` 属性的 Vue
|
|
103
|
-
* @param name - 非空、无空白且不以 `v-`
|
|
102
|
+
* @param directive - 尚未定义或继承 `install` 属性的 Vue 指令对象
|
|
103
|
+
* @param name - 非空、无空白且不以 `v-` 开头的全局指令名
|
|
104
104
|
* @returns 原指令引用及 Vue Plugin `install` 方法。
|
|
105
105
|
* @throws `TypeError` 当名称非法、指令已有 `install`,或安装目标无效。
|
|
106
106
|
* @throws `Error` 当 App 中同名位置已经注册其他指令。
|
|
107
107
|
*/
|
|
108
108
|
function withInstallDirective(directive, name) {
|
|
109
|
-
if (name.length === 0 || /\s/u.test(name) || name.startsWith("v-")) throw new TypeError("
|
|
110
|
-
if ("install" in Object(directive)) throw new TypeError("Vue
|
|
109
|
+
if (name.length === 0 || /\s/u.test(name) || name.startsWith("v-")) throw new TypeError("An installable Vue directive name must not contain whitespace or the `v-` prefix.");
|
|
110
|
+
if ("install" in Object(directive)) throw new TypeError("The Vue directive already defines an `install` property.");
|
|
111
111
|
const installable = directive;
|
|
112
112
|
installable.install = (value) => {
|
|
113
113
|
const app = assertApp(value);
|
|
114
114
|
const existing = app.directive(name);
|
|
115
|
-
if (existing !== void 0 && existing !== directive) throw new Error(`Vue
|
|
115
|
+
if (existing !== void 0 && existing !== directive) throw new Error(`The Vue directive name "${name}" is already registered to another directive.`);
|
|
116
116
|
if (existing !== directive) app.directive(name, directive);
|
|
117
117
|
};
|
|
118
118
|
return installable;
|