{"version":3,"file":"index.cjs","sources":["../src/type/type.ts","../src/utils/clone.ts","../src/utils/chunk.ts","../src/utils/copy.ts","../src/utils/debounce.ts","../src/type/identityCodeValid.ts","../src/type/isChinesePhone.ts","../src/type/isEqualArray.ts","../src/type/isHttpUrl.ts","../src/math/index.ts","../src/utils/normalizeMoney.ts","../src/utils/randomNum.ts","../src/utils/randomStr.ts","../src/utils/removeRepeat.ts","../src/utils/repeatRun.ts","../src/utils/throttle.ts","../src/utils/uuid.ts"],"sourcesContent":["/**\n * @group 类型检查\n * @param {any} value 需要检查类型的值\n * @returns {string} 返回类型的小写字符串\n */\nfunction type(value: any): string {\n  const typeStr = Object.prototype.toString.call(value)\n  return typeStr.slice(8, -1).toLowerCase()\n}\n\n/**\n * @group 类型检查\n * @param value\n * @returns\n */\nfunction isObject(value: any) {\n  return typeof value === 'object' && value !== null\n}\n/**\n * @group 类型检查\n * @param value\n * @returns\n */\nfunction isPrimitive(value: any) {\n  return (\n    value === null ||\n    typeof value === 'boolean' ||\n    typeof value === 'number' ||\n    typeof value === 'bigint' ||\n    typeof value === 'string' ||\n    typeof value === 'symbol' || // ES6 symbol\n    typeof value === 'undefined'\n  )\n}\n/**\n * @group 类型检查\n * @param e\n * @returns\n */\nfunction isError(e: any) {\n  return type(e) === 'error' || e instanceof Error\n}\n\n/**\n * @group 类型检查\n * @param value\n * @returns\n */\nfunction isDate(d: any) {\n  return type(d) === 'date'\n}\n\n/**\n * @group 类型检查\n * @param value\n * @returns\n */\nfunction isArray(value: any) {\n  if (Array.isArray) {\n    return Array.isArray(value)\n  }\n  return type(value) === 'array'\n}\n\n/**\n * @group 类型检查\n * @param value\n * @returns\n */\nfunction isBoolean(value: any) {\n  return typeof value === 'boolean'\n}\n\n/**\n * @group 类型检查\n * @param value\n * @returns\n */\nfunction isNull(value: any) {\n  return value === null\n}\n\n/**\n * @group 类型检查\n * @description 检查是否为 null 或者 undefined\n * @param value\n * @returns\n */\nfunction isNullish(value: any) {\n  // https://stackoverflow.com/a/46716365/6524962\n  return value == null\n}\n\n\n/**\n * @group 类型检查\n * @description 检查给定的值是否为数字 是 number 或 bigint，则返回 true，否则返回 false\n * @param value - 要检查的值，可以是任何类型\n * @return 如果是数字或 BigInt，则返回 true，否则返回 false\n */\nfunction isNumber(value: any) {\n  // NaN, Infinity, -Infinity\n  // NaN - NaN  =  NaN\n  // Infinity - Infinity = NaN\n  // -Infinity - -Infinity = NaN\n  // Infinity * 0 = NaN\n  // NaN * 0 = NaN\n  // -Infinity * 0 = NaN\n  if (typeof value === 'number') return value * 0 === 0\n  if (typeof value === 'bigint') return true\n  return false\n}\n/**\n * @group 类型检查\n * @description  检查给定的值是否为数值，包括数字、字符串数字 和 BigInt\n * 此外，如果给定值是一个非空字符串，它将尝试将其转换为数字并检查其有效性\n * @param value - 要检查的值，可以是任何类型\n * @return 如果是数字或可转换为有效数字的字符串，则返回 true，否则返回 false\n */\nfunction isNumerical(value: any) {\n  if (typeof value === 'number') return value * 0 === 0\n  if (typeof value === 'bigint') return true\n  if (isString(value) && value.trim() !== '') {\n    return Number.isFinite ? Number.isFinite(+value) : isFinite(+value)\n  }\n  return false\n}\n\n/**\n * @group 类型检查\n * @param value\n * @returns\n */\nfunction isString(value: any) {\n  return typeof value === 'string'\n}\n\n/**\n * @group 类型检查\n * @param value\n * @returns\n */\nfunction isEmptyStr(value: any) {\n  return value === ''\n}\n\n/**\n * @group 类型检查\n * @param value\n * @returns\n */\nfunction hasStr(value: any) {\n  return isString(value) && value !== ''\n}\n\n/**\n * @group 类型检查\n * @param value\n * @returns\n */\nfunction isSymbol(value: any) {\n  return typeof value === 'symbol'\n}\n\n/**\n * @group 类型检查\n * @param value\n * @returns\n */\nfunction isUndefined(value: any) {\n  return value === void 0\n}\n\n/**\n * @group 类型检查\n * @param value\n * @returns\n */\nfunction isRegExp(value: any) {\n  return type(value) === 'regexp'\n}\n\n/**\n * @group 类型检查\n * @param value\n * @returns\n */\nfunction isFalsy(value: any) {\n  return !value // 0 '' NaN null undefined\n}\n\n/**\n * @group 类型检查\n * @param value\n * @returns\n */\nfunction isFalsyNon0(value: any) {\n  return !value && value !== 0\n}\n/**\n * @group 类型检查\n * @param value\n * @returns\n */\nfunction isTruthy(value: any) {\n  return !!value\n}\n\n/**\n * @group 类型检查\n * @param value\n * @returns\n */\nfunction isFunction(value: any) {\n  if (isNullish(value)) return false\n  if (value) {\n    return (\n      type(value) === 'function' ||\n      'function' === typeof value ||\n      value instanceof Function\n    )\n  }\n  return false\n}\n\n/**\n * @group 类型检查\n * @param value\n * @returns\n */\nfunction isEmpty(value: any) {\n  // ''\n  if (isEmptyStr(value)) return true\n  // []\n  if (Array.isArray(value)) return value.length === 0\n  // null undefined\n  if (isNullish(value)) return true\n  if (isObject(value)) {\n    for (var prop in value) {\n      if (value.hasOwnProperty(prop)) return false\n    }\n    return true\n  }\n  return false\n}\n\nexport {\n  type,\n  isObject,\n  isArray,\n  isBoolean,\n  isDate,\n  isError,\n  isNull,\n  isUndefined,\n  isNullish,\n  isNumber,\n  isNumerical,\n  isString,\n  isSymbol,\n  isRegExp,\n  isPrimitive,\n  isFalsy,\n  isFalsyNon0,\n  isTruthy,\n  isFunction,\n  isEmptyStr,\n  isEmpty,\n}\n","/*\n * @Author      : ZhouQiJun\n * @Date        : 2023-04-29 20:19:57\n * @LastEditors : ZhouQiJun\n * @LastEditTime: 2025-03-22 22:31:32\n * @Description : 深复制\n */\nimport { type } from '../type/type'\n\n// import from from 'core-js/features/array/from'\n/**\n * @group 工具函数\n * @param {any} source\n * @returns\n */\nconst clone = <T>(source: T) => {\n  const t = type(source)\n  if (!['object', 'array'].includes(t)) return source\n  let target\n  if (t === 'array') {\n    target = []\n    let i = 0\n    const len = (source as Array<any>).length\n    while (i < len) {\n      target[i] = clone(source[i])\n      i++\n    }\n  } else if (t === 'object') {\n    target = {}\n    for (const key in source) {\n      if (Object.prototype.hasOwnProperty.call(source, key)) {\n        // @ts-ignore\n        target[key] = clone(source[key])\n      }\n    }\n  }\n  return target\n}\n\nexport { clone }\n","/*\n * @Author      : ZhouQiJun\n * @Date        : 2024-08-18 00:32:26\n * @LastEditors : ZhouQiJun\n * @LastEditTime: 2025-03-22 22:29:50\n * @Description : 数组分块\n */\nimport { isNumber } from '../type/type'\n\n/**\n * @group 工具函数\n * @param array 数组\n * @param size 分块大小\n * @returns  返回分块后的数组\n */\nexport function chunk<T>(array: T[], size: number): T[][] {\n  if (!Array.isArray(array)) {\n    throw new Error('第一个参数必须是一个一维数组')\n  }\n  if (!isNumber(size)) {\n    throw new Error('第二个参数必须是一个数字')\n  }\n  const result: T[][] = []\n  for (let i = 0; i < array.length; i += size) {\n    result.push(array.slice(i, i + size))\n  }\n  return result\n}\n","/* eslint-disable @typescript-eslint/no-unused-vars */\n/*\n * @Author      : ZhouQiJun\n * @Date        : 2024-05-28 10:20:59\n * @LastEditors : ZhouQiJun\n * @LastEditTime: 2025-03-22 21:54:35\n * @Description : 复制文本\n */\n/**\n * @group 工具函数\n * @description  copy text\n * @param text some text you want to copy\n * @returns\n */\nexport function copy(text: string): Promise<boolean> {\n  if (navigator.clipboard && navigator.permissions) {\n    return navigator.clipboard\n      .writeText(text)\n      .then(() => {\n        return Promise.resolve(true)\n      })\n      .catch(() => {\n        return Promise.resolve(false)\n      })\n  } else {\n    return new Promise(resolve => {\n      const textArea = document.createElement('textArea')\n      // @ts-ignore\n      textArea.value = text\n      textArea.style.width = '0px'\n      textArea.style.position = 'fixed'\n      textArea.style.left = '-999px'\n      textArea.style.top = '10px'\n      textArea.setAttribute('readonly', 'readonly')\n      document.body.appendChild(textArea)\n      // @ts-ignore\n      textArea.select()\n      document.execCommand('copy')\n      document.body.removeChild(textArea)\n      resolve(true)\n    })\n  }\n}\n","/*\n * @Author      : ZhouQiJun\n * @Date        : 2024-05-28 03:00:17\n * @LastEditors : ZhouQiJun\n * @LastEditTime: 2025-03-23 21:13:48\n * @Description : 防抖\n */\n/**\n * @group 工具函数\n * @param fn function need to debounce\n * @param wait debounce time default 200ms\n * @param immediate if true, execute immediately when trigger, default false\n * @returns\n */\nexport function debounce(fn, wait = 200, immediate = false) {\n  let timer\n  return (...rest) => {\n    immediate && !timer && fn(...rest)\n    if (timer) {\n      clearTimeout(timer)\n    }\n    timer = setTimeout(() => {\n      fn(...rest)\n    }, wait)\n  }\n}\n","import { isEmptyStr, isNullish, isNumber, isString } from './type'\n\n/**\n * @group 类型检查\n * @description 身份证号合法性验证，支持15位和18位身份证号，支持地址编码、出生日期、校验位验证\n * @param code\n * @returns {[boolean,string]} 该函数返回一个数组 [true,''] 或 [false,\"身份证号格式错误\"]\n * ============================================================================================\n * 根据〖中华人民共和国国家标准 GB 11643-1999〗中有关公民身份号码的规定，公民身份号码是特征组合码，由十七位数字本体码和一位数字校验码组成。\n * 排列顺序从左至右依次为：六位数字地址码，八位数字出生日期码，三位数字顺序码和一位数字校验码。\n * 地址码表示编码对象常住户口所在县(市、旗、区)的行政区划代码。\n * 出生日期码表示编码对象出生的年、月、日，其中年份用四位数字表示，年、月、日之间不用分隔符。\n * 顺序码表示同一地址码所标识的区域范围内，对同年、月、日出生的人员编定的顺序号。顺序码的奇数分给男性，偶数分给女性。\n * 校验码是根据前面十七位数字码，按照ISO 7064:1983.MOD 11-2校验码计算出来的检验码。\n * 出生日期计算方法。\n * 15位的身份证编码首先把出生年扩展为4位，简单的就是增加一个19或18,这样就包含了所有1800-1999年出生的人;\n * 2000年后出生的肯定都是18位的了没有这个烦恼，至于1800年前出生的,那啥那时应该还没身份证号这个东东，⊙﹏⊙b汗...\n * 下面是正则表达式:\n * 出生日期1800-2099  (18|19|20)?\\d{2}(0[1-9]|1[12])(0[1-9]|[12]\\d|3[01])\n * 身份证正则表达式 /^\\d{6}(18|19|20)?\\d{2}(0[1-9]|1[12])(0[1-9]|[12]\\d|3[01])\\d{3}(\\d|X)$/i\n * 15位校验规则 6位地址编码+6位出生日期+3位顺序号\n * 18位校验规则 6位地址编码+8位出生日期+3位顺序号+1位校验位\n * 校验位规则     公式:∑(ai×Wi)(mod 11)……………………………………(1)\n * 公式(1)中：\n * i----表示号码字符从由至左包括校验码在内的位置序号；\n * ai----表示第i位置上的号码字符值；\n * Wi----示第i位置上的加权因子，其数值依据公式Wi=2^(n-1）(mod 11)计算得出。\n * i 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1\n * Wi 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2 1\n *\n */\nfunction identityCodeValid(code: string | number): [boolean, string] {\n  if (isNullish(code) || isEmptyStr(code)) return [false, '身份证号不能为空']\n  if (!isNumber(code) && !isString(code))\n    return [false, '身份证号必须是数字或者字符串']\n  code = code.toString()\n  const city: any = {\n    11: '北京',\n    12: '天津',\n    13: '河北',\n    14: '山西',\n    15: '内蒙古',\n    21: '辽宁',\n    22: '吉林',\n    23: '黑龙江 ',\n    31: '上海',\n    32: '江苏',\n    33: '浙江',\n    34: '安徽',\n    35: '福建',\n    36: '江西',\n    37: '山东',\n    41: '河南',\n    42: '湖北 ',\n    43: '湖南',\n    44: '广东',\n    45: '广西',\n    46: '海南',\n    50: '重庆',\n    51: '四川',\n    52: '贵州',\n    53: '云南',\n    54: '西藏 ',\n    61: '陕西',\n    62: '甘肃',\n    63: '青海',\n    64: '宁夏',\n    65: '新疆',\n    71: '台湾',\n    81: '香港',\n    82: '澳门',\n    91: '国外 ',\n  }\n  let tip = ''\n  let pass = true\n\n  if (code.length !== 15 && code.length !== 18) {\n    return [false, '身份证号长度错误, 必须是15位或者18位']\n  }\n\n  const codeRegex =\n    /^\\d{6}(18|19|20)?\\d{2}(0[1-9]|1[012])(0[1-9]|[12]\\d|3[01])\\d{3}(\\d|[xX])$/i\n  const isFormatCorrect = codeRegex.test(code)\n\n  if (!isFormatCorrect) {\n    return [false, '身份证号格式错误']\n  }\n\n  if (!city[code.slice(0, 2)]) {\n    return [false, '地址编码错误']\n  }\n\n  //18位身份证需要验证最后一位校验位\n  if (code.length == 18) {\n    const arr = code.split('')\n    //∑(ai×Wi)(mod 11)\n    //加权因子\n    const factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]\n    //校验位\n    const parity = [1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2]\n    let sum = 0\n    let ai = 0\n    let wi = 0\n    for (let i = 0; i < 17; i++) {\n      ai = +arr[i]\n      wi = factor[i]\n      sum += ai * wi\n    }\n    const last = parity[sum % 11]\n    if (last != arr[17]) {\n      tip = '校验位错误,结尾是字母请注意大小写'\n      pass = false\n    }\n  }\n\n  return [pass, tip]\n}\n\nexport { identityCodeValid }\n","/*\n * @Author      : ZhouQiJun\n * @Date        : 2024-05-01 18:32:48\n * @LastEditors : ZhouQiJun\n * @LastEditTime: 2025-03-22 22:42:35\n * @Description : 检查是否为中国大陆号码\n */\n\n/**\n * @group 类型检查\n * @param number 待检测的手机号码\n * @returns\n */\nexport function isChinesePhone(number: string): boolean {\n  // const phoneReg =\n  //   /^(((13[0-9]{1})|(14[0-9]{1})|(15[0-9]{1})|(16[0-9]{1})|(17[0-9]{1})|(18[0-9]{1}))+\\d{8})$/\n  const phoneReg = /^1[3-9]\\d{9}$/\n  return phoneReg.test(number)\n}\n","/*\n * @Author      : ZhouQiJun\n * @Date        : 2024-05-01 19:22:50\n * @LastEditors : ZhouQiJun\n * @LastEditTime: 2025-03-22 22:44:55\n * @Description : 数组元素是否相同\n */\n/**\n * @group 类型检查\n * @param arr1 第一个数组\n * @param arr2 第二个数组\n * @returns\n */\nexport function isEqualArray(arr1: any[], arr2: any[]): boolean {\n  if (arr1.length !== arr2.length) {\n    return false\n  }\n  for (let i = 0; i < arr1.length; i++) {\n    if (arr1[i] !== arr2[i]) {\n      return false\n    }\n  }\n  return true\n}\n","/*\n * @Author      : ZhouQiJun\n * @Date        : 2024-05-02 00:01:01\n * @LastEditors : ZhouQiJun\n * @LastEditTime: 2025-03-22 22:43:44\n * @Description : 检查字符是否为 http 网址\n */\n/**\n * @group 类型检查\n * @param string 检查字符串是否为 http 地址\n * @returns\n */\nexport function isHttpUrl(string: string): boolean {\n  let url\n\n  try {\n    url = new URL(string)\n  } catch (_) {\n    return false\n  }\n\n  return url.protocol === 'http:' || url.protocol === 'https:'\n}\n","/*\n * @Author      : ZhouQiJun\n * @Date        : 2024-11-28 11:34:51\n * @LastEditors : ZhouQiJun\n * @LastEditTime: 2024-11-28 12:59:40\n * @Description : math 相关函数\n */\n/**\n * m mod n,\n * it is different from % operator in javascript\n * % operator is remainder operator,  m % n is same to  m - n * Math.trunc(m / n).\n * Modulo operator is m mod n is same to  m - n * Math.floor(m / n)\n * {@link https://www.designcise.com/web/tutorial/what-is-the-difference-between-the-javascript-remainder-operator-and-the-modulo-operator}\n * @example\n * modulo(7, 3) // 1\n * modulo(-7, -3) // -1\n * modulo(7, -3) // -2\n * modulo(-7, 3) // 2\n * @param m\n * @param n\n * @returns\n */\nfunction modulo(m: number, n: number): number {\n  // same to\n  // m - n * Math.floor(m / n)\n  return ((m % n) + n) % n\n}\n\n/**\n * m remainder n 取余数\n * @example\n * remainder(7, 3) // 1\n * remainder(-7, 3) // -1\n * remainder(7, -3) // 1\n * remainder(-7, -3) // -1\n * @param dividend\n * @param divisor\n * @returns remainder\n * {@link https://stackoverflow.com/questions/38702724/math-floor-vs-math-trunc-javascript}\n */\nfunction remainder(dividend: number, divisor: number): number {\n  const quotient = Math.trunc(dividend / divisor)\n  return dividend - divisor * quotient\n}\n\nexport { modulo, remainder }\n","/*\n * @Author      : ZhouQiJun\n * @Date        : 2024-07-16 23:03:23\n * @LastEditors : ZhouQiJun\n * @LastEditTime: 2025-03-22 22:09:54\n * @Description : 格式化金额\n */\nimport { isNumber, isString } from '../type/type'\n/**\n * @group 工具函数\n * @param money 金钱数额\n * @returns\n */\nexport function normalizeMoney(money: number | string): string {\n  if ((!isNumber(money) && !isString(money)) || money === '') {\n    return '0'\n  }\n\n  money = money.toString()\n  if (/[^0-9\\.]/.test(money)) return '0'\n\n  if (+money === 0) return '0.00'\n\n  money = money.replace(/^(\\d*)$/, '$1.')\n  money = (money + '00').replace(/(\\d*\\.\\d\\d)\\d*/, '$1')\n  money = money.replace('.', ',')\n\n  const re = /(\\d)(\\d{3},)/\n  while (re.test(money)) {\n    money = money.replace(re, '$1,$2')\n  }\n  money = money.replace(/,(\\d\\d)$/, '.$1')\n  //   不带小数位(默认是有小数位)\n  //   if (precision == 0) {\n  //     var a = money.split('.')\n  //     if (a[1] == '00') {\n  //       money = a[0]\n  //     }\n  //   }\n  return money\n}\n","/*\n * @Author      : ZhouQiJun\n * @Date        : 2025-03-06 16:02:51\n * @LastEditors : ZhouQiJun\n * @LastEditTime: 2025-03-22 21:59:23\n * @Description : randomNum 函数 - 生成随机数\n */\n\n/**\n * @group 工具函数\n * @param [length=6] 长度\n * @returns\n */\nexport function randomNum(length: number = 6) {\n  const arr: number[] = []\n  let n = ''\n  const str = '1234566789'\n  for (var i = 0; i < length; i++) {\n    if (i === 0) {\n      arr[i] = +str[Math.ceil(Math.random() * 9)]\n    } else {\n      arr[i] = Number.parseInt(Math.random() * 10 + '')\n    }\n    n += String(arr[i])\n  }\n  return Number.parseInt(n)\n}\n","/*\n * @Author      : ZhouQiJun\n * @Date        : 2024-07-16 23:03:23\n * @LastEditors : ZhouQiJun\n * @LastEditTime: 2025-03-22 22:00:48\n * @Description : 随机字符串\n */\nimport { isBoolean, isNumber } from '../type/type'\n\n/**\n * @group 工具函数\n * @param [min=7] 最小长度\n * @param [max=36] 最大长度\n * @param [startLetter=true] 是否需要字母开头\n * @returns\n */\nexport function randomStr(\n  min: number | string = 7,\n  max: number | string = 36,\n  startLetter = true,\n) {\n  if (!isNumber(+min) || !isNumber(+max) || !isBoolean(startLetter)) {\n    return 'min, max should be number, startLetter should be boolean'\n  }\n  if (+min < 0 || +max < 0) {\n    return 'min, max should be positive number'\n  }\n  if (min > max) {\n    return 'min should be less than max'\n  }\n  min = +min\n  max = +max\n  const number = '0123456789'\n  const letter = 'abcdefghijklmnopqrstuvwxyz'\n  const LETTER = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'\n  const all = number + letter + LETTER\n  const allLetters = letter + LETTER\n  let str = ''\n  const length = Math.floor(Math.random() * (max - min)) + min\n  for (let i = 0; i < length; i++) {\n    const index = Math.floor(Math.random() * all.length)\n    str += all[index]\n  }\n  if (startLetter && /^[0-9]/.test(str)) {\n    const index = Math.floor(Math.random() * allLetters.length)\n    str = allLetters[index] + str.slice(1)\n  }\n  if (!startLetter && /^[a-zA-Z]/.test(str)) {\n    const index = Math.floor(Math.random() * number.length)\n    str = number[index] + str.slice(1)\n  }\n  return str\n}\n","/*\n * @Author      : ZhouQiJun\n * @Date        : 2024-05-01 20:10:15\n * @LastEditors : ZhouQiJun\n * @LastEditTime: 2025-03-22 22:02:43\n * @Description : 数组去重\n */\n/**\n * @group 工具函数\n * @param arr 数组\n * @returns\n */\nexport function removeRepeat(arr: any[]) {\n  if (!Array.isArray(arr)) {\n    return []\n  }\n  return Array.from(new Set(arr))\n}\n","/*\n * @Author      : ZhouQiJun\n * @Date        : 2024-10-28 01:04:56\n * @LastEditors : ZhouQiJun\n * @LastEditTime: 2025-03-22 21:40:58\n * @Description : repeatRun 函数 - 重复执行函数\n * 解决 setInterval 时间不精确的问题\n */\nimport { isFunction, isNumber } from '../type/type'\n\n/**\n * @description: stop run repeat-function\n */\nexport type StopRepeat = () => void\n\nexport type RepeatFn = (\n  repeatTimes: number,\n  stop: StopRepeat,\n  params?: unknown,\n) => void\n\nexport interface RepeatOptions {\n  interval?: number\n  immediate?: boolean\n}\n\n/**\n * ## repeat call function\n * @group 工具函数\n * @param fn will be called repeatly\n * @param param1.interval interval time default 1000\n * @param param1.immediate call fn immediately default false\n * @param params params pass to fn\n * @returns stopFunction to stop repeat\n * @example\n * ### pass a arrow function to repeat\n * ```ts\n * repeatRun((repeatTimes, stop) => {\n *  console.log(repeatTimes)\n * if (repeatTimes === 5) {\n *    stop() // stop function from fn params\n *  }\n * })\n * ```\n * @example\n * ### pass a function definition to repeat and stop it by repeat return value\n * ```ts\n * let stop = repeatRun(sayHi, { interval: 1000 })\n * function sayHi(repeatTimes) {\n *  console.log(repeatTimes)\n *  if (repeatTimes === 5) {\n *   stop() // stop from repeatRun return value\n *  }\n * }\n * ```\n */\nexport function repeatRun(\n  fn: RepeatFn,\n  { interval = 1000, immediate = false }: RepeatOptions = {},\n  params?: unknown,\n): StopRepeat {\n  if (!isFunction(fn)) {\n    throw new Error('first argument must be a function')\n  }\n\n  if (!isNumber(interval) || interval <= 0) {\n    throw new Error('interval must be a positive number')\n  }\n  const stop: StopRepeat = () => {\n    hasStopped = true\n    clearTimeout(timer)\n    clearTimeout(timer2)\n  }\n  let hasStopped = false\n  let timer2\n  let repeatTimes = 0\n  if (immediate) {\n    ++repeatTimes\n    fn(repeatTimes, stop, params)\n  }\n  let timer = setTimeout(function repeat() {\n    if (hasStopped) {\n      return\n    }\n    ++repeatTimes\n    fn(repeatTimes, stop, params)\n    timer2 = setTimeout(repeat, interval)\n  }, interval)\n  return stop\n}\n\n// 函数定义和函数表达式的区别\n// 函数定义会被提升，var 的函数表达式不会被提升，let const 的函数表达式不会被提升\n// let stop = repeat(hello)\n// // this is ok, because function definition is hoisted\n// function hello(_, times) {\n//   console.log('hello', times)\n//   if (times === 10) {\n//     stop()\n//   }\n// }\n// // this is not ok, because var initialization is hoisted  ❌\n// var hello = function (_, time) {\n//   console.log('hello', times)\n//   if (times === 10) {\n//     stop()\n//   }\n// }\n//  // this is not ok, because let and const variable are not hoisted ❌\n// let hello = (_, time) => {\n//   console.log('hello', times)\n//   if (times === 10) {\n//     stop()\n//   }\n// }\n","/*\n * @Author      : ZhouQiJun\n * @Date        : 2024-05-28 03:04:01\n * @LastEditors : ZhouQiJun\n * @LastEditTime: 2025-03-23 21:09:29\n * @Description : 节流\n */\n/**\n * @group 工具函数\n * @param fn 待节流的函数\n * @param interval 间隔时间，毫秒，默认 200\n * @param immediate 是否立即执行，默认 false\n * @returns\n */\nexport function throttle(fn, interval = 200, immediate = false) {\n  let last = Date.now() // 上次执行的时间戳\n  let timer = null // 定时器\n  let hasCalled = false // 是否是第一次调用\n\n  return (...rest) => {\n    const now = Date.now()\n\n    if (immediate && !hasCalled) {\n      // 如果是第一次调用且需要立即执行\n      fn(...rest)\n      last = now\n      hasCalled = true\n    }\n\n    clearTimeout(timer) // 清除之前的定时器\n\n    if (now - last >= interval) {\n      // 如果距离上次执行的时间超过 interval，则立即执行\n      fn(...rest)\n      last = now\n    } else {\n      // 否则，设置定时器，在剩余时间后执行\n      timer = setTimeout(\n        () => {\n          fn(...rest)\n          last = Date.now()\n        },\n        // 保证时间间隔为 interval 内\n        interval - (now - last),\n      )\n    }\n  }\n}\n","/*\n * @Author      : ZhouQiJun\n * @Date        : 2024-05-01 18:25:22\n * @LastEditors : ZhouQiJun\n * @LastEditTime: 2025-03-22 22:05:37\n * @Description : 生成 uuid\n */\n/**\n * @group 工具函数\n * @returns\n */\nexport function uuid() {\n  let d = new Date().getTime()\n  const uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(\n    /[xy]/g,\n    function (c) {\n      var r = (d + Math.random() * 16) % 16 | 0\n      d = Math.floor(d / 16)\n      const str = c === 'x' ? r : (r & 0x7) | 0x8\n      return str.toString(16)\n    },\n  )\n  return uuid\n}\n"],"names":["type","value","Object","prototype","toString","call","slice","toLowerCase","isObject","isBoolean","isNullish","isNumber","isString","isEmptyStr","isFunction","Function","clone","source","target","t","includes","i","len","length","key","hasOwnProperty","array","size","Array","isArray","Error","result","push","text","navigator","clipboard","permissions","writeText","then","Promise","resolve","textArea","document","createElement","style","width","position","left","top","setAttribute","body","appendChild","select","execCommand","removeChild","fn","wait","immediate","timer","rest","arguments","apply","clearTimeout","setTimeout","code","tip","pass","test","arr","split","factor","sum","number","d","prop","arr1","arr2","e","string","url","URL","_","protocol","trim","Number","isFinite","m","n","money","replace","re","Math","ceil","random","parseInt","String","min","max","startLetter","letter","LETTER","all","allLetters","str","floor","dividend","divisor","trunc","from","Set","_temp","params","_ref","_ref$interval","interval","_ref$immediate","timer2","stop","hasStopped","repeatTimes","repeat","last","Date","now","hasCalled","getTime","c","r"],"mappings":"AAKA,SAASA,EAAKC,GAEZ,OADgBC,OAAOC,UAAUC,SAASC,KAAKJ,GAChCK,MAAM,GAAI,GAAGC,aAC9B,CAOA,SAASC,EAASP,GAChB,MAAwB,iBAAVA,GAAgC,OAAVA,CACtC,CAoDA,SAASQ,EAAUR,GACjB,MAAwB,kBAAVA,CAChB,CAiBA,SAASS,EAAUT,GAEjB,OAAgB,MAATA,CACT,CASA,SAASU,EAASV,GAQhB,MAAqB,iBAAVA,EAAmC,EAARA,GAAc,EAC/B,iBAAVA,CAEb,CAsBA,SAASW,EAASX,GAChB,MAAwB,iBAAVA,CAChB,CAOA,SAASY,EAAWZ,GAClB,MAAiB,KAAVA,CACT,CAqEA,SAASa,EAAWb,GAClB,OAAIS,EAAUT,MACVA,IAEgB,aAAhBD,EAAKC,IACL,mBAAsBA,GACtBA,aAAiBc,SAIvB,CChNM,IAAAC,EAAQ,SAAIC,GAChB,IAEIC,EAFEC,EAAInB,EAAKiB,GACf,IAAK,CAAC,SAAU,SAASG,SAASD,GAAI,OAAOF,EAE7C,GAAU,UAANE,EAAe,CACjBD,EAAS,GAGT,IAFA,IAAIG,EAAI,EACFC,EAAOL,EAAsBM,OAC5BF,EAAIC,GACTJ,EAAOG,GAAKL,EAAMC,EAAOI,IACzBA,GAEJ,MAAWF,GAAM,WAANA,EAET,IAAK,IAAMK,KADXN,EAAS,CAAA,EACSD,EACZf,OAAOC,UAAUsB,eAAepB,KAAKY,EAAQO,KAE/CN,EAAOM,GAAOR,EAAMC,EAAOO,KAIjC,OAAON,CACT,gBCtBgB,SAASQ,EAAYC,GACnC,IAAKC,MAAMC,QAAQH,GACjB,MAAU,IAAAI,MAAM,kBAElB,IAAKnB,EAASgB,GACZ,MAAM,IAAIG,MAAM,gBAGlB,IADA,IAAMC,EAAgB,GACbV,EAAI,EAAGA,EAAIK,EAAMH,OAAQF,GAAKM,EACrCI,EAAOC,KAAKN,EAAMpB,MAAMe,EAAGA,EAAIM,IAEjC,OAAOI,CACT,wCCbqBE,GACnB,OAAIC,UAAUC,WAAaD,UAAUE,YAC5BF,UAAUC,UACdE,UAAUJ,GACVK,KAAK,WACJ,OAAOC,QAAQC,SAAQ,EACzB,GACM,MAAC,WACL,OAAOD,QAAQC,SAAQ,EACzB,GAES,IAAAD,QAAQ,SAAAC,GACjB,IAAMC,EAAWC,SAASC,cAAc,YAExCF,EAASxC,MAAQgC,EACjBQ,EAASG,MAAMC,MAAQ,MACvBJ,EAASG,MAAME,SAAW,QAC1BL,EAASG,MAAMG,KAAO,SACtBN,EAASG,MAAMI,IAAM,OACrBP,EAASQ,aAAa,WAAY,YAClCP,SAASQ,KAAKC,YAAYV,GAE1BA,EAASW,SACTV,SAASW,YAAY,QACrBX,SAASQ,KAAKI,YAAYb,GAC1BD,GAAQ,EACV,EAEJ,4BC5ByBe,EAAIC,EAAYC,GACvC,IAAIC,EACJ,YAF+B,IAAJF,IAAAA,EAAO,UAAKC,IAAAA,IAAAA,GAAY,GAEhC,WAAA,IAARE,EAAI,GAAArD,MAAAD,KAAAuD,WACbH,IAAcC,GAASH,EAAEM,WAAA,EAAIF,GACzBD,GACFI,aAAaJ,GAEfA,EAAQK,WAAW,WACjBR,EAAEM,WAAA,EAAIF,EACR,EAAGH,EACL,CACF,4BCMA,SAA2BQ,GACzB,GAAItD,EAAUsD,IAASnD,EAAWmD,GAAO,MAAO,EAAC,EAAO,YACxD,IAAKrD,EAASqD,KAAUpD,EAASoD,GAC/B,MAAO,EAAC,EAAO,kBAEjB,IAqCIC,EAAM,GACNC,GAAO,EAEX,GAAoB,MAzCpBF,EAAOA,EAAK5D,YAyCHmB,QAAiC,KAAhByC,EAAKzC,OAC7B,MAAO,EAAC,EAAO,yBAOjB,IAHE,6EACgC4C,KAAKH,GAGrC,MAAO,EAAC,EAAO,YAGjB,IApDkB,CAChB,GAAI,KACJ,GAAI,KACJ,GAAI,KACJ,GAAI,KACJ,GAAI,MACJ,GAAI,KACJ,GAAI,KACJ,GAAI,OACJ,GAAI,KACJ,GAAI,KACJ,GAAI,KACJ,GAAI,KACJ,GAAI,KACJ,GAAI,KACJ,GAAI,KACJ,GAAI,KACJ,GAAI,MACJ,GAAI,KACJ,GAAI,KACJ,GAAI,KACJ,GAAI,KACJ,GAAI,KACJ,GAAI,KACJ,GAAI,KACJ,GAAI,KACJ,GAAI,MACJ,GAAI,KACJ,GAAI,KACJ,GAAI,KACJ,GAAI,KACJ,GAAI,KACJ,GAAI,KACJ,GAAI,KACJ,GAAI,KACJ,GAAI,OAiBIA,EAAK1D,MAAM,EAAG,IACtB,MAAO,EAAC,EAAO,UAIjB,GAAmB,IAAf0D,EAAKzC,OAAc,CAUrB,IATA,IAAM6C,EAAMJ,EAAKK,MAAM,IAGjBC,EAAS,CAAC,EAAG,EAAG,GAAI,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,EAAG,EAAG,EAAG,GAG9DC,EAAM,EAGDlD,EAAI,EAAGA,EAAI,GAAIA,IAGtBkD,IAFMH,EAAI/C,GACLiD,EAAOjD,GANC,CAAC,EAAG,EAAG,IAAK,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAS5BkD,EAAM,KACdH,EAAI,MACdH,EAAM,oBACNC,GAAO,EAEX,CAEA,MAAO,CAACA,EAAMD,EAChB,kBL3DA,SAAiBhE,GACf,OAAI2B,MAAMC,QACDD,MAAMC,QAAQ5B,GAEA,UAAhBD,EAAKC,EACd,6CMjDM,SAAyBuE,GAI7B,MADiB,gBACDL,KAAKK,EACvB,iBN8BA,SAAgBC,GACd,MAAmB,SAAZzE,EAAKyE,EACd,kBAoLA,SAAiBxE,GAEf,GAAIY,EAAWZ,GAAQ,SAEvB,GAAI2B,MAAMC,QAAQ5B,GAAQ,OAAwB,IAAjBA,EAAMsB,OAEvC,GAAIb,EAAUT,GAAQ,OAAW,EACjC,GAAIO,EAASP,GAAQ,CACnB,IAAK,IAAIyE,KAAQzE,EACf,GAAIA,EAAMwB,eAAeiD,GAAO,SAElC,OACF,CAAA,CACA,OACF,CAAA,4COvOgB,SAAaC,EAAaC,GACxC,GAAID,EAAKpD,SAAWqD,EAAKrD,OACvB,OACF,EACA,IAAK,IAAIF,EAAI,EAAGA,EAAIsD,EAAKpD,OAAQF,IAC/B,GAAIsD,EAAKtD,KAAOuD,EAAKvD,GACnB,OACF,EAEF,OACF,CAAA,kBPgBA,SAAiBwD,GACf,MAAmB,UAAZ7E,EAAK6E,IAAkBA,aAAa/C,KAC7C,kBAkJA,SAAiB7B,GACf,OAAQA,CACV,sBAOA,SAAqBA,GACnB,OAAQA,GAAmB,IAAVA,CACnB,kDQ1L0B6E,GACxB,IAAIC,EAEJ,IACEA,EAAM,IAAIC,IAAIF,EAChB,CAAE,MAAOG,GACP,OAAO,CACT,CAEA,MAAwB,UAAjBF,EAAIG,UAAyC,WAAjBH,EAAIG,QACzC,iBRwDA,SAAgBjF,GACd,OAAiB,OAAVA,CACT,6DAuCA,SAAqBA,GACnB,MAAqB,iBAAVA,EAAmC,EAARA,GAAc,EAC/B,iBAAVA,MACPW,EAASX,IAA2B,KAAjBA,EAAMkF,UACpBC,OAAOC,SAAWD,OAAOC,UAAUpF,GAASoF,UAAUpF,GAGjE,yCAvGA,SAAqBA,GACnB,OACY,OAAVA,GACiB,kBAAVA,GACU,iBAAVA,GACU,iBAAVA,GACU,iBAAVA,GACU,iBAAVA,QACU,IAAVA,CAEX,mBAiJA,SAAkBA,GAChB,MAAuB,WAAhBD,EAAKC,EACd,sCApBA,SAAkBA,GAChB,MAAwB,iBAAVA,CAChB,mBA0CA,SAAkBA,GAChB,QAASA,CACX,sBArCA,SAAqBA,GACnB,YAAiB,IAAVA,CACT,iBSrJA,SAAgBqF,EAAWC,GAGzB,OAASD,EAAIC,EAAKA,GAAKA,CACzB,yBCbM,SAAyBC,GAC7B,IAAM7E,EAAS6E,KAAW5E,EAAS4E,IAAqB,KAAVA,EAC5C,MAAO,IAIT,GADAA,EAAQA,EAAMpF,WACV,WAAW+D,KAAKqB,GAAQ,MAAO,IAEnC,GAAe,IAAVA,EAAa,MAAO,OAIzBA,GADAA,IADAA,EAAQA,EAAMC,QAAQ,UAAW,QAChB,MAAMA,QAAQ,iBAAkB,OACnCA,QAAQ,IAAK,KAG3B,IADA,IAAMC,EAAK,eACJA,EAAGvB,KAAKqB,IACbA,EAAQA,EAAMC,QAAQC,EAAI,SAU5B,OARQF,EAAMC,QAAQ,WAAY,MASpC,oBC3BgB,SAAUlE,QAAAA,IAAAA,IAAAA,EAAiB,GAIzC,IAHA,IAAM6C,EAAgB,GAClBmB,EAAI,GAEClE,EAAI,EAAGA,EAAIE,EAAQF,IAExB+C,EAAI/C,GADI,IAANA,GAFM,aAGMsE,KAAKC,KAAqB,EAAhBD,KAAKE,WAEpBT,OAAOU,SAAyB,GAAhBH,KAAKE,SAAgB,IAEhDN,GAAKQ,OAAO3B,EAAI/C,IAElB,OAAO+D,OAAOU,SAASP,EACzB,oBCVgB,SACdS,EACAC,EACAC,GAEA,QAJuB,IAAvBF,IAAAA,EAAuB,QACvBC,IAAAA,IAAAA,EAAuB,aACvBC,IAAAA,GAAc,IAETvF,GAAUqF,KAASrF,GAAUsF,KAASxF,EAAUyF,GACnD,MAAO,2DAET,IAAKF,EAAM,IAAMC,EAAM,EACrB,MAAO,qCAET,GAAID,EAAMC,EACR,MAAO,8BAETD,GAAOA,EACPC,GAAOA,EAQP,IAPA,IAAMzB,EAAS,aACT2B,EAAS,6BACTC,EAAS,6BACTC,EAAM7B,EAAS2B,EAASC,EACxBE,EAAaH,EAASC,EACxBG,EAAM,GACJhF,EAASoE,KAAKa,MAAMb,KAAKE,UAAYI,EAAMD,IAAQA,EAChD3E,EAAI,EAAGA,EAAIE,EAAQF,IAE1BkF,GAAOF,EADOV,KAAKa,MAAsBH,GAAhBV,KAAKE,WAWhC,OARIK,GAAe,SAAS/B,KAAKoC,KAE/BA,EAAMD,EADQX,KAAKa,MAAsBF,GAAhBX,KAAKE,WACJU,EAAIjG,MAAM,KAEjC4F,GAAe,YAAY/B,KAAKoC,KAEnCA,EAAM/B,EADQmB,KAAKa,MAAsBhC,GAAhBmB,KAAKE,WACRU,EAAIjG,MAAM,IAE3BiG,CACT,oBHZA,SAAmBE,EAAkBC,GAEnC,OAAOD,EAAWC,EADDf,KAAKgB,MAAMF,EAAWC,EAEzC,uBI/BgB,SAAatC,GAC3B,OAAKxC,MAAMC,QAAQuC,GAGZxC,MAAMgF,KAAK,IAAIC,IAAIzC,IAFjB,EAGX,6BCwCEb,EAAYuD,EAEZC,GAAgBC,IAAAA,OAAA,IAAAF,EADwC,CAAA,EAAEA,EAAAG,EAAAD,EAAxDE,SAAAA,OAAQ,IAAAD,EAAG,IAAIA,EAAAE,EAAAH,EAAEvD,UAAAA,WAAS0D,GAAQA,EAGpC,IAAKrG,EAAWyC,GACd,MAAM,IAAIzB,MAAM,qCAGlB,IAAKnB,EAASuG,IAAaA,GAAY,EACrC,MAAU,IAAApF,MAAM,sCAElB,IAMIsF,EANEC,EAAmB,WACvBC,GAAa,EACbxD,aAAaJ,GACbI,aAAasD,EACf,EACIE,GAAa,EAEbC,EAAc,EACd9D,MACA8D,EACFhE,EAAGgE,EAAaF,EAAMN,IAExB,IAAIrD,EAAQK,WAAW,SAASyD,IAC1BF,MAGFC,EACFhE,EAAGgE,EAAaF,EAAMN,GACtBK,EAASrD,WAAWyD,EAAQN,GAC9B,EAAGA,GACH,OAAOG,CACT,mBC3EgB,SAAS9D,EAAI2D,EAAgBzD,QAAR,IAARyD,IAAAA,EAAW,UAAKzD,IAAAA,IAAAA,GAAY,GACvD,IAAIgE,EAAOC,KAAKC,MACZjE,EAAQ,KACRkE,GAAY,EAEhB,OAAmB,WAAA,IAARjE,KAAIrD,MAAAD,KAAAuD,WACP+D,EAAMD,KAAKC,MAEblE,IAAcmE,IAEhBrE,EAAEM,WAAA,EAAIF,GACN8D,EAAOE,EACPC,GAAY,GAGd9D,aAAaJ,GAETiE,EAAMF,GAAQP,GAEhB3D,EAAEM,WAAA,EAAIF,GACN8D,EAAOE,GAGPjE,EAAQK,WACN,WACER,EAAEM,WAAA,EAAIF,GACN8D,EAAOC,KAAKC,KACd,EAEAT,GAAYS,EAAMF,GAGxB,CACF,yCCnCE,IAAIhD,GAAI,IAAIiD,MAAOG,UAUnB,MATa,uCAAuCpC,QAClD,QACA,SAAUqC,GACR,IAAIC,GAAKtD,EAAoB,GAAhBkB,KAAKE,UAAiB,GAAK,EAGxC,OAFApB,EAAIkB,KAAKa,MAAM/B,EAAI,KACD,MAANqD,EAAYC,EAAS,EAAJA,EAAW,GAC7B3H,SAAS,GACtB,EAGJ"}