superjs-core 0.4.3 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +117 -0
- package/CONTRIBUTING.md +55 -0
- package/PUBLISH.md +45 -0
- package/README.md +9 -5
- package/ROADMAP.md +72 -0
- package/SECURITY.md +35 -0
- package/SUMMARY.md +321 -0
- package/dist/async/index.d.ts +106 -1
- package/dist/async/index.js +128 -1
- package/dist/async/index.js.map +1 -1
- package/dist/collection/index.d.ts +135 -1
- package/dist/collection/index.js +145 -1
- package/dist/collection/index.js.map +1 -1
- package/dist/color/index.d.ts +79 -1
- package/dist/color/index.js +101 -0
- package/dist/color/index.js.map +1 -1
- package/dist/date/index.d.ts +316 -1
- package/dist/date/index.js +339 -1
- package/dist/date/index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js.map +1 -1
- package/dist/isNoRekening-CHSpgD4P.d.ts +167 -0
- package/dist/math/index.d.ts +188 -1
- package/dist/math/index.js +199 -1
- package/dist/math/index.js.map +1 -1
- package/dist/string/index.d.ts +71 -1
- package/dist/string/index.js +94 -0
- package/dist/string/index.js.map +1 -1
- package/dist/validation/index.d.ts +22 -150
- package/dist/validation/index.js +27 -0
- package/dist/validation/index.js.map +1 -1
- package/package.json +3 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/collection/index.ts"],"sourcesContent":["/**\r\n * Groups an array of items by a key extracted from each item.\r\n *\r\n * @example groupBy([{ type: 'a' }, { type: 'b' }, { type: 'a' }], x => x.type)\r\n * // => { a: [{ type: 'a' }, { type: 'a' }], b: [{ type: 'b' }] }\r\n */\r\nexport function groupBy<T, K extends string | number | symbol>(items: T[], keyFn: (item: T) => K): Record<K, T[]> {\r\n const result = {} as Record<K, T[]>\r\n for (const item of items) {\r\n const key = keyFn(item)\r\n if (!result[key]) result[key] = []\r\n result[key]!.push(item)\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * Creates an object keyed by the result of keyFn for each item.\r\n *\r\n * @example keyBy([{ id: 1, name: 'a' }, { id: 2, name: 'b' }], x => x.id)\r\n * // => { 1: { id: 1, name: 'a' }, 2: { id: 2, name: 'b' } }\r\n */\r\nexport function keyBy<T, K extends string | number | symbol>(items: T[], keyFn: (item: T) => K): Record<K, T> {\r\n const result = {} as Record<K, T>\r\n for (const item of items) {\r\n const key = keyFn(item)\r\n result[key] = item\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * Returns a copy of the object with the specified keys omitted.\r\n */\r\nexport function omit<T extends Record<string, unknown>, K extends keyof T>(obj: T, keys: K[]): Omit<T, K> {\r\n const result = { ...obj } as T\r\n for (const key of keys) {\r\n delete result[key]\r\n }\r\n return result as Omit<T, K>\r\n}\r\n\r\n/**\r\n * Returns a copy of the object with only the specified keys.\r\n */\r\nexport function pick<T extends Record<string, unknown>, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> {\r\n const result = {} as Pick<T, K>\r\n for (const key of keys) {\r\n if (key in obj) {\r\n result[key] = obj[key]\r\n }\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * Extracts a property value from each item in an array.\r\n */\r\nexport function pluck<T, K extends keyof T>(items: T[], key: K): T[K][] {\r\n return items.map(item => item[key])\r\n}\r\n\r\n/**\r\n * Randomizes array order in-place using the Fisher-Yates algorithm.\r\n */\r\nexport function shuffle<T>(items: T[]): T[] {\r\n const result = [...items]\r\n for (let i = result.length - 1; i > 0; i--) {\r\n const j = Math.floor(Math.random() * (i + 1))\r\n const temp = result[i]!\r\n result[i] = result[j]!\r\n result[j] = temp\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * Returns a random element from the array, or undefined if empty.\r\n */\r\nexport function sample<T>(items: T[]): T | undefined {\r\n return items.length > 0 ? items[Math.floor(Math.random() * items.length)] : undefined\r\n}\r\n\r\n/**\r\n * Returns an array of `size` random elements (without duplicates).\r\n */\r\nexport function sampleSize<T>(items: T[], size: number): T[] {\r\n if (size <= 0 || items.length === 0) return []\r\n const pool = shuffle(items)\r\n return pool.slice(0, Math.min(size, items.length))\r\n}\r\n\r\n/**\r\n * Splits an array into chunks of the specified size.\r\n */\r\nexport function chunk<T>(items: T[], size: number): T[][] {\r\n if (size <= 0 || items.length === 0) return []\r\n const result: T[][] = []\r\n for (let i = 0; i < items.length; i += size) {\r\n result.push(items.slice(i, i + size))\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * Returns a sorted copy of the array using the provided criteria functions.\r\n * Earlier criteria take precedence.\r\n */\r\nfunction compareValues(a: unknown, b: unknown): number {\r\n if (a === b) return 0\r\n if (a == null) return -1\r\n if (b == null) return 1\r\n if (typeof a === 'string' && typeof b === 'string') return a < b ? -1 : 1\r\n if (typeof a === 'number' && typeof b === 'number') return a < b ? -1 : 1\r\n return String(a) < String(b) ? -1 : 1\r\n}\r\n\r\nexport function sortBy<T>(items: T[], ...criteria: Array<(item: T) => unknown>): T[] {\r\n return [...items].sort((a, b) => {\r\n for (const criterion of criteria) {\r\n const cmp = compareValues(criterion(a), criterion(b))\r\n if (cmp !== 0) return cmp\r\n }\r\n return 0\r\n })\r\n}\r\n\r\n/**\r\n * Returns a sorted copy of the array by a single key and direction.\r\n */\r\nexport function orderBy<T>(items: T[], key: (item: T) => unknown, direction: SortDirection = 'asc'): T[] {\r\n return [...items].sort((a, b) => {\r\n const cmp = compareValues(key(a), key(b))\r\n return direction === 'asc' ? cmp : -cmp\r\n })\r\n}\r\n\r\n/**\r\n * Returns unique elements based on the result of keyFn.\r\n */\r\nexport function uniqueBy<T>(items: T[], keyFn: (item: T) => unknown): T[] {\r\n const seen = new Set<unknown>()\r\n return items.filter(item => {\r\n const key = keyFn(item)\r\n if (seen.has(key)) return false\r\n seen.add(key)\r\n return true\r\n })\r\n}\r\n\r\n/**\r\n * Flattens an array of arrays one level.\r\n */\r\nexport function flatten<T>(items: T[][]): T[] {\r\n const result: T[] = []\r\n for (const sub of items) {\r\n for (const item of sub) {\r\n result.push(item)\r\n }\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * Returns an array with unique primitive values.\r\n */\r\nexport function uniq<T>(items: T[]): T[] {\r\n return [...new Set(items)]\r\n}\r\n\r\n/**\r\n * Returns the first element, or undefined if empty.\r\n */\r\nexport function first<T>(items: T[]): T | undefined {\r\n return items[0]\r\n}\r\n\r\n/**\r\n * Returns the last element, or undefined if empty.\r\n */\r\nexport function last<T>(items: T[]): T | undefined {\r\n return items[items.length - 1]\r\n}\r\n\r\n/**\r\n * Checks if a value is empty.\r\n * Works for arrays, objects, strings, Map, and Set.\r\n */\r\nexport function isEmpty(value: unknown): boolean {\r\n if (Array.isArray(value)) return value.length === 0\r\n if (typeof value === 'string') return value.length === 0\r\n if (value instanceof Map || value instanceof Set) return value.size === 0\r\n if (value !== null && typeof value === 'object') return Object.keys(value as Record<string, unknown>).length === 0\r\n return false\r\n}\r\n\r\nexport type SortDirection = 'asc' | 'desc'\r\n\r\nexport function topoSort<T extends { id: string; dependencies?: string[] }>(items: T[]): T[] {\r\n const adj = new Map<string, string[]>()\r\n const inDegree = new Map<string, number>()\r\n const itemMap = new Map<string, T>()\r\n\r\n for (const item of items) {\r\n itemMap.set(item.id, item)\r\n if (!adj.has(item.id)) adj.set(item.id, [])\r\n if (!inDegree.has(item.id)) inDegree.set(item.id, 0)\r\n }\r\n\r\n for (const item of items) {\r\n if (item.dependencies) {\r\n for (const depId of item.dependencies) {\r\n adj.get(depId)?.push(item.id)\r\n inDegree.set(item.id, (inDegree.get(item.id) ?? 0) + 1)\r\n }\r\n }\r\n }\r\n\r\n const queue: string[] = []\r\n for (const [id, degree] of inDegree) {\r\n if (degree === 0) queue.push(id)\r\n }\r\n\r\n const sorted: string[] = []\r\n while (queue.length > 0) {\r\n const id = queue.shift()!\r\n sorted.push(id)\r\n for (const neighbor of adj.get(id) ?? []) {\r\n const newDegree = (inDegree.get(neighbor) ?? 1) - 1\r\n inDegree.set(neighbor, newDegree)\r\n if (newDegree === 0) queue.push(neighbor)\r\n }\r\n }\r\n\r\n if (sorted.length !== items.length) {\r\n throw new Error('Circular dependency detected')\r\n }\r\n\r\n return sorted.map(id => itemMap.get(id)!)\r\n}\r\n\r\nexport function slidingWindows<T>(items: T[], size: number, step: number = 1): T[][] {\r\n if (size <= 0 || items.length === 0 || step <= 0) return []\r\n const result: T[][] = []\r\n for (let i = 0; i + size <= items.length; i += step) {\r\n result.push(items.slice(i, i + size))\r\n }\r\n return result\r\n}\r\n\r\nexport function tumblingWindows<T>(items: T[], size: number): T[][] {\r\n if (size <= 0 || items.length === 0) return []\r\n const result: T[][] = []\r\n for (let i = 0; i < items.length; i += size) {\r\n result.push(items.slice(i, i + size))\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * Gets a nested value from an object using a dot-separated path.\r\n *\r\n * @example deepGet({ a: { b: 2 } }, 'a.b') // 2\r\n * @example deepGet({ a: { b: 2 } }, 'a.c') // undefined\r\n */\r\nexport function deepGet<T = unknown>(obj: unknown, path: string, default_?: T): T | undefined {\r\n const keys = path.split('.')\r\n let current: unknown = obj\r\n for (const key of keys) {\r\n if (current === null || current === undefined) return default_\r\n if (typeof current !== 'object') return default_\r\n const curObj = current as Record<string, unknown>\r\n if (!(key in curObj)) return default_\r\n current = curObj[key]\r\n }\r\n return (current as T) ?? default_\r\n}\r\n\r\n/**\r\n * Sets a nested value in an object using a dot-separated path.\r\n * Creates intermediate objects/arrays as needed.\r\n *\r\n * @example deepSet({ a: { b: 2 } }, 'a.b', 3) // { a: { b: 3 } }\r\n * @example deepSet({}, 'a.b.c', 1) // { a: { b: { c: 1 } } }\r\n */\r\nexport function deepSet<T extends Record<string, unknown>>(obj: T, path: string, value: unknown): T {\r\n const keys = path.split('.')\r\n const result = { ...obj } as Record<string, unknown>\r\n let current = result\r\n for (let i = 0; i < keys.length - 1; i++) {\r\n const key = keys[i]!\r\n const next = current[key]\r\n if (next === null || next === undefined || typeof next !== 'object') {\r\n const isArray = /^\\d+$/.test(keys[i + 1]!)\r\n current[key] = isArray ? [] : {}\r\n }\r\n current = current[key] as Record<string, unknown>\r\n }\r\n current[keys[keys.length - 1]!] = value\r\n return result as T\r\n}\r\n"],"mappings":";AAMO,SAAS,QAA+C,OAAY,OAAuC;AAChH,QAAM,SAAS,CAAC;AAChB,aAAW,QAAQ,OAAO;AACxB,UAAM,MAAM,MAAM,IAAI;AACtB,QAAI,CAAC,OAAO,GAAG,EAAG,QAAO,GAAG,IAAI,CAAC;AACjC,WAAO,GAAG,EAAG,KAAK,IAAI;AAAA,EACxB;AACA,SAAO;AACT;AAQO,SAAS,MAA6C,OAAY,OAAqC;AAC5G,QAAM,SAAS,CAAC;AAChB,aAAW,QAAQ,OAAO;AACxB,UAAM,MAAM,MAAM,IAAI;AACtB,WAAO,GAAG,IAAI;AAAA,EAChB;AACA,SAAO;AACT;AAKO,SAAS,KAA2D,KAAQ,MAAuB;AACxG,QAAM,SAAS,EAAE,GAAG,IAAI;AACxB,aAAW,OAAO,MAAM;AACtB,WAAO,OAAO,GAAG;AAAA,EACnB;AACA,SAAO;AACT;AAKO,SAAS,KAA2D,KAAQ,MAAuB;AACxG,QAAM,SAAS,CAAC;AAChB,aAAW,OAAO,MAAM;AACtB,QAAI,OAAO,KAAK;AACd,aAAO,GAAG,IAAI,IAAI,GAAG;AAAA,IACvB;AAAA,EACF;AACA,SAAO;AACT;AAKO,SAAS,MAA4B,OAAY,KAAgB;AACtE,SAAO,MAAM,IAAI,UAAQ,KAAK,GAAG,CAAC;AACpC;AAKO,SAAS,QAAW,OAAiB;AAC1C,QAAM,SAAS,CAAC,GAAG,KAAK;AACxB,WAAS,IAAI,OAAO,SAAS,GAAG,IAAI,GAAG,KAAK;AAC1C,UAAM,IAAI,KAAK,MAAM,KAAK,OAAO,KAAK,IAAI,EAAE;AAC5C,UAAM,OAAO,OAAO,CAAC;AACrB,WAAO,CAAC,IAAI,OAAO,CAAC;AACpB,WAAO,CAAC,IAAI;AAAA,EACd;AACA,SAAO;AACT;AAKO,SAAS,OAAU,OAA2B;AACnD,SAAO,MAAM,SAAS,IAAI,MAAM,KAAK,MAAM,KAAK,OAAO,IAAI,MAAM,MAAM,CAAC,IAAI;AAC9E;AAKO,SAAS,WAAc,OAAY,MAAmB;AAC3D,MAAI,QAAQ,KAAK,MAAM,WAAW,EAAG,QAAO,CAAC;AAC7C,QAAM,OAAO,QAAQ,KAAK;AAC1B,SAAO,KAAK,MAAM,GAAG,KAAK,IAAI,MAAM,MAAM,MAAM,CAAC;AACnD;AAKO,SAAS,MAAS,OAAY,MAAqB;AACxD,MAAI,QAAQ,KAAK,MAAM,WAAW,EAAG,QAAO,CAAC;AAC7C,QAAM,SAAgB,CAAC;AACvB,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,MAAM;AAC3C,WAAO,KAAK,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC;AAAA,EACtC;AACA,SAAO;AACT;AAMA,SAAS,cAAc,GAAY,GAAoB;AACrD,MAAI,MAAM,EAAG,QAAO;AACpB,MAAI,KAAK,KAAM,QAAO;AACtB,MAAI,KAAK,KAAM,QAAO;AACtB,MAAI,OAAO,MAAM,YAAY,OAAO,MAAM,SAAU,QAAO,IAAI,IAAI,KAAK;AACxE,MAAI,OAAO,MAAM,YAAY,OAAO,MAAM,SAAU,QAAO,IAAI,IAAI,KAAK;AACxE,SAAO,OAAO,CAAC,IAAI,OAAO,CAAC,IAAI,KAAK;AACtC;AAEO,SAAS,OAAU,UAAe,UAA4C;AACnF,SAAO,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM;AAC/B,eAAW,aAAa,UAAU;AAChC,YAAM,MAAM,cAAc,UAAU,CAAC,GAAG,UAAU,CAAC,CAAC;AACpD,UAAI,QAAQ,EAAG,QAAO;AAAA,IACxB;AACA,WAAO;AAAA,EACT,CAAC;AACH;AAKO,SAAS,QAAW,OAAY,KAA2B,YAA2B,OAAY;AACvG,SAAO,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM;AAC/B,UAAM,MAAM,cAAc,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;AACxC,WAAO,cAAc,QAAQ,MAAM,CAAC;AAAA,EACtC,CAAC;AACH;AAKO,SAAS,SAAY,OAAY,OAAkC;AACxE,QAAM,OAAO,oBAAI,IAAa;AAC9B,SAAO,MAAM,OAAO,UAAQ;AAC1B,UAAM,MAAM,MAAM,IAAI;AACtB,QAAI,KAAK,IAAI,GAAG,EAAG,QAAO;AAC1B,SAAK,IAAI,GAAG;AACZ,WAAO;AAAA,EACT,CAAC;AACH;AAKO,SAAS,QAAW,OAAmB;AAC5C,QAAM,SAAc,CAAC;AACrB,aAAW,OAAO,OAAO;AACvB,eAAW,QAAQ,KAAK;AACtB,aAAO,KAAK,IAAI;AAAA,IAClB;AAAA,EACF;AACA,SAAO;AACT;AAKO,SAAS,KAAQ,OAAiB;AACvC,SAAO,CAAC,GAAG,IAAI,IAAI,KAAK,CAAC;AAC3B;AAKO,SAAS,MAAS,OAA2B;AAClD,SAAO,MAAM,CAAC;AAChB;AAKO,SAAS,KAAQ,OAA2B;AACjD,SAAO,MAAM,MAAM,SAAS,CAAC;AAC/B;AAMO,SAAS,QAAQ,OAAyB;AAC/C,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,MAAM,WAAW;AAClD,MAAI,OAAO,UAAU,SAAU,QAAO,MAAM,WAAW;AACvD,MAAI,iBAAiB,OAAO,iBAAiB,IAAK,QAAO,MAAM,SAAS;AACxE,MAAI,UAAU,QAAQ,OAAO,UAAU,SAAU,QAAO,OAAO,KAAK,KAAgC,EAAE,WAAW;AACjH,SAAO;AACT;AAIO,SAAS,SAA4D,OAAiB;AAC3F,QAAM,MAAM,oBAAI,IAAsB;AACtC,QAAM,WAAW,oBAAI,IAAoB;AACzC,QAAM,UAAU,oBAAI,IAAe;AAEnC,aAAW,QAAQ,OAAO;AACxB,YAAQ,IAAI,KAAK,IAAI,IAAI;AACzB,QAAI,CAAC,IAAI,IAAI,KAAK,EAAE,EAAG,KAAI,IAAI,KAAK,IAAI,CAAC,CAAC;AAC1C,QAAI,CAAC,SAAS,IAAI,KAAK,EAAE,EAAG,UAAS,IAAI,KAAK,IAAI,CAAC;AAAA,EACrD;AAEA,aAAW,QAAQ,OAAO;AACxB,QAAI,KAAK,cAAc;AACrB,iBAAW,SAAS,KAAK,cAAc;AACrC,YAAI,IAAI,KAAK,GAAG,KAAK,KAAK,EAAE;AAC5B,iBAAS,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,EAAE,KAAK,KAAK,CAAC;AAAA,MACxD;AAAA,IACF;AAAA,EACF;AAEA,QAAM,QAAkB,CAAC;AACzB,aAAW,CAAC,IAAI,MAAM,KAAK,UAAU;AACnC,QAAI,WAAW,EAAG,OAAM,KAAK,EAAE;AAAA,EACjC;AAEA,QAAM,SAAmB,CAAC;AAC1B,SAAO,MAAM,SAAS,GAAG;AACvB,UAAM,KAAK,MAAM,MAAM;AACvB,WAAO,KAAK,EAAE;AACd,eAAW,YAAY,IAAI,IAAI,EAAE,KAAK,CAAC,GAAG;AACxC,YAAM,aAAa,SAAS,IAAI,QAAQ,KAAK,KAAK;AAClD,eAAS,IAAI,UAAU,SAAS;AAChC,UAAI,cAAc,EAAG,OAAM,KAAK,QAAQ;AAAA,IAC1C;AAAA,EACF;AAEA,MAAI,OAAO,WAAW,MAAM,QAAQ;AAClC,UAAM,IAAI,MAAM,8BAA8B;AAAA,EAChD;AAEA,SAAO,OAAO,IAAI,QAAM,QAAQ,IAAI,EAAE,CAAE;AAC1C;AAEO,SAAS,eAAkB,OAAY,MAAc,OAAe,GAAU;AACnF,MAAI,QAAQ,KAAK,MAAM,WAAW,KAAK,QAAQ,EAAG,QAAO,CAAC;AAC1D,QAAM,SAAgB,CAAC;AACvB,WAAS,IAAI,GAAG,IAAI,QAAQ,MAAM,QAAQ,KAAK,MAAM;AACnD,WAAO,KAAK,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC;AAAA,EACtC;AACA,SAAO;AACT;AAEO,SAAS,gBAAmB,OAAY,MAAqB;AAClE,MAAI,QAAQ,KAAK,MAAM,WAAW,EAAG,QAAO,CAAC;AAC7C,QAAM,SAAgB,CAAC;AACvB,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,MAAM;AAC3C,WAAO,KAAK,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC;AAAA,EACtC;AACA,SAAO;AACT;AAQO,SAAS,QAAqB,KAAc,MAAc,UAA6B;AAC5F,QAAM,OAAO,KAAK,MAAM,GAAG;AAC3B,MAAI,UAAmB;AACvB,aAAW,OAAO,MAAM;AACtB,QAAI,YAAY,QAAQ,YAAY,OAAW,QAAO;AACtD,QAAI,OAAO,YAAY,SAAU,QAAO;AACxC,UAAM,SAAS;AACf,QAAI,EAAE,OAAO,QAAS,QAAO;AAC7B,cAAU,OAAO,GAAG;AAAA,EACtB;AACA,SAAQ,WAAiB;AAC3B;AASO,SAAS,QAA2C,KAAQ,MAAc,OAAmB;AAClG,QAAM,OAAO,KAAK,MAAM,GAAG;AAC3B,QAAM,SAAS,EAAE,GAAG,IAAI;AACxB,MAAI,UAAU;AACd,WAAS,IAAI,GAAG,IAAI,KAAK,SAAS,GAAG,KAAK;AACxC,UAAM,MAAM,KAAK,CAAC;AAClB,UAAM,OAAO,QAAQ,GAAG;AACxB,QAAI,SAAS,QAAQ,SAAS,UAAa,OAAO,SAAS,UAAU;AACnE,YAAM,UAAU,QAAQ,KAAK,KAAK,IAAI,CAAC,CAAE;AACzC,cAAQ,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC;AAAA,IACjC;AACA,cAAU,QAAQ,GAAG;AAAA,EACvB;AACA,UAAQ,KAAK,KAAK,SAAS,CAAC,CAAE,IAAI;AAClC,SAAO;AACT;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/collection/index.ts"],"sourcesContent":["/**\r\n * Groups an array of items by a key extracted from each item.\r\n *\r\n * @example groupBy([{ type: 'a' }, { type: 'b' }, { type: 'a' }], x => x.type)\r\n * // => { a: [{ type: 'a' }, { type: 'a' }], b: [{ type: 'b' }] }\r\n */\r\nexport function groupBy<T, K extends string | number | symbol>(items: T[], keyFn: (item: T) => K): Record<K, T[]> {\r\n const result = {} as Record<K, T[]>\r\n for (const item of items) {\r\n const key = keyFn(item)\r\n if (!result[key]) result[key] = []\r\n result[key]!.push(item)\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * Creates an object keyed by the result of keyFn for each item.\r\n *\r\n * @example keyBy([{ id: 1, name: 'a' }, { id: 2, name: 'b' }], x => x.id)\r\n * // => { 1: { id: 1, name: 'a' }, 2: { id: 2, name: 'b' } }\r\n */\r\nexport function keyBy<T, K extends string | number | symbol>(items: T[], keyFn: (item: T) => K): Record<K, T> {\r\n const result = {} as Record<K, T>\r\n for (const item of items) {\r\n const key = keyFn(item)\r\n result[key] = item\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * Returns a copy of the object with the specified keys omitted.\r\n */\r\nexport function omit<T extends Record<string, unknown>, K extends keyof T>(obj: T, keys: K[]): Omit<T, K> {\r\n const result = { ...obj } as T\r\n for (const key of keys) {\r\n delete result[key]\r\n }\r\n return result as Omit<T, K>\r\n}\r\n\r\n/**\r\n * Returns a copy of the object with only the specified keys.\r\n */\r\nexport function pick<T extends Record<string, unknown>, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> {\r\n const result = {} as Pick<T, K>\r\n for (const key of keys) {\r\n if (key in obj) {\r\n result[key] = obj[key]\r\n }\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * Extracts a property value from each item in an array.\r\n */\r\nexport function pluck<T, K extends keyof T>(items: T[], key: K): T[K][] {\r\n return items.map(item => item[key])\r\n}\r\n\r\n/**\r\n * Randomizes array order in-place using the Fisher-Yates algorithm.\r\n */\r\nexport function shuffle<T>(items: T[]): T[] {\r\n const result = [...items]\r\n for (let i = result.length - 1; i > 0; i--) {\r\n const j = Math.floor(Math.random() * (i + 1))\r\n const temp = result[i]!\r\n result[i] = result[j]!\r\n result[j] = temp\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * Returns a random element from the array, or undefined if empty.\r\n */\r\nexport function sample<T>(items: T[]): T | undefined {\r\n return items.length > 0 ? items[Math.floor(Math.random() * items.length)] : undefined\r\n}\r\n\r\n/**\r\n * Returns an array of `size` random elements (without duplicates).\r\n */\r\nexport function sampleSize<T>(items: T[], size: number): T[] {\r\n if (size <= 0 || items.length === 0) return []\r\n const pool = shuffle(items)\r\n return pool.slice(0, Math.min(size, items.length))\r\n}\r\n\r\n/**\r\n * Splits an array into chunks of the specified size.\r\n */\r\nexport function chunk<T>(items: T[], size: number): T[][] {\r\n if (size <= 0 || items.length === 0) return []\r\n const result: T[][] = []\r\n for (let i = 0; i < items.length; i += size) {\r\n result.push(items.slice(i, i + size))\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * Returns a sorted copy of the array using the provided criteria functions.\r\n * Earlier criteria take precedence.\r\n */\r\nfunction compareValues(a: unknown, b: unknown): number {\r\n if (a === b) return 0\r\n if (a == null) return -1\r\n if (b == null) return 1\r\n if (typeof a === 'string' && typeof b === 'string') return a < b ? -1 : 1\r\n if (typeof a === 'number' && typeof b === 'number') return a < b ? -1 : 1\r\n return String(a) < String(b) ? -1 : 1\r\n}\r\n\r\nexport function sortBy<T>(items: T[], ...criteria: Array<(item: T) => unknown>): T[] {\r\n return [...items].sort((a, b) => {\r\n for (const criterion of criteria) {\r\n const cmp = compareValues(criterion(a), criterion(b))\r\n if (cmp !== 0) return cmp\r\n }\r\n return 0\r\n })\r\n}\r\n\r\n/**\r\n * Returns a sorted copy of the array by a single key and direction.\r\n */\r\nexport function orderBy<T>(items: T[], key: (item: T) => unknown, direction: SortDirection = 'asc'): T[] {\r\n return [...items].sort((a, b) => {\r\n const cmp = compareValues(key(a), key(b))\r\n return direction === 'asc' ? cmp : -cmp\r\n })\r\n}\r\n\r\n/**\r\n * Returns unique elements based on the result of keyFn.\r\n */\r\nexport function uniqueBy<T>(items: T[], keyFn: (item: T) => unknown): T[] {\r\n const seen = new Set<unknown>()\r\n return items.filter(item => {\r\n const key = keyFn(item)\r\n if (seen.has(key)) return false\r\n seen.add(key)\r\n return true\r\n })\r\n}\r\n\r\n/**\r\n * Flattens an array of arrays one level.\r\n */\r\nexport function flatten<T>(items: T[][]): T[] {\r\n const result: T[] = []\r\n for (const sub of items) {\r\n for (const item of sub) {\r\n result.push(item)\r\n }\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * Returns an array with unique primitive values.\r\n */\r\nexport function uniq<T>(items: T[]): T[] {\r\n return [...new Set(items)]\r\n}\r\n\r\n/**\r\n * Returns the first element, or undefined if empty.\r\n */\r\nexport function first<T>(items: T[]): T | undefined {\r\n return items[0]\r\n}\r\n\r\n/**\r\n * Returns the last element, or undefined if empty.\r\n */\r\nexport function last<T>(items: T[]): T | undefined {\r\n return items[items.length - 1]\r\n}\r\n\r\n/**\r\n * Checks if a value is empty.\r\n * Works for arrays, objects, strings, Map, and Set.\r\n */\r\nexport function isEmpty(value: unknown): boolean {\r\n if (Array.isArray(value)) return value.length === 0\r\n if (typeof value === 'string') return value.length === 0\r\n if (value instanceof Map || value instanceof Set) return value.size === 0\r\n if (value !== null && typeof value === 'object') return Object.keys(value as Record<string, unknown>).length === 0\r\n return false\r\n}\r\n\r\nexport type SortDirection = 'asc' | 'desc'\r\n\r\nexport function topoSort<T extends { id: string; dependencies?: string[] }>(items: T[]): T[] {\r\n const adj = new Map<string, string[]>()\r\n const inDegree = new Map<string, number>()\r\n const itemMap = new Map<string, T>()\r\n\r\n for (const item of items) {\r\n itemMap.set(item.id, item)\r\n if (!adj.has(item.id)) adj.set(item.id, [])\r\n if (!inDegree.has(item.id)) inDegree.set(item.id, 0)\r\n }\r\n\r\n for (const item of items) {\r\n if (item.dependencies) {\r\n for (const depId of item.dependencies) {\r\n adj.get(depId)?.push(item.id)\r\n inDegree.set(item.id, (inDegree.get(item.id) ?? 0) + 1)\r\n }\r\n }\r\n }\r\n\r\n const queue: string[] = []\r\n for (const [id, degree] of inDegree) {\r\n if (degree === 0) queue.push(id)\r\n }\r\n\r\n const sorted: string[] = []\r\n while (queue.length > 0) {\r\n const id = queue.shift()!\r\n sorted.push(id)\r\n for (const neighbor of adj.get(id) ?? []) {\r\n const newDegree = (inDegree.get(neighbor) ?? 1) - 1\r\n inDegree.set(neighbor, newDegree)\r\n if (newDegree === 0) queue.push(neighbor)\r\n }\r\n }\r\n\r\n if (sorted.length !== items.length) {\r\n throw new Error('Circular dependency detected')\r\n }\r\n\r\n return sorted.map(id => itemMap.get(id)!)\r\n}\r\n\r\nexport function slidingWindows<T>(items: T[], size: number, step: number = 1): T[][] {\r\n if (size <= 0 || items.length === 0 || step <= 0) return []\r\n const result: T[][] = []\r\n for (let i = 0; i + size <= items.length; i += step) {\r\n result.push(items.slice(i, i + size))\r\n }\r\n return result\r\n}\r\n\r\nexport function tumblingWindows<T>(items: T[], size: number): T[][] {\r\n if (size <= 0 || items.length === 0) return []\r\n const result: T[][] = []\r\n for (let i = 0; i < items.length; i += size) {\r\n result.push(items.slice(i, i + size))\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * Gets a nested value from an object using a dot-separated path.\r\n *\r\n * @example deepGet({ a: { b: 2 } }, 'a.b') // 2\r\n * @example deepGet({ a: { b: 2 } }, 'a.c') // undefined\r\n */\r\nexport function deepGet<T = unknown>(obj: unknown, path: string, default_?: T): T | undefined {\r\n const keys = path.split('.')\r\n let current: unknown = obj\r\n for (const key of keys) {\r\n if (current === null || current === undefined) return default_\r\n if (typeof current !== 'object') return default_\r\n const curObj = current as Record<string, unknown>\r\n if (!(key in curObj)) return default_\r\n current = curObj[key]\r\n }\r\n return (current as T) ?? default_\r\n}\r\n\r\n/**\r\n * Sets a nested value in an object using a dot-separated path.\r\n * Creates intermediate objects/arrays as needed.\r\n *\r\n * @example deepSet({ a: { b: 2 } }, 'a.b', 3) // { a: { b: 3 } }\r\n * @example deepSet({}, 'a.b.c', 1) // { a: { b: { c: 1 } } }\r\n */\r\nexport function deepSet<T extends Record<string, unknown>>(obj: T, path: string, value: unknown): T {\r\n const keys = path.split('.')\r\n const result = { ...obj } as Record<string, unknown>\r\n let current = result\r\n for (let i = 0; i < keys.length - 1; i++) {\r\n const key = keys[i]!\r\n const next = current[key]\r\n if (next === null || next === undefined || typeof next !== 'object') {\r\n const isArray = /^\\d+$/.test(keys[i + 1]!)\r\n current[key] = isArray ? [] : {}\r\n }\r\n current = current[key] as Record<string, unknown>\r\n }\r\n current[keys[keys.length - 1]!] = value\r\n return result as T\r\n}\r\n\r\n/**\r\n * Splits an array into two groups: those that pass the predicate and those that don't.\r\n *\r\n * @example partition([1, 2, 3, 4, 5], n => n % 2 === 0)\r\n * // => [[2, 4], [1, 3, 5]]\r\n */\r\nexport function partition<T>(items: T[], predicate: (item: T) => boolean): [T[], T[]] {\r\n const pass: T[] = []\r\n const fail: T[] = []\r\n for (const item of items) {\r\n if (predicate(item)) pass.push(item)\r\n else fail.push(item)\r\n }\r\n return [pass, fail]\r\n}\r\n\r\n/**\r\n * Removes all falsy values from an array (false, null, 0, '', undefined, NaN).\r\n *\r\n * @example compact([0, 1, false, 2, '', 3, null, undefined, NaN])\r\n * // => [1, 2, 3]\r\n */\r\nexport function compact<T>(items: (T | false | null | 0 | '' | undefined)[]): T[] {\r\n return items.filter(Boolean) as T[]\r\n}\r\n\r\n/**\r\n * Returns elements in array A that are not in array B (uses SameValueZero).\r\n *\r\n * @example difference([1, 2, 3, 4], [2, 4])\r\n * // => [1, 3]\r\n */\r\nexport function difference<T>(a: T[], b: T[]): T[] {\r\n const setB = new Set(b)\r\n return a.filter(item => !setB.has(item))\r\n}\r\n\r\n/**\r\n * Returns elements present in all given arrays (uses SameValueZero).\r\n *\r\n * @example intersection([1, 2, 3], [2, 3, 4])\r\n * // => [2, 3]\r\n */\r\nexport function intersection<T>(a: T[], b: T[]): T[] {\r\n const setB = new Set(b)\r\n return a.filter(item => setB.has(item))\r\n}\r\n\r\n/**\r\n * Returns unique elements from all given arrays.\r\n *\r\n * @example union([1, 2], [2, 3], [3, 4])\r\n * // => [1, 2, 3, 4]\r\n */\r\nexport function union<T>(...arrays: T[][]): T[] {\r\n const set = new Set<T>()\r\n for (const arr of arrays) {\r\n for (const item of arr) {\r\n set.add(item)\r\n }\r\n }\r\n return [...set]\r\n}\r\n\r\n/**\r\n * Merges arrays element-wise into tuples, stopping at the shortest array.\r\n *\r\n * @example zip(['a', 'b', 'c'], [1, 2])\r\n * // => [['a', 1], ['b', 2]]\r\n */\r\nexport function zip<T, U>(a: T[], b: U[]): [T, U][]\r\nexport function zip<T, U, V>(a: T[], b: U[], c: V[]): [T, U, V][]\r\nexport function zip<T>(...arrays: T[][]): T[][] {\r\n if (arrays.length === 0) return []\r\n const minLen = Math.min(...arrays.map(a => a.length))\r\n const result: T[][] = []\r\n for (let i = 0; i < minLen; i++) {\r\n const tuple: T[] = []\r\n for (const arr of arrays) {\r\n tuple.push(arr[i]!)\r\n }\r\n result.push(tuple)\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * Inverse of zip: splits an array of tuples back into individual arrays.\r\n *\r\n * @example unzip([['a', 1], ['b', 2]])\r\n * // => [['a', 'b'], [1, 2]]\r\n */\r\nexport function unzip<T>(paired: T[][]): T[][] {\r\n if (paired.length === 0) return []\r\n const tupleLen = paired.reduce((max, t) => Math.max(max, t.length), 0)\r\n const result: T[][] = Array.from({ length: tupleLen }, () => [])\r\n for (const tuple of paired) {\r\n for (let i = 0; i < tupleLen; i++) {\r\n result[i]!.push(tuple[i] as T)\r\n }\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * Counts occurrences of each key produced by the key function.\r\n *\r\n * @example countBy([1, 2, 3, 4, 5], n => n % 2 === 0 ? 'even' : 'odd')\r\n * // => { odd: 3, even: 2 }\r\n */\r\nexport function countBy<T, K extends string | number | symbol>(items: T[], keyFn: (item: T) => K): Record<K, number> {\r\n const result = {} as Record<K, number>\r\n for (const item of items) {\r\n const key = keyFn(item)\r\n result[key] = (result[key] ?? 0) + 1\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * Returns the element with the maximum value by the key function.\r\n *\r\n * @example maxBy([{ name: 'a', score: 10 }, { name: 'b', score: 20 }], x => x.score)\r\n * // => { name: 'b', score: 20 }\r\n */\r\nexport function maxBy<T>(items: T[], keyFn: (item: T) => number): T | undefined {\r\n if (items.length === 0) return undefined\r\n let maxItem = items[0]!\r\n let maxVal = keyFn(maxItem)\r\n for (let i = 1; i < items.length; i++) {\r\n const val = keyFn(items[i]!)\r\n if (val > maxVal) {\r\n maxVal = val\r\n maxItem = items[i]!\r\n }\r\n }\r\n return maxItem\r\n}\r\n\r\n/**\r\n * Returns the element with the minimum value by the key function.\r\n *\r\n * @example minBy([{ name: 'a', score: 10 }, { name: 'b', score: 20 }], x => x.score)\r\n * // => { name: 'a', score: 10 }\r\n */\r\nexport function minBy<T>(items: T[], keyFn: (item: T) => number): T | undefined {\r\n if (items.length === 0) return undefined\r\n let minItem = items[0]!\r\n let minVal = keyFn(minItem)\r\n for (let i = 1; i < items.length; i++) {\r\n const val = keyFn(items[i]!)\r\n if (val < minVal) {\r\n minVal = val\r\n minItem = items[i]!\r\n }\r\n }\r\n return minItem\r\n}\r\n\r\n/**\r\n * Returns the sum of values produced by the key function.\r\n *\r\n * @example sumBy([{ n: 1 }, { n: 2 }, { n: 3 }], x => x.n)\r\n * // => 6\r\n */\r\nexport function sumBy<T>(items: T[], keyFn: (item: T) => number): number {\r\n let total = 0\r\n for (const item of items) {\r\n total += keyFn(item)\r\n }\r\n return total\r\n}\r\n\r\n/**\r\n * Returns the index of the first element satisfying the predicate, or -1.\r\n *\r\n * @example findIndex([1, 3, 5, 8, 10], n => n % 2 === 0)\r\n * // => 3\r\n */\r\nexport function findIndex<T>(items: T[], predicate: (item: T) => boolean, fromIndex: number = 0): number {\r\n for (let i = fromIndex; i < items.length; i++) {\r\n if (predicate(items[i]!)) return i\r\n }\r\n return -1\r\n}\r\n\r\n/**\r\n * Finds the last element satisfying the predicate.\r\n *\r\n * @example findLast([1, 2, 3, 4, 5], n => n % 2 === 0)\r\n * // => 4\r\n */\r\nexport function findLast<T>(items: T[], predicate: (item: T) => boolean): T | undefined {\r\n for (let i = items.length - 1; i >= 0; i--) {\r\n if (predicate(items[i]!)) return items[i]\r\n }\r\n return undefined\r\n}\r\n\r\n/**\r\n * Drops the first n elements from the array.\r\n *\r\n * @example drop([1, 2, 3, 4, 5], 2)\r\n * // => [3, 4, 5]\r\n */\r\nexport function drop<T>(items: T[], n: number = 1): T[] {\r\n return items.slice(Math.max(0, n))\r\n}\r\n\r\n/**\r\n * Drops the last n elements from the array.\r\n *\r\n * @example dropRight([1, 2, 3, 4, 5], 2)\r\n * // => [1, 2, 3]\r\n */\r\nexport function dropRight<T>(items: T[], n: number = 1): T[] {\r\n return items.slice(0, Math.max(0, items.length - n))\r\n}\r\n\r\n/**\r\n * Takes the first n elements from the array.\r\n *\r\n * @example take([1, 2, 3, 4, 5], 2)\r\n * // => [1, 2]\r\n */\r\nexport function take<T>(items: T[], n: number = 1): T[] {\r\n return items.slice(0, Math.max(0, n))\r\n}\r\n\r\n/**\r\n * Takes the last n elements from the array.\r\n *\r\n * @example takeRight([1, 2, 3, 4, 5], 2)\r\n * // => [4, 5]\r\n */\r\nexport function takeRight<T>(items: T[], n: number = 1): T[] {\r\n return items.slice(Math.max(0, items.length - n))\r\n}\r\n\r\n/**\r\n * Removes specified values from the array (uses SameValueZero).\r\n *\r\n * @example without([1, 2, 1, 3, 1, 4], 1, 3)\r\n * // => [2, 4]\r\n */\r\nexport function without<T>(items: T[], ...values: T[]): T[] {\r\n const exclude = new Set(values)\r\n return items.filter(item => !exclude.has(item))\r\n}\r\n\r\n/**\r\n * Gets the element at the given index. Supports negative indexing.\r\n *\r\n * @example nth([1, 2, 3], 1) // => 2\r\n * @example nth([1, 2, 3], -1) // => 3\r\n */\r\nexport function nth<T>(items: T[], index: number): T | undefined {\r\n return index < 0 ? items[items.length + index] : items[index]\r\n}\r\n"],"mappings":";AAMO,SAAS,QAA+C,OAAY,OAAuC;AAChH,QAAM,SAAS,CAAC;AAChB,aAAW,QAAQ,OAAO;AACxB,UAAM,MAAM,MAAM,IAAI;AACtB,QAAI,CAAC,OAAO,GAAG,EAAG,QAAO,GAAG,IAAI,CAAC;AACjC,WAAO,GAAG,EAAG,KAAK,IAAI;AAAA,EACxB;AACA,SAAO;AACT;AAQO,SAAS,MAA6C,OAAY,OAAqC;AAC5G,QAAM,SAAS,CAAC;AAChB,aAAW,QAAQ,OAAO;AACxB,UAAM,MAAM,MAAM,IAAI;AACtB,WAAO,GAAG,IAAI;AAAA,EAChB;AACA,SAAO;AACT;AAKO,SAAS,KAA2D,KAAQ,MAAuB;AACxG,QAAM,SAAS,EAAE,GAAG,IAAI;AACxB,aAAW,OAAO,MAAM;AACtB,WAAO,OAAO,GAAG;AAAA,EACnB;AACA,SAAO;AACT;AAKO,SAAS,KAA2D,KAAQ,MAAuB;AACxG,QAAM,SAAS,CAAC;AAChB,aAAW,OAAO,MAAM;AACtB,QAAI,OAAO,KAAK;AACd,aAAO,GAAG,IAAI,IAAI,GAAG;AAAA,IACvB;AAAA,EACF;AACA,SAAO;AACT;AAKO,SAAS,MAA4B,OAAY,KAAgB;AACtE,SAAO,MAAM,IAAI,UAAQ,KAAK,GAAG,CAAC;AACpC;AAKO,SAAS,QAAW,OAAiB;AAC1C,QAAM,SAAS,CAAC,GAAG,KAAK;AACxB,WAAS,IAAI,OAAO,SAAS,GAAG,IAAI,GAAG,KAAK;AAC1C,UAAM,IAAI,KAAK,MAAM,KAAK,OAAO,KAAK,IAAI,EAAE;AAC5C,UAAM,OAAO,OAAO,CAAC;AACrB,WAAO,CAAC,IAAI,OAAO,CAAC;AACpB,WAAO,CAAC,IAAI;AAAA,EACd;AACA,SAAO;AACT;AAKO,SAAS,OAAU,OAA2B;AACnD,SAAO,MAAM,SAAS,IAAI,MAAM,KAAK,MAAM,KAAK,OAAO,IAAI,MAAM,MAAM,CAAC,IAAI;AAC9E;AAKO,SAAS,WAAc,OAAY,MAAmB;AAC3D,MAAI,QAAQ,KAAK,MAAM,WAAW,EAAG,QAAO,CAAC;AAC7C,QAAM,OAAO,QAAQ,KAAK;AAC1B,SAAO,KAAK,MAAM,GAAG,KAAK,IAAI,MAAM,MAAM,MAAM,CAAC;AACnD;AAKO,SAAS,MAAS,OAAY,MAAqB;AACxD,MAAI,QAAQ,KAAK,MAAM,WAAW,EAAG,QAAO,CAAC;AAC7C,QAAM,SAAgB,CAAC;AACvB,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,MAAM;AAC3C,WAAO,KAAK,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC;AAAA,EACtC;AACA,SAAO;AACT;AAMA,SAAS,cAAc,GAAY,GAAoB;AACrD,MAAI,MAAM,EAAG,QAAO;AACpB,MAAI,KAAK,KAAM,QAAO;AACtB,MAAI,KAAK,KAAM,QAAO;AACtB,MAAI,OAAO,MAAM,YAAY,OAAO,MAAM,SAAU,QAAO,IAAI,IAAI,KAAK;AACxE,MAAI,OAAO,MAAM,YAAY,OAAO,MAAM,SAAU,QAAO,IAAI,IAAI,KAAK;AACxE,SAAO,OAAO,CAAC,IAAI,OAAO,CAAC,IAAI,KAAK;AACtC;AAEO,SAAS,OAAU,UAAe,UAA4C;AACnF,SAAO,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM;AAC/B,eAAW,aAAa,UAAU;AAChC,YAAM,MAAM,cAAc,UAAU,CAAC,GAAG,UAAU,CAAC,CAAC;AACpD,UAAI,QAAQ,EAAG,QAAO;AAAA,IACxB;AACA,WAAO;AAAA,EACT,CAAC;AACH;AAKO,SAAS,QAAW,OAAY,KAA2B,YAA2B,OAAY;AACvG,SAAO,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM;AAC/B,UAAM,MAAM,cAAc,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;AACxC,WAAO,cAAc,QAAQ,MAAM,CAAC;AAAA,EACtC,CAAC;AACH;AAKO,SAAS,SAAY,OAAY,OAAkC;AACxE,QAAM,OAAO,oBAAI,IAAa;AAC9B,SAAO,MAAM,OAAO,UAAQ;AAC1B,UAAM,MAAM,MAAM,IAAI;AACtB,QAAI,KAAK,IAAI,GAAG,EAAG,QAAO;AAC1B,SAAK,IAAI,GAAG;AACZ,WAAO;AAAA,EACT,CAAC;AACH;AAKO,SAAS,QAAW,OAAmB;AAC5C,QAAM,SAAc,CAAC;AACrB,aAAW,OAAO,OAAO;AACvB,eAAW,QAAQ,KAAK;AACtB,aAAO,KAAK,IAAI;AAAA,IAClB;AAAA,EACF;AACA,SAAO;AACT;AAKO,SAAS,KAAQ,OAAiB;AACvC,SAAO,CAAC,GAAG,IAAI,IAAI,KAAK,CAAC;AAC3B;AAKO,SAAS,MAAS,OAA2B;AAClD,SAAO,MAAM,CAAC;AAChB;AAKO,SAAS,KAAQ,OAA2B;AACjD,SAAO,MAAM,MAAM,SAAS,CAAC;AAC/B;AAMO,SAAS,QAAQ,OAAyB;AAC/C,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,MAAM,WAAW;AAClD,MAAI,OAAO,UAAU,SAAU,QAAO,MAAM,WAAW;AACvD,MAAI,iBAAiB,OAAO,iBAAiB,IAAK,QAAO,MAAM,SAAS;AACxE,MAAI,UAAU,QAAQ,OAAO,UAAU,SAAU,QAAO,OAAO,KAAK,KAAgC,EAAE,WAAW;AACjH,SAAO;AACT;AAIO,SAAS,SAA4D,OAAiB;AAC3F,QAAM,MAAM,oBAAI,IAAsB;AACtC,QAAM,WAAW,oBAAI,IAAoB;AACzC,QAAM,UAAU,oBAAI,IAAe;AAEnC,aAAW,QAAQ,OAAO;AACxB,YAAQ,IAAI,KAAK,IAAI,IAAI;AACzB,QAAI,CAAC,IAAI,IAAI,KAAK,EAAE,EAAG,KAAI,IAAI,KAAK,IAAI,CAAC,CAAC;AAC1C,QAAI,CAAC,SAAS,IAAI,KAAK,EAAE,EAAG,UAAS,IAAI,KAAK,IAAI,CAAC;AAAA,EACrD;AAEA,aAAW,QAAQ,OAAO;AACxB,QAAI,KAAK,cAAc;AACrB,iBAAW,SAAS,KAAK,cAAc;AACrC,YAAI,IAAI,KAAK,GAAG,KAAK,KAAK,EAAE;AAC5B,iBAAS,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,EAAE,KAAK,KAAK,CAAC;AAAA,MACxD;AAAA,IACF;AAAA,EACF;AAEA,QAAM,QAAkB,CAAC;AACzB,aAAW,CAAC,IAAI,MAAM,KAAK,UAAU;AACnC,QAAI,WAAW,EAAG,OAAM,KAAK,EAAE;AAAA,EACjC;AAEA,QAAM,SAAmB,CAAC;AAC1B,SAAO,MAAM,SAAS,GAAG;AACvB,UAAM,KAAK,MAAM,MAAM;AACvB,WAAO,KAAK,EAAE;AACd,eAAW,YAAY,IAAI,IAAI,EAAE,KAAK,CAAC,GAAG;AACxC,YAAM,aAAa,SAAS,IAAI,QAAQ,KAAK,KAAK;AAClD,eAAS,IAAI,UAAU,SAAS;AAChC,UAAI,cAAc,EAAG,OAAM,KAAK,QAAQ;AAAA,IAC1C;AAAA,EACF;AAEA,MAAI,OAAO,WAAW,MAAM,QAAQ;AAClC,UAAM,IAAI,MAAM,8BAA8B;AAAA,EAChD;AAEA,SAAO,OAAO,IAAI,QAAM,QAAQ,IAAI,EAAE,CAAE;AAC1C;AAEO,SAAS,eAAkB,OAAY,MAAc,OAAe,GAAU;AACnF,MAAI,QAAQ,KAAK,MAAM,WAAW,KAAK,QAAQ,EAAG,QAAO,CAAC;AAC1D,QAAM,SAAgB,CAAC;AACvB,WAAS,IAAI,GAAG,IAAI,QAAQ,MAAM,QAAQ,KAAK,MAAM;AACnD,WAAO,KAAK,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC;AAAA,EACtC;AACA,SAAO;AACT;AAEO,SAAS,gBAAmB,OAAY,MAAqB;AAClE,MAAI,QAAQ,KAAK,MAAM,WAAW,EAAG,QAAO,CAAC;AAC7C,QAAM,SAAgB,CAAC;AACvB,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,MAAM;AAC3C,WAAO,KAAK,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC;AAAA,EACtC;AACA,SAAO;AACT;AAQO,SAAS,QAAqB,KAAc,MAAc,UAA6B;AAC5F,QAAM,OAAO,KAAK,MAAM,GAAG;AAC3B,MAAI,UAAmB;AACvB,aAAW,OAAO,MAAM;AACtB,QAAI,YAAY,QAAQ,YAAY,OAAW,QAAO;AACtD,QAAI,OAAO,YAAY,SAAU,QAAO;AACxC,UAAM,SAAS;AACf,QAAI,EAAE,OAAO,QAAS,QAAO;AAC7B,cAAU,OAAO,GAAG;AAAA,EACtB;AACA,SAAQ,WAAiB;AAC3B;AASO,SAAS,QAA2C,KAAQ,MAAc,OAAmB;AAClG,QAAM,OAAO,KAAK,MAAM,GAAG;AAC3B,QAAM,SAAS,EAAE,GAAG,IAAI;AACxB,MAAI,UAAU;AACd,WAAS,IAAI,GAAG,IAAI,KAAK,SAAS,GAAG,KAAK;AACxC,UAAM,MAAM,KAAK,CAAC;AAClB,UAAM,OAAO,QAAQ,GAAG;AACxB,QAAI,SAAS,QAAQ,SAAS,UAAa,OAAO,SAAS,UAAU;AACnE,YAAM,UAAU,QAAQ,KAAK,KAAK,IAAI,CAAC,CAAE;AACzC,cAAQ,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC;AAAA,IACjC;AACA,cAAU,QAAQ,GAAG;AAAA,EACvB;AACA,UAAQ,KAAK,KAAK,SAAS,CAAC,CAAE,IAAI;AAClC,SAAO;AACT;AAQO,SAAS,UAAa,OAAY,WAA6C;AACpF,QAAM,OAAY,CAAC;AACnB,QAAM,OAAY,CAAC;AACnB,aAAW,QAAQ,OAAO;AACxB,QAAI,UAAU,IAAI,EAAG,MAAK,KAAK,IAAI;AAAA,QAC9B,MAAK,KAAK,IAAI;AAAA,EACrB;AACA,SAAO,CAAC,MAAM,IAAI;AACpB;AAQO,SAAS,QAAW,OAAuD;AAChF,SAAO,MAAM,OAAO,OAAO;AAC7B;AAQO,SAAS,WAAc,GAAQ,GAAa;AACjD,QAAM,OAAO,IAAI,IAAI,CAAC;AACtB,SAAO,EAAE,OAAO,UAAQ,CAAC,KAAK,IAAI,IAAI,CAAC;AACzC;AAQO,SAAS,aAAgB,GAAQ,GAAa;AACnD,QAAM,OAAO,IAAI,IAAI,CAAC;AACtB,SAAO,EAAE,OAAO,UAAQ,KAAK,IAAI,IAAI,CAAC;AACxC;AAQO,SAAS,SAAY,QAAoB;AAC9C,QAAM,MAAM,oBAAI,IAAO;AACvB,aAAW,OAAO,QAAQ;AACxB,eAAW,QAAQ,KAAK;AACtB,UAAI,IAAI,IAAI;AAAA,IACd;AAAA,EACF;AACA,SAAO,CAAC,GAAG,GAAG;AAChB;AAUO,SAAS,OAAU,QAAsB;AAC9C,MAAI,OAAO,WAAW,EAAG,QAAO,CAAC;AACjC,QAAM,SAAS,KAAK,IAAI,GAAG,OAAO,IAAI,OAAK,EAAE,MAAM,CAAC;AACpD,QAAM,SAAgB,CAAC;AACvB,WAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC/B,UAAM,QAAa,CAAC;AACpB,eAAW,OAAO,QAAQ;AACxB,YAAM,KAAK,IAAI,CAAC,CAAE;AAAA,IACpB;AACA,WAAO,KAAK,KAAK;AAAA,EACnB;AACA,SAAO;AACT;AAQO,SAAS,MAAS,QAAsB;AAC7C,MAAI,OAAO,WAAW,EAAG,QAAO,CAAC;AACjC,QAAM,WAAW,OAAO,OAAO,CAAC,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,MAAM,GAAG,CAAC;AACrE,QAAM,SAAgB,MAAM,KAAK,EAAE,QAAQ,SAAS,GAAG,MAAM,CAAC,CAAC;AAC/D,aAAW,SAAS,QAAQ;AAC1B,aAAS,IAAI,GAAG,IAAI,UAAU,KAAK;AACjC,aAAO,CAAC,EAAG,KAAK,MAAM,CAAC,CAAM;AAAA,IAC/B;AAAA,EACF;AACA,SAAO;AACT;AAQO,SAAS,QAA+C,OAAY,OAA0C;AACnH,QAAM,SAAS,CAAC;AAChB,aAAW,QAAQ,OAAO;AACxB,UAAM,MAAM,MAAM,IAAI;AACtB,WAAO,GAAG,KAAK,OAAO,GAAG,KAAK,KAAK;AAAA,EACrC;AACA,SAAO;AACT;AAQO,SAAS,MAAS,OAAY,OAA2C;AAC9E,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,MAAI,UAAU,MAAM,CAAC;AACrB,MAAI,SAAS,MAAM,OAAO;AAC1B,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAM,MAAM,MAAM,MAAM,CAAC,CAAE;AAC3B,QAAI,MAAM,QAAQ;AAChB,eAAS;AACT,gBAAU,MAAM,CAAC;AAAA,IACnB;AAAA,EACF;AACA,SAAO;AACT;AAQO,SAAS,MAAS,OAAY,OAA2C;AAC9E,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,MAAI,UAAU,MAAM,CAAC;AACrB,MAAI,SAAS,MAAM,OAAO;AAC1B,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAM,MAAM,MAAM,MAAM,CAAC,CAAE;AAC3B,QAAI,MAAM,QAAQ;AAChB,eAAS;AACT,gBAAU,MAAM,CAAC;AAAA,IACnB;AAAA,EACF;AACA,SAAO;AACT;AAQO,SAAS,MAAS,OAAY,OAAoC;AACvE,MAAI,QAAQ;AACZ,aAAW,QAAQ,OAAO;AACxB,aAAS,MAAM,IAAI;AAAA,EACrB;AACA,SAAO;AACT;AAQO,SAAS,UAAa,OAAY,WAAiC,YAAoB,GAAW;AACvG,WAAS,IAAI,WAAW,IAAI,MAAM,QAAQ,KAAK;AAC7C,QAAI,UAAU,MAAM,CAAC,CAAE,EAAG,QAAO;AAAA,EACnC;AACA,SAAO;AACT;AAQO,SAAS,SAAY,OAAY,WAAgD;AACtF,WAAS,IAAI,MAAM,SAAS,GAAG,KAAK,GAAG,KAAK;AAC1C,QAAI,UAAU,MAAM,CAAC,CAAE,EAAG,QAAO,MAAM,CAAC;AAAA,EAC1C;AACA,SAAO;AACT;AAQO,SAAS,KAAQ,OAAY,IAAY,GAAQ;AACtD,SAAO,MAAM,MAAM,KAAK,IAAI,GAAG,CAAC,CAAC;AACnC;AAQO,SAAS,UAAa,OAAY,IAAY,GAAQ;AAC3D,SAAO,MAAM,MAAM,GAAG,KAAK,IAAI,GAAG,MAAM,SAAS,CAAC,CAAC;AACrD;AAQO,SAAS,KAAQ,OAAY,IAAY,GAAQ;AACtD,SAAO,MAAM,MAAM,GAAG,KAAK,IAAI,GAAG,CAAC,CAAC;AACtC;AAQO,SAAS,UAAa,OAAY,IAAY,GAAQ;AAC3D,SAAO,MAAM,MAAM,KAAK,IAAI,GAAG,MAAM,SAAS,CAAC,CAAC;AAClD;AAQO,SAAS,QAAW,UAAe,QAAkB;AAC1D,QAAM,UAAU,IAAI,IAAI,MAAM;AAC9B,SAAO,MAAM,OAAO,UAAQ,CAAC,QAAQ,IAAI,IAAI,CAAC;AAChD;AAQO,SAAS,IAAO,OAAY,OAA8B;AAC/D,SAAO,QAAQ,IAAI,MAAM,MAAM,SAAS,KAAK,IAAI,MAAM,KAAK;AAC9D;","names":[]}
|
package/dist/color/index.d.ts
CHANGED
|
@@ -46,5 +46,83 @@ declare function contrastRatio(hex1: string, hex2: string): number;
|
|
|
46
46
|
* @example meetsWCAG('#999999', '#ffffff') // false (gray on white)
|
|
47
47
|
*/
|
|
48
48
|
declare function meetsWCAG(hex1: string, hex2: string, level?: 'AA' | 'AAA'): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Checks if a string is a valid hex color.
|
|
51
|
+
* Supports 3-digit (#rgb), 6-digit (#rrggbb), with or without leading `#`.
|
|
52
|
+
*
|
|
53
|
+
* @example isValidHex('#ff0000') // true
|
|
54
|
+
* @example isValidHex('#f00') // true
|
|
55
|
+
* @example isValidHex('ff0000') // true
|
|
56
|
+
* @example isValidHex('#xyz') // false
|
|
57
|
+
*/
|
|
58
|
+
declare function isValidHex(value: string): boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Converts a hex color to an HSL object.
|
|
61
|
+
* Returns `null` for invalid input.
|
|
62
|
+
*
|
|
63
|
+
* @example hexToHsl('#ff0000') // { h: 0, s: 100, l: 50 }
|
|
64
|
+
* @example hexToHsl('#00ff00') // { h: 120, s: 100, l: 50 }
|
|
65
|
+
* @example hexToHsl('#0000ff') // { h: 240, s: 100, l: 50 }
|
|
66
|
+
*/
|
|
67
|
+
declare function hexToHsl(hex: string): {
|
|
68
|
+
h: number;
|
|
69
|
+
s: number;
|
|
70
|
+
l: number;
|
|
71
|
+
} | null;
|
|
72
|
+
/**
|
|
73
|
+
* Converts HSL values to a hex color string.
|
|
74
|
+
*
|
|
75
|
+
* @example hslToHex(0, 100, 50) // '#ff0000'
|
|
76
|
+
* @example hslToHex(120, 100, 50) // '#00ff00'
|
|
77
|
+
* @example hslToHex(240, 100, 50) // '#0000ff'
|
|
78
|
+
*/
|
|
79
|
+
declare function hslToHex(h: number, s: number, l: number): string;
|
|
80
|
+
/**
|
|
81
|
+
* Blends two hex colors together with a weight factor.
|
|
82
|
+
* Weight 0 = fully color1, weight 1 = fully color2. Default 0.5.
|
|
83
|
+
*
|
|
84
|
+
* @example mix('#ff0000', '#0000ff') // '#7f007f'
|
|
85
|
+
* @example mix('#ff0000', '#0000ff', 0) // '#ff0000'
|
|
86
|
+
* @example mix('#ff0000', '#0000ff', 1) // '#0000ff'
|
|
87
|
+
*/
|
|
88
|
+
declare function mix(color1: string, color2: string, weight?: number): string;
|
|
89
|
+
/**
|
|
90
|
+
* Generates a random hex color.
|
|
91
|
+
*
|
|
92
|
+
* @example randomColor() // '#a3f07b'
|
|
93
|
+
*/
|
|
94
|
+
declare function randomColor(): string;
|
|
95
|
+
/**
|
|
96
|
+
* Checks if a hex color is perceived as light (useful for text contrast decisions).
|
|
97
|
+
*
|
|
98
|
+
* @example isLight('#ffffff') // true
|
|
99
|
+
* @example isLight('#000000') // false
|
|
100
|
+
* @example isLight('#ff0000') // false
|
|
101
|
+
*/
|
|
102
|
+
declare function isLight(hex: string): boolean;
|
|
103
|
+
/**
|
|
104
|
+
* Checks if a hex color is perceived as dark.
|
|
105
|
+
*
|
|
106
|
+
* @example isDark('#000000') // true
|
|
107
|
+
* @example isDark('#ffffff') // false
|
|
108
|
+
*/
|
|
109
|
+
declare function isDark(hex: string): boolean;
|
|
110
|
+
/**
|
|
111
|
+
* Returns the complementary color (180° hue rotation).
|
|
112
|
+
*
|
|
113
|
+
* @example complementary('#ff0000') // '#00ffff'
|
|
114
|
+
* @example complementary('#00ff00') // '#ff00ff'
|
|
115
|
+
* @example complementary('#0000ff') // '#ffff00'
|
|
116
|
+
*/
|
|
117
|
+
declare function complementary(hex: string): string;
|
|
118
|
+
/**
|
|
119
|
+
* Sets opacity on a hex color, returning an 8-digit hex (#rrggbbaa).
|
|
120
|
+
* Opacity is clamped to 0-1.
|
|
121
|
+
*
|
|
122
|
+
* @example alpha('#ff0000', 0.5) // '#ff000080'
|
|
123
|
+
* @example alpha('#00ff00', 1) // '#00ff00ff'
|
|
124
|
+
* @example alpha('#0000ff', 0) // '#0000ff00'
|
|
125
|
+
*/
|
|
126
|
+
declare function alpha(hex: string, opacity: number): string;
|
|
49
127
|
|
|
50
|
-
export { contrastRatio, darken, hexToRgb, lighten, meetsWCAG, rgbToHex };
|
|
128
|
+
export { alpha, complementary, contrastRatio, darken, hexToHsl, hexToRgb, hslToHex, isDark, isLight, isValidHex, lighten, meetsWCAG, mix, randomColor, rgbToHex };
|
package/dist/color/index.js
CHANGED
|
@@ -55,12 +55,113 @@ function meetsWCAG(hex1, hex2, level) {
|
|
|
55
55
|
const threshold = level === "AAA" ? 7 : 4.5;
|
|
56
56
|
return ratio >= threshold;
|
|
57
57
|
}
|
|
58
|
+
function isValidHex(value) {
|
|
59
|
+
return /^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(value);
|
|
60
|
+
}
|
|
61
|
+
function hexToHsl(hex) {
|
|
62
|
+
const rgb = hexToRgb(hex);
|
|
63
|
+
if (!rgb) return null;
|
|
64
|
+
const r = rgb.r / 255;
|
|
65
|
+
const g = rgb.g / 255;
|
|
66
|
+
const b = rgb.b / 255;
|
|
67
|
+
const max = Math.max(r, g, b);
|
|
68
|
+
const min = Math.min(r, g, b);
|
|
69
|
+
const l = (max + min) / 2;
|
|
70
|
+
if (max === min) return { h: 0, s: 0, l: Math.round(l * 100) };
|
|
71
|
+
const d = max - min;
|
|
72
|
+
const s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
73
|
+
let h = 0;
|
|
74
|
+
switch (max) {
|
|
75
|
+
case r:
|
|
76
|
+
h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
|
|
77
|
+
break;
|
|
78
|
+
case g:
|
|
79
|
+
h = ((b - r) / d + 2) / 6;
|
|
80
|
+
break;
|
|
81
|
+
case b:
|
|
82
|
+
h = ((r - g) / d + 4) / 6;
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
h: Math.round(h * 360),
|
|
87
|
+
s: Math.round(s * 100),
|
|
88
|
+
l: Math.round(l * 100)
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
function hslToHex(h, s, l) {
|
|
92
|
+
const hue = h / 360;
|
|
93
|
+
const sat = s / 100;
|
|
94
|
+
const lig = l / 100;
|
|
95
|
+
if (sat === 0) {
|
|
96
|
+
const val = Math.round(lig * 255);
|
|
97
|
+
return rgbToHex(val, val, val);
|
|
98
|
+
}
|
|
99
|
+
const hue2rgb = (p2, q2, t) => {
|
|
100
|
+
let tt = t;
|
|
101
|
+
if (tt < 0) tt += 1;
|
|
102
|
+
if (tt > 1) tt -= 1;
|
|
103
|
+
if (tt < 1 / 6) return p2 + (q2 - p2) * 6 * tt;
|
|
104
|
+
if (tt < 1 / 2) return q2;
|
|
105
|
+
if (tt < 2 / 3) return p2 + (q2 - p2) * (2 / 3 - tt) * 6;
|
|
106
|
+
return p2;
|
|
107
|
+
};
|
|
108
|
+
const q = lig < 0.5 ? lig * (1 + sat) : lig + sat - lig * sat;
|
|
109
|
+
const p = 2 * lig - q;
|
|
110
|
+
return rgbToHex(
|
|
111
|
+
Math.round(hue2rgb(p, q, hue + 1 / 3) * 255),
|
|
112
|
+
Math.round(hue2rgb(p, q, hue) * 255),
|
|
113
|
+
Math.round(hue2rgb(p, q, hue - 1 / 3) * 255)
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
function mix(color1, color2, weight = 0.5) {
|
|
117
|
+
const rgb1 = hexToRgb(color1);
|
|
118
|
+
const rgb2 = hexToRgb(color2);
|
|
119
|
+
if (!rgb1 || !rgb2) return color1;
|
|
120
|
+
const w = Math.max(0, Math.min(1, weight));
|
|
121
|
+
const lerp = (a, b) => Math.floor(a + (b - a) * w);
|
|
122
|
+
return rgbToHex(lerp(rgb1.r, rgb2.r), lerp(rgb1.g, rgb2.g), lerp(rgb1.b, rgb2.b));
|
|
123
|
+
}
|
|
124
|
+
function randomColor() {
|
|
125
|
+
const r = Math.floor(Math.random() * 256);
|
|
126
|
+
const g = Math.floor(Math.random() * 256);
|
|
127
|
+
const b = Math.floor(Math.random() * 256);
|
|
128
|
+
return rgbToHex(r, g, b);
|
|
129
|
+
}
|
|
130
|
+
function isLight(hex) {
|
|
131
|
+
const rgb = hexToRgb(hex);
|
|
132
|
+
if (!rgb) return false;
|
|
133
|
+
return (0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.b) / 255 > 0.5;
|
|
134
|
+
}
|
|
135
|
+
function isDark(hex) {
|
|
136
|
+
return !isLight(hex);
|
|
137
|
+
}
|
|
138
|
+
function complementary(hex) {
|
|
139
|
+
const hsl = hexToHsl(hex);
|
|
140
|
+
if (!hsl) return hex;
|
|
141
|
+
return hslToHex((hsl.h + 180) % 360, hsl.s, hsl.l);
|
|
142
|
+
}
|
|
143
|
+
function alpha(hex, opacity) {
|
|
144
|
+
const rgb = hexToRgb(hex);
|
|
145
|
+
if (!rgb) return hex;
|
|
146
|
+
const a = Math.max(0, Math.min(1, opacity));
|
|
147
|
+
const alphaHex = Math.round(a * 255).toString(16).padStart(2, "0");
|
|
148
|
+
return rgbToHex(rgb.r, rgb.g, rgb.b) + alphaHex;
|
|
149
|
+
}
|
|
58
150
|
export {
|
|
151
|
+
alpha,
|
|
152
|
+
complementary,
|
|
59
153
|
contrastRatio,
|
|
60
154
|
darken,
|
|
155
|
+
hexToHsl,
|
|
61
156
|
hexToRgb,
|
|
157
|
+
hslToHex,
|
|
158
|
+
isDark,
|
|
159
|
+
isLight,
|
|
160
|
+
isValidHex,
|
|
62
161
|
lighten,
|
|
63
162
|
meetsWCAG,
|
|
163
|
+
mix,
|
|
164
|
+
randomColor,
|
|
64
165
|
rgbToHex
|
|
65
166
|
};
|
|
66
167
|
//# sourceMappingURL=index.js.map
|
package/dist/color/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/color/index.ts"],"sourcesContent":["/**\n * Converts a hex color string to RGB values.\n *\n * @example hexToRgb('#ff0000') // { r: 255, g: 0, b: 0 }\n * @example hexToRgb('#f00') // { r: 255, g: 0, b: 0 }\n * @example hexToRgb('#FF8800') // { r: 255, g: 136, b: 0 }\n */\nexport function hexToRgb(hex: string): { r: number; g: number; b: number } | null {\n let h = hex.replace('#', '')\n if (h.length === 3) h = h[0]! + h[0] + h[1]! + h[1] + h[2]! + h[2]\n if (h.length !== 6) return null\n const num = Number.parseInt(h, 16)\n if (isNaN(num)) return null\n return {\n r: (num >> 16) & 255,\n g: (num >> 8) & 255,\n b: num & 255,\n }\n}\n\n/**\n * Converts RGB values to a hex color string.\n *\n * @example rgbToHex(255, 0, 0) // \"#ff0000\"\n * @example rgbToHex(255, 136, 0) // \"#ff8800\"\n */\nexport function rgbToHex(r: number, g: number, b: number): string {\n const toHex = (n: number) => Math.max(0, Math.min(255, Math.round(n))).toString(16).padStart(2, '0')\n return '#' + toHex(r) + toHex(g) + toHex(b)\n}\n\n/**\n * Lightens a hex color by a given percentage (0-100).\n *\n * @example lighten('#ff0000', 20) // \"#ff3333\"\n * @example lighten('#0000ff', 50) // \"#7f7fff\"\n */\nexport function lighten(hex: string, percent: number): string {\n const rgb = hexToRgb(hex)\n if (!rgb) return hex\n const factor = percent / 100\n return rgbToHex(\n rgb.r + (255 - rgb.r) * factor,\n rgb.g + (255 - rgb.g) * factor,\n rgb.b + (255 - rgb.b) * factor,\n )\n}\n\n/**\n * Darkens a hex color by a given percentage (0-100).\n *\n * @example darken('#ff0000', 20) // \"#cc0000\"\n * @example darken('#00ff00', 50) // \"#008000\"\n */\nexport function darken(hex: string, percent: number): string {\n const rgb = hexToRgb(hex)\n if (!rgb) return hex\n const factor = percent / 100\n return rgbToHex(\n rgb.r * (1 - factor),\n rgb.g * (1 - factor),\n rgb.b * (1 - factor),\n )\n}\n\n/**\n * Checks the WCAG contrast ratio between two hex colors.\n * Returns the ratio as a number (1-21). WCAG AA requires 4.5:1 for normal text.\n *\n * @example contrastRatio('#000000', '#ffffff') // 21\n * @example contrastRatio('#ff0000', '#ffffff') // 3.99\n */\nexport function contrastRatio(hex1: string, hex2: string): number {\n const lum1 = relativeLuminance(hex1)\n const lum2 = relativeLuminance(hex2)\n const lighter = Math.max(lum1, lum2)\n const darker = Math.min(lum1, lum2)\n return Number(((lighter + 0.05) / (darker + 0.05)).toFixed(2))\n}\n\nfunction relativeLuminance(hex: string): number {\n const rgb = hexToRgb(hex)\n if (!rgb) return 0\n const vals = [rgb.r / 255, rgb.g / 255, rgb.b / 255].map((c) => {\n return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4)\n })\n return 0.2126 * vals[0]! + 0.7152 * vals[1]! + 0.0722 * vals[2]!\n}\n\n/**\n * Checks if a hex color meets WCAG AA contrast ratio (4.5:1) against another color.\n *\n * @example meetsWCAG('#000000', '#ffffff') // true (black on white)\n * @example meetsWCAG('#999999', '#ffffff') // false (gray on white)\n */\nexport function meetsWCAG(hex1: string, hex2: string, level?: 'AA' | 'AAA'): boolean {\n const ratio = contrastRatio(hex1, hex2)\n const threshold = level === 'AAA' ? 7 : 4.5\n return ratio >= threshold\n}\n"],"mappings":";AAOO,SAAS,SAAS,KAAyD;AAChF,MAAI,IAAI,IAAI,QAAQ,KAAK,EAAE;AAC3B,MAAI,EAAE,WAAW,EAAG,KAAI,EAAE,CAAC,IAAK,EAAE,CAAC,IAAI,EAAE,CAAC,IAAK,EAAE,CAAC,IAAI,EAAE,CAAC,IAAK,EAAE,CAAC;AACjE,MAAI,EAAE,WAAW,EAAG,QAAO;AAC3B,QAAM,MAAM,OAAO,SAAS,GAAG,EAAE;AACjC,MAAI,MAAM,GAAG,EAAG,QAAO;AACvB,SAAO;AAAA,IACL,GAAI,OAAO,KAAM;AAAA,IACjB,GAAI,OAAO,IAAK;AAAA,IAChB,GAAG,MAAM;AAAA,EACX;AACF;AAQO,SAAS,SAAS,GAAW,GAAW,GAAmB;AAChE,QAAM,QAAQ,CAAC,MAAc,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG;AACnG,SAAO,MAAM,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,MAAM,CAAC;AAC5C;AAQO,SAAS,QAAQ,KAAa,SAAyB;AAC5D,QAAM,MAAM,SAAS,GAAG;AACxB,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,SAAS,UAAU;AACzB,SAAO;AAAA,IACL,IAAI,KAAK,MAAM,IAAI,KAAK;AAAA,IACxB,IAAI,KAAK,MAAM,IAAI,KAAK;AAAA,IACxB,IAAI,KAAK,MAAM,IAAI,KAAK;AAAA,EAC1B;AACF;AAQO,SAAS,OAAO,KAAa,SAAyB;AAC3D,QAAM,MAAM,SAAS,GAAG;AACxB,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,SAAS,UAAU;AACzB,SAAO;AAAA,IACL,IAAI,KAAK,IAAI;AAAA,IACb,IAAI,KAAK,IAAI;AAAA,IACb,IAAI,KAAK,IAAI;AAAA,EACf;AACF;AASO,SAAS,cAAc,MAAc,MAAsB;AAChE,QAAM,OAAO,kBAAkB,IAAI;AACnC,QAAM,OAAO,kBAAkB,IAAI;AACnC,QAAM,UAAU,KAAK,IAAI,MAAM,IAAI;AACnC,QAAM,SAAS,KAAK,IAAI,MAAM,IAAI;AAClC,SAAO,SAAS,UAAU,SAAS,SAAS,OAAO,QAAQ,CAAC,CAAC;AAC/D;AAEA,SAAS,kBAAkB,KAAqB;AAC9C,QAAM,MAAM,SAAS,GAAG;AACxB,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,OAAO,CAAC,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI,GAAG,EAAE,IAAI,CAAC,MAAM;AAC9D,WAAO,KAAK,UAAU,IAAI,QAAQ,KAAK,KAAK,IAAI,SAAS,OAAO,GAAG;AAAA,EACrE,CAAC;AACD,SAAO,SAAS,KAAK,CAAC,IAAK,SAAS,KAAK,CAAC,IAAK,SAAS,KAAK,CAAC;AAChE;AAQO,SAAS,UAAU,MAAc,MAAc,OAA+B;AACnF,QAAM,QAAQ,cAAc,MAAM,IAAI;AACtC,QAAM,YAAY,UAAU,QAAQ,IAAI;AACxC,SAAO,SAAS;AAClB;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/color/index.ts"],"sourcesContent":["/**\n * Converts a hex color string to RGB values.\n *\n * @example hexToRgb('#ff0000') // { r: 255, g: 0, b: 0 }\n * @example hexToRgb('#f00') // { r: 255, g: 0, b: 0 }\n * @example hexToRgb('#FF8800') // { r: 255, g: 136, b: 0 }\n */\nexport function hexToRgb(hex: string): { r: number; g: number; b: number } | null {\n let h = hex.replace('#', '')\n if (h.length === 3) h = h[0]! + h[0] + h[1]! + h[1] + h[2]! + h[2]\n if (h.length !== 6) return null\n const num = Number.parseInt(h, 16)\n if (isNaN(num)) return null\n return {\n r: (num >> 16) & 255,\n g: (num >> 8) & 255,\n b: num & 255,\n }\n}\n\n/**\n * Converts RGB values to a hex color string.\n *\n * @example rgbToHex(255, 0, 0) // \"#ff0000\"\n * @example rgbToHex(255, 136, 0) // \"#ff8800\"\n */\nexport function rgbToHex(r: number, g: number, b: number): string {\n const toHex = (n: number) => Math.max(0, Math.min(255, Math.round(n))).toString(16).padStart(2, '0')\n return '#' + toHex(r) + toHex(g) + toHex(b)\n}\n\n/**\n * Lightens a hex color by a given percentage (0-100).\n *\n * @example lighten('#ff0000', 20) // \"#ff3333\"\n * @example lighten('#0000ff', 50) // \"#7f7fff\"\n */\nexport function lighten(hex: string, percent: number): string {\n const rgb = hexToRgb(hex)\n if (!rgb) return hex\n const factor = percent / 100\n return rgbToHex(\n rgb.r + (255 - rgb.r) * factor,\n rgb.g + (255 - rgb.g) * factor,\n rgb.b + (255 - rgb.b) * factor,\n )\n}\n\n/**\n * Darkens a hex color by a given percentage (0-100).\n *\n * @example darken('#ff0000', 20) // \"#cc0000\"\n * @example darken('#00ff00', 50) // \"#008000\"\n */\nexport function darken(hex: string, percent: number): string {\n const rgb = hexToRgb(hex)\n if (!rgb) return hex\n const factor = percent / 100\n return rgbToHex(\n rgb.r * (1 - factor),\n rgb.g * (1 - factor),\n rgb.b * (1 - factor),\n )\n}\n\n/**\n * Checks the WCAG contrast ratio between two hex colors.\n * Returns the ratio as a number (1-21). WCAG AA requires 4.5:1 for normal text.\n *\n * @example contrastRatio('#000000', '#ffffff') // 21\n * @example contrastRatio('#ff0000', '#ffffff') // 3.99\n */\nexport function contrastRatio(hex1: string, hex2: string): number {\n const lum1 = relativeLuminance(hex1)\n const lum2 = relativeLuminance(hex2)\n const lighter = Math.max(lum1, lum2)\n const darker = Math.min(lum1, lum2)\n return Number(((lighter + 0.05) / (darker + 0.05)).toFixed(2))\n}\n\nfunction relativeLuminance(hex: string): number {\n const rgb = hexToRgb(hex)\n if (!rgb) return 0\n const vals = [rgb.r / 255, rgb.g / 255, rgb.b / 255].map((c) => {\n return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4)\n })\n return 0.2126 * vals[0]! + 0.7152 * vals[1]! + 0.0722 * vals[2]!\n}\n\n/**\n * Checks if a hex color meets WCAG AA contrast ratio (4.5:1) against another color.\n *\n * @example meetsWCAG('#000000', '#ffffff') // true (black on white)\n * @example meetsWCAG('#999999', '#ffffff') // false (gray on white)\n */\nexport function meetsWCAG(hex1: string, hex2: string, level?: 'AA' | 'AAA'): boolean {\n const ratio = contrastRatio(hex1, hex2)\n const threshold = level === 'AAA' ? 7 : 4.5\n return ratio >= threshold\n}\n\n/**\n * Checks if a string is a valid hex color.\n * Supports 3-digit (#rgb), 6-digit (#rrggbb), with or without leading `#`.\n *\n * @example isValidHex('#ff0000') // true\n * @example isValidHex('#f00') // true\n * @example isValidHex('ff0000') // true\n * @example isValidHex('#xyz') // false\n */\nexport function isValidHex(value: string): boolean {\n return /^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(value)\n}\n\n/**\n * Converts a hex color to an HSL object.\n * Returns `null` for invalid input.\n *\n * @example hexToHsl('#ff0000') // { h: 0, s: 100, l: 50 }\n * @example hexToHsl('#00ff00') // { h: 120, s: 100, l: 50 }\n * @example hexToHsl('#0000ff') // { h: 240, s: 100, l: 50 }\n */\nexport function hexToHsl(hex: string): { h: number; s: number; l: number } | null {\n const rgb = hexToRgb(hex)\n if (!rgb) return null\n const r = rgb.r / 255\n const g = rgb.g / 255\n const b = rgb.b / 255\n const max = Math.max(r, g, b)\n const min = Math.min(r, g, b)\n const l = (max + min) / 2\n if (max === min) return { h: 0, s: 0, l: Math.round(l * 100) }\n const d = max - min\n const s = l > 0.5 ? d / (2 - max - min) : d / (max + min)\n let h = 0\n switch (max) {\n case r: h = ((g - b) / d + (g < b ? 6 : 0)) / 6; break\n case g: h = ((b - r) / d + 2) / 6; break\n case b: h = ((r - g) / d + 4) / 6; break\n }\n return {\n h: Math.round(h * 360),\n s: Math.round(s * 100),\n l: Math.round(l * 100),\n }\n}\n\n/**\n * Converts HSL values to a hex color string.\n *\n * @example hslToHex(0, 100, 50) // '#ff0000'\n * @example hslToHex(120, 100, 50) // '#00ff00'\n * @example hslToHex(240, 100, 50) // '#0000ff'\n */\nexport function hslToHex(h: number, s: number, l: number): string {\n const hue = h / 360\n const sat = s / 100\n const lig = l / 100\n if (sat === 0) {\n const val = Math.round(lig * 255)\n return rgbToHex(val, val, val)\n }\n const hue2rgb = (p: number, q: number, t: number): number => {\n let tt = t\n if (tt < 0) tt += 1\n if (tt > 1) tt -= 1\n if (tt < 1 / 6) return p + (q - p) * 6 * tt\n if (tt < 1 / 2) return q\n if (tt < 2 / 3) return p + (q - p) * (2 / 3 - tt) * 6\n return p\n }\n const q = lig < 0.5 ? lig * (1 + sat) : lig + sat - lig * sat\n const p = 2 * lig - q\n return rgbToHex(\n Math.round(hue2rgb(p, q, hue + 1 / 3) * 255),\n Math.round(hue2rgb(p, q, hue) * 255),\n Math.round(hue2rgb(p, q, hue - 1 / 3) * 255),\n )\n}\n\n/**\n * Blends two hex colors together with a weight factor.\n * Weight 0 = fully color1, weight 1 = fully color2. Default 0.5.\n *\n * @example mix('#ff0000', '#0000ff') // '#7f007f'\n * @example mix('#ff0000', '#0000ff', 0) // '#ff0000'\n * @example mix('#ff0000', '#0000ff', 1) // '#0000ff'\n */\nexport function mix(color1: string, color2: string, weight: number = 0.5): string {\n const rgb1 = hexToRgb(color1)\n const rgb2 = hexToRgb(color2)\n if (!rgb1 || !rgb2) return color1\n const w = Math.max(0, Math.min(1, weight))\n const lerp = (a: number, b: number) => Math.floor(a + (b - a) * w)\n return rgbToHex(lerp(rgb1.r, rgb2.r), lerp(rgb1.g, rgb2.g), lerp(rgb1.b, rgb2.b))\n}\n\n/**\n * Generates a random hex color.\n *\n * @example randomColor() // '#a3f07b'\n */\nexport function randomColor(): string {\n const r = Math.floor(Math.random() * 256)\n const g = Math.floor(Math.random() * 256)\n const b = Math.floor(Math.random() * 256)\n return rgbToHex(r, g, b)\n}\n\n/**\n * Checks if a hex color is perceived as light (useful for text contrast decisions).\n *\n * @example isLight('#ffffff') // true\n * @example isLight('#000000') // false\n * @example isLight('#ff0000') // false\n */\nexport function isLight(hex: string): boolean {\n const rgb = hexToRgb(hex)\n if (!rgb) return false\n return (0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.b) / 255 > 0.5\n}\n\n/**\n * Checks if a hex color is perceived as dark.\n *\n * @example isDark('#000000') // true\n * @example isDark('#ffffff') // false\n */\nexport function isDark(hex: string): boolean {\n return !isLight(hex)\n}\n\n/**\n * Returns the complementary color (180° hue rotation).\n *\n * @example complementary('#ff0000') // '#00ffff'\n * @example complementary('#00ff00') // '#ff00ff'\n * @example complementary('#0000ff') // '#ffff00'\n */\nexport function complementary(hex: string): string {\n const hsl = hexToHsl(hex)\n if (!hsl) return hex\n return hslToHex((hsl.h + 180) % 360, hsl.s, hsl.l)\n}\n\n/**\n * Sets opacity on a hex color, returning an 8-digit hex (#rrggbbaa).\n * Opacity is clamped to 0-1.\n *\n * @example alpha('#ff0000', 0.5) // '#ff000080'\n * @example alpha('#00ff00', 1) // '#00ff00ff'\n * @example alpha('#0000ff', 0) // '#0000ff00'\n */\nexport function alpha(hex: string, opacity: number): string {\n const rgb = hexToRgb(hex)\n if (!rgb) return hex\n const a = Math.max(0, Math.min(1, opacity))\n const alphaHex = Math.round(a * 255).toString(16).padStart(2, '0')\n return rgbToHex(rgb.r, rgb.g, rgb.b) + alphaHex\n}\n"],"mappings":"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","names":["p","q"]}
|
package/dist/date/index.d.ts
CHANGED
|
@@ -269,5 +269,320 @@ declare function toTimezone(date: Date, offsetHours: number): Date;
|
|
|
269
269
|
* @returns The formatted date string.
|
|
270
270
|
*/
|
|
271
271
|
declare function formatInTimezone(date: Date, format: string, offsetHours: number): string;
|
|
272
|
+
/**
|
|
273
|
+
* Checks if a date is today.
|
|
274
|
+
*
|
|
275
|
+
* @param date - The date to check.
|
|
276
|
+
* @returns Whether the date is today.
|
|
277
|
+
* @throws {InvalidDateError} If the input date is invalid.
|
|
278
|
+
*
|
|
279
|
+
* @example
|
|
280
|
+
* isToday(new Date()) // true
|
|
281
|
+
*/
|
|
282
|
+
declare function isToday(date: Date): boolean;
|
|
283
|
+
/**
|
|
284
|
+
* Checks if a date is yesterday.
|
|
285
|
+
*
|
|
286
|
+
* @param date - The date to check.
|
|
287
|
+
* @returns Whether the date is yesterday.
|
|
288
|
+
* @throws {InvalidDateError} If the input date is invalid.
|
|
289
|
+
*
|
|
290
|
+
* @example
|
|
291
|
+
* isYesterday(new Date(Date.now() - 86400000)) // true
|
|
292
|
+
*/
|
|
293
|
+
declare function isYesterday(date: Date): boolean;
|
|
294
|
+
/**
|
|
295
|
+
* Checks if a date is tomorrow.
|
|
296
|
+
*
|
|
297
|
+
* @param date - The date to check.
|
|
298
|
+
* @returns Whether the date is tomorrow.
|
|
299
|
+
* @throws {InvalidDateError} If the input date is invalid.
|
|
300
|
+
*
|
|
301
|
+
* @example
|
|
302
|
+
* isTomorrow(new Date(Date.now() + 86400000)) // true
|
|
303
|
+
*/
|
|
304
|
+
declare function isTomorrow(date: Date): boolean;
|
|
305
|
+
/**
|
|
306
|
+
* Checks if a date is in the past (before now).
|
|
307
|
+
*
|
|
308
|
+
* @param date - The date to check.
|
|
309
|
+
* @returns Whether the date is in the past.
|
|
310
|
+
* @throws {InvalidDateError} If the input date is invalid.
|
|
311
|
+
*
|
|
312
|
+
* @example
|
|
313
|
+
* isPast(new Date('2020-01-01')) // true
|
|
314
|
+
*/
|
|
315
|
+
declare function isPast(date: Date): boolean;
|
|
316
|
+
/**
|
|
317
|
+
* Checks if a date is in the future (after now).
|
|
318
|
+
*
|
|
319
|
+
* @param date - The date to check.
|
|
320
|
+
* @returns Whether the date is in the future.
|
|
321
|
+
* @throws {InvalidDateError} If the input date is invalid.
|
|
322
|
+
*
|
|
323
|
+
* @example
|
|
324
|
+
* isFuture(new Date('2099-01-01')) // true
|
|
325
|
+
*/
|
|
326
|
+
declare function isFuture(date: Date): boolean;
|
|
327
|
+
/**
|
|
328
|
+
* Checks if two dates fall on the same calendar day.
|
|
329
|
+
*
|
|
330
|
+
* @param date1 - First date.
|
|
331
|
+
* @param date2 - Second date.
|
|
332
|
+
* @returns Whether the dates are the same day.
|
|
333
|
+
* @throws {InvalidDateError} If either date is invalid.
|
|
334
|
+
*
|
|
335
|
+
* @example
|
|
336
|
+
* isSameDay(new Date('2024-01-01'), new Date('2024-01-01')) // true
|
|
337
|
+
*/
|
|
338
|
+
declare function isSameDay(date1: Date, date2: Date): boolean;
|
|
339
|
+
/**
|
|
340
|
+
* Returns the number of days in the month of the given date.
|
|
341
|
+
*
|
|
342
|
+
* @param date - The date.
|
|
343
|
+
* @returns Number of days in the month (28–31).
|
|
344
|
+
* @throws {InvalidDateError} If the input date is invalid.
|
|
345
|
+
*
|
|
346
|
+
* @example
|
|
347
|
+
* daysInMonth(new Date('2024-02-01')) // 29 (leap year)
|
|
348
|
+
*/
|
|
349
|
+
declare function daysInMonth(date: Date): number;
|
|
350
|
+
/**
|
|
351
|
+
* Returns the day of the year (1–366).
|
|
352
|
+
*
|
|
353
|
+
* @param date - The date.
|
|
354
|
+
* @returns Day of the year (1-indexed).
|
|
355
|
+
* @throws {InvalidDateError} If the input date is invalid.
|
|
356
|
+
*
|
|
357
|
+
* @example
|
|
358
|
+
* dayOfYear(new Date('2024-01-01')) // 1
|
|
359
|
+
*/
|
|
360
|
+
declare function dayOfYear(date: Date): number;
|
|
361
|
+
/**
|
|
362
|
+
* Returns the ISO week number (1–53).
|
|
363
|
+
*
|
|
364
|
+
* The algorithm uses the Thursday of the same week as the reference
|
|
365
|
+
* to determine which year the week belongs to, per ISO 8601.
|
|
366
|
+
*
|
|
367
|
+
* @param date - The date.
|
|
368
|
+
* @returns The ISO week number.
|
|
369
|
+
* @throws {InvalidDateError} If the input date is invalid.
|
|
370
|
+
*
|
|
371
|
+
* @example
|
|
372
|
+
* weekOfYear(new Date('2024-01-01')) // 1
|
|
373
|
+
*/
|
|
374
|
+
declare function weekOfYear(date: Date): number;
|
|
375
|
+
/**
|
|
376
|
+
* Returns the quarter of the year (1–4).
|
|
377
|
+
*
|
|
378
|
+
* @param date - The date.
|
|
379
|
+
* @returns The quarter (1 for Jan–Mar, 2 for Apr–Jun, etc.).
|
|
380
|
+
* @throws {InvalidDateError} If the input date is invalid.
|
|
381
|
+
*
|
|
382
|
+
* @example
|
|
383
|
+
* quarter(new Date('2024-04-01')) // 2
|
|
384
|
+
*/
|
|
385
|
+
declare function quarter(date: Date): number;
|
|
386
|
+
/**
|
|
387
|
+
* Returns the latest (maximum) date from an array of dates.
|
|
388
|
+
*
|
|
389
|
+
* @param dates - Array of Date objects.
|
|
390
|
+
* @returns The latest date.
|
|
391
|
+
* @throws {Error} If the array is empty.
|
|
392
|
+
* @throws {InvalidDateError} If any date is invalid.
|
|
393
|
+
*
|
|
394
|
+
* @example
|
|
395
|
+
* maxDate([new Date('2024-01-01'), new Date('2025-01-01')]) // 2025-01-01
|
|
396
|
+
*/
|
|
397
|
+
declare function maxDate(dates: Date[]): Date;
|
|
398
|
+
/**
|
|
399
|
+
* Returns the earliest (minimum) date from an array of dates.
|
|
400
|
+
*
|
|
401
|
+
* @param dates - Array of Date objects.
|
|
402
|
+
* @returns The earliest date.
|
|
403
|
+
* @throws {Error} If the array is empty.
|
|
404
|
+
* @throws {InvalidDateError} If any date is invalid.
|
|
405
|
+
*
|
|
406
|
+
* @example
|
|
407
|
+
* minDate([new Date('2024-01-01'), new Date('2025-01-01')]) // 2024-01-01
|
|
408
|
+
*/
|
|
409
|
+
declare function minDate(dates: Date[]): Date;
|
|
410
|
+
/**
|
|
411
|
+
* Returns the next Monday from the given date.
|
|
412
|
+
*
|
|
413
|
+
* @param date - Reference date.
|
|
414
|
+
* @returns The next Monday.
|
|
415
|
+
* @throws {InvalidDateError} If the input date is invalid.
|
|
416
|
+
*
|
|
417
|
+
* @example
|
|
418
|
+
* nextMonday(new Date('2024-01-01')) // 2024-01-08 (Monday)
|
|
419
|
+
*/
|
|
420
|
+
declare function nextMonday(date: Date): Date;
|
|
421
|
+
/**
|
|
422
|
+
* Returns the next Tuesday from the given date.
|
|
423
|
+
*
|
|
424
|
+
* @param date - Reference date.
|
|
425
|
+
* @returns The next Tuesday.
|
|
426
|
+
* @throws {InvalidDateError} If the input date is invalid.
|
|
427
|
+
*
|
|
428
|
+
* @example
|
|
429
|
+
* nextTuesday(new Date('2024-01-01')) // 2024-01-02 (Tuesday)
|
|
430
|
+
*/
|
|
431
|
+
declare function nextTuesday(date: Date): Date;
|
|
432
|
+
/**
|
|
433
|
+
* Returns the next Wednesday from the given date.
|
|
434
|
+
*
|
|
435
|
+
* @param date - Reference date.
|
|
436
|
+
* @returns The next Wednesday.
|
|
437
|
+
* @throws {InvalidDateError} If the input date is invalid.
|
|
438
|
+
*/
|
|
439
|
+
declare function nextWednesday(date: Date): Date;
|
|
440
|
+
/**
|
|
441
|
+
* Returns the next Thursday from the given date.
|
|
442
|
+
*
|
|
443
|
+
* @param date - Reference date.
|
|
444
|
+
* @returns The next Thursday.
|
|
445
|
+
* @throws {InvalidDateError} If the input date is invalid.
|
|
446
|
+
*/
|
|
447
|
+
declare function nextThursday(date: Date): Date;
|
|
448
|
+
/**
|
|
449
|
+
* Returns the next Friday from the given date.
|
|
450
|
+
*
|
|
451
|
+
* @param date - Reference date.
|
|
452
|
+
* @returns The next Friday.
|
|
453
|
+
* @throws {InvalidDateError} If the input date is invalid.
|
|
454
|
+
*/
|
|
455
|
+
declare function nextFriday(date: Date): Date;
|
|
456
|
+
/**
|
|
457
|
+
* Returns the next Saturday from the given date.
|
|
458
|
+
*
|
|
459
|
+
* @param date - Reference date.
|
|
460
|
+
* @returns The next Saturday.
|
|
461
|
+
* @throws {InvalidDateError} If the input date is invalid.
|
|
462
|
+
*/
|
|
463
|
+
declare function nextSaturday(date: Date): Date;
|
|
464
|
+
/**
|
|
465
|
+
* Returns the next Sunday from the given date.
|
|
466
|
+
*
|
|
467
|
+
* @param date - Reference date.
|
|
468
|
+
* @returns The next Sunday.
|
|
469
|
+
* @throws {InvalidDateError} If the input date is invalid.
|
|
470
|
+
*/
|
|
471
|
+
declare function nextSunday(date: Date): Date;
|
|
472
|
+
/**
|
|
473
|
+
* Returns the last (previous) Monday from the given date.
|
|
474
|
+
*
|
|
475
|
+
* @param date - Reference date.
|
|
476
|
+
* @returns The last Monday.
|
|
477
|
+
* @throws {InvalidDateError} If the input date is invalid.
|
|
478
|
+
*
|
|
479
|
+
* @example
|
|
480
|
+
* lastMonday(new Date('2024-01-03')) // 2024-01-01 (Monday)
|
|
481
|
+
*/
|
|
482
|
+
declare function lastMonday(date: Date): Date;
|
|
483
|
+
/**
|
|
484
|
+
* Returns the last (previous) Tuesday from the given date.
|
|
485
|
+
*
|
|
486
|
+
* @param date - Reference date.
|
|
487
|
+
* @returns The last Tuesday.
|
|
488
|
+
* @throws {InvalidDateError} If the input date is invalid.
|
|
489
|
+
*/
|
|
490
|
+
declare function lastTuesday(date: Date): Date;
|
|
491
|
+
/**
|
|
492
|
+
* Returns the last (previous) Wednesday from the given date.
|
|
493
|
+
*
|
|
494
|
+
* @param date - Reference date.
|
|
495
|
+
* @returns The last Wednesday.
|
|
496
|
+
* @throws {InvalidDateError} If the input date is invalid.
|
|
497
|
+
*/
|
|
498
|
+
declare function lastWednesday(date: Date): Date;
|
|
499
|
+
/**
|
|
500
|
+
* Returns the last (previous) Thursday from the given date.
|
|
501
|
+
*
|
|
502
|
+
* @param date - Reference date.
|
|
503
|
+
* @returns The last Thursday.
|
|
504
|
+
* @throws {InvalidDateError} If the input date is invalid.
|
|
505
|
+
*/
|
|
506
|
+
declare function lastThursday(date: Date): Date;
|
|
507
|
+
/**
|
|
508
|
+
* Returns the last (previous) Friday from the given date.
|
|
509
|
+
*
|
|
510
|
+
* @param date - Reference date.
|
|
511
|
+
* @returns The last Friday.
|
|
512
|
+
* @throws {InvalidDateError} If the input date is invalid.
|
|
513
|
+
*
|
|
514
|
+
* @example
|
|
515
|
+
* lastFriday(new Date('2024-01-03')) // 2023-12-29 (Friday)
|
|
516
|
+
*/
|
|
517
|
+
declare function lastFriday(date: Date): Date;
|
|
518
|
+
/**
|
|
519
|
+
* Returns the last (previous) Saturday from the given date.
|
|
520
|
+
*
|
|
521
|
+
* @param date - Reference date.
|
|
522
|
+
* @returns The last Saturday.
|
|
523
|
+
* @throws {InvalidDateError} If the input date is invalid.
|
|
524
|
+
*/
|
|
525
|
+
declare function lastSaturday(date: Date): Date;
|
|
526
|
+
/**
|
|
527
|
+
* Returns the last (previous) Sunday from the given date.
|
|
528
|
+
*
|
|
529
|
+
* @param date - Reference date.
|
|
530
|
+
* @returns The last Sunday.
|
|
531
|
+
* @throws {InvalidDateError} If the input date is invalid.
|
|
532
|
+
*/
|
|
533
|
+
declare function lastSunday(date: Date): Date;
|
|
534
|
+
/**
|
|
535
|
+
* Parses a human-readable duration string into milliseconds.
|
|
536
|
+
*
|
|
537
|
+
* Supported units:
|
|
538
|
+
* - `w` — weeks
|
|
539
|
+
* - `d` — days
|
|
540
|
+
* - `h` — hours
|
|
541
|
+
* - `m` — minutes
|
|
542
|
+
* - `s` — seconds
|
|
543
|
+
*
|
|
544
|
+
* @param input - Duration string (e.g. `"1h30m"`, `"2d"`, `"1w2d6h"`).
|
|
545
|
+
* @returns Total milliseconds.
|
|
546
|
+
*
|
|
547
|
+
* @example
|
|
548
|
+
* parseDuration('1h30m') // 5400000
|
|
549
|
+
* parseDuration('2d') // 172800000
|
|
550
|
+
* parseDuration('1w') // 604800000
|
|
551
|
+
*/
|
|
552
|
+
declare function parseDuration(input: string): number;
|
|
553
|
+
/**
|
|
554
|
+
* Checks if a date is an Indonesian public holiday.
|
|
555
|
+
*
|
|
556
|
+
* Includes fixed-date holidays (New Year, Labor Day, Pancasila Day,
|
|
557
|
+
* Independence Day, National Awakening Day, National Heroes Day, Christmas),
|
|
558
|
+
* Easter-based holidays (Good Friday, Easter, Ascension), and lookup-based
|
|
559
|
+
* movable holidays (Chinese New Year, Nyepi, Vesak, Eid al-Fitr,
|
|
560
|
+
* Eid al-Adha, Islamic New Year, Prophet's Birthday, Isra' Mi'raj).
|
|
561
|
+
*
|
|
562
|
+
* Movable holidays (Chinese New Year, Nyepi, Vesak, Islamic holidays) are
|
|
563
|
+
* precomputed for years 2024–2030. Dates outside this range may return
|
|
564
|
+
* `false` for those holidays.
|
|
565
|
+
*
|
|
566
|
+
* @param date - The date to check.
|
|
567
|
+
* @returns Whether the date is an Indonesian public holiday.
|
|
568
|
+
* @throws {InvalidDateError} If the input date is invalid.
|
|
569
|
+
*
|
|
570
|
+
* @example
|
|
571
|
+
* isHolidayIndonesia(new Date('2024-08-17')) // true (Independence Day)
|
|
572
|
+
* isHolidayIndonesia(new Date('2024-12-25')) // true (Christmas)
|
|
573
|
+
*/
|
|
574
|
+
declare function isHolidayIndonesia(date: Date): boolean;
|
|
575
|
+
/**
|
|
576
|
+
* Returns the name(s) of Indonesian public holidays for a given date, or an
|
|
577
|
+
* empty array if the date is not a holiday.
|
|
578
|
+
*
|
|
579
|
+
* @param date - The date to check.
|
|
580
|
+
* @returns Array of holiday names.
|
|
581
|
+
* @throws {InvalidDateError} If the input date is invalid.
|
|
582
|
+
*
|
|
583
|
+
* @example
|
|
584
|
+
* getIndonesianHolidayNames(new Date('2024-08-17')) // ['Independence Day']
|
|
585
|
+
*/
|
|
586
|
+
declare function getIndonesianHolidayNames(date: Date): string[];
|
|
272
587
|
|
|
273
|
-
export { type DateDiff, type Duration, InvalidDateError, TIMEZONE_WIB, TIMEZONE_WIT, TIMEZONE_WITA, addBusinessDays, addDays, addMonths, addYears, calculateAge, dateDiff, endOfDay, endOfMonth, endOfYear, formatDate, formatDuration, formatInTimezone, isAfter, isBefore, isBetween, isBusinessDay, isLeapYear, isWeekend, parseDate, startOfDay, startOfMonth, startOfYear, timeAgo, timeRemaining, toTimezone };
|
|
588
|
+
export { type DateDiff, type Duration, InvalidDateError, TIMEZONE_WIB, TIMEZONE_WIT, TIMEZONE_WITA, addBusinessDays, addDays, addMonths, addYears, calculateAge, dateDiff, dayOfYear, daysInMonth, endOfDay, endOfMonth, endOfYear, formatDate, formatDuration, formatInTimezone, getIndonesianHolidayNames, isAfter, isBefore, isBetween, isBusinessDay, isFuture, isHolidayIndonesia, isLeapYear, isPast, isSameDay, isToday, isTomorrow, isWeekend, isYesterday, lastFriday, lastMonday, lastSaturday, lastSunday, lastThursday, lastTuesday, lastWednesday, maxDate, minDate, nextFriday, nextMonday, nextSaturday, nextSunday, nextThursday, nextTuesday, nextWednesday, parseDate, parseDuration, quarter, startOfDay, startOfMonth, startOfYear, timeAgo, timeRemaining, toTimezone, weekOfYear };
|