@entry-ui/utilities 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/add-event-listener-once/index.d.ts +64 -0
- package/dist/add-event-listener-once/index.js +2 -0
- package/dist/add-event-listener-once/index.js.map +1 -0
- package/dist/chunk-AYHMR4G2.js +2 -0
- package/dist/chunk-AYHMR4G2.js.map +1 -0
- package/dist/chunk-GLPQ4KOF.js +2 -0
- package/dist/chunk-GLPQ4KOF.js.map +1 -0
- package/dist/chunk-JW4DI4Q2.js +2 -0
- package/dist/chunk-JW4DI4Q2.js.map +1 -0
- package/dist/{chunk-JLS3437A.js → chunk-NBN5PUZ6.js} +2 -2
- package/dist/chunk-NBN5PUZ6.js.map +1 -0
- package/dist/chunk-OUZ54COH.js +2 -0
- package/dist/chunk-OUZ54COH.js.map +1 -0
- package/dist/chunk-TAV72HQS.js +2 -0
- package/dist/chunk-TAV72HQS.js.map +1 -0
- package/dist/chunk-YRBGPPKC.js +2 -0
- package/dist/chunk-YRBGPPKC.js.map +1 -0
- package/dist/clamp/index.d.ts +54 -0
- package/dist/clamp/index.js +2 -0
- package/dist/clamp/index.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +1 -1
- package/dist/is-valid-number/index.d.ts +23 -0
- package/dist/is-valid-number/index.js +2 -0
- package/dist/is-valid-number/index.js.map +1 -0
- package/dist/merge-styles/index.d.ts +6 -2
- package/dist/merge-styles/index.js +1 -1
- package/dist/visually-hidden-input-style/index.d.ts +31 -0
- package/dist/visually-hidden-input-style/index.js +2 -0
- package/dist/visually-hidden-input-style/index.js.map +1 -0
- package/dist/visually-hidden-style/index.d.ts +34 -0
- package/dist/visually-hidden-style/index.js +2 -0
- package/dist/visually-hidden-style/index.js.map +1 -0
- package/dist/wait/index.d.ts +19 -0
- package/dist/wait/index.js +2 -0
- package/dist/wait/index.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-JLS3437A.js.map +0 -1
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A comprehensive union of all standard event maps available in the browser environment.
|
|
3
|
+
*
|
|
4
|
+
* This type aggregates event definitions from `HTMLElement`, `Document`, and `Window`
|
|
5
|
+
* into a single unified interface. It is used to provide exhaustive type safety and
|
|
6
|
+
* accurate IntelliSense during event registration, ensuring that the event object
|
|
7
|
+
* signature is correctly inferred based on the target and event type.
|
|
8
|
+
*/
|
|
9
|
+
type AllEventMaps = HTMLElementEventMap & DocumentEventMap & WindowEventMap;
|
|
10
|
+
/**
|
|
11
|
+
* Configuration object for the `addEventListenerOnce` utility.
|
|
12
|
+
*
|
|
13
|
+
* This interface defines the necessary properties to register a one-time event listener.
|
|
14
|
+
* It uses a generic type `K` constrained to `AllEventMaps` to ensure that the event
|
|
15
|
+
* type and its corresponding listener remain synchronized and type-safe across
|
|
16
|
+
* different DOM targets.
|
|
17
|
+
*/
|
|
18
|
+
interface AddEventListenerOnceParams<K extends keyof AllEventMaps> {
|
|
19
|
+
/**
|
|
20
|
+
* The DOM node or global object to which the event listener will be attached.
|
|
21
|
+
* Supports `HTMLElement`, `Document`, and `Window` targets.
|
|
22
|
+
*/
|
|
23
|
+
target: HTMLElement | Document | Window;
|
|
24
|
+
/**
|
|
25
|
+
* A case-sensitive string representing the event type to monitor.
|
|
26
|
+
* The available types are dynamically inferred based on the `target` category.
|
|
27
|
+
*/
|
|
28
|
+
type: K;
|
|
29
|
+
/**
|
|
30
|
+
* The callback function executed when the event is dispatched.
|
|
31
|
+
* It receives a strictly typed event object corresponding to the provided event `type`.
|
|
32
|
+
*/
|
|
33
|
+
listener: (this: HTMLElement | Document | Window, ev: AllEventMaps[K]) => any;
|
|
34
|
+
/**
|
|
35
|
+
* An optional configuration object that specifies characteristics about the event listener.
|
|
36
|
+
* While most native options are supported, the `once` property is internally enforced
|
|
37
|
+
* as `true` and cannot be overridden to ensure the utility's one-time execution behavior.
|
|
38
|
+
*/
|
|
39
|
+
options?: Omit<AddEventListenerOptions, 'once'>;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Registers an event listener that is automatically removed after its first invocation.
|
|
44
|
+
*
|
|
45
|
+
* This utility wraps the native `addEventListener` method and enforces the `once: true`
|
|
46
|
+
* option. It provides a clean way to handle one-time events while returning a manual
|
|
47
|
+
* cleanup function, which can be used to remove the listener before it even fires.
|
|
48
|
+
* It is fully type-safe, supporting event maps for `HTMLElement`, `Document`, and `Window`.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```ts
|
|
52
|
+
* const cleanup = addEventListenerOnce({
|
|
53
|
+
* target: window,
|
|
54
|
+
* type: "scroll",
|
|
55
|
+
* listener: (event) => console.log("First scroll detected!"", event),
|
|
56
|
+
* options: { passive: true },
|
|
57
|
+
* });
|
|
58
|
+
*
|
|
59
|
+
* cleanup(); // If the listener is no longer needed before the first scroll.
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
declare const addEventListenerOnce: <K extends keyof AllEventMaps>(params: AddEventListenerOnceParams<K>) => () => void;
|
|
63
|
+
|
|
64
|
+
export { type AddEventListenerOnceParams, type AllEventMaps, addEventListenerOnce };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/visually-hidden-input-style/visually-hidden-input-style.ts"],"names":["visuallyHiddenInputStyle"],"mappings":"AAoBO,IAAMA,CAAAA,CAA2B,OAAO,MAAA,CAAO,CACpD,SAAU,YAAA,CACV,QAAA,CAAU,QAAA,CACV,UAAA,CAAY,QAAA,CACZ,MAAA,CAAQ,EACR,OAAA,CAAS,CAAA,CACT,MAAO,CAAA,CACP,MAAA,CAAQ,EACR,MAAA,CAAQ,EAAA,CACR,QAAA,CAAU,UACZ,CAAC","file":"chunk-AYHMR4G2.js","sourcesContent":["import type * as CSS from 'csstype';\n\n/**\n * Visually hides an input element while keeping it functional and accessible.\n *\n * Commonly used for styling native checkboxes, radio buttons, or file inputs\n * by hiding the default browser element and replacing it with a custom-styled\n * UI, while ensuring the underlying input remains focusable and reachable\n * by assistive technologies.\n *\n * @example\n * ```tsx\n * const CustomCheckbox = () => (\n * \t<>\n * \t\t<input type=\"checkbox\" id=\"terms\" style={visuallyHiddenInputStyle} />\n * \t\t<label htmlFor=\"terms\">I agree to the terms</label>\n * \t</>\n * );\n * ```\n */\nexport const visuallyHiddenInputStyle = Object.freeze({\n clipPath: 'inset(50%)',\n overflow: 'hidden',\n whiteSpace: 'nowrap',\n border: 0,\n padding: 0,\n width: 1,\n height: 1,\n margin: -1,\n position: 'absolute',\n}) satisfies CSS.Properties<string | number>;\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/add-event-listener-once/add-event-listener-once.ts"],"names":["addEventListenerOnce","params","target","type","listener","options","eventOptions"],"mappings":"AAsBO,IAAMA,EAAsDC,CAAAA,EAA0C,CAC3G,GAAM,CAAE,OAAAC,CAAAA,CAAQ,IAAA,CAAAC,CAAAA,CAAM,QAAA,CAAAC,EAAU,OAAA,CAAAC,CAAQ,CAAA,CAAIJ,CAAAA,CAEtCK,EAAe,CAAE,GAAGD,CAAAA,CAAS,IAAA,CAAM,IAAK,CAAA,CAE9C,OAAAH,CAAAA,CAAO,gBAAA,CAAiBC,EAAMC,CAAAA,CAAgDE,CAAY,CAAA,CAE1E,IAAM,CACpBJ,CAAAA,CAAO,mBAAA,CAAoBC,EAAMC,CAAAA,CAAgDE,CAAY,EAC/F,CAGF","file":"chunk-GLPQ4KOF.js","sourcesContent":["import type { AllEventMaps, AddEventListenerOnceParams } from './add-event-listener-once.types';\n\n/**\n * Registers an event listener that is automatically removed after its first invocation.\n *\n * This utility wraps the native `addEventListener` method and enforces the `once: true`\n * option. It provides a clean way to handle one-time events while returning a manual\n * cleanup function, which can be used to remove the listener before it even fires.\n * It is fully type-safe, supporting event maps for `HTMLElement`, `Document`, and `Window`.\n *\n * @example\n * ```ts\n * const cleanup = addEventListenerOnce({\n * \ttarget: window,\n * \ttype: \"scroll\",\n * \tlistener: (event) => console.log(\"First scroll detected!\"\", event),\n * \toptions: { passive: true },\n * });\n *\n * cleanup(); // If the listener is no longer needed before the first scroll.\n * ```\n */\nexport const addEventListenerOnce = <K extends keyof AllEventMaps>(params: AddEventListenerOnceParams<K>) => {\n const { target, type, listener, options } = params;\n\n const eventOptions = { ...options, once: true };\n\n target.addEventListener(type, listener as EventListenerOrEventListenerObject, eventOptions);\n\n const cleanup = () => {\n target.removeEventListener(type, listener as EventListenerOrEventListenerObject, eventOptions);\n };\n\n return cleanup;\n};\n"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import {a as a$1}from'./chunk-O4WYO5SA.js';import {a}from'./chunk-TAV72HQS.js';var s=r=>{let{value:m,min:e,max:i}=r;return a(m)||a$1({prefix:"[Entry UI Utilities]",messages:["Invalid 'value' parameter in 'clamp' utility.",`Expected a finite number, but received: ${m}`]}),a(e)||a$1({prefix:"[Entry UI Utilities]",messages:["Invalid 'min' parameter in 'clamp' utility.",`Expected a finite number, but received: ${e}`]}),a(i)||a$1({prefix:"[Entry UI Utilities]",messages:["Invalid 'max' parameter in 'clamp' utility.",`Expected a finite number, but received: ${i}`]}),e>i&&a$1({prefix:"[Entry UI Utilities]",messages:["Invalid range for 'clamp' utility.",`The 'min' parameter (${e}) must be less than or equal to the 'max' parameter (${i}).`]}),Math.min(i,Math.max(e,m))};export{s as a};//# sourceMappingURL=chunk-JW4DI4Q2.js.map
|
|
2
|
+
//# sourceMappingURL=chunk-JW4DI4Q2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/clamp/clamp.ts"],"names":["clamp","params","value","min","max","isValidNumber","fail"],"mappings":"+EA2BO,IAAMA,EAASC,CAAAA,EAAwB,CAC5C,GAAM,CAAE,KAAA,CAAAC,EAAO,GAAA,CAAAC,CAAAA,CAAK,GAAA,CAAAC,CAAI,EAAIH,CAAAA,CAE5B,OAAKI,EAAcH,CAAK,CAAA,EACtBI,IAAK,CACH,MAAA,CAAQ,sBAAA,CACR,QAAA,CAAU,CAAC,+CAAA,CAAiD,CAAA,wCAAA,EAA2CJ,CAAK,CAAA,CAAE,CAChH,CAAC,CAAA,CAGEG,CAAAA,CAAcF,CAAG,CAAA,EACpBG,GAAAA,CAAK,CACH,MAAA,CAAQ,sBAAA,CACR,SAAU,CAAC,6CAAA,CAA+C,2CAA2CH,CAAG,CAAA,CAAE,CAC5G,CAAC,EAGEE,CAAAA,CAAcD,CAAG,GACpBE,GAAAA,CAAK,CACH,OAAQ,sBAAA,CACR,QAAA,CAAU,CAAC,6CAAA,CAA+C,CAAA,wCAAA,EAA2CF,CAAG,CAAA,CAAE,CAC5G,CAAC,CAAA,CAGCD,CAAAA,CAAMC,GACRE,GAAAA,CAAK,CACH,MAAA,CAAQ,sBAAA,CACR,SAAU,CACR,oCAAA,CACA,wBAAwBH,CAAG,CAAA,qDAAA,EAAwDC,CAAG,CAAA,EAAA,CACxF,CACF,CAAC,CAAA,CAGI,IAAA,CAAK,IAAIA,CAAAA,CAAK,IAAA,CAAK,IAAID,CAAAA,CAAKD,CAAK,CAAC,CAC3C","file":"chunk-JW4DI4Q2.js","sourcesContent":["import type { ClampParams } from './clamp.types';\nimport { isValidNumber } from '../is-valid-number';\nimport { fail } from '../fail';\n\n/**\n * Clamps a number between a minimum and maximum value.\n *\n * This utility ensures that the returned value is restricted to a specified range.\n * If the input value is smaller than the minimum boundary, the minimum value is\n * returned. If it exceeds the maximum boundary, the maximum value is returned.\n *\n * This function will throw an error if:\n * - Any of the input parameters are not finite numbers.\n * - The `min` value is greater than the `max` value.\n *\n * @example\n * ```ts\n * clamp({ value: 150, min: 0, max: 100 });\n * // Returns: 100\n *\n * clamp({ value: -20, min: 0, max: 100 });\n * Returns: 0\n *\n * clamp({ value: 50, min: 0, max: 100 });\n * // Returns: 50\n * ```\n */\nexport const clamp = (params: ClampParams) => {\n const { value, min, max } = params;\n\n if (!isValidNumber(value)) {\n fail({\n prefix: '[Entry UI Utilities]',\n messages: [`Invalid 'value' parameter in 'clamp' utility.`, `Expected a finite number, but received: ${value}`],\n });\n }\n\n if (!isValidNumber(min)) {\n fail({\n prefix: '[Entry UI Utilities]',\n messages: [`Invalid 'min' parameter in 'clamp' utility.`, `Expected a finite number, but received: ${min}`],\n });\n }\n\n if (!isValidNumber(max)) {\n fail({\n prefix: '[Entry UI Utilities]',\n messages: [`Invalid 'max' parameter in 'clamp' utility.`, `Expected a finite number, but received: ${max}`],\n });\n }\n\n if (min > max) {\n fail({\n prefix: '[Entry UI Utilities]',\n messages: [\n `Invalid range for 'clamp' utility.`,\n `The 'min' parameter (${min}) must be less than or equal to the 'max' parameter (${max}).`,\n ],\n });\n }\n\n return Math.min(max, Math.max(min, value));\n};\n"]}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var u=f=>f.length===0?{}:f.reduce((l,n)=>{if(!n)return l;let c;if(typeof n=="string"){c={};let s=[],r="",i=0;for(let t=0;t<n.length;t++){let e=n[t];e==="("?(i++,r+=e):e===")"?(i--,r+=e):e===";"&&i===0?(r.trim()&&s.push(r.trim()),r=""):r+=e;}r.trim()&&s.push(r.trim());for(let t of s){let e=t.indexOf(":");if(e===-1)continue;let o=t.slice(0,e).trim(),p=t.slice(e+1).trim();o&&p&&(c[o]=p);}}else c=n;for(let[s,r]of Object.entries(c)){if(s.startsWith("--")){l[s]=r;continue}let i;if(s.startsWith("-")){let t=s.slice(1);if(t.startsWith("ms-")){let e=t.slice(3);i="ms"+e.charAt(0).toUpperCase()+e.slice(1).replace(/-([a-z])/g,(o,p)=>p.toUpperCase());}else i=t.charAt(0).toUpperCase()+t.slice(1).replace(/-([a-z])/g,(e,o)=>o.toUpperCase());}else i=s.replace(/-([a-z])/g,(t,e)=>e.toUpperCase());l[i]=r;}return l},{});export{u as a};//# sourceMappingURL=chunk-
|
|
2
|
-
//# sourceMappingURL=chunk-
|
|
1
|
+
var u=f=>f.length===0?{}:f.reduce((l,n)=>{if(!n)return l;let c;if(typeof n=="string"){c={};let s=[],r="",i=0;for(let t=0;t<n.length;t++){let e=n[t];e==="("?(i++,r+=e):e===")"?(i--,r+=e):e===";"&&i===0?(r.trim()&&s.push(r.trim()),r=""):r+=e;}r.trim()&&s.push(r.trim());for(let t of s){let e=t.indexOf(":");if(e===-1)continue;let o=t.slice(0,e).trim(),p=t.slice(e+1).trim();o&&p&&(c[o]=p);}}else c=n;for(let[s,r]of Object.entries(c)){if(s.startsWith("--")){l[s]=r;continue}let i;if(s.startsWith("-")){let t=s.slice(1);if(t.startsWith("ms-")){let e=t.slice(3);i="ms"+e.charAt(0).toUpperCase()+e.slice(1).replace(/-([a-z])/g,(o,p)=>p.toUpperCase());}else i=t.charAt(0).toUpperCase()+t.slice(1).replace(/-([a-z])/g,(e,o)=>o.toUpperCase());}else i=s.replace(/-([a-z])/g,(t,e)=>e.toUpperCase());l[i]=r;}return l},{});export{u as a};//# sourceMappingURL=chunk-NBN5PUZ6.js.map
|
|
2
|
+
//# sourceMappingURL=chunk-NBN5PUZ6.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/merge-styles/merge-styles.ts"],"names":["mergeStyles","styles","acc","style","styleObject","declarations","currentDeclaration","parenDepth","i","char","declaration","colonIndex","property","value","key","normalizedKey","withoutPrefix","rest","_","letter"],"mappings":"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","file":"chunk-NBN5PUZ6.js","sourcesContent":["import type { PossibleStyle } from './merge-styles.types';\n\n/**\n * Merges multiple style values into a single, unified style object.\n *\n * This function consolidates a variety of style formats (inline strings, object records,\n * or undefined) into a single object. It ensures that all property keys are normalized\n * to camelCase or PascalCase where appropriate (e.g., handling vendor prefixes like\n * `-webkit-` as `Webkit` and `-ms-` as `ms`), while preserving CSS custom properties.\n *\n * The parser intelligently handles complex string values like `calc()` or `url()` to\n * ensure semicolons within them do not break the merging process. Following the CSS\n * cascade principle, styles appearing later in the array will override matching\n * properties from earlier ones.\n *\n * @example\n * ```ts\n * mergeStyles([\"color: red; margin-top: 10px;\", { marginTop: \"20px\", \"--spacing-unit\": \"20px\" }]);\n * // Returns: { color: \"red\", marginTop: \"20px\", \"--spacing-unit\": \"20px\" }\n * ```\n */\nexport const mergeStyles = (styles: PossibleStyle[]) => {\n // Short-circuit if no styles are provided to avoid unnecessary processing.\n if (styles.length === 0) return {};\n\n return styles.reduce<Record<string, string | number | undefined>>((acc, style) => {\n // Skip nullish values (`null`, `undefined`) which are common in conditional styling.\n if (!style) return acc;\n\n let styleObject: Record<string, string | number | undefined>;\n\n // Case 1: Handle inline style strings (e.g., `\"color: red; margin-top: 10px\"`).\n if (typeof style === 'string') {\n styleObject = {};\n const declarations: string[] = [];\n let currentDeclaration = '';\n let parenDepth = 0;\n\n // Manual tokenizer that splits declarations by semicolon while respecting\n // parentheses. This ensures that semicolons inside `calc()`, `url()`, or\n // data URIs do not break the parsing logic.\n for (let i = 0; i < style.length; i++) {\n const char = style[i];\n\n if (char === '(') {\n parenDepth++;\n currentDeclaration += char;\n } else if (char === ')') {\n parenDepth--;\n currentDeclaration += char;\n } else if (char === ';' && parenDepth === 0) {\n // Found a valid declaration boundary.\n if (currentDeclaration.trim()) {\n declarations.push(currentDeclaration.trim());\n }\n currentDeclaration = '';\n } else {\n currentDeclaration += char;\n }\n }\n\n // Capture the remaining part if the string doesn't end with a semicolon.\n if (currentDeclaration.trim()) {\n declarations.push(currentDeclaration.trim());\n }\n\n // Convert `\"property: value\"` pairs into object entries.\n for (const declaration of declarations) {\n const colonIndex = declaration.indexOf(':');\n if (colonIndex === -1) continue; // Skip malformed declarations.\n\n const property = declaration.slice(0, colonIndex).trim();\n const value = declaration.slice(colonIndex + 1).trim();\n\n if (property && value) {\n styleObject[property] = value;\n }\n }\n } else {\n // Case 2: Style is already an object, use it directly for normalization.\n styleObject = style;\n }\n\n // Normalization Loop:\n // Converts kebab-case keys and vendor prefixes into JS-friendly camelCase/PascalCase.\n for (const [key, value] of Object.entries(styleObject)) {\n // CSS Custom Properties (Variables) should remain in kebab-case.\n if (key.startsWith('--')) {\n acc[key] = value;\n continue;\n }\n\n let normalizedKey: string;\n\n if (key.startsWith('-')) {\n const withoutPrefix = key.slice(1);\n\n // Special handling for Internet Explorer prefix.\n // In JS style objects, `\"-ms-property\"` becomes `\"msProperty\"` (lowercase 'm').\n if (withoutPrefix.startsWith('ms-')) {\n const rest = withoutPrefix.slice(3);\n normalizedKey =\n 'ms' +\n rest.charAt(0).toUpperCase() +\n rest.slice(1).replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());\n } else {\n // Standard vendor prefixes (e.g., `-webkit-`, `-moz-`, `-o-`).\n // These are normalized to PascalCase (e.g., `\"WebkitTransform\"`).\n normalizedKey =\n withoutPrefix.charAt(0).toUpperCase() +\n withoutPrefix.slice(1).replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());\n }\n } else {\n // Standard CSS properties: convert `\"background-color\"` to `\"backgroundColor\"`.\n normalizedKey = key.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());\n }\n\n // Later styles in the array will overwrite earlier ones.\n acc[normalizedKey] = value;\n }\n\n return acc;\n }, {});\n};\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/wait/wait.ts"],"names":["wait","delayMs","resolve"],"mappings":"AAgBO,IAAMA,CAAAA,CAAQC,GACZ,IAAI,OAAA,CAASC,GAAY,UAAA,CAAWA,CAAAA,CAASD,CAAO,CAAC","file":"chunk-OUZ54COH.js","sourcesContent":["/**\n * Pauses the execution of the current asynchronous function for a specified duration.\n *\n * This function utilizes a Promise-based wrapper around `setTimeout` to create\n * a non-blocking delay, allowing for cleaner asynchronous control flows using\n * async/await syntax.\n *\n * @example\n * ```ts\n * const performTask = async () => {\n * \tconsole.log(\"Starting task...\");\n * \tawait wait(2000); // Pauses execution for 2 seconds\n * \tconsole.log(\"Task resumed after 2 seconds.\");\n * };\n * ```\n */\nexport const wait = (delayMs: number) => {\n return new Promise((resolve) => setTimeout(resolve, delayMs));\n};\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/is-valid-number/is-valid-number.ts"],"names":["isValidNumber","value"],"mappings":"AAoBO,IAAMA,EAAiBC,CAAAA,EACrB,OAAOA,GAAU,QAAA,EAAY,MAAA,CAAO,SAASA,CAAK","file":"chunk-TAV72HQS.js","sourcesContent":["/**\n * Determines whether the provided value is a valid, finite number.\n *\n * This utility serves as a type guard that goes beyond a simple `typeof` check.\n * While `typeof NaN` or `typeof Infinity` returns `\"number\"`, this function\n * ensures the value is a usable numeric value by excluding these edge cases\n * using `Number.isFinite`.\n *\n * @example\n * ```ts\n * isValidNumber(10);\n * // Returns: true\n *\n * isValidNumber(NaN);\n * // Returns: false\n *\n * isValidNumber(Infinity);\n * // Returns: false\n * ```\n */\nexport const isValidNumber = (value: number): value is number => {\n return typeof value === 'number' && Number.isFinite(value);\n};\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/visually-hidden-style/visually-hidden-style.ts"],"names":["visuallyHiddenStyle"],"mappings":"AAqBO,IAAMA,CAAAA,CAAsB,MAAA,CAAO,MAAA,CAAO,CAC/C,QAAA,CAAU,YAAA,CACV,QAAA,CAAU,QAAA,CACV,UAAA,CAAY,QAAA,CACZ,MAAA,CAAQ,CAAA,CACR,OAAA,CAAS,EACT,KAAA,CAAO,CAAA,CACP,MAAA,CAAQ,CAAA,CACR,MAAA,CAAQ,EAAA,CACR,QAAA,CAAU,OAAA,CACV,GAAA,CAAK,CAAA,CACL,IAAA,CAAM,CACR,CAAC","file":"chunk-YRBGPPKC.js","sourcesContent":["import type * as CSS from 'csstype';\n\n/**\n * A set of CSS properties used to hide an element visually while keeping it\n * accessible to screen readers.\n *\n * This utility is essential for providing additional context to assistive\n * technologies without affecting the visual layout. It uses a combination of\n * clipping, overflow, and absolute positioning to ensure the element has\n * dimensions of 1x1 pixel but remains \"visible\" in the accessibility tree.\n *\n * @example\n * ```tsx\n * const SearchButton = () => (\n * \t<button type=\"button\">\n * \t\t<Icon name=\"search\" />\n * \t\t<span style={visuallyHiddenStyle}>Search</span>\n * \t</button>\n * );\n * ```\n */\nexport const visuallyHiddenStyle = Object.freeze({\n clipPath: 'inset(50%)',\n overflow: 'hidden',\n whiteSpace: 'nowrap',\n border: 0,\n padding: 0,\n width: 1,\n height: 1,\n margin: -1,\n position: 'fixed',\n top: 0,\n left: 0,\n}) satisfies CSS.Properties<string | number>;\n"]}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration object for the `clamp` utility.
|
|
3
|
+
*
|
|
4
|
+
* This interface defines the numerical boundaries and the target value required
|
|
5
|
+
* to perform a clamping operation. It ensures that all provided properties are
|
|
6
|
+
* valid, finite numbers, maintaining strict mathematical constraints where
|
|
7
|
+
* the minimum bound must not exceed the maximum bound.
|
|
8
|
+
*/
|
|
9
|
+
interface ClampParams {
|
|
10
|
+
/**
|
|
11
|
+
* The numerical value to be restricted within the specified range.
|
|
12
|
+
* Must be a finite number.
|
|
13
|
+
*/
|
|
14
|
+
value: number;
|
|
15
|
+
/**
|
|
16
|
+
* The lower bound of the range.
|
|
17
|
+
* If `value` is less than `min`, the function returns `min`.
|
|
18
|
+
* Must be a finite number and less than or equal to `max`.
|
|
19
|
+
*/
|
|
20
|
+
min: number;
|
|
21
|
+
/**
|
|
22
|
+
* The upper bound of the range.
|
|
23
|
+
* If `value` is greater than `max`, the function returns `max`.
|
|
24
|
+
* Must be a finite number and greater than or equal to `min`.
|
|
25
|
+
*/
|
|
26
|
+
max: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Clamps a number between a minimum and maximum value.
|
|
31
|
+
*
|
|
32
|
+
* This utility ensures that the returned value is restricted to a specified range.
|
|
33
|
+
* If the input value is smaller than the minimum boundary, the minimum value is
|
|
34
|
+
* returned. If it exceeds the maximum boundary, the maximum value is returned.
|
|
35
|
+
*
|
|
36
|
+
* This function will throw an error if:
|
|
37
|
+
* - Any of the input parameters are not finite numbers.
|
|
38
|
+
* - The `min` value is greater than the `max` value.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```ts
|
|
42
|
+
* clamp({ value: 150, min: 0, max: 100 });
|
|
43
|
+
* // Returns: 100
|
|
44
|
+
*
|
|
45
|
+
* clamp({ value: -20, min: 0, max: 100 });
|
|
46
|
+
* Returns: 0
|
|
47
|
+
*
|
|
48
|
+
* clamp({ value: 50, min: 0, max: 100 });
|
|
49
|
+
* // Returns: 50
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
declare const clamp: (params: ClampParams) => number;
|
|
53
|
+
|
|
54
|
+
export { type ClampParams, clamp };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
+
export { AddEventListenerOnceParams, AllEventMaps, addEventListenerOnce } from './add-event-listener-once/index.js';
|
|
2
|
+
export { ClampParams, clamp } from './clamp/index.js';
|
|
1
3
|
export { ErrorParams, error } from './error/index.js';
|
|
2
4
|
export { FailParams, fail } from './fail/index.js';
|
|
5
|
+
export { isValidNumber } from './is-valid-number/index.js';
|
|
3
6
|
export { PossibleStyle, mergeStyles } from './merge-styles/index.js';
|
|
7
|
+
export { visuallyHiddenInputStyle } from './visually-hidden-input-style/index.js';
|
|
8
|
+
export { visuallyHiddenStyle } from './visually-hidden-style/index.js';
|
|
9
|
+
export { wait } from './wait/index.js';
|
|
4
10
|
export { WarnParams, warn } from './warn/index.js';
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export{a as error}from'./chunk-GG6DRWSS.js';export{a as fail}from'./chunk-O4WYO5SA.js';export{a as
|
|
1
|
+
export{a as visuallyHiddenStyle}from'./chunk-YRBGPPKC.js';export{a as wait}from'./chunk-OUZ54COH.js';export{a as warn}from'./chunk-6L6DIP5N.js';export{a as addEventListenerOnce}from'./chunk-GLPQ4KOF.js';export{a as clamp}from'./chunk-JW4DI4Q2.js';export{a as error}from'./chunk-GG6DRWSS.js';export{a as fail}from'./chunk-O4WYO5SA.js';export{a as isValidNumber}from'./chunk-TAV72HQS.js';export{a as mergeStyles}from'./chunk-NBN5PUZ6.js';export{a as visuallyHiddenInputStyle}from'./chunk-AYHMR4G2.js';//# sourceMappingURL=index.js.map
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Determines whether the provided value is a valid, finite number.
|
|
3
|
+
*
|
|
4
|
+
* This utility serves as a type guard that goes beyond a simple `typeof` check.
|
|
5
|
+
* While `typeof NaN` or `typeof Infinity` returns `"number"`, this function
|
|
6
|
+
* ensures the value is a usable numeric value by excluding these edge cases
|
|
7
|
+
* using `Number.isFinite`.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* isValidNumber(10);
|
|
12
|
+
* // Returns: true
|
|
13
|
+
*
|
|
14
|
+
* isValidNumber(NaN);
|
|
15
|
+
* // Returns: false
|
|
16
|
+
*
|
|
17
|
+
* isValidNumber(Infinity);
|
|
18
|
+
* // Returns: false
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
declare const isValidNumber: (value: number) => value is number;
|
|
22
|
+
|
|
23
|
+
export { isValidNumber };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|
|
@@ -4,9 +4,13 @@
|
|
|
4
4
|
* This type allows for flexibility in how styles are defined, supporting:
|
|
5
5
|
*
|
|
6
6
|
* - `string`: Standard inline CSS strings (e.g., `"color: red; padding: 10px"`).
|
|
7
|
+
*
|
|
7
8
|
* - `Record<string, string | number | undefined>`: A structured object of CSS declarations.
|
|
8
|
-
* Supports camelCase, kebab-case, and CSS custom properties (e.g., `{ color:
|
|
9
|
+
* Supports camelCase, kebab-case, and CSS custom properties (e.g., `{ color: "red", "margin-top": 10, "--spacing-unit": "20px" }`).
|
|
10
|
+
*
|
|
9
11
|
* - `undefined`: Useful for conditional styling where a style might not be present.
|
|
12
|
+
* Since `boolean` is not accepted, use ternary operators or logical OR
|
|
13
|
+
* to ensure a valid type (e.g., `isActive ? "color: red" : undefined`).
|
|
10
14
|
*/
|
|
11
15
|
type PossibleStyle = string | Record<string, string | number | undefined> | undefined;
|
|
12
16
|
|
|
@@ -25,7 +29,7 @@ type PossibleStyle = string | Record<string, string | number | undefined> | unde
|
|
|
25
29
|
*
|
|
26
30
|
* @example
|
|
27
31
|
* ```ts
|
|
28
|
-
* mergeStyles(["color: red; margin-top: 10px;"
|
|
32
|
+
* mergeStyles(["color: red; margin-top: 10px;", { marginTop: "20px", "--spacing-unit": "20px" }]);
|
|
29
33
|
* // Returns: { color: "red", marginTop: "20px", "--spacing-unit": "20px" }
|
|
30
34
|
* ```
|
|
31
35
|
*/
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export{a as mergeStyles}from'../chunk-
|
|
1
|
+
export{a as mergeStyles}from'../chunk-NBN5PUZ6.js';//# sourceMappingURL=index.js.map
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Visually hides an input element while keeping it functional and accessible.
|
|
3
|
+
*
|
|
4
|
+
* Commonly used for styling native checkboxes, radio buttons, or file inputs
|
|
5
|
+
* by hiding the default browser element and replacing it with a custom-styled
|
|
6
|
+
* UI, while ensuring the underlying input remains focusable and reachable
|
|
7
|
+
* by assistive technologies.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```tsx
|
|
11
|
+
* const CustomCheckbox = () => (
|
|
12
|
+
* <>
|
|
13
|
+
* <input type="checkbox" id="terms" style={visuallyHiddenInputStyle} />
|
|
14
|
+
* <label htmlFor="terms">I agree to the terms</label>
|
|
15
|
+
* </>
|
|
16
|
+
* );
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
declare const visuallyHiddenInputStyle: Readonly<{
|
|
20
|
+
clipPath: "inset(50%)";
|
|
21
|
+
overflow: "hidden";
|
|
22
|
+
whiteSpace: "nowrap";
|
|
23
|
+
border: 0;
|
|
24
|
+
padding: 0;
|
|
25
|
+
width: 1;
|
|
26
|
+
height: 1;
|
|
27
|
+
margin: -1;
|
|
28
|
+
position: "absolute";
|
|
29
|
+
}>;
|
|
30
|
+
|
|
31
|
+
export { visuallyHiddenInputStyle };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A set of CSS properties used to hide an element visually while keeping it
|
|
3
|
+
* accessible to screen readers.
|
|
4
|
+
*
|
|
5
|
+
* This utility is essential for providing additional context to assistive
|
|
6
|
+
* technologies without affecting the visual layout. It uses a combination of
|
|
7
|
+
* clipping, overflow, and absolute positioning to ensure the element has
|
|
8
|
+
* dimensions of 1x1 pixel but remains "visible" in the accessibility tree.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* const SearchButton = () => (
|
|
13
|
+
* <button type="button">
|
|
14
|
+
* <Icon name="search" />
|
|
15
|
+
* <span style={visuallyHiddenStyle}>Search</span>
|
|
16
|
+
* </button>
|
|
17
|
+
* );
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
declare const visuallyHiddenStyle: Readonly<{
|
|
21
|
+
clipPath: "inset(50%)";
|
|
22
|
+
overflow: "hidden";
|
|
23
|
+
whiteSpace: "nowrap";
|
|
24
|
+
border: 0;
|
|
25
|
+
padding: 0;
|
|
26
|
+
width: 1;
|
|
27
|
+
height: 1;
|
|
28
|
+
margin: -1;
|
|
29
|
+
position: "fixed";
|
|
30
|
+
top: 0;
|
|
31
|
+
left: 0;
|
|
32
|
+
}>;
|
|
33
|
+
|
|
34
|
+
export { visuallyHiddenStyle };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pauses the execution of the current asynchronous function for a specified duration.
|
|
3
|
+
*
|
|
4
|
+
* This function utilizes a Promise-based wrapper around `setTimeout` to create
|
|
5
|
+
* a non-blocking delay, allowing for cleaner asynchronous control flows using
|
|
6
|
+
* async/await syntax.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* const performTask = async () => {
|
|
11
|
+
* console.log("Starting task...");
|
|
12
|
+
* await wait(2000); // Pauses execution for 2 seconds
|
|
13
|
+
* console.log("Task resumed after 2 seconds.");
|
|
14
|
+
* };
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
declare const wait: (delayMs: number) => Promise<unknown>;
|
|
18
|
+
|
|
19
|
+
export { wait };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/merge-styles/merge-styles.ts"],"names":["mergeStyles","styles","acc","style","styleObject","declarations","currentDeclaration","parenDepth","i","char","declaration","colonIndex","property","value","key","normalizedKey","withoutPrefix","rest","_","letter"],"mappings":"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","file":"chunk-JLS3437A.js","sourcesContent":["import type { PossibleStyle } from './merge-styles.types';\n\n/**\n * Merges multiple style values into a single, unified style object.\n *\n * This function consolidates a variety of style formats (inline strings, object records,\n * or undefined) into a single object. It ensures that all property keys are normalized\n * to camelCase or PascalCase where appropriate (e.g., handling vendor prefixes like\n * `-webkit-` as `Webkit` and `-ms-` as `ms`), while preserving CSS custom properties.\n *\n * The parser intelligently handles complex string values like `calc()` or `url()` to\n * ensure semicolons within them do not break the merging process. Following the CSS\n * cascade principle, styles appearing later in the array will override matching\n * properties from earlier ones.\n *\n * @example\n * ```ts\n * mergeStyles([\"color: red; margin-top: 10px;\"\", { marginTop: \"20px\", \"--spacing-unit\": \"20px\" }]);\n * // Returns: { color: \"red\", marginTop: \"20px\", \"--spacing-unit\": \"20px\" }\n * ```\n */\nexport const mergeStyles = (styles: PossibleStyle[]) => {\n // Short-circuit if no styles are provided to avoid unnecessary processing.\n if (styles.length === 0) return {};\n\n return styles.reduce<Record<string, string | number | undefined>>((acc, style) => {\n // Skip nullish values (`null`, `undefined`) which are common in conditional styling.\n if (!style) return acc;\n\n let styleObject: Record<string, string | number | undefined>;\n\n // Case 1: Handle inline style strings (e.g., `\"color: red; margin-top: 10px\"`).\n if (typeof style === 'string') {\n styleObject = {};\n const declarations: string[] = [];\n let currentDeclaration = '';\n let parenDepth = 0;\n\n // Manual tokenizer that splits declarations by semicolon while respecting\n // parentheses. This ensures that semicolons inside `calc()`, `url()`, or\n // data URIs do not break the parsing logic.\n for (let i = 0; i < style.length; i++) {\n const char = style[i];\n\n if (char === '(') {\n parenDepth++;\n currentDeclaration += char;\n } else if (char === ')') {\n parenDepth--;\n currentDeclaration += char;\n } else if (char === ';' && parenDepth === 0) {\n // Found a valid declaration boundary.\n if (currentDeclaration.trim()) {\n declarations.push(currentDeclaration.trim());\n }\n currentDeclaration = '';\n } else {\n currentDeclaration += char;\n }\n }\n\n // Capture the remaining part if the string doesn't end with a semicolon.\n if (currentDeclaration.trim()) {\n declarations.push(currentDeclaration.trim());\n }\n\n // Convert `\"property: value\"` pairs into object entries.\n for (const declaration of declarations) {\n const colonIndex = declaration.indexOf(':');\n if (colonIndex === -1) continue; // Skip malformed declarations.\n\n const property = declaration.slice(0, colonIndex).trim();\n const value = declaration.slice(colonIndex + 1).trim();\n\n if (property && value) {\n styleObject[property] = value;\n }\n }\n } else {\n // Case 2: Style is already an object, use it directly for normalization.\n styleObject = style;\n }\n\n // Normalization Loop:\n // Converts kebab-case keys and vendor prefixes into JS-friendly camelCase/PascalCase.\n for (const [key, value] of Object.entries(styleObject)) {\n // CSS Custom Properties (Variables) should remain in kebab-case.\n if (key.startsWith('--')) {\n acc[key] = value;\n continue;\n }\n\n let normalizedKey: string;\n\n if (key.startsWith('-')) {\n const withoutPrefix = key.slice(1);\n\n // Special handling for Internet Explorer prefix.\n // In JS style objects, `\"-ms-property\"` becomes `\"msProperty\"` (lowercase 'm').\n if (withoutPrefix.startsWith('ms-')) {\n const rest = withoutPrefix.slice(3);\n normalizedKey =\n 'ms' +\n rest.charAt(0).toUpperCase() +\n rest.slice(1).replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());\n } else {\n // Standard vendor prefixes (e.g., `-webkit-`, `-moz-`, `-o-`).\n // These are normalized to PascalCase (e.g., `\"WebkitTransform\"`).\n normalizedKey =\n withoutPrefix.charAt(0).toUpperCase() +\n withoutPrefix.slice(1).replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());\n }\n } else {\n // Standard CSS properties: convert `\"background-color\"` to `\"backgroundColor\"`.\n normalizedKey = key.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());\n }\n\n // Later styles in the array will overwrite earlier ones.\n acc[normalizedKey] = value;\n }\n\n return acc;\n }, {});\n};\n"]}
|