@isikk/core 0.4.0 → 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.
@@ -0,0 +1,79 @@
1
+ import { ReactNode } from 'react';
2
+
3
+ type Caster<T> = ((value: string) => T) & {
4
+ missingDefault?: T;
5
+ errorDefault?: T;
6
+ };
7
+ declare function caster<T>(fn: (value: string) => T): (options?: {
8
+ missingDefault?: T;
9
+ errorDefault?: T;
10
+ }) => Caster<T>;
11
+ declare const string: (options?: {
12
+ missingDefault?: string | undefined;
13
+ errorDefault?: string | undefined;
14
+ }) => Caster<string>;
15
+ declare const integer: (options?: {
16
+ missingDefault?: number | undefined;
17
+ errorDefault?: number | undefined;
18
+ }) => Caster<number>;
19
+ declare const float: (options?: {
20
+ missingDefault?: number | undefined;
21
+ errorDefault?: number | undefined;
22
+ }) => Caster<number>;
23
+ declare const boolean: (options?: {
24
+ missingDefault?: boolean | undefined;
25
+ errorDefault?: boolean | undefined;
26
+ }) => Caster<boolean>;
27
+ declare const commaSeparatedList: (options?: {
28
+ missingDefault?: string[] | undefined;
29
+ errorDefault?: string[] | undefined;
30
+ }) => Caster<string[]>;
31
+ declare const commaSeparatedIntList: (options?: {
32
+ missingDefault?: number[] | undefined;
33
+ errorDefault?: number[] | undefined;
34
+ }) => Caster<number[]>;
35
+ declare const commaSeparatedFloatList: (options?: {
36
+ missingDefault?: number[] | undefined;
37
+ errorDefault?: number[] | undefined;
38
+ }) => Caster<number[]>;
39
+
40
+ type ConfigSchema = {
41
+ [key: string]: Caster<unknown> | ConfigSchema;
42
+ };
43
+ type InferConfig<S> = {
44
+ [K in keyof S]: S[K] extends Caster<infer T> ? T : S[K] extends ConfigSchema ? InferConfig<S[K]> : never;
45
+ };
46
+
47
+ interface PublicConfigOptions {
48
+ /**
49
+ * The property the payload is injected under on `window`. Required, with no default and no
50
+ * derived fallback: the name belongs in your application's namespace, not this package's, and
51
+ * naming it at the call site is what stops two configs from silently landing on a name neither
52
+ * of them chose.
53
+ */
54
+ globalKey: string;
55
+ /** Prepended to every environment variable name this call reads, joined with `sep`. */
56
+ prefix?: string;
57
+ /** Joins the prefix and the nested key path into a variable name. Defaults to `"__"`. */
58
+ sep?: string;
59
+ }
60
+ interface PublicConfigScriptProps {
61
+ /** Forwarded to the injected `<script>` so a CSP with a per-request nonce keeps working. */
62
+ nonce?: string;
63
+ }
64
+ type PublicConfigScriptComponent = (props: PublicConfigScriptProps) => ReactNode | Promise<ReactNode>;
65
+ interface PublicConfig<S extends ConfigSchema> {
66
+ CONFIG: InferConfig<S>;
67
+ PublicConfigScript: PublicConfigScriptComponent;
68
+ }
69
+
70
+ /**
71
+ * Isolated in its own module - with no `process.env` access anywhere in it - so that the browser
72
+ * half of `@isikk/core/next/config` can throw the same error type without importing
73
+ * anything that reads the environment. Keeping the split structural means the guarantee holds
74
+ * because of what the file contains, not because a bundler happened to tree-shake it away.
75
+ */
76
+ declare class ConfigError extends Error {
77
+ }
78
+
79
+ export { type ConfigSchema as C, type InferConfig as I, type PublicConfigOptions as P, type PublicConfig as a, type Caster as b, ConfigError as c, type PublicConfigScriptComponent as d, type PublicConfigScriptProps as e, boolean as f, caster as g, commaSeparatedFloatList as h, commaSeparatedIntList as i, commaSeparatedList as j, float as k, integer as l, string as s };
@@ -127,10 +127,14 @@ function useFilePaste({
127
127
  const [files, setFiles] = (0, import_react.useState)([]);
128
128
  const [isLoading, setIsLoading] = (0, import_react.useState)(false);
129
129
  const [error, setError] = (0, import_react.useState)(null);
130
- const clearFiles = (0, import_react.useCallback)(() => {
131
- setFiles([]);
132
- setError(null);
133
- }, []);
130
+ const clearFiles = (0, import_react.useCallback)(
131
+ () => {
132
+ setFiles([]);
133
+ setError(null);
134
+ },
135
+ // Stryker disable next-line ArrayDeclaration: equivalent mutant, see above.
136
+ []
137
+ );
134
138
  const validateFiles = (0, import_react.useCallback)(
135
139
  (pastedFiles) => {
136
140
  if (acceptedTypes && acceptedTypes.length > 0) {
@@ -317,12 +321,16 @@ function useFileDragDrop(options = {}) {
317
321
  }
318
322
  return void 0;
319
323
  }, [handleDragOver, handleDragEnter, handleDragLeave, handleDrop]);
320
- const reset = (0, import_react.useCallback)(() => {
321
- setState({
322
- isDragging: false,
323
- files: null
324
- });
325
- }, []);
324
+ const reset = (0, import_react.useCallback)(
325
+ () => {
326
+ setState({
327
+ isDragging: false,
328
+ files: null
329
+ });
330
+ },
331
+ // Stryker disable next-line ArrayDeclaration: equivalent mutant, see above.
332
+ []
333
+ );
326
334
  return {
327
335
  ref,
328
336
  isDragging: state.isDragging,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/hooks/index.ts"],"sourcesContent":["import type { ChangeEvent, DependencyList, DragEvent, EffectCallback } from 'react'\nimport { useCallback, useEffect, useRef, useState } from 'react'\n\nexport function useElementAttributes<T extends HTMLElement, K extends keyof T>(attributeKeys: K[]) {\n const ref = useRef<T | null>(null)\n const [attributeValues, setAttributeValue] = useState<Partial<Pick<T, K>>>({})\n\n const updateAttribute = useCallback(() => {\n if (ref.current) {\n const values = {} as Partial<Pick<T, K>>\n for (const key of attributeKeys) {\n // Object.defineProperty (unlike a plain `values[key] = value` assignment) always creates/\n // overwrites an own property, even if a consumer's T somehow has a key like \"__proto__\" -\n // matches the same defensive pattern used everywhere else in this package that writes a\n // non-literal key onto an object.\n Object.defineProperty(values, key, {\n value: ref.current[key],\n writable: true,\n configurable: true,\n enumerable: true,\n })\n }\n\n setAttributeValue((prevValues) => {\n const hasChanged = attributeKeys.some((key) => prevValues[key] !== values[key])\n return hasChanged ? values : prevValues\n })\n }\n }, [attributeKeys])\n\n useEffect(() => {\n updateAttribute()\n window.addEventListener('resize', updateAttribute)\n\n if (ref.current) {\n const observer = new MutationObserver(updateAttribute)\n observer.observe(ref.current, { attributes: true })\n\n return () => {\n window.removeEventListener('resize', updateAttribute)\n observer.disconnect()\n }\n }\n\n return () => {\n window.removeEventListener('resize', updateAttribute)\n }\n }, [updateAttribute])\n\n return { ref, attributeValues }\n}\n\ntype InputEventType = ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>\n\nexport function useFormState<T>(initialState: T) {\n const [formState, setFormState] = useState<T>(initialState)\n const [formErrors, setFormErrors] = useState<Partial<Record<keyof T, string[]>> & { non_field_errors?: string[] }>()\n\n function resetFormState() {\n setFormState(initialState)\n }\n\n function handleFormState<K extends keyof T, HandlerInputType>({\n key,\n inputType,\n }: {\n key: K\n inputType: 'event' | 'value'\n }) {\n return (event: HandlerInputType) => {\n let value: T[K]\n if (inputType === 'event') {\n const target = (event as InputEventType).target\n if (target.type === 'checkbox') {\n value = (target as HTMLInputElement).checked as T[K]\n } else if (target.type === 'number' || target.type === 'range') {\n value = (target as HTMLInputElement).valueAsNumber as T[K]\n } else {\n value = target.value as T[K]\n }\n } else {\n value = event as T[K]\n }\n setFormState((prev) => ({ ...prev, [key]: value }))\n }\n }\n\n const handleFormStateValue = <K extends keyof T>(key: K) => handleFormState<K, T[K]>({ key, inputType: 'value' })\n const handleFormStateEvent = <K extends keyof T>(key: K) =>\n handleFormState<K, InputEventType>({ key, inputType: 'event' })\n const handleFormStateOnClick =\n <K extends keyof T>(key: K, value: T[K]) =>\n () => {\n setFormState((prev) => ({ ...prev, [key]: value }))\n }\n\n return {\n formState,\n setFormState,\n formErrors,\n setFormErrors,\n handleFormStateValue,\n handleFormStateEvent,\n handleFormStateOnClick,\n resetFormState,\n }\n}\n\nexport function useEffectAfterMount(effect: EffectCallback, deps: DependencyList) {\n const isFirstRender = useRef(true)\n\n // No manual \"did deps actually change\" recheck needed here: React's own useEffect already\n // only re-invokes this callback when a dependency's value changed (shallow-compared against\n // the last time *this exact effect* ran) - which is exactly the same comparison a hand-rolled\n // check against a \"previous deps\" ref would be making, just duplicated.\n useEffect(() => {\n if (isFirstRender.current) {\n isFirstRender.current = false\n return\n }\n return effect()\n }, deps)\n}\n\nexport function useFilePaste({\n acceptedTypes,\n maxSize,\n targetElement,\n enabled = true,\n}: {\n acceptedTypes?: string[]\n maxSize?: number\n targetElement?: HTMLElement | null\n enabled?: boolean\n} = {}): {\n files: File[]\n isLoading: boolean\n error: string | null\n clearFiles: () => void\n} {\n const [files, setFiles] = useState<File[]>([])\n const [isLoading, setIsLoading] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n const clearFiles = useCallback(() => {\n setFiles([])\n setError(null)\n }, [])\n\n const validateFiles = useCallback(\n (pastedFiles: File[]): { valid: true } | { valid: false; error: string } => {\n if (acceptedTypes && acceptedTypes.length > 0) {\n const wildcardAcceptedTypes = acceptedTypes\n .filter((type) => type.endsWith('/*'))\n .map((type) => type.slice(0, -1))\n const normalizedAcceptedTypes = acceptedTypes.map((type) => (type.endsWith('/*') ? type.slice(0, -2) : type))\n\n const invalidFiles = pastedFiles.filter((file) => {\n const fileType = file.type\n return (\n !normalizedAcceptedTypes.includes(fileType) &&\n !wildcardAcceptedTypes.some((wildcardType) => fileType.startsWith(wildcardType))\n )\n })\n if (invalidFiles.length > 0) {\n const invalidFileNames = invalidFiles.map((file) => file.name).join(', ')\n return {\n valid: false,\n error: `Invalid file types: ${invalidFileNames}. Accepted types: ${acceptedTypes.join(', ')}`,\n }\n }\n }\n\n if (maxSize) {\n const oversizedFile = pastedFiles.find((file) => file.size > maxSize)\n if (oversizedFile) {\n const fileSizeMB = (oversizedFile.size / (1024 * 1024)).toFixed(2)\n const maxSizeMB = (maxSize / (1024 * 1024)).toFixed(2)\n return {\n valid: false,\n error: `File \"${oversizedFile.name}\" (${fileSizeMB} MB) exceeds the maximum size of ${maxSizeMB} MB`,\n }\n }\n }\n\n return { valid: true }\n },\n [acceptedTypes, maxSize]\n )\n\n const handlePaste = useCallback(\n (event: ClipboardEvent) => {\n const { clipboardData } = event\n if (!clipboardData) return\n\n const hasFiles = clipboardData.files && clipboardData.files.length > 0\n if (!hasFiles) return\n\n event.preventDefault()\n setIsLoading(true)\n setError(null)\n\n try {\n const pastedFiles = Array.from(clipboardData.files)\n const validation = validateFiles(pastedFiles)\n\n if (!validation.valid) {\n setError(validation.error)\n setFiles([])\n } else {\n setFiles(pastedFiles)\n }\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to process pasted files')\n setFiles([])\n } finally {\n setIsLoading(false)\n }\n },\n [validateFiles]\n )\n\n useEffect(() => {\n if (!enabled) return\n\n const target = targetElement || document\n\n target.addEventListener('paste', handlePaste as EventListener)\n return () => {\n target.removeEventListener('paste', handlePaste as EventListener)\n }\n }, [enabled, handlePaste, targetElement])\n\n return { files, isLoading, error, clearFiles }\n}\n\ntype FileDragDropState = {\n isDragging: boolean\n files: File[] | null\n}\n\ntype FileDragDropOptions = {\n onDrop?: (files: File[]) => void\n onDragOver?: (e: DragEvent<HTMLElement>) => void\n onDragLeave?: (e: DragEvent<HTMLElement>) => void\n acceptedFileTypes?: string[]\n maxFileSize?: number\n multiple?: boolean\n}\n\nexport function useFileDragDrop<T extends HTMLElement = HTMLDivElement>(options: FileDragDropOptions = {}) {\n const { onDrop, onDragOver, onDragLeave, acceptedFileTypes, maxFileSize, multiple = true } = options\n\n const [state, setState] = useState<FileDragDropState>({\n isDragging: false,\n files: null,\n })\n\n const ref = useRef<T | null>(null)\n const dragCounter = useRef(0)\n\n const handleDragOver = useCallback(\n (e: DragEvent<T>) => {\n e.preventDefault()\n e.stopPropagation()\n\n onDragOver?.(e)\n },\n [onDragOver]\n )\n\n const handleDragEnter = useCallback(\n (e: DragEvent<T>) => {\n e.preventDefault()\n e.stopPropagation()\n\n dragCounter.current += 1\n\n if (e.dataTransfer.items && e.dataTransfer.items.length > 0) {\n const hasValidItems = Array.from(e.dataTransfer.items).some((item) => {\n if (item.kind !== 'file') {\n return false\n }\n\n if (acceptedFileTypes && acceptedFileTypes.length > 0) {\n return acceptedFileTypes.some((type) => {\n if (type.endsWith('/*')) {\n const category = type.split('/')[0]\n return item.type.startsWith(`${category}/`)\n }\n return item.type === type\n })\n }\n\n return true\n })\n\n if (hasValidItems) {\n setState((prevState) => ({\n ...prevState,\n isDragging: true,\n }))\n }\n }\n },\n [acceptedFileTypes]\n )\n\n const handleDragLeave = useCallback(\n (e: DragEvent<T>) => {\n e.preventDefault()\n e.stopPropagation()\n\n dragCounter.current -= 1\n\n if (dragCounter.current === 0) {\n setState((prevState) => ({\n ...prevState,\n isDragging: false,\n }))\n }\n\n onDragLeave?.(e)\n },\n [onDragLeave]\n )\n\n const handleDrop = useCallback(\n (e: DragEvent<T>) => {\n e.preventDefault()\n e.stopPropagation()\n\n dragCounter.current = 0\n setState((prevState) => ({\n ...prevState,\n isDragging: false,\n }))\n\n if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {\n let validFiles = Array.from(e.dataTransfer.files)\n\n if (acceptedFileTypes && acceptedFileTypes.length > 0) {\n validFiles = validFiles.filter((file) =>\n acceptedFileTypes.some((type) => {\n if (type.endsWith('/*')) {\n const category = type.split('/')[0]\n return file.type.startsWith(`${category}/`)\n }\n return file.type === type\n })\n )\n }\n\n if (maxFileSize) {\n validFiles = validFiles.filter((file) => file.size <= maxFileSize)\n }\n\n if (!multiple && validFiles.length > 0) {\n validFiles = [validFiles[0]]\n }\n\n if (validFiles.length > 0) {\n setState((prevState) => ({\n ...prevState,\n files: validFiles,\n }))\n\n onDrop?.(validFiles)\n }\n }\n },\n [onDrop, acceptedFileTypes, maxFileSize, multiple]\n )\n\n useEffect(() => {\n const currentRef = ref.current\n if (currentRef) {\n currentRef.addEventListener('dragover', handleDragOver as unknown as EventListener)\n currentRef.addEventListener('dragenter', handleDragEnter as unknown as EventListener)\n currentRef.addEventListener('dragleave', handleDragLeave as unknown as EventListener)\n currentRef.addEventListener('drop', handleDrop as unknown as EventListener)\n\n return () => {\n currentRef.removeEventListener('dragover', handleDragOver as unknown as EventListener)\n currentRef.removeEventListener('dragenter', handleDragEnter as unknown as EventListener)\n currentRef.removeEventListener('dragleave', handleDragLeave as unknown as EventListener)\n currentRef.removeEventListener('drop', handleDrop as unknown as EventListener)\n }\n }\n return undefined\n }, [handleDragOver, handleDragEnter, handleDragLeave, handleDrop])\n\n const reset = useCallback(() => {\n setState({\n isDragging: false,\n files: null,\n })\n }, [])\n\n return {\n ref,\n isDragging: state.isDragging,\n files: state.files,\n reset,\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/hooks/index.ts"],"sourcesContent":["import type { ChangeEvent, DependencyList, DragEvent, EffectCallback } from 'react'\nimport { useCallback, useEffect, useRef, useState } from 'react'\n\nexport function useElementAttributes<T extends HTMLElement, K extends keyof T>(attributeKeys: K[]) {\n const ref = useRef<T | null>(null)\n const [attributeValues, setAttributeValue] = useState<Partial<Pick<T, K>>>({})\n\n const updateAttribute = useCallback(() => {\n if (ref.current) {\n const values = {} as Partial<Pick<T, K>>\n for (const key of attributeKeys) {\n // Object.defineProperty (unlike a plain `values[key] = value` assignment) always creates/\n // overwrites an own property, even if a consumer's T somehow has a key like \"__proto__\" -\n // matches the same defensive pattern used everywhere else in this package that writes a\n // non-literal key onto an object.\n Object.defineProperty(values, key, {\n value: ref.current[key],\n writable: true,\n configurable: true,\n enumerable: true,\n })\n }\n\n setAttributeValue((prevValues) => {\n const hasChanged = attributeKeys.some((key) => prevValues[key] !== values[key])\n return hasChanged ? values : prevValues\n })\n }\n }, [attributeKeys])\n\n useEffect(() => {\n updateAttribute()\n window.addEventListener('resize', updateAttribute)\n\n if (ref.current) {\n const observer = new MutationObserver(updateAttribute)\n observer.observe(ref.current, { attributes: true })\n\n return () => {\n window.removeEventListener('resize', updateAttribute)\n observer.disconnect()\n }\n }\n\n return () => {\n window.removeEventListener('resize', updateAttribute)\n }\n }, [updateAttribute])\n\n return { ref, attributeValues }\n}\n\ntype InputEventType = ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>\n\nexport function useFormState<T>(initialState: T) {\n const [formState, setFormState] = useState<T>(initialState)\n const [formErrors, setFormErrors] = useState<Partial<Record<keyof T, string[]>> & { non_field_errors?: string[] }>()\n\n function resetFormState() {\n setFormState(initialState)\n }\n\n function handleFormState<K extends keyof T, HandlerInputType>({\n key,\n inputType,\n }: {\n key: K\n inputType: 'event' | 'value'\n }) {\n return (event: HandlerInputType) => {\n let value: T[K]\n if (inputType === 'event') {\n const target = (event as InputEventType).target\n if (target.type === 'checkbox') {\n value = (target as HTMLInputElement).checked as T[K]\n } else if (target.type === 'number' || target.type === 'range') {\n value = (target as HTMLInputElement).valueAsNumber as T[K]\n } else {\n value = target.value as T[K]\n }\n } else {\n value = event as T[K]\n }\n setFormState((prev) => ({ ...prev, [key]: value }))\n }\n }\n\n // Stryker disable next-line StringLiteral: equivalent mutant. handleFormState only ever\n // compares inputType against 'event' - any other string, including this one, takes the exact\n // same branch, so the specific label 'value' carries no behavior of its own.\n const handleFormStateValue = <K extends keyof T>(key: K) => handleFormState<K, T[K]>({ key, inputType: 'value' })\n const handleFormStateEvent = <K extends keyof T>(key: K) =>\n handleFormState<K, InputEventType>({ key, inputType: 'event' })\n const handleFormStateOnClick =\n <K extends keyof T>(key: K, value: T[K]) =>\n () => {\n setFormState((prev) => ({ ...prev, [key]: value }))\n }\n\n return {\n formState,\n setFormState,\n formErrors,\n setFormErrors,\n handleFormStateValue,\n handleFormStateEvent,\n handleFormStateOnClick,\n resetFormState,\n }\n}\n\nexport function useEffectAfterMount(effect: EffectCallback, deps: DependencyList) {\n const isFirstRender = useRef(true)\n\n // No manual \"did deps actually change\" recheck needed here: React's own useEffect already\n // only re-invokes this callback when a dependency's value changed (shallow-compared against\n // the last time *this exact effect* ran) - which is exactly the same comparison a hand-rolled\n // check against a \"previous deps\" ref would be making, just duplicated.\n useEffect(() => {\n if (isFirstRender.current) {\n isFirstRender.current = false\n return\n }\n return effect()\n }, deps)\n}\n\nexport function useFilePaste({\n acceptedTypes,\n maxSize,\n targetElement,\n enabled = true,\n}: {\n acceptedTypes?: string[]\n maxSize?: number\n targetElement?: HTMLElement | null\n enabled?: boolean\n} = {}): {\n files: File[]\n isLoading: boolean\n error: string | null\n clearFiles: () => void\n} {\n const [files, setFiles] = useState<File[]>([])\n const [isLoading, setIsLoading] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n // The callback body below closes over nothing but the stable setFiles/setError setters, so\n // its dependency array's contents can never affect whether useCallback returns the same\n // function - a literal added there would compare equal (Object.is) to itself every render.\n const clearFiles = useCallback(\n () => {\n setFiles([])\n setError(null)\n }, // Stryker disable next-line ArrayDeclaration: equivalent mutant, see above.\n []\n )\n\n const validateFiles = useCallback(\n (pastedFiles: File[]): { valid: true } | { valid: false; error: string } => {\n if (acceptedTypes && acceptedTypes.length > 0) {\n const wildcardAcceptedTypes = acceptedTypes\n .filter((type) => type.endsWith('/*'))\n .map((type) => type.slice(0, -1))\n const normalizedAcceptedTypes = acceptedTypes.map((type) => (type.endsWith('/*') ? type.slice(0, -2) : type))\n\n const invalidFiles = pastedFiles.filter((file) => {\n const fileType = file.type\n return (\n !normalizedAcceptedTypes.includes(fileType) &&\n !wildcardAcceptedTypes.some((wildcardType) => fileType.startsWith(wildcardType))\n )\n })\n if (invalidFiles.length > 0) {\n const invalidFileNames = invalidFiles.map((file) => file.name).join(', ')\n return {\n valid: false,\n error: `Invalid file types: ${invalidFileNames}. Accepted types: ${acceptedTypes.join(', ')}`,\n }\n }\n }\n\n if (maxSize) {\n const oversizedFile = pastedFiles.find((file) => file.size > maxSize)\n if (oversizedFile) {\n const fileSizeMB = (oversizedFile.size / (1024 * 1024)).toFixed(2)\n const maxSizeMB = (maxSize / (1024 * 1024)).toFixed(2)\n return {\n valid: false,\n error: `File \"${oversizedFile.name}\" (${fileSizeMB} MB) exceeds the maximum size of ${maxSizeMB} MB`,\n }\n }\n }\n\n return { valid: true }\n },\n [acceptedTypes, maxSize]\n )\n\n const handlePaste = useCallback(\n (event: ClipboardEvent) => {\n const { clipboardData } = event\n if (!clipboardData) return\n\n const hasFiles = clipboardData.files && clipboardData.files.length > 0\n if (!hasFiles) return\n\n event.preventDefault()\n // Stryker disable next-line BooleanLiteral: equivalent mutant. validateFiles never yields\n // (no await between here and the `finally` below), so this and the `finally`'s\n // setIsLoading(false) land in the same synchronous React commit - an observer can only ever\n // see the final `false`, never a transient `true`, no matter what this call passes.\n setIsLoading(true)\n setError(null)\n\n try {\n const pastedFiles = Array.from(clipboardData.files)\n const validation = validateFiles(pastedFiles)\n\n if (!validation.valid) {\n setError(validation.error)\n setFiles([])\n } else {\n setFiles(pastedFiles)\n }\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to process pasted files')\n setFiles([])\n } finally {\n setIsLoading(false)\n }\n },\n [validateFiles]\n )\n\n useEffect(() => {\n if (!enabled) return\n\n const target = targetElement || document\n\n target.addEventListener('paste', handlePaste as EventListener)\n return () => {\n target.removeEventListener('paste', handlePaste as EventListener)\n }\n }, [enabled, handlePaste, targetElement])\n\n return { files, isLoading, error, clearFiles }\n}\n\ntype FileDragDropState = {\n isDragging: boolean\n files: File[] | null\n}\n\ntype FileDragDropOptions = {\n onDrop?: (files: File[]) => void\n onDragOver?: (e: DragEvent<HTMLElement>) => void\n onDragLeave?: (e: DragEvent<HTMLElement>) => void\n acceptedFileTypes?: string[]\n maxFileSize?: number\n multiple?: boolean\n}\n\nexport function useFileDragDrop<T extends HTMLElement = HTMLDivElement>(options: FileDragDropOptions = {}) {\n const { onDrop, onDragOver, onDragLeave, acceptedFileTypes, maxFileSize, multiple = true } = options\n\n const [state, setState] = useState<FileDragDropState>({\n isDragging: false,\n files: null,\n })\n\n const ref = useRef<T | null>(null)\n const dragCounter = useRef(0)\n\n const handleDragOver = useCallback(\n (e: DragEvent<T>) => {\n e.preventDefault()\n e.stopPropagation()\n\n onDragOver?.(e)\n },\n [onDragOver]\n )\n\n const handleDragEnter = useCallback(\n (e: DragEvent<T>) => {\n e.preventDefault()\n e.stopPropagation()\n\n dragCounter.current += 1\n\n // Stryker disable next-line ConditionalExpression,EqualityOperator: equivalent mutant on\n // the `.length > 0` half specifically. When items is truthy but empty, entering the block\n // anyway still runs Array.from([]).some(...), which is vacuously false - the same no-op as\n // skipping it - so relaxing this to `>= 0` (or dropping it) can't change the outcome.\n if (e.dataTransfer.items && e.dataTransfer.items.length > 0) {\n const hasValidItems = Array.from(e.dataTransfer.items).some((item) => {\n if (item.kind !== 'file') {\n return false\n }\n\n if (acceptedFileTypes && acceptedFileTypes.length > 0) {\n return acceptedFileTypes.some((type) => {\n if (type.endsWith('/*')) {\n const category = type.split('/')[0]\n return item.type.startsWith(`${category}/`)\n }\n return item.type === type\n })\n }\n\n return true\n })\n\n if (hasValidItems) {\n setState((prevState) => ({\n ...prevState,\n isDragging: true,\n }))\n }\n }\n },\n [acceptedFileTypes]\n )\n\n const handleDragLeave = useCallback(\n (e: DragEvent<T>) => {\n e.preventDefault()\n e.stopPropagation()\n\n dragCounter.current -= 1\n\n if (dragCounter.current === 0) {\n setState((prevState) => ({\n ...prevState,\n isDragging: false,\n }))\n }\n\n onDragLeave?.(e)\n },\n [onDragLeave]\n )\n\n const handleDrop = useCallback(\n (e: DragEvent<T>) => {\n e.preventDefault()\n e.stopPropagation()\n\n dragCounter.current = 0\n setState((prevState) => ({\n ...prevState,\n isDragging: false,\n }))\n\n // Stryker disable next-line ConditionalExpression,EqualityOperator: equivalent mutant on\n // the `.length > 0` half specifically. When files is truthy but empty, entering the block\n // anyway still runs Array.from([]) and every downstream filter/length check on it, which\n // stay vacuously empty - the same no-op as skipping it - so relaxing this to `>= 0` (or\n // dropping it) can't change the outcome.\n if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {\n let validFiles = Array.from(e.dataTransfer.files)\n\n if (acceptedFileTypes && acceptedFileTypes.length > 0) {\n validFiles = validFiles.filter((file) =>\n acceptedFileTypes.some((type) => {\n if (type.endsWith('/*')) {\n const category = type.split('/')[0]\n return file.type.startsWith(`${category}/`)\n }\n return file.type === type\n })\n )\n }\n\n if (maxFileSize) {\n validFiles = validFiles.filter((file) => file.size <= maxFileSize)\n }\n\n if (!multiple && validFiles.length > 0) {\n validFiles = [validFiles[0]]\n }\n\n if (validFiles.length > 0) {\n setState((prevState) => ({\n ...prevState,\n files: validFiles,\n }))\n\n onDrop?.(validFiles)\n }\n }\n },\n [onDrop, acceptedFileTypes, maxFileSize, multiple]\n )\n\n useEffect(() => {\n const currentRef = ref.current\n if (currentRef) {\n currentRef.addEventListener('dragover', handleDragOver as unknown as EventListener)\n currentRef.addEventListener('dragenter', handleDragEnter as unknown as EventListener)\n currentRef.addEventListener('dragleave', handleDragLeave as unknown as EventListener)\n currentRef.addEventListener('drop', handleDrop as unknown as EventListener)\n\n return () => {\n currentRef.removeEventListener('dragover', handleDragOver as unknown as EventListener)\n currentRef.removeEventListener('dragenter', handleDragEnter as unknown as EventListener)\n currentRef.removeEventListener('dragleave', handleDragLeave as unknown as EventListener)\n currentRef.removeEventListener('drop', handleDrop as unknown as EventListener)\n }\n }\n return undefined\n }, [handleDragOver, handleDragEnter, handleDragLeave, handleDrop])\n\n // The callback body below closes over nothing but the stable setState setter, so its\n // dependency array's contents can never affect whether useCallback returns the same function -\n // a literal added there would compare equal (Object.is) to itself every render.\n const reset = useCallback(\n () => {\n setState({\n isDragging: false,\n files: null,\n })\n }, // Stryker disable next-line ArrayDeclaration: equivalent mutant, see above.\n []\n )\n\n return {\n ref,\n isDragging: state.isDragging,\n files: state.files,\n reset,\n }\n}\n"],"mappings":"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","names":[]}
@@ -99,10 +99,14 @@ function useFilePaste({
99
99
  const [files, setFiles] = useState([]);
100
100
  const [isLoading, setIsLoading] = useState(false);
101
101
  const [error, setError] = useState(null);
102
- const clearFiles = useCallback(() => {
103
- setFiles([]);
104
- setError(null);
105
- }, []);
102
+ const clearFiles = useCallback(
103
+ () => {
104
+ setFiles([]);
105
+ setError(null);
106
+ },
107
+ // Stryker disable next-line ArrayDeclaration: equivalent mutant, see above.
108
+ []
109
+ );
106
110
  const validateFiles = useCallback(
107
111
  (pastedFiles) => {
108
112
  if (acceptedTypes && acceptedTypes.length > 0) {
@@ -289,12 +293,16 @@ function useFileDragDrop(options = {}) {
289
293
  }
290
294
  return void 0;
291
295
  }, [handleDragOver, handleDragEnter, handleDragLeave, handleDrop]);
292
- const reset = useCallback(() => {
293
- setState({
294
- isDragging: false,
295
- files: null
296
- });
297
- }, []);
296
+ const reset = useCallback(
297
+ () => {
298
+ setState({
299
+ isDragging: false,
300
+ files: null
301
+ });
302
+ },
303
+ // Stryker disable next-line ArrayDeclaration: equivalent mutant, see above.
304
+ []
305
+ );
298
306
  return {
299
307
  ref,
300
308
  isDragging: state.isDragging,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/hooks/index.ts"],"sourcesContent":["import type { ChangeEvent, DependencyList, DragEvent, EffectCallback } from 'react'\nimport { useCallback, useEffect, useRef, useState } from 'react'\n\nexport function useElementAttributes<T extends HTMLElement, K extends keyof T>(attributeKeys: K[]) {\n const ref = useRef<T | null>(null)\n const [attributeValues, setAttributeValue] = useState<Partial<Pick<T, K>>>({})\n\n const updateAttribute = useCallback(() => {\n if (ref.current) {\n const values = {} as Partial<Pick<T, K>>\n for (const key of attributeKeys) {\n // Object.defineProperty (unlike a plain `values[key] = value` assignment) always creates/\n // overwrites an own property, even if a consumer's T somehow has a key like \"__proto__\" -\n // matches the same defensive pattern used everywhere else in this package that writes a\n // non-literal key onto an object.\n Object.defineProperty(values, key, {\n value: ref.current[key],\n writable: true,\n configurable: true,\n enumerable: true,\n })\n }\n\n setAttributeValue((prevValues) => {\n const hasChanged = attributeKeys.some((key) => prevValues[key] !== values[key])\n return hasChanged ? values : prevValues\n })\n }\n }, [attributeKeys])\n\n useEffect(() => {\n updateAttribute()\n window.addEventListener('resize', updateAttribute)\n\n if (ref.current) {\n const observer = new MutationObserver(updateAttribute)\n observer.observe(ref.current, { attributes: true })\n\n return () => {\n window.removeEventListener('resize', updateAttribute)\n observer.disconnect()\n }\n }\n\n return () => {\n window.removeEventListener('resize', updateAttribute)\n }\n }, [updateAttribute])\n\n return { ref, attributeValues }\n}\n\ntype InputEventType = ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>\n\nexport function useFormState<T>(initialState: T) {\n const [formState, setFormState] = useState<T>(initialState)\n const [formErrors, setFormErrors] = useState<Partial<Record<keyof T, string[]>> & { non_field_errors?: string[] }>()\n\n function resetFormState() {\n setFormState(initialState)\n }\n\n function handleFormState<K extends keyof T, HandlerInputType>({\n key,\n inputType,\n }: {\n key: K\n inputType: 'event' | 'value'\n }) {\n return (event: HandlerInputType) => {\n let value: T[K]\n if (inputType === 'event') {\n const target = (event as InputEventType).target\n if (target.type === 'checkbox') {\n value = (target as HTMLInputElement).checked as T[K]\n } else if (target.type === 'number' || target.type === 'range') {\n value = (target as HTMLInputElement).valueAsNumber as T[K]\n } else {\n value = target.value as T[K]\n }\n } else {\n value = event as T[K]\n }\n setFormState((prev) => ({ ...prev, [key]: value }))\n }\n }\n\n const handleFormStateValue = <K extends keyof T>(key: K) => handleFormState<K, T[K]>({ key, inputType: 'value' })\n const handleFormStateEvent = <K extends keyof T>(key: K) =>\n handleFormState<K, InputEventType>({ key, inputType: 'event' })\n const handleFormStateOnClick =\n <K extends keyof T>(key: K, value: T[K]) =>\n () => {\n setFormState((prev) => ({ ...prev, [key]: value }))\n }\n\n return {\n formState,\n setFormState,\n formErrors,\n setFormErrors,\n handleFormStateValue,\n handleFormStateEvent,\n handleFormStateOnClick,\n resetFormState,\n }\n}\n\nexport function useEffectAfterMount(effect: EffectCallback, deps: DependencyList) {\n const isFirstRender = useRef(true)\n\n // No manual \"did deps actually change\" recheck needed here: React's own useEffect already\n // only re-invokes this callback when a dependency's value changed (shallow-compared against\n // the last time *this exact effect* ran) - which is exactly the same comparison a hand-rolled\n // check against a \"previous deps\" ref would be making, just duplicated.\n useEffect(() => {\n if (isFirstRender.current) {\n isFirstRender.current = false\n return\n }\n return effect()\n }, deps)\n}\n\nexport function useFilePaste({\n acceptedTypes,\n maxSize,\n targetElement,\n enabled = true,\n}: {\n acceptedTypes?: string[]\n maxSize?: number\n targetElement?: HTMLElement | null\n enabled?: boolean\n} = {}): {\n files: File[]\n isLoading: boolean\n error: string | null\n clearFiles: () => void\n} {\n const [files, setFiles] = useState<File[]>([])\n const [isLoading, setIsLoading] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n const clearFiles = useCallback(() => {\n setFiles([])\n setError(null)\n }, [])\n\n const validateFiles = useCallback(\n (pastedFiles: File[]): { valid: true } | { valid: false; error: string } => {\n if (acceptedTypes && acceptedTypes.length > 0) {\n const wildcardAcceptedTypes = acceptedTypes\n .filter((type) => type.endsWith('/*'))\n .map((type) => type.slice(0, -1))\n const normalizedAcceptedTypes = acceptedTypes.map((type) => (type.endsWith('/*') ? type.slice(0, -2) : type))\n\n const invalidFiles = pastedFiles.filter((file) => {\n const fileType = file.type\n return (\n !normalizedAcceptedTypes.includes(fileType) &&\n !wildcardAcceptedTypes.some((wildcardType) => fileType.startsWith(wildcardType))\n )\n })\n if (invalidFiles.length > 0) {\n const invalidFileNames = invalidFiles.map((file) => file.name).join(', ')\n return {\n valid: false,\n error: `Invalid file types: ${invalidFileNames}. Accepted types: ${acceptedTypes.join(', ')}`,\n }\n }\n }\n\n if (maxSize) {\n const oversizedFile = pastedFiles.find((file) => file.size > maxSize)\n if (oversizedFile) {\n const fileSizeMB = (oversizedFile.size / (1024 * 1024)).toFixed(2)\n const maxSizeMB = (maxSize / (1024 * 1024)).toFixed(2)\n return {\n valid: false,\n error: `File \"${oversizedFile.name}\" (${fileSizeMB} MB) exceeds the maximum size of ${maxSizeMB} MB`,\n }\n }\n }\n\n return { valid: true }\n },\n [acceptedTypes, maxSize]\n )\n\n const handlePaste = useCallback(\n (event: ClipboardEvent) => {\n const { clipboardData } = event\n if (!clipboardData) return\n\n const hasFiles = clipboardData.files && clipboardData.files.length > 0\n if (!hasFiles) return\n\n event.preventDefault()\n setIsLoading(true)\n setError(null)\n\n try {\n const pastedFiles = Array.from(clipboardData.files)\n const validation = validateFiles(pastedFiles)\n\n if (!validation.valid) {\n setError(validation.error)\n setFiles([])\n } else {\n setFiles(pastedFiles)\n }\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to process pasted files')\n setFiles([])\n } finally {\n setIsLoading(false)\n }\n },\n [validateFiles]\n )\n\n useEffect(() => {\n if (!enabled) return\n\n const target = targetElement || document\n\n target.addEventListener('paste', handlePaste as EventListener)\n return () => {\n target.removeEventListener('paste', handlePaste as EventListener)\n }\n }, [enabled, handlePaste, targetElement])\n\n return { files, isLoading, error, clearFiles }\n}\n\ntype FileDragDropState = {\n isDragging: boolean\n files: File[] | null\n}\n\ntype FileDragDropOptions = {\n onDrop?: (files: File[]) => void\n onDragOver?: (e: DragEvent<HTMLElement>) => void\n onDragLeave?: (e: DragEvent<HTMLElement>) => void\n acceptedFileTypes?: string[]\n maxFileSize?: number\n multiple?: boolean\n}\n\nexport function useFileDragDrop<T extends HTMLElement = HTMLDivElement>(options: FileDragDropOptions = {}) {\n const { onDrop, onDragOver, onDragLeave, acceptedFileTypes, maxFileSize, multiple = true } = options\n\n const [state, setState] = useState<FileDragDropState>({\n isDragging: false,\n files: null,\n })\n\n const ref = useRef<T | null>(null)\n const dragCounter = useRef(0)\n\n const handleDragOver = useCallback(\n (e: DragEvent<T>) => {\n e.preventDefault()\n e.stopPropagation()\n\n onDragOver?.(e)\n },\n [onDragOver]\n )\n\n const handleDragEnter = useCallback(\n (e: DragEvent<T>) => {\n e.preventDefault()\n e.stopPropagation()\n\n dragCounter.current += 1\n\n if (e.dataTransfer.items && e.dataTransfer.items.length > 0) {\n const hasValidItems = Array.from(e.dataTransfer.items).some((item) => {\n if (item.kind !== 'file') {\n return false\n }\n\n if (acceptedFileTypes && acceptedFileTypes.length > 0) {\n return acceptedFileTypes.some((type) => {\n if (type.endsWith('/*')) {\n const category = type.split('/')[0]\n return item.type.startsWith(`${category}/`)\n }\n return item.type === type\n })\n }\n\n return true\n })\n\n if (hasValidItems) {\n setState((prevState) => ({\n ...prevState,\n isDragging: true,\n }))\n }\n }\n },\n [acceptedFileTypes]\n )\n\n const handleDragLeave = useCallback(\n (e: DragEvent<T>) => {\n e.preventDefault()\n e.stopPropagation()\n\n dragCounter.current -= 1\n\n if (dragCounter.current === 0) {\n setState((prevState) => ({\n ...prevState,\n isDragging: false,\n }))\n }\n\n onDragLeave?.(e)\n },\n [onDragLeave]\n )\n\n const handleDrop = useCallback(\n (e: DragEvent<T>) => {\n e.preventDefault()\n e.stopPropagation()\n\n dragCounter.current = 0\n setState((prevState) => ({\n ...prevState,\n isDragging: false,\n }))\n\n if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {\n let validFiles = Array.from(e.dataTransfer.files)\n\n if (acceptedFileTypes && acceptedFileTypes.length > 0) {\n validFiles = validFiles.filter((file) =>\n acceptedFileTypes.some((type) => {\n if (type.endsWith('/*')) {\n const category = type.split('/')[0]\n return file.type.startsWith(`${category}/`)\n }\n return file.type === type\n })\n )\n }\n\n if (maxFileSize) {\n validFiles = validFiles.filter((file) => file.size <= maxFileSize)\n }\n\n if (!multiple && validFiles.length > 0) {\n validFiles = [validFiles[0]]\n }\n\n if (validFiles.length > 0) {\n setState((prevState) => ({\n ...prevState,\n files: validFiles,\n }))\n\n onDrop?.(validFiles)\n }\n }\n },\n [onDrop, acceptedFileTypes, maxFileSize, multiple]\n )\n\n useEffect(() => {\n const currentRef = ref.current\n if (currentRef) {\n currentRef.addEventListener('dragover', handleDragOver as unknown as EventListener)\n currentRef.addEventListener('dragenter', handleDragEnter as unknown as EventListener)\n currentRef.addEventListener('dragleave', handleDragLeave as unknown as EventListener)\n currentRef.addEventListener('drop', handleDrop as unknown as EventListener)\n\n return () => {\n currentRef.removeEventListener('dragover', handleDragOver as unknown as EventListener)\n currentRef.removeEventListener('dragenter', handleDragEnter as unknown as EventListener)\n currentRef.removeEventListener('dragleave', handleDragLeave as unknown as EventListener)\n currentRef.removeEventListener('drop', handleDrop as unknown as EventListener)\n }\n }\n return undefined\n }, [handleDragOver, handleDragEnter, handleDragLeave, handleDrop])\n\n const reset = useCallback(() => {\n setState({\n isDragging: false,\n files: null,\n })\n }, [])\n\n return {\n ref,\n isDragging: state.isDragging,\n files: state.files,\n reset,\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/hooks/index.ts"],"sourcesContent":["import type { ChangeEvent, DependencyList, DragEvent, EffectCallback } from 'react'\nimport { useCallback, useEffect, useRef, useState } from 'react'\n\nexport function useElementAttributes<T extends HTMLElement, K extends keyof T>(attributeKeys: K[]) {\n const ref = useRef<T | null>(null)\n const [attributeValues, setAttributeValue] = useState<Partial<Pick<T, K>>>({})\n\n const updateAttribute = useCallback(() => {\n if (ref.current) {\n const values = {} as Partial<Pick<T, K>>\n for (const key of attributeKeys) {\n // Object.defineProperty (unlike a plain `values[key] = value` assignment) always creates/\n // overwrites an own property, even if a consumer's T somehow has a key like \"__proto__\" -\n // matches the same defensive pattern used everywhere else in this package that writes a\n // non-literal key onto an object.\n Object.defineProperty(values, key, {\n value: ref.current[key],\n writable: true,\n configurable: true,\n enumerable: true,\n })\n }\n\n setAttributeValue((prevValues) => {\n const hasChanged = attributeKeys.some((key) => prevValues[key] !== values[key])\n return hasChanged ? values : prevValues\n })\n }\n }, [attributeKeys])\n\n useEffect(() => {\n updateAttribute()\n window.addEventListener('resize', updateAttribute)\n\n if (ref.current) {\n const observer = new MutationObserver(updateAttribute)\n observer.observe(ref.current, { attributes: true })\n\n return () => {\n window.removeEventListener('resize', updateAttribute)\n observer.disconnect()\n }\n }\n\n return () => {\n window.removeEventListener('resize', updateAttribute)\n }\n }, [updateAttribute])\n\n return { ref, attributeValues }\n}\n\ntype InputEventType = ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>\n\nexport function useFormState<T>(initialState: T) {\n const [formState, setFormState] = useState<T>(initialState)\n const [formErrors, setFormErrors] = useState<Partial<Record<keyof T, string[]>> & { non_field_errors?: string[] }>()\n\n function resetFormState() {\n setFormState(initialState)\n }\n\n function handleFormState<K extends keyof T, HandlerInputType>({\n key,\n inputType,\n }: {\n key: K\n inputType: 'event' | 'value'\n }) {\n return (event: HandlerInputType) => {\n let value: T[K]\n if (inputType === 'event') {\n const target = (event as InputEventType).target\n if (target.type === 'checkbox') {\n value = (target as HTMLInputElement).checked as T[K]\n } else if (target.type === 'number' || target.type === 'range') {\n value = (target as HTMLInputElement).valueAsNumber as T[K]\n } else {\n value = target.value as T[K]\n }\n } else {\n value = event as T[K]\n }\n setFormState((prev) => ({ ...prev, [key]: value }))\n }\n }\n\n // Stryker disable next-line StringLiteral: equivalent mutant. handleFormState only ever\n // compares inputType against 'event' - any other string, including this one, takes the exact\n // same branch, so the specific label 'value' carries no behavior of its own.\n const handleFormStateValue = <K extends keyof T>(key: K) => handleFormState<K, T[K]>({ key, inputType: 'value' })\n const handleFormStateEvent = <K extends keyof T>(key: K) =>\n handleFormState<K, InputEventType>({ key, inputType: 'event' })\n const handleFormStateOnClick =\n <K extends keyof T>(key: K, value: T[K]) =>\n () => {\n setFormState((prev) => ({ ...prev, [key]: value }))\n }\n\n return {\n formState,\n setFormState,\n formErrors,\n setFormErrors,\n handleFormStateValue,\n handleFormStateEvent,\n handleFormStateOnClick,\n resetFormState,\n }\n}\n\nexport function useEffectAfterMount(effect: EffectCallback, deps: DependencyList) {\n const isFirstRender = useRef(true)\n\n // No manual \"did deps actually change\" recheck needed here: React's own useEffect already\n // only re-invokes this callback when a dependency's value changed (shallow-compared against\n // the last time *this exact effect* ran) - which is exactly the same comparison a hand-rolled\n // check against a \"previous deps\" ref would be making, just duplicated.\n useEffect(() => {\n if (isFirstRender.current) {\n isFirstRender.current = false\n return\n }\n return effect()\n }, deps)\n}\n\nexport function useFilePaste({\n acceptedTypes,\n maxSize,\n targetElement,\n enabled = true,\n}: {\n acceptedTypes?: string[]\n maxSize?: number\n targetElement?: HTMLElement | null\n enabled?: boolean\n} = {}): {\n files: File[]\n isLoading: boolean\n error: string | null\n clearFiles: () => void\n} {\n const [files, setFiles] = useState<File[]>([])\n const [isLoading, setIsLoading] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n // The callback body below closes over nothing but the stable setFiles/setError setters, so\n // its dependency array's contents can never affect whether useCallback returns the same\n // function - a literal added there would compare equal (Object.is) to itself every render.\n const clearFiles = useCallback(\n () => {\n setFiles([])\n setError(null)\n }, // Stryker disable next-line ArrayDeclaration: equivalent mutant, see above.\n []\n )\n\n const validateFiles = useCallback(\n (pastedFiles: File[]): { valid: true } | { valid: false; error: string } => {\n if (acceptedTypes && acceptedTypes.length > 0) {\n const wildcardAcceptedTypes = acceptedTypes\n .filter((type) => type.endsWith('/*'))\n .map((type) => type.slice(0, -1))\n const normalizedAcceptedTypes = acceptedTypes.map((type) => (type.endsWith('/*') ? type.slice(0, -2) : type))\n\n const invalidFiles = pastedFiles.filter((file) => {\n const fileType = file.type\n return (\n !normalizedAcceptedTypes.includes(fileType) &&\n !wildcardAcceptedTypes.some((wildcardType) => fileType.startsWith(wildcardType))\n )\n })\n if (invalidFiles.length > 0) {\n const invalidFileNames = invalidFiles.map((file) => file.name).join(', ')\n return {\n valid: false,\n error: `Invalid file types: ${invalidFileNames}. Accepted types: ${acceptedTypes.join(', ')}`,\n }\n }\n }\n\n if (maxSize) {\n const oversizedFile = pastedFiles.find((file) => file.size > maxSize)\n if (oversizedFile) {\n const fileSizeMB = (oversizedFile.size / (1024 * 1024)).toFixed(2)\n const maxSizeMB = (maxSize / (1024 * 1024)).toFixed(2)\n return {\n valid: false,\n error: `File \"${oversizedFile.name}\" (${fileSizeMB} MB) exceeds the maximum size of ${maxSizeMB} MB`,\n }\n }\n }\n\n return { valid: true }\n },\n [acceptedTypes, maxSize]\n )\n\n const handlePaste = useCallback(\n (event: ClipboardEvent) => {\n const { clipboardData } = event\n if (!clipboardData) return\n\n const hasFiles = clipboardData.files && clipboardData.files.length > 0\n if (!hasFiles) return\n\n event.preventDefault()\n // Stryker disable next-line BooleanLiteral: equivalent mutant. validateFiles never yields\n // (no await between here and the `finally` below), so this and the `finally`'s\n // setIsLoading(false) land in the same synchronous React commit - an observer can only ever\n // see the final `false`, never a transient `true`, no matter what this call passes.\n setIsLoading(true)\n setError(null)\n\n try {\n const pastedFiles = Array.from(clipboardData.files)\n const validation = validateFiles(pastedFiles)\n\n if (!validation.valid) {\n setError(validation.error)\n setFiles([])\n } else {\n setFiles(pastedFiles)\n }\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to process pasted files')\n setFiles([])\n } finally {\n setIsLoading(false)\n }\n },\n [validateFiles]\n )\n\n useEffect(() => {\n if (!enabled) return\n\n const target = targetElement || document\n\n target.addEventListener('paste', handlePaste as EventListener)\n return () => {\n target.removeEventListener('paste', handlePaste as EventListener)\n }\n }, [enabled, handlePaste, targetElement])\n\n return { files, isLoading, error, clearFiles }\n}\n\ntype FileDragDropState = {\n isDragging: boolean\n files: File[] | null\n}\n\ntype FileDragDropOptions = {\n onDrop?: (files: File[]) => void\n onDragOver?: (e: DragEvent<HTMLElement>) => void\n onDragLeave?: (e: DragEvent<HTMLElement>) => void\n acceptedFileTypes?: string[]\n maxFileSize?: number\n multiple?: boolean\n}\n\nexport function useFileDragDrop<T extends HTMLElement = HTMLDivElement>(options: FileDragDropOptions = {}) {\n const { onDrop, onDragOver, onDragLeave, acceptedFileTypes, maxFileSize, multiple = true } = options\n\n const [state, setState] = useState<FileDragDropState>({\n isDragging: false,\n files: null,\n })\n\n const ref = useRef<T | null>(null)\n const dragCounter = useRef(0)\n\n const handleDragOver = useCallback(\n (e: DragEvent<T>) => {\n e.preventDefault()\n e.stopPropagation()\n\n onDragOver?.(e)\n },\n [onDragOver]\n )\n\n const handleDragEnter = useCallback(\n (e: DragEvent<T>) => {\n e.preventDefault()\n e.stopPropagation()\n\n dragCounter.current += 1\n\n // Stryker disable next-line ConditionalExpression,EqualityOperator: equivalent mutant on\n // the `.length > 0` half specifically. When items is truthy but empty, entering the block\n // anyway still runs Array.from([]).some(...), which is vacuously false - the same no-op as\n // skipping it - so relaxing this to `>= 0` (or dropping it) can't change the outcome.\n if (e.dataTransfer.items && e.dataTransfer.items.length > 0) {\n const hasValidItems = Array.from(e.dataTransfer.items).some((item) => {\n if (item.kind !== 'file') {\n return false\n }\n\n if (acceptedFileTypes && acceptedFileTypes.length > 0) {\n return acceptedFileTypes.some((type) => {\n if (type.endsWith('/*')) {\n const category = type.split('/')[0]\n return item.type.startsWith(`${category}/`)\n }\n return item.type === type\n })\n }\n\n return true\n })\n\n if (hasValidItems) {\n setState((prevState) => ({\n ...prevState,\n isDragging: true,\n }))\n }\n }\n },\n [acceptedFileTypes]\n )\n\n const handleDragLeave = useCallback(\n (e: DragEvent<T>) => {\n e.preventDefault()\n e.stopPropagation()\n\n dragCounter.current -= 1\n\n if (dragCounter.current === 0) {\n setState((prevState) => ({\n ...prevState,\n isDragging: false,\n }))\n }\n\n onDragLeave?.(e)\n },\n [onDragLeave]\n )\n\n const handleDrop = useCallback(\n (e: DragEvent<T>) => {\n e.preventDefault()\n e.stopPropagation()\n\n dragCounter.current = 0\n setState((prevState) => ({\n ...prevState,\n isDragging: false,\n }))\n\n // Stryker disable next-line ConditionalExpression,EqualityOperator: equivalent mutant on\n // the `.length > 0` half specifically. When files is truthy but empty, entering the block\n // anyway still runs Array.from([]) and every downstream filter/length check on it, which\n // stay vacuously empty - the same no-op as skipping it - so relaxing this to `>= 0` (or\n // dropping it) can't change the outcome.\n if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {\n let validFiles = Array.from(e.dataTransfer.files)\n\n if (acceptedFileTypes && acceptedFileTypes.length > 0) {\n validFiles = validFiles.filter((file) =>\n acceptedFileTypes.some((type) => {\n if (type.endsWith('/*')) {\n const category = type.split('/')[0]\n return file.type.startsWith(`${category}/`)\n }\n return file.type === type\n })\n )\n }\n\n if (maxFileSize) {\n validFiles = validFiles.filter((file) => file.size <= maxFileSize)\n }\n\n if (!multiple && validFiles.length > 0) {\n validFiles = [validFiles[0]]\n }\n\n if (validFiles.length > 0) {\n setState((prevState) => ({\n ...prevState,\n files: validFiles,\n }))\n\n onDrop?.(validFiles)\n }\n }\n },\n [onDrop, acceptedFileTypes, maxFileSize, multiple]\n )\n\n useEffect(() => {\n const currentRef = ref.current\n if (currentRef) {\n currentRef.addEventListener('dragover', handleDragOver as unknown as EventListener)\n currentRef.addEventListener('dragenter', handleDragEnter as unknown as EventListener)\n currentRef.addEventListener('dragleave', handleDragLeave as unknown as EventListener)\n currentRef.addEventListener('drop', handleDrop as unknown as EventListener)\n\n return () => {\n currentRef.removeEventListener('dragover', handleDragOver as unknown as EventListener)\n currentRef.removeEventListener('dragenter', handleDragEnter as unknown as EventListener)\n currentRef.removeEventListener('dragleave', handleDragLeave as unknown as EventListener)\n currentRef.removeEventListener('drop', handleDrop as unknown as EventListener)\n }\n }\n return undefined\n }, [handleDragOver, handleDragEnter, handleDragLeave, handleDrop])\n\n // The callback body below closes over nothing but the stable setState setter, so its\n // dependency array's contents can never affect whether useCallback returns the same function -\n // a literal added there would compare equal (Object.is) to itself every render.\n const reset = useCallback(\n () => {\n setState({\n isDragging: false,\n files: null,\n })\n }, // Stryker disable next-line ArrayDeclaration: equivalent mutant, see above.\n []\n )\n\n return {\n ref,\n isDragging: state.isDragging,\n files: state.files,\n reset,\n }\n}\n"],"mappings":"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","names":[]}
package/dist/index.cjs CHANGED
@@ -230,7 +230,11 @@ function slugify(value, allowUnicode = false) {
230
230
  if (allowUnicode) {
231
231
  value = value.normalize("NFKC").replace(/[^\p{L}\p{N}_\s-]/gu, "");
232
232
  } else {
233
- value = value.normalize("NFKD").replace(/[^\x00-\x7F]/g, "").replace(/[\r\n]+/g, " ").trim().replace(/[^\w\s-]/g, "");
233
+ value = value.normalize("NFKD");
234
+ value = value.replace(/[^\x00-\x7F]/g, "");
235
+ value = value.replace(/[\r\n]+/g, " ");
236
+ value = value.trim();
237
+ value = value.replace(/[^\w\s-]/g, "");
234
238
  }
235
239
  value = value.toLowerCase();
236
240
  return value.replace(/[-\s]+/g, "-").replace(/^[-_]+|[-_]+$/g, "");
@@ -267,6 +271,8 @@ function guessImageMimeType(filename) {
267
271
  const withoutQueryOrHash = filename.split(/[?#]/)[0];
268
272
  const extension = withoutQueryOrHash.split(".").pop()?.toLowerCase();
269
273
  switch (extension) {
274
+ // Stryker disable next-line StringLiteral: equivalent mutant. This case and `default` below
275
+ // both return 'image/png', so no input can distinguish which of the two branches ran it.
270
276
  case "png":
271
277
  return "image/png";
272
278
  case "jfif":
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/types/index.ts","../src/arrays/index.ts","../src/functions/index.ts","../src/objects/index.ts","../src/strings/index.ts","../src/dates/_format.ts","../src/dates/index.ts","../src/files/index.ts","../src/cookies/index.ts","../src/console/index.ts","../src/colors/index.ts"],"sourcesContent":["export * from './types'\nexport * from './arrays'\nexport * from './functions'\nexport * from './objects'\nexport * from './strings'\nexport * from './dates'\nexport * from './files'\nexport * from './cookies'\nexport * from './console'\nexport * from './colors'\n","export const getKeys = Object.keys as <T extends object>(obj: T) => Array<keyof T>\n\nexport type RecursivePartial<T> = { [P in keyof T]?: RecursivePartial<T[P]> }\n\nexport type RecursiveRecord = {\n [key: string]: string | number | boolean | RecursiveRecord | Array<RecursiveRecord>\n}\n\nexport function forcedType<T>(obj: unknown): T {\n return obj as unknown as T\n}\n","export function notNone<T>(value: T | null | undefined): value is T {\n return value !== null && value !== undefined\n}\n\nfunction combinationsOfSize<T>(items: T[], size: number): T[][] {\n if (size === 0) {\n return [[]]\n }\n if (size > items.length) {\n return []\n }\n const [first, ...rest] = items\n const withFirst = combinationsOfSize(rest, size - 1).map((combination) => [first, ...combination])\n const withoutFirst = combinationsOfSize(rest, size)\n return [...withFirst, ...withoutFirst]\n}\n\nexport function allCombinations<T>(options: T[]): T[][] {\n const result: T[][] = []\n for (let size = 1; size <= options.length; size++) {\n result.push(...combinationsOfSize(options, size))\n }\n return result\n}\n","export function withAttributes<Fn extends (...args: never[]) => unknown, Attrs extends Record<string, unknown>>(\n fn: Fn,\n attributes: Attrs\n): Fn & Attrs {\n for (const key of Object.keys(attributes)) {\n // Object.defineProperty (unlike a plain `fn[key] = value` assignment) always creates/\n // overwrites an own property, even when key is \"__proto__\" - a plain assignment would instead\n // be intercepted by Object.prototype's special __proto__ accessor and reassign fn's own\n // prototype instead of setting a property on it.\n Object.defineProperty(fn, key, {\n value: attributes[key],\n writable: true,\n configurable: true,\n enumerable: true,\n })\n }\n return fn as Fn & Attrs\n}\n\nexport function makeCallable<T, R>(originalCallable: (arg: T) => R) {\n return (data: T) => () => originalCallable(data)\n}\n\nexport function getLazyValue<T>(input: T | (() => T)): T {\n if (typeof input === 'function') {\n return (input as () => T)()\n }\n return input\n}\n\nexport async function getLazyValueAsync<T>(input: T | (() => Promise<T>) | (() => T)): Promise<T> {\n if (typeof input === 'function') {\n const result = (input as () => Promise<T>)()\n if (result instanceof Promise) {\n return await result\n }\n return result as unknown as T\n }\n return input\n}\n\nexport function suppress<T, ERT>(\n exceptions: Array<new (message?: string) => Error>,\n fn: () => T,\n onError?: (error: unknown) => ERT\n): T | ERT | undefined {\n try {\n return fn()\n } catch (error) {\n if (exceptions.some((exception) => error instanceof exception)) {\n return onError ? onError(error) : undefined\n }\n throw error\n }\n}\n\nexport function preventDefault<E extends Event, R>(callable: (event: E) => R): (event: E) => Promise<Awaited<R>> {\n return async function (event: E): Promise<Awaited<R>> {\n event.preventDefault()\n return await callable(event)\n }\n}\n\nexport function isPathMatched(pathname: string, pattern: RegExp, exemptPatterns: RegExp[] = []): boolean {\n if (exemptPatterns.some((exempt) => exempt.test(pathname))) {\n return false\n }\n return pattern.test(pathname)\n}\n\nexport function raises(error: Error): (...args: unknown[]) => never {\n return () => {\n throw error\n }\n}\n\nexport function cloned<Fn extends (...args: never[]) => unknown>(fn: Fn): Fn {\n return ((...args: Parameters<Fn>) => fn(...args)) as Fn\n}\n\nexport function enabledIf<R>(condition: boolean | (() => boolean), options: { ifNotEnabledReturnValue: R }) {\n const enabled = typeof condition === 'function' ? condition() : condition\n\n return function <Fn extends (...args: never[]) => R>(fn: Fn): Fn {\n if (!enabled) {\n return cloned((() => options.ifNotEnabledReturnValue) as Fn)\n }\n return cloned(fn)\n }\n}\n\nexport function transformExceptions<E extends Error>(\n exceptionTypes: Array<new (...args: never[]) => E>,\n transform: (error: E) => Error,\n options: { keepOriginal?: boolean } = {}\n) {\n const { keepOriginal = true } = options\n\n return function <Fn extends (...args: never[]) => unknown>(fn: Fn): Fn {\n return ((...args: Parameters<Fn>) => {\n try {\n return fn(...args)\n } catch (error) {\n if (!exceptionTypes.some((ExceptionType) => error instanceof ExceptionType)) {\n throw error\n }\n const newError = transform(error as E)\n if (keepOriginal) {\n newError.cause = error\n }\n throw newError\n }\n }) as Fn\n }\n}\n","export function checkRequiredKeys<T extends Record<string, unknown>, C extends Record<string, Array<keyof T>>>(\n obj: T,\n conditions: C\n): keyof C {\n const matchingConditions = Object.entries(conditions).filter(\n ([, keys]) =>\n keys.every((key) => obj[key] !== undefined) &&\n Object.keys(obj).every((key) => keys.includes(key as keyof T) || obj[key] === undefined)\n )\n\n if (matchingConditions.length !== 1) {\n throw new Error(`Object keys do not match exactly one required condition. ${JSON.stringify(conditions)}`)\n }\n\n return matchingConditions[0][0] as keyof C\n}\n\nexport function requireExclusiveKeys<T extends Record<string, unknown>, C extends Record<string, Array<keyof T>>>(\n conditions: C,\n options: { allowEmpty?: boolean } = {}\n) {\n const conditionEntries = Object.entries(conditions) as Array<[string, Array<keyof T>]>\n if (conditionEntries.length === 0) {\n throw new Error('At least one condition must be provided.')\n }\n const { allowEmpty = false } = options\n const governedKeys = new Set(conditionEntries.flatMap(([, keys]) => keys))\n\n return function <Fn extends (arg: T) => unknown>(fn: Fn): Fn {\n return ((arg: T) => {\n // Only keys that are actually governed by a condition are considered - unlike\n // checkRequiredKeys, any other key on `arg` is fully unconstrained and ignored here\n // regardless of its value, since this is meant to validate one options object that may\n // legitimately carry other, unrelated fields alongside the mutually-exclusive ones.\n const provided = new Set(\n Object.keys(arg).filter((key) => governedKeys.has(key as keyof T) && arg[key] !== undefined)\n )\n\n if (allowEmpty && provided.size === 0) {\n return fn(arg)\n }\n\n const matches = conditionEntries.filter(\n ([, keys]) => keys.length === provided.size && keys.every((key) => provided.has(key as string))\n )\n if (matches.length !== 1) {\n throw new Error(`Object keys do not match exactly one required condition. ${JSON.stringify(conditions)}`)\n }\n return fn(arg)\n }) as Fn\n }\n}\n\nexport function setKeyValueToObjectIfValue(key: string, value: unknown, object: Record<string, unknown>) {\n if (value) {\n // Object.defineProperty (unlike a plain `object[key] = value` assignment) always creates/\n // overwrites an own property, even when key is \"__proto__\" - a plain assignment would instead\n // be intercepted by Object.prototype's special __proto__ accessor and reassign this object's\n // prototype instead of setting a property on it.\n Object.defineProperty(object, key, { value, writable: true, configurable: true, enumerable: true })\n }\n}\n","export function slugify(value: string, allowUnicode: boolean = false): string {\n if (allowUnicode) {\n value = value.normalize('NFKC').replace(/[^\\p{L}\\p{N}_\\s-]/gu, '')\n } else {\n value = value\n .normalize('NFKD')\n // eslint-disable-next-line no-control-regex\n .replace(/[^\\x00-\\x7F]/g, '')\n .replace(/[\\r\\n]+/g, ' ')\n .trim()\n .replace(/[^\\w\\s-]/g, '')\n }\n\n value = value.toLowerCase()\n\n return value.replace(/[-\\s]+/g, '-').replace(/^[-_]+|[-_]+$/g, '')\n}\n","import { format } from 'date-fns'\n\nexport function formatDate(date: Date, pattern: string): string {\n return format(date, pattern)\n}\n","import { formatDate } from './_format'\n\nexport const LONG_DATE_FORMAT = \"EEEE, MMMM dd, yyyy 'at' hh:mm a\"\nexport const SHORT_DATE_FORMAT = 'dd.MM.yyyy'\nexport const SHORT_DATETIME_FORMAT = 'dd.MM.yyyy HH:mm a'\n\nexport function formattedDate(pattern: string, date: Date = new Date()): string {\n return formatDate(date, pattern)\n}\n\nexport function longFormattedDate(date: Date = new Date()): string {\n return formattedDate(LONG_DATE_FORMAT, date)\n}\n\nexport function shortFormattedDate(date: Date = new Date()): string {\n return formattedDate(SHORT_DATE_FORMAT, date)\n}\n\nexport function shortFormattedDateTime(date: Date = new Date()): string {\n return formattedDate(SHORT_DATETIME_FORMAT, date)\n}\n\nexport function optionalDate(date?: string): Date | undefined {\n return date ? new Date(date) : undefined\n}\n","type MimeType = 'image/png' | 'image/jpeg' | 'image/webp'\n\nexport function guessImageMimeType(filename: string): MimeType {\n const withoutQueryOrHash = filename.split(/[?#]/)[0]\n const extension = withoutQueryOrHash.split('.').pop()?.toLowerCase()\n switch (extension) {\n case 'png':\n return 'image/png'\n case 'jfif':\n case 'jpg':\n case 'jpeg':\n return 'image/jpeg'\n case 'webp':\n return 'image/webp'\n default:\n return 'image/png'\n }\n}\n\nexport function isImageMimeType(mimeType: string): mimeType is MimeType {\n return mimeType === 'image/png' || mimeType === 'image/jpeg' || mimeType === 'image/webp'\n}\n\nexport function escapeName(name: string): string {\n return name.replace(/[^a-zA-Z0-9-_.]/g, '_')\n}\n\nexport function safeFileName(filename: string, maxLength: number = 255): string {\n if (filename.length <= maxLength) return filename\n\n const dotIndex = filename.lastIndexOf('.')\n const hasExtension = dotIndex > 0\n const extension = escapeName(hasExtension ? filename.slice(dotIndex) : '')\n const name = escapeName(hasExtension ? filename.slice(0, dotIndex) : filename)\n\n return name.slice(0, Math.max(0, maxLength - extension.length)) + extension\n}\n\nexport async function downloadAndFormatImage(\n src: string,\n name: string = 'image.png',\n mimeType: MimeType = guessImageMimeType(name),\n quality: number = 1\n): Promise<void> {\n name = safeFileName(name)\n try {\n const img = new Image()\n img.crossOrigin = 'anonymous'\n\n await new Promise((resolve, reject) => {\n img.onload = resolve\n img.onerror = reject\n img.src = src\n })\n\n const canvas = document.createElement('canvas')\n canvas.width = img.width\n canvas.height = img.height\n const ctx = canvas.getContext('2d')\n\n if (!ctx) {\n throw new Error('Could not get canvas context')\n }\n\n ctx.drawImage(img, 0, 0)\n\n const blob = await new Promise<Blob | null>((resolve) => {\n canvas.toBlob(resolve, mimeType, quality)\n })\n\n if (!blob) {\n throw new Error('Could not generate blob')\n }\n\n const link = document.createElement('a')\n const downloadUrl = URL.createObjectURL(blob)\n try {\n link.href = downloadUrl\n link.download = name\n document.body.appendChild(link)\n link.click()\n } finally {\n document.body.removeChild(link)\n URL.revokeObjectURL(downloadUrl)\n }\n } catch (error) {\n console.error('Failed to download image:', error)\n }\n}\n\nexport async function fileToBase64Native(file: File): Promise<string> {\n const result = await new Promise<string | ArrayBuffer | null>((resolve, reject) => {\n const reader = new FileReader()\n reader.readAsDataURL(file)\n reader.onload = () => resolve(reader.result)\n reader.onerror = (error) => reject(error)\n })\n\n if (typeof result === 'string') {\n return result\n } else {\n throw new Error('Failed to read file as Data URL')\n }\n}\n\nexport async function fileToBase64(file: File, quality: number = 1): Promise<string> {\n if (isImageMimeType(file.type)) {\n const img = new Image()\n const url = URL.createObjectURL(file)\n try {\n await new Promise<void>((resolve, reject) => {\n img.onload = () => resolve()\n img.onerror = () => reject(new Error('Failed to load image for metadata removal'))\n img.src = url\n })\n\n const canvas = document.createElement('canvas')\n canvas.width = img.width\n canvas.height = img.height\n\n const ctx = canvas.getContext('2d')\n if (!ctx) {\n throw new Error('Failed to get canvas context')\n }\n ctx.drawImage(img, 0, 0)\n\n const cleanDataUrl = canvas.toDataURL(file.type, quality)\n if (cleanDataUrl === 'data:,') {\n return await fileToBase64Native(file)\n }\n\n return cleanDataUrl\n } finally {\n URL.revokeObjectURL(url)\n }\n } else {\n return await fileToBase64Native(file)\n }\n}\n","export function getCookie(name: string): string | undefined {\n for (const pair of document.cookie.split('; ')) {\n const separatorIndex = pair.indexOf('=')\n if (separatorIndex === -1) {\n continue\n }\n if (pair.slice(0, separatorIndex) === name) {\n return pair.slice(separatorIndex + 1)\n }\n }\n return undefined\n}\n\nexport interface SetCookieOptions {\n /** Days until the cookie expires. Omit for a session cookie (cleared when the browser closes). */\n days?: number\n path?: string\n}\n\nexport function setCookie(name: string, value: string, options: SetCookieOptions = {}): void {\n const { days, path = '/' } = options\n const expires = days === undefined ? '' : `; expires=${new Date(Date.now() + days * 86_400_000).toUTCString()}`\n document.cookie = `${name}=${value}${expires}; path=${path}`\n}\n\nexport function removeCookie(name: string, path: string = '/'): void {\n document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=${path}`\n}\n","type ConsoleMethod = (...args: unknown[]) => void\ntype WindowLike = Window & typeof globalThis\n\nconst patchedWindows = new WeakMap<WindowLike, Set<string>>()\n\nexport function createConsoleDebugSwitch(targetWindow: WindowLike, options: { namespace: string }): void {\n if (!targetWindow) {\n return\n }\n\n const { namespace } = options\n\n let enabledNamespaces = patchedWindows.get(targetWindow)\n if (!enabledNamespaces) {\n enabledNamespaces = new Set<string>()\n patchedWindows.set(targetWindow, enabledNamespaces)\n\n const original = {\n log: targetWindow.console.log.bind(targetWindow.console),\n info: targetWindow.console.info.bind(targetWindow.console),\n warn: targetWindow.console.warn.bind(targetWindow.console),\n error: targetWindow.console.error.bind(targetWindow.console),\n }\n\n const conditional =\n (method: ConsoleMethod): ConsoleMethod =>\n (...args) => {\n if (enabledNamespaces!.size > 0) {\n method(...args)\n }\n }\n\n targetWindow.console.log = conditional(original.log)\n targetWindow.console.info = conditional(original.info)\n targetWindow.console.warn = conditional(original.warn)\n targetWindow.console.error = conditional(original.error)\n }\n\n type Namespace = { debug: (enabled: boolean) => void }\n const globals = targetWindow as unknown as Record<string, Namespace | undefined>\n const existing = Object.prototype.hasOwnProperty.call(globals, namespace)\n ? (Object.getOwnPropertyDescriptor(globals, namespace)?.value as Namespace | undefined)\n : undefined\n const target = existing ?? ({} as Namespace)\n target.debug = (flag: boolean) => {\n if (flag) {\n enabledNamespaces!.add(namespace)\n } else {\n enabledNamespaces!.delete(namespace)\n }\n }\n // Object.defineProperty (unlike a plain `globals[namespace] = target` assignment) always\n // creates/overwrites an own property, even when namespace is a name like \"__proto__\" that\n // would otherwise be intercepted by Object.prototype's special __proto__ accessor and\n // pollute the shared prototype instead of setting a property on this specific object.\n Object.defineProperty(globals, namespace, { value: target, writable: true, configurable: true, enumerable: true })\n}\n","export type TailwindShade = 50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 950\n\nexport type TailwindColorScale = Record<TailwindShade, string>\n\ninterface Rgb {\n r: number\n g: number\n b: number\n}\n\nconst HEX_PATTERN = /^#?([0-9a-f]{3}|[0-9a-f]{6})$/i\n\nfunction hexToRgb(hex: string): Rgb {\n const match = HEX_PATTERN.exec(hex.trim())\n if (!match) {\n throw new Error(`Invalid hex color: \"${hex}\"`)\n }\n\n const digits = match[1]\n const normalized =\n digits.length === 3\n ? digits\n .split('')\n .map((char) => char + char)\n .join('')\n : digits\n\n return {\n r: parseInt(normalized.slice(0, 2), 16),\n g: parseInt(normalized.slice(2, 4), 16),\n b: parseInt(normalized.slice(4, 6), 16),\n }\n}\n\nfunction rgbToHex({ r, g, b }: Rgb): string {\n return `#${[r, g, b].map((channel) => Math.round(channel).toString(16).padStart(2, '0')).join('')}`\n}\n\nfunction mixRgb(base: Rgb, target: Rgb, weight: number): Rgb {\n return {\n r: base.r + (target.r - base.r) * weight,\n g: base.g + (target.g - base.g) * weight,\n b: base.b + (target.b - base.b) * weight,\n }\n}\n\nconst WHITE: Rgb = { r: 255, g: 255, b: 255 }\nconst BLACK: Rgb = { r: 0, g: 0, b: 0 }\n\n// Weight of white/black mixed into the base color at each shade, tuned so 500 is the input\n// color unchanged and the rest approximate the spread of Tailwind's own default palettes.\nconst TINT_WEIGHTS: Record<50 | 100 | 200 | 300 | 400, number> = { 50: 0.95, 100: 0.9, 200: 0.75, 300: 0.6, 400: 0.3 }\nconst SHADE_WEIGHTS: Record<600 | 700 | 800 | 900 | 950, number> = {\n 600: 0.15,\n 700: 0.3,\n 800: 0.45,\n 900: 0.6,\n 950: 0.8,\n}\n\n/**\n * Generates a Tailwind-style 50-950 color scale from a single base hex color, treated as the 500 shade.\n */\nexport function generateTailwindColorScale(baseColor: string): TailwindColorScale {\n const base = hexToRgb(baseColor)\n\n return {\n 50: rgbToHex(mixRgb(base, WHITE, TINT_WEIGHTS[50])),\n 100: rgbToHex(mixRgb(base, WHITE, TINT_WEIGHTS[100])),\n 200: rgbToHex(mixRgb(base, WHITE, TINT_WEIGHTS[200])),\n 300: rgbToHex(mixRgb(base, WHITE, TINT_WEIGHTS[300])),\n 400: rgbToHex(mixRgb(base, WHITE, TINT_WEIGHTS[400])),\n 500: rgbToHex(base),\n 600: rgbToHex(mixRgb(base, BLACK, SHADE_WEIGHTS[600])),\n 700: rgbToHex(mixRgb(base, BLACK, SHADE_WEIGHTS[700])),\n 800: rgbToHex(mixRgb(base, BLACK, SHADE_WEIGHTS[800])),\n 900: rgbToHex(mixRgb(base, BLACK, SHADE_WEIGHTS[900])),\n 950: rgbToHex(mixRgb(base, BLACK, SHADE_WEIGHTS[950])),\n }\n}\n\n/**\n * Like {@link generateTailwindColorScale}, but prefixes each shade with `name` (e.g. `primary500`)\n * so multiple scales can be spread into one flat palette object.\n */\nexport function generateNamedTailwindColorScale<T extends string>(\n baseColor: string,\n name: T\n): Record<`${T}${TailwindShade}`, string> {\n const scale = generateTailwindColorScale(baseColor)\n\n return Object.fromEntries(Object.entries(scale).map(([shade, hex]) => [`${name}${shade}`, hex])) as Record<\n `${T}${TailwindShade}`,\n string\n >\n}\n\nfunction rgbToHsl({ r, g, b }: Rgb): { h: number; s: number; l: number } {\n const rN = r / 255\n const gN = g / 255\n const bN = b / 255\n\n const max = Math.max(rN, gN, bN)\n const min = Math.min(rN, gN, bN)\n const l = (max + min) / 2\n\n if (max === min) {\n return { h: 0, s: 0, l: l * 100 }\n }\n\n const delta = max - min\n const s = l > 0.5 ? delta / (2 - max - min) : delta / (max + min)\n\n let h: number\n if (max === rN) {\n h = ((gN - bN) / delta + (gN < bN ? 6 : 0)) * 60\n } else if (max === gN) {\n h = ((bN - rN) / delta + 2) * 60\n } else {\n h = ((rN - gN) / delta + 4) * 60\n }\n\n return { h, s: s * 100, l: l * 100 }\n}\n\n/**\n * Formats a hex color as the \"H S% L%\" triplet shadcn/Tailwind CSS variable themes expect,\n * e.g. for `--primary: 240 5.9% 10%;` consumed as `hsl(var(--primary))`.\n */\nexport function hexToHslTriplet(hex: string, precision: number = 1): string {\n const { h, s, l } = rgbToHsl(hexToRgb(hex))\n const round = (value: number) => Number(value.toFixed(precision))\n\n return `${round(h)} ${round(s)}% ${round(l)}%`\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/types/index.ts","../src/arrays/index.ts","../src/functions/index.ts","../src/objects/index.ts","../src/strings/index.ts","../src/dates/_format.ts","../src/dates/index.ts","../src/files/index.ts","../src/cookies/index.ts","../src/console/index.ts","../src/colors/index.ts"],"sourcesContent":["export * from './types'\nexport * from './arrays'\nexport * from './functions'\nexport * from './objects'\nexport * from './strings'\nexport * from './dates'\nexport * from './files'\nexport * from './cookies'\nexport * from './console'\nexport * from './colors'\n","export const getKeys = Object.keys as <T extends object>(obj: T) => Array<keyof T>\n\nexport type RecursivePartial<T> = { [P in keyof T]?: RecursivePartial<T[P]> }\n\nexport type RecursiveRecord = {\n [key: string]: string | number | boolean | RecursiveRecord | Array<RecursiveRecord>\n}\n\nexport function forcedType<T>(obj: unknown): T {\n return obj as unknown as T\n}\n","export function notNone<T>(value: T | null | undefined): value is T {\n return value !== null && value !== undefined\n}\n\nfunction combinationsOfSize<T>(items: T[], size: number): T[][] {\n if (size === 0) {\n return [[]]\n }\n if (size > items.length) {\n return []\n }\n const [first, ...rest] = items\n const withFirst = combinationsOfSize(rest, size - 1).map((combination) => [first, ...combination])\n const withoutFirst = combinationsOfSize(rest, size)\n return [...withFirst, ...withoutFirst]\n}\n\nexport function allCombinations<T>(options: T[]): T[][] {\n const result: T[][] = []\n for (let size = 1; size <= options.length; size++) {\n result.push(...combinationsOfSize(options, size))\n }\n return result\n}\n","export function withAttributes<Fn extends (...args: never[]) => unknown, Attrs extends Record<string, unknown>>(\n fn: Fn,\n attributes: Attrs\n): Fn & Attrs {\n for (const key of Object.keys(attributes)) {\n // Object.defineProperty (unlike a plain `fn[key] = value` assignment) always creates/\n // overwrites an own property, even when key is \"__proto__\" - a plain assignment would instead\n // be intercepted by Object.prototype's special __proto__ accessor and reassign fn's own\n // prototype instead of setting a property on it.\n Object.defineProperty(fn, key, {\n value: attributes[key],\n writable: true,\n configurable: true,\n enumerable: true,\n })\n }\n return fn as Fn & Attrs\n}\n\nexport function makeCallable<T, R>(originalCallable: (arg: T) => R) {\n return (data: T) => () => originalCallable(data)\n}\n\nexport function getLazyValue<T>(input: T | (() => T)): T {\n if (typeof input === 'function') {\n return (input as () => T)()\n }\n return input\n}\n\nexport async function getLazyValueAsync<T>(input: T | (() => Promise<T>) | (() => T)): Promise<T> {\n if (typeof input === 'function') {\n const result = (input as () => Promise<T>)()\n // Stryker disable next-line ConditionalExpression,BlockStatement: equivalent mutant. An async\n // function auto-adopts a returned thenable through the same resolution algorithm `await`\n // uses, so `return result` here resolves to the same value as `return await result` - the\n // only difference is an extra microtask tick, which isn't part of this function's contract.\n if (result instanceof Promise) {\n return await result\n }\n return result as unknown as T\n }\n return input\n}\n\nexport function suppress<T, ERT>(\n exceptions: Array<new (message?: string) => Error>,\n fn: () => T,\n onError?: (error: unknown) => ERT\n): T | ERT | undefined {\n try {\n return fn()\n } catch (error) {\n if (exceptions.some((exception) => error instanceof exception)) {\n return onError ? onError(error) : undefined\n }\n throw error\n }\n}\n\nexport function preventDefault<E extends Event, R>(callable: (event: E) => R): (event: E) => Promise<Awaited<R>> {\n return async function (event: E): Promise<Awaited<R>> {\n event.preventDefault()\n return await callable(event)\n }\n}\n\nexport function isPathMatched(pathname: string, pattern: RegExp, exemptPatterns: RegExp[] = []): boolean {\n if (exemptPatterns.some((exempt) => exempt.test(pathname))) {\n return false\n }\n return pattern.test(pathname)\n}\n\nexport function raises(error: Error): (...args: unknown[]) => never {\n return () => {\n throw error\n }\n}\n\nexport function cloned<Fn extends (...args: never[]) => unknown>(fn: Fn): Fn {\n return ((...args: Parameters<Fn>) => fn(...args)) as Fn\n}\n\nexport function enabledIf<R>(condition: boolean | (() => boolean), options: { ifNotEnabledReturnValue: R }) {\n const enabled = typeof condition === 'function' ? condition() : condition\n\n return function <Fn extends (...args: never[]) => R>(fn: Fn): Fn {\n if (!enabled) {\n return cloned((() => options.ifNotEnabledReturnValue) as Fn)\n }\n return cloned(fn)\n }\n}\n\nexport function transformExceptions<E extends Error>(\n exceptionTypes: Array<new (...args: never[]) => E>,\n transform: (error: E) => Error,\n options: { keepOriginal?: boolean } = {}\n) {\n const { keepOriginal = true } = options\n\n return function <Fn extends (...args: never[]) => unknown>(fn: Fn): Fn {\n return ((...args: Parameters<Fn>) => {\n try {\n return fn(...args)\n } catch (error) {\n if (!exceptionTypes.some((ExceptionType) => error instanceof ExceptionType)) {\n throw error\n }\n const newError = transform(error as E)\n if (keepOriginal) {\n newError.cause = error\n }\n throw newError\n }\n }) as Fn\n }\n}\n","export function checkRequiredKeys<T extends Record<string, unknown>, C extends Record<string, Array<keyof T>>>(\n obj: T,\n conditions: C\n): keyof C {\n const matchingConditions = Object.entries(conditions).filter(\n ([, keys]) =>\n keys.every((key) => obj[key] !== undefined) &&\n Object.keys(obj).every((key) => keys.includes(key as keyof T) || obj[key] === undefined)\n )\n\n if (matchingConditions.length !== 1) {\n throw new Error(`Object keys do not match exactly one required condition. ${JSON.stringify(conditions)}`)\n }\n\n return matchingConditions[0][0] as keyof C\n}\n\nexport function requireExclusiveKeys<T extends Record<string, unknown>, C extends Record<string, Array<keyof T>>>(\n conditions: C,\n options: { allowEmpty?: boolean } = {}\n) {\n const conditionEntries = Object.entries(conditions) as Array<[string, Array<keyof T>]>\n if (conditionEntries.length === 0) {\n throw new Error('At least one condition must be provided.')\n }\n const { allowEmpty = false } = options\n const governedKeys = new Set(conditionEntries.flatMap(([, keys]) => keys))\n\n return function <Fn extends (arg: T) => unknown>(fn: Fn): Fn {\n return ((arg: T) => {\n // Only keys that are actually governed by a condition are considered - unlike\n // checkRequiredKeys, any other key on `arg` is fully unconstrained and ignored here\n // regardless of its value, since this is meant to validate one options object that may\n // legitimately carry other, unrelated fields alongside the mutually-exclusive ones.\n const provided = new Set(\n Object.keys(arg).filter((key) => governedKeys.has(key as keyof T) && arg[key] !== undefined)\n )\n\n if (allowEmpty && provided.size === 0) {\n return fn(arg)\n }\n\n const matches = conditionEntries.filter(\n ([, keys]) => keys.length === provided.size && keys.every((key) => provided.has(key as string))\n )\n if (matches.length !== 1) {\n throw new Error(`Object keys do not match exactly one required condition. ${JSON.stringify(conditions)}`)\n }\n return fn(arg)\n }) as Fn\n }\n}\n\nexport function setKeyValueToObjectIfValue(key: string, value: unknown, object: Record<string, unknown>) {\n if (value) {\n // Object.defineProperty (unlike a plain `object[key] = value` assignment) always creates/\n // overwrites an own property, even when key is \"__proto__\" - a plain assignment would instead\n // be intercepted by Object.prototype's special __proto__ accessor and reassign this object's\n // prototype instead of setting a property on it.\n Object.defineProperty(object, key, { value, writable: true, configurable: true, enumerable: true })\n }\n}\n","export function slugify(value: string, allowUnicode: boolean = false): string {\n if (allowUnicode) {\n value = value.normalize('NFKC').replace(/[^\\p{L}\\p{N}_\\s-]/gu, '')\n } else {\n value = value.normalize('NFKD')\n // eslint-disable-next-line no-control-regex\n value = value.replace(/[^\\x00-\\x7F]/g, '')\n // Stryker disable next-line Regex: equivalent mutant. The `+` quantifier is redundant with\n // the `[-\\s]+` -> '-' collapse below, which flattens a run of replaced newlines to a single\n // dash regardless of how many spaces this leaves - kept for clarity/intent, not correctness.\n value = value.replace(/[\\r\\n]+/g, ' ')\n // Stryker disable next-line MethodExpression: equivalent mutant. Redundant with the collapse\n // + trim below, which strips any whitespace this would have removed once it's converted to\n // leading/trailing dashes - kept for clarity/intent, not correctness.\n value = value.trim()\n value = value.replace(/[^\\w\\s-]/g, '')\n }\n\n value = value.toLowerCase()\n\n return value.replace(/[-\\s]+/g, '-').replace(/^[-_]+|[-_]+$/g, '')\n}\n","import { format } from 'date-fns'\n\nexport function formatDate(date: Date, pattern: string): string {\n return format(date, pattern)\n}\n","import { formatDate } from './_format'\n\nexport const LONG_DATE_FORMAT = \"EEEE, MMMM dd, yyyy 'at' hh:mm a\"\nexport const SHORT_DATE_FORMAT = 'dd.MM.yyyy'\nexport const SHORT_DATETIME_FORMAT = 'dd.MM.yyyy HH:mm a'\n\nexport function formattedDate(pattern: string, date: Date = new Date()): string {\n return formatDate(date, pattern)\n}\n\nexport function longFormattedDate(date: Date = new Date()): string {\n return formattedDate(LONG_DATE_FORMAT, date)\n}\n\nexport function shortFormattedDate(date: Date = new Date()): string {\n return formattedDate(SHORT_DATE_FORMAT, date)\n}\n\nexport function shortFormattedDateTime(date: Date = new Date()): string {\n return formattedDate(SHORT_DATETIME_FORMAT, date)\n}\n\nexport function optionalDate(date?: string): Date | undefined {\n return date ? new Date(date) : undefined\n}\n","type MimeType = 'image/png' | 'image/jpeg' | 'image/webp'\n\nexport function guessImageMimeType(filename: string): MimeType {\n const withoutQueryOrHash = filename.split(/[?#]/)[0]\n // Stryker disable next-line OptionalChaining: equivalent mutant. String#split always returns at\n // least one element for any input (including ''), so .pop() here can never actually be\n // undefined - the `?.` exists only to satisfy Array#pop()'s TypeScript signature.\n const extension = withoutQueryOrHash.split('.').pop()?.toLowerCase()\n switch (extension) {\n // Stryker disable next-line StringLiteral: equivalent mutant. This case and `default` below\n // both return 'image/png', so no input can distinguish which of the two branches ran it.\n case 'png':\n return 'image/png'\n case 'jfif':\n case 'jpg':\n case 'jpeg':\n return 'image/jpeg'\n case 'webp':\n return 'image/webp'\n default:\n return 'image/png'\n }\n}\n\nexport function isImageMimeType(mimeType: string): mimeType is MimeType {\n return mimeType === 'image/png' || mimeType === 'image/jpeg' || mimeType === 'image/webp'\n}\n\nexport function escapeName(name: string): string {\n return name.replace(/[^a-zA-Z0-9-_.]/g, '_')\n}\n\nexport function safeFileName(filename: string, maxLength: number = 255): string {\n if (filename.length <= maxLength) return filename\n\n const dotIndex = filename.lastIndexOf('.')\n const hasExtension = dotIndex > 0\n const extension = escapeName(hasExtension ? filename.slice(dotIndex) : '')\n // Stryker disable next-line MethodExpression: equivalent mutant. This branch only runs when\n // filename.length > maxLength, and escapeName preserves length, so\n // maxLength - extension.length < maxLength - (filename.length - dotIndex) = dotIndex always\n // holds. The slice below therefore never reads past index dotIndex, which is exactly where\n // filename and filename.slice(0, dotIndex) still agree - dropping the slice can't change it.\n const name = escapeName(hasExtension ? filename.slice(0, dotIndex) : filename)\n\n return name.slice(0, Math.max(0, maxLength - extension.length)) + extension\n}\n\nexport async function downloadAndFormatImage(\n src: string,\n name: string = 'image.png',\n mimeType: MimeType = guessImageMimeType(name),\n quality: number = 1\n): Promise<void> {\n name = safeFileName(name)\n try {\n const img = new Image()\n img.crossOrigin = 'anonymous'\n\n await new Promise((resolve, reject) => {\n img.onload = resolve\n img.onerror = reject\n img.src = src\n })\n\n const canvas = document.createElement('canvas')\n canvas.width = img.width\n canvas.height = img.height\n const ctx = canvas.getContext('2d')\n\n if (!ctx) {\n throw new Error('Could not get canvas context')\n }\n\n ctx.drawImage(img, 0, 0)\n\n const blob = await new Promise<Blob | null>((resolve) => {\n canvas.toBlob(resolve, mimeType, quality)\n })\n\n if (!blob) {\n throw new Error('Could not generate blob')\n }\n\n const link = document.createElement('a')\n const downloadUrl = URL.createObjectURL(blob)\n try {\n link.href = downloadUrl\n link.download = name\n document.body.appendChild(link)\n link.click()\n } finally {\n document.body.removeChild(link)\n URL.revokeObjectURL(downloadUrl)\n }\n } catch (error) {\n console.error('Failed to download image:', error)\n }\n}\n\nexport async function fileToBase64Native(file: File): Promise<string> {\n const result = await new Promise<string | ArrayBuffer | null>((resolve, reject) => {\n const reader = new FileReader()\n reader.readAsDataURL(file)\n reader.onload = () => resolve(reader.result)\n reader.onerror = (error) => reject(error)\n })\n\n if (typeof result === 'string') {\n return result\n } else {\n throw new Error('Failed to read file as Data URL')\n }\n}\n\nexport async function fileToBase64(file: File, quality: number = 1): Promise<string> {\n if (isImageMimeType(file.type)) {\n const img = new Image()\n const url = URL.createObjectURL(file)\n try {\n await new Promise<void>((resolve, reject) => {\n img.onload = () => resolve()\n img.onerror = () => reject(new Error('Failed to load image for metadata removal'))\n img.src = url\n })\n\n const canvas = document.createElement('canvas')\n canvas.width = img.width\n canvas.height = img.height\n\n const ctx = canvas.getContext('2d')\n if (!ctx) {\n throw new Error('Failed to get canvas context')\n }\n ctx.drawImage(img, 0, 0)\n\n const cleanDataUrl = canvas.toDataURL(file.type, quality)\n if (cleanDataUrl === 'data:,') {\n return await fileToBase64Native(file)\n }\n\n return cleanDataUrl\n } finally {\n URL.revokeObjectURL(url)\n }\n } else {\n return await fileToBase64Native(file)\n }\n}\n","export function getCookie(name: string): string | undefined {\n for (const pair of document.cookie.split('; ')) {\n const separatorIndex = pair.indexOf('=')\n if (separatorIndex === -1) {\n continue\n }\n if (pair.slice(0, separatorIndex) === name) {\n return pair.slice(separatorIndex + 1)\n }\n }\n return undefined\n}\n\nexport interface SetCookieOptions {\n /** Days until the cookie expires. Omit for a session cookie (cleared when the browser closes). */\n days?: number\n path?: string\n}\n\nexport function setCookie(name: string, value: string, options: SetCookieOptions = {}): void {\n const { days, path = '/' } = options\n const expires = days === undefined ? '' : `; expires=${new Date(Date.now() + days * 86_400_000).toUTCString()}`\n document.cookie = `${name}=${value}${expires}; path=${path}`\n}\n\nexport function removeCookie(name: string, path: string = '/'): void {\n document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=${path}`\n}\n","type ConsoleMethod = (...args: unknown[]) => void\ntype WindowLike = Window & typeof globalThis\n\nconst patchedWindows = new WeakMap<WindowLike, Set<string>>()\n\nexport function createConsoleDebugSwitch(targetWindow: WindowLike, options: { namespace: string }): void {\n if (!targetWindow) {\n return\n }\n\n const { namespace } = options\n\n let enabledNamespaces = patchedWindows.get(targetWindow)\n if (!enabledNamespaces) {\n enabledNamespaces = new Set<string>()\n patchedWindows.set(targetWindow, enabledNamespaces)\n\n const original = {\n log: targetWindow.console.log.bind(targetWindow.console),\n info: targetWindow.console.info.bind(targetWindow.console),\n warn: targetWindow.console.warn.bind(targetWindow.console),\n error: targetWindow.console.error.bind(targetWindow.console),\n }\n\n const conditional =\n (method: ConsoleMethod): ConsoleMethod =>\n (...args) => {\n if (enabledNamespaces!.size > 0) {\n method(...args)\n }\n }\n\n targetWindow.console.log = conditional(original.log)\n targetWindow.console.info = conditional(original.info)\n targetWindow.console.warn = conditional(original.warn)\n targetWindow.console.error = conditional(original.error)\n }\n\n type Namespace = { debug: (enabled: boolean) => void }\n const globals = targetWindow as unknown as Record<string, Namespace | undefined>\n const existing = Object.prototype.hasOwnProperty.call(globals, namespace)\n ? (Object.getOwnPropertyDescriptor(globals, namespace)?.value as Namespace | undefined)\n : undefined\n const target = existing ?? ({} as Namespace)\n target.debug = (flag: boolean) => {\n if (flag) {\n enabledNamespaces!.add(namespace)\n } else {\n enabledNamespaces!.delete(namespace)\n }\n }\n // Object.defineProperty (unlike a plain `globals[namespace] = target` assignment) always\n // creates/overwrites an own property, even when namespace is a name like \"__proto__\" that\n // would otherwise be intercepted by Object.prototype's special __proto__ accessor and\n // pollute the shared prototype instead of setting a property on this specific object.\n Object.defineProperty(globals, namespace, { value: target, writable: true, configurable: true, enumerable: true })\n}\n","export type TailwindShade = 50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 950\n\nexport type TailwindColorScale = Record<TailwindShade, string>\n\ninterface Rgb {\n r: number\n g: number\n b: number\n}\n\nconst HEX_PATTERN = /^#?([0-9a-f]{3}|[0-9a-f]{6})$/i\n\nfunction hexToRgb(hex: string): Rgb {\n const match = HEX_PATTERN.exec(hex.trim())\n if (!match) {\n throw new Error(`Invalid hex color: \"${hex}\"`)\n }\n\n const digits = match[1]\n const normalized =\n digits.length === 3\n ? digits\n .split('')\n .map((char) => char + char)\n .join('')\n : digits\n\n return {\n r: parseInt(normalized.slice(0, 2), 16),\n g: parseInt(normalized.slice(2, 4), 16),\n b: parseInt(normalized.slice(4, 6), 16),\n }\n}\n\nfunction rgbToHex({ r, g, b }: Rgb): string {\n return `#${[r, g, b].map((channel) => Math.round(channel).toString(16).padStart(2, '0')).join('')}`\n}\n\nfunction mixRgb(base: Rgb, target: Rgb, weight: number): Rgb {\n return {\n r: base.r + (target.r - base.r) * weight,\n g: base.g + (target.g - base.g) * weight,\n b: base.b + (target.b - base.b) * weight,\n }\n}\n\nconst WHITE: Rgb = { r: 255, g: 255, b: 255 }\nconst BLACK: Rgb = { r: 0, g: 0, b: 0 }\n\n// Weight of white/black mixed into the base color at each shade, tuned so 500 is the input\n// color unchanged and the rest approximate the spread of Tailwind's own default palettes.\nconst TINT_WEIGHTS: Record<50 | 100 | 200 | 300 | 400, number> = { 50: 0.95, 100: 0.9, 200: 0.75, 300: 0.6, 400: 0.3 }\nconst SHADE_WEIGHTS: Record<600 | 700 | 800 | 900 | 950, number> = {\n 600: 0.15,\n 700: 0.3,\n 800: 0.45,\n 900: 0.6,\n 950: 0.8,\n}\n\n/**\n * Generates a Tailwind-style 50-950 color scale from a single base hex color, treated as the 500 shade.\n */\nexport function generateTailwindColorScale(baseColor: string): TailwindColorScale {\n const base = hexToRgb(baseColor)\n\n return {\n 50: rgbToHex(mixRgb(base, WHITE, TINT_WEIGHTS[50])),\n 100: rgbToHex(mixRgb(base, WHITE, TINT_WEIGHTS[100])),\n 200: rgbToHex(mixRgb(base, WHITE, TINT_WEIGHTS[200])),\n 300: rgbToHex(mixRgb(base, WHITE, TINT_WEIGHTS[300])),\n 400: rgbToHex(mixRgb(base, WHITE, TINT_WEIGHTS[400])),\n 500: rgbToHex(base),\n 600: rgbToHex(mixRgb(base, BLACK, SHADE_WEIGHTS[600])),\n 700: rgbToHex(mixRgb(base, BLACK, SHADE_WEIGHTS[700])),\n 800: rgbToHex(mixRgb(base, BLACK, SHADE_WEIGHTS[800])),\n 900: rgbToHex(mixRgb(base, BLACK, SHADE_WEIGHTS[900])),\n 950: rgbToHex(mixRgb(base, BLACK, SHADE_WEIGHTS[950])),\n }\n}\n\n/**\n * Like {@link generateTailwindColorScale}, but prefixes each shade with `name` (e.g. `primary500`)\n * so multiple scales can be spread into one flat palette object.\n */\nexport function generateNamedTailwindColorScale<T extends string>(\n baseColor: string,\n name: T\n): Record<`${T}${TailwindShade}`, string> {\n const scale = generateTailwindColorScale(baseColor)\n\n return Object.fromEntries(Object.entries(scale).map(([shade, hex]) => [`${name}${shade}`, hex])) as Record<\n `${T}${TailwindShade}`,\n string\n >\n}\n\nfunction rgbToHsl({ r, g, b }: Rgb): { h: number; s: number; l: number } {\n const rN = r / 255\n const gN = g / 255\n const bN = b / 255\n\n const max = Math.max(rN, gN, bN)\n const min = Math.min(rN, gN, bN)\n const l = (max + min) / 2\n\n if (max === min) {\n return { h: 0, s: 0, l: l * 100 }\n }\n\n const delta = max - min\n // Stryker disable next-line EqualityOperator: equivalent mutant. l === 0.5 iff max + min === 1,\n // in which case 2 - max - min === max + min too, so both branches compute the same value and\n // no test can ever distinguish `>` from `>=` here.\n const s = l > 0.5 ? delta / (2 - max - min) : delta / (max + min)\n\n let h: number\n if (max === rN) {\n h = ((gN - bN) / delta + (gN < bN ? 6 : 0)) * 60\n } else if (max === gN) {\n h = ((bN - rN) / delta + 2) * 60\n } else {\n h = ((rN - gN) / delta + 4) * 60\n }\n\n return { h, s: s * 100, l: l * 100 }\n}\n\n/**\n * Formats a hex color as the \"H S% L%\" triplet shadcn/Tailwind CSS variable themes expect,\n * e.g. for `--primary: 240 5.9% 10%;` consumed as `hsl(var(--primary))`.\n */\nexport function hexToHslTriplet(hex: string, precision: number = 1): string {\n const { h, s, l } = rgbToHsl(hexToRgb(hex))\n const round = (value: number) => Number(value.toFixed(precision))\n\n return `${round(h)} ${round(s)}% ${round(l)}%`\n}\n"],"mappings":"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","names":[]}
package/dist/index.js CHANGED
@@ -164,7 +164,11 @@ function slugify(value, allowUnicode = false) {
164
164
  if (allowUnicode) {
165
165
  value = value.normalize("NFKC").replace(/[^\p{L}\p{N}_\s-]/gu, "");
166
166
  } else {
167
- value = value.normalize("NFKD").replace(/[^\x00-\x7F]/g, "").replace(/[\r\n]+/g, " ").trim().replace(/[^\w\s-]/g, "");
167
+ value = value.normalize("NFKD");
168
+ value = value.replace(/[^\x00-\x7F]/g, "");
169
+ value = value.replace(/[\r\n]+/g, " ");
170
+ value = value.trim();
171
+ value = value.replace(/[^\w\s-]/g, "");
168
172
  }
169
173
  value = value.toLowerCase();
170
174
  return value.replace(/[-\s]+/g, "-").replace(/^[-_]+|[-_]+$/g, "");
@@ -201,6 +205,8 @@ function guessImageMimeType(filename) {
201
205
  const withoutQueryOrHash = filename.split(/[?#]/)[0];
202
206
  const extension = withoutQueryOrHash.split(".").pop()?.toLowerCase();
203
207
  switch (extension) {
208
+ // Stryker disable next-line StringLiteral: equivalent mutant. This case and `default` below
209
+ // both return 'image/png', so no input can distinguish which of the two branches ran it.
204
210
  case "png":
205
211
  return "image/png";
206
212
  case "jfif":