superjs-core 0.4.4 → 0.6.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.
@@ -198,18 +198,155 @@ function deepSet(obj, path, value) {
198
198
  current[keys[keys.length - 1]] = value;
199
199
  return result;
200
200
  }
201
+ function partition(items, predicate) {
202
+ const pass = [];
203
+ const fail = [];
204
+ for (const item of items) {
205
+ if (predicate(item)) pass.push(item);
206
+ else fail.push(item);
207
+ }
208
+ return [pass, fail];
209
+ }
210
+ function compact(items) {
211
+ return items.filter(Boolean);
212
+ }
213
+ function difference(a, b) {
214
+ const setB = new Set(b);
215
+ return a.filter((item) => !setB.has(item));
216
+ }
217
+ function intersection(a, b) {
218
+ const setB = new Set(b);
219
+ return a.filter((item) => setB.has(item));
220
+ }
221
+ function union(...arrays) {
222
+ const set = /* @__PURE__ */ new Set();
223
+ for (const arr of arrays) {
224
+ for (const item of arr) {
225
+ set.add(item);
226
+ }
227
+ }
228
+ return [...set];
229
+ }
230
+ function zip(...arrays) {
231
+ if (arrays.length === 0) return [];
232
+ const minLen = Math.min(...arrays.map((a) => a.length));
233
+ const result = [];
234
+ for (let i = 0; i < minLen; i++) {
235
+ const tuple = [];
236
+ for (const arr of arrays) {
237
+ tuple.push(arr[i]);
238
+ }
239
+ result.push(tuple);
240
+ }
241
+ return result;
242
+ }
243
+ function unzip(paired) {
244
+ if (paired.length === 0) return [];
245
+ const tupleLen = paired.reduce((max, t) => Math.max(max, t.length), 0);
246
+ const result = Array.from({ length: tupleLen }, () => []);
247
+ for (const tuple of paired) {
248
+ for (let i = 0; i < tupleLen; i++) {
249
+ result[i].push(tuple[i]);
250
+ }
251
+ }
252
+ return result;
253
+ }
254
+ function countBy(items, keyFn) {
255
+ const result = {};
256
+ for (const item of items) {
257
+ const key = keyFn(item);
258
+ result[key] = (result[key] ?? 0) + 1;
259
+ }
260
+ return result;
261
+ }
262
+ function maxBy(items, keyFn) {
263
+ if (items.length === 0) return void 0;
264
+ let maxItem = items[0];
265
+ let maxVal = keyFn(maxItem);
266
+ for (let i = 1; i < items.length; i++) {
267
+ const val = keyFn(items[i]);
268
+ if (val > maxVal) {
269
+ maxVal = val;
270
+ maxItem = items[i];
271
+ }
272
+ }
273
+ return maxItem;
274
+ }
275
+ function minBy(items, keyFn) {
276
+ if (items.length === 0) return void 0;
277
+ let minItem = items[0];
278
+ let minVal = keyFn(minItem);
279
+ for (let i = 1; i < items.length; i++) {
280
+ const val = keyFn(items[i]);
281
+ if (val < minVal) {
282
+ minVal = val;
283
+ minItem = items[i];
284
+ }
285
+ }
286
+ return minItem;
287
+ }
288
+ function sumBy(items, keyFn) {
289
+ let total = 0;
290
+ for (const item of items) {
291
+ total += keyFn(item);
292
+ }
293
+ return total;
294
+ }
295
+ function findIndex(items, predicate, fromIndex = 0) {
296
+ for (let i = fromIndex; i < items.length; i++) {
297
+ if (predicate(items[i])) return i;
298
+ }
299
+ return -1;
300
+ }
301
+ function findLast(items, predicate) {
302
+ for (let i = items.length - 1; i >= 0; i--) {
303
+ if (predicate(items[i])) return items[i];
304
+ }
305
+ return void 0;
306
+ }
307
+ function drop(items, n = 1) {
308
+ return items.slice(Math.max(0, n));
309
+ }
310
+ function dropRight(items, n = 1) {
311
+ return items.slice(0, Math.max(0, items.length - n));
312
+ }
313
+ function take(items, n = 1) {
314
+ return items.slice(0, Math.max(0, n));
315
+ }
316
+ function takeRight(items, n = 1) {
317
+ return items.slice(Math.max(0, items.length - n));
318
+ }
319
+ function without(items, ...values) {
320
+ const exclude = new Set(values);
321
+ return items.filter((item) => !exclude.has(item));
322
+ }
323
+ function nth(items, index) {
324
+ return index < 0 ? items[items.length + index] : items[index];
325
+ }
201
326
  export {
202
327
  chunk,
328
+ compact,
329
+ countBy,
203
330
  deepGet,
204
331
  deepSet,
332
+ difference,
333
+ drop,
334
+ dropRight,
335
+ findIndex,
336
+ findLast,
205
337
  first,
206
338
  flatten,
207
339
  groupBy,
340
+ intersection,
208
341
  isEmpty,
209
342
  keyBy,
210
343
  last,
344
+ maxBy,
345
+ minBy,
346
+ nth,
211
347
  omit,
212
348
  orderBy,
349
+ partition,
213
350
  pick,
214
351
  pluck,
215
352
  sample,
@@ -217,9 +354,16 @@ export {
217
354
  shuffle,
218
355
  slidingWindows,
219
356
  sortBy,
357
+ sumBy,
358
+ take,
359
+ takeRight,
220
360
  topoSort,
221
361
  tumblingWindows,
362
+ union,
222
363
  uniq,
223
- uniqueBy
364
+ uniqueBy,
365
+ unzip,
366
+ without,
367
+ zip
224
368
  };
225
369
  //# sourceMappingURL=index.js.map
@@ -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":"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","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":"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","names":[]}
@@ -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 };
@@ -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
@@ -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":";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;AAWO,SAAS,WAAW,OAAwB;AACjD,SAAO,sCAAsC,KAAK,KAAK;AACzD;AAUO,SAAS,SAAS,KAAyD;AAChF,QAAM,MAAM,SAAS,GAAG;AACxB,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,IAAI,IAAI,IAAI;AAClB,QAAM,IAAI,IAAI,IAAI;AAClB,QAAM,IAAI,IAAI,IAAI;AAClB,QAAM,MAAM,KAAK,IAAI,GAAG,GAAG,CAAC;AAC5B,QAAM,MAAM,KAAK,IAAI,GAAG,GAAG,CAAC;AAC5B,QAAM,KAAK,MAAM,OAAO;AACxB,MAAI,QAAQ,IAAK,QAAO,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,KAAK,MAAM,IAAI,GAAG,EAAE;AAC7D,QAAM,IAAI,MAAM;AAChB,QAAM,IAAI,IAAI,MAAM,KAAK,IAAI,MAAM,OAAO,KAAK,MAAM;AACrD,MAAI,IAAI;AACR,UAAQ,KAAK;AAAA,IACX,KAAK;AAAG,YAAM,IAAI,KAAK,KAAK,IAAI,IAAI,IAAI,MAAM;AAAG;AAAA,IACjD,KAAK;AAAG,YAAM,IAAI,KAAK,IAAI,KAAK;AAAG;AAAA,IACnC,KAAK;AAAG,YAAM,IAAI,KAAK,IAAI,KAAK;AAAG;AAAA,EACrC;AACA,SAAO;AAAA,IACL,GAAG,KAAK,MAAM,IAAI,GAAG;AAAA,IACrB,GAAG,KAAK,MAAM,IAAI,GAAG;AAAA,IACrB,GAAG,KAAK,MAAM,IAAI,GAAG;AAAA,EACvB;AACF;AASO,SAAS,SAAS,GAAW,GAAW,GAAmB;AAChE,QAAM,MAAM,IAAI;AAChB,QAAM,MAAM,IAAI;AAChB,QAAM,MAAM,IAAI;AAChB,MAAI,QAAQ,GAAG;AACb,UAAM,MAAM,KAAK,MAAM,MAAM,GAAG;AAChC,WAAO,SAAS,KAAK,KAAK,GAAG;AAAA,EAC/B;AACA,QAAM,UAAU,CAACA,IAAWC,IAAW,MAAsB;AAC3D,QAAI,KAAK;AACT,QAAI,KAAK,EAAG,OAAM;AAClB,QAAI,KAAK,EAAG,OAAM;AAClB,QAAI,KAAK,IAAI,EAAG,QAAOD,MAAKC,KAAID,MAAK,IAAI;AACzC,QAAI,KAAK,IAAI,EAAG,QAAOC;AACvB,QAAI,KAAK,IAAI,EAAG,QAAOD,MAAKC,KAAID,OAAM,IAAI,IAAI,MAAM;AACpD,WAAOA;AAAA,EACT;AACA,QAAM,IAAI,MAAM,MAAM,OAAO,IAAI,OAAO,MAAM,MAAM,MAAM;AAC1D,QAAM,IAAI,IAAI,MAAM;AACpB,SAAO;AAAA,IACL,KAAK,MAAM,QAAQ,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,GAAG;AAAA,IAC3C,KAAK,MAAM,QAAQ,GAAG,GAAG,GAAG,IAAI,GAAG;AAAA,IACnC,KAAK,MAAM,QAAQ,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,GAAG;AAAA,EAC7C;AACF;AAUO,SAAS,IAAI,QAAgB,QAAgB,SAAiB,KAAa;AAChF,QAAM,OAAO,SAAS,MAAM;AAC5B,QAAM,OAAO,SAAS,MAAM;AAC5B,MAAI,CAAC,QAAQ,CAAC,KAAM,QAAO;AAC3B,QAAM,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,MAAM,CAAC;AACzC,QAAM,OAAO,CAAC,GAAW,MAAc,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC;AACjE,SAAO,SAAS,KAAK,KAAK,GAAG,KAAK,CAAC,GAAG,KAAK,KAAK,GAAG,KAAK,CAAC,GAAG,KAAK,KAAK,GAAG,KAAK,CAAC,CAAC;AAClF;AAOO,SAAS,cAAsB;AACpC,QAAM,IAAI,KAAK,MAAM,KAAK,OAAO,IAAI,GAAG;AACxC,QAAM,IAAI,KAAK,MAAM,KAAK,OAAO,IAAI,GAAG;AACxC,QAAM,IAAI,KAAK,MAAM,KAAK,OAAO,IAAI,GAAG;AACxC,SAAO,SAAS,GAAG,GAAG,CAAC;AACzB;AASO,SAAS,QAAQ,KAAsB;AAC5C,QAAM,MAAM,SAAS,GAAG;AACxB,MAAI,CAAC,IAAK,QAAO;AACjB,UAAQ,QAAQ,IAAI,IAAI,QAAQ,IAAI,IAAI,QAAQ,IAAI,KAAK,MAAM;AACjE;AAQO,SAAS,OAAO,KAAsB;AAC3C,SAAO,CAAC,QAAQ,GAAG;AACrB;AASO,SAAS,cAAc,KAAqB;AACjD,QAAM,MAAM,SAAS,GAAG;AACxB,MAAI,CAAC,IAAK,QAAO;AACjB,SAAO,UAAU,IAAI,IAAI,OAAO,KAAK,IAAI,GAAG,IAAI,CAAC;AACnD;AAUO,SAAS,MAAM,KAAa,SAAyB;AAC1D,QAAM,MAAM,SAAS,GAAG;AACxB,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,OAAO,CAAC;AAC1C,QAAM,WAAW,KAAK,MAAM,IAAI,GAAG,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG;AACjE,SAAO,SAAS,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC,IAAI;AACzC;","names":["p","q"]}