[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M754E0Z4FM2H192C4B1WC44J":3,"skill-same:01M754E0Z4FM2H192C4B1WC44J":47},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":19,"linkOnly":20,"markdownContent":21,"markdownBody":22,"frontMatter":23,"refName":24,"commitSha":25,"skillDirectory":26,"forksCount":14,"repositoryHtmlUrl":27,"repositoryHomepageUrl":28,"ownerHtmlUrl":29,"ownerBlogUrl":30,"ownerDescription":31,"updatedAt":32,"install":33,"resources":46},"01M754E0Z4FM2H192C4B1WC44J","gsap-utils",null,"Official GSAP skill for gsap.utils — clamp, mapRange, normalize, interpolate, random, snap, toArray, wrap, pipe. Use when the user asks about gsap.utils, clamp, mapRange, random, snap, toArray, wrap, or helper utilities in GSAP.","Amon20044\u002FNetra","Amon20044","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F111745899?v=4","01M754D32M6XBBFMCNCWF25F9G","Amon Sharma","01M754D33MVQ07CZC7KNSVTV3P",0,"MIT","https:\u002F\u002Fgithub.com\u002FAmon20044\u002FNetra\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fgsap-utils\u002FSKILL.md",[],[],"2026-11-12 13:55:43",false,"---\nname: gsap-utils\ndescription: Official GSAP skill for gsap.utils — clamp, mapRange, normalize, interpolate, random, snap, toArray, wrap, pipe. Use when the user asks about gsap.utils, clamp, mapRange, random, snap, toArray, wrap, or helper utilities in GSAP.\nlicense: MIT\n---\n\n# gsap.utils\n\n## When to Use This Skill\n\nApply when writing or reviewing code that uses **gsap.utils** for math, array\u002Fcollection handling, unit parsing, or value mapping in animations (e.g. mapping scroll to a value, randomizing, snapping to a grid, or normalizing inputs).\n\n**Related skills:** Use with **gsap-core**, **gsap-timeline**, and **gsap-scrolltrigger** when building animations; CustomEase and other easing utilities are in **gsap-plugins**.\n\n## Overview\n\n**gsap.utils** provides pure helpers; no need to register. Use in tween vars (e.g. function-based values), in ScrollTrigger or Observer callbacks, or in any JS that drives GSAP. All are on **gsap.utils** (e.g. `gsap.utils.clamp()`).\n\n**Omitting the value: function form.** Many utils accept the value to transform as the **last** argument. If you omit that argument, the util returns a **function** that accepts the value later. Use the function form when you need to clamp, map, normalize, or snap many values with the same config (e.g. in a mousemove handler or tween callback). **Exception: random()** — pass **true** as the last argument to get a reusable function (do not omit the value); see [random()](https:\u002F\u002Fgsap.com\u002Fdocs\u002Fv3\u002FGSAP\u002FUtilityMethods\u002Frandom()).\n\n```javascript\n\u002F\u002F With value: returns the result\ngsap.utils.clamp(0, 100, 150); \u002F\u002F 100\n\n\u002F\u002F Without value: returns a function you call with the value later\nlet c = gsap.utils.clamp(0, 100);\nc(150);  \u002F\u002F 100\nc(-10);  \u002F\u002F 0\n```\n\n## Clamping and Ranges\n\n### clamp(min, max, value?)\n\nConstrains a value between min and max. Omit **value** to get a function: `clamp(min, max)(value)`.\n\n```javascript\ngsap.utils.clamp(0, 100, 150); \u002F\u002F 100\ngsap.utils.clamp(0, 100, -10); \u002F\u002F 0\n\nlet clampFn = gsap.utils.clamp(0, 100);\nclampFn(150); \u002F\u002F 100\n```\n\n### mapRange(inMin, inMax, outMin, outMax, value?)\n\nMaps a value from one range to another. Use when converting scroll position, progress (0–1), or input range to an animation range. Omit **value** to get a function: `mapRange(inMin, inMax, outMin, outMax)(value)`.\n\n```javascript\ngsap.utils.mapRange(0, 100, 0, 500, 50);  \u002F\u002F 250\ngsap.utils.mapRange(0, 1, 0, 360, 0.5);   \u002F\u002F 180 (progress to degrees)\n\nlet mapFn = gsap.utils.mapRange(0, 100, 0, 500);\nmapFn(50);  \u002F\u002F 250\n```\n\n### normalize(min, max, value?)\n\nReturns a value normalized to 0–1 for the given range. Inverse of mapping when the target range is 0–1. Omit **value** to get a function: `normalize(min, max)(value)`.\n\n```javascript\ngsap.utils.normalize(0, 100, 50);   \u002F\u002F 0.5\ngsap.utils.normalize(100, 300, 200); \u002F\u002F 0.5\n\nlet normFn = gsap.utils.normalize(0, 100);\nnormFn(50); \u002F\u002F 0.5\n```\n\n### interpolate(start, end, progress?)\n\nInterpolates between two values at a given progress (0–1). Handles numbers, colors, and objects with matching keys. Omit **progress** to get a function: `interpolate(start, end)(progress)`.\n\n```javascript\ngsap.utils.interpolate(0, 100, 0.5);       \u002F\u002F 50\ngsap.utils.interpolate(\"#ff0000\", \"#0000ff\", 0.5); \u002F\u002F mid color\ngsap.utils.interpolate({ x: 0, y: 0 }, { x: 100, y: 50 }, 0.5); \u002F\u002F { x: 50, y: 25 }\n\nlet lerp = gsap.utils.interpolate(0, 100);\nlerp(0.5); \u002F\u002F 50\n```\n\n## Random and Snap\n\n### random(minimum, maximum[, snapIncrement, returnFunction]) \u002F random(array[, returnFunction])\n\nReturns a random number in the range **minimum**–**maximum**, or a random element from an **array**. Optional **snapIncrement** snaps the result to the nearest multiple (e.g. `5` → multiples of 5). **To get a reusable function**, pass **true** as the last argument (**returnFunction**); the returned function takes no args and returns a new random value each time. This is the only util that uses `true` for the function form instead of omitting the value.\n\n```javascript\n\u002F\u002F immediate value: number in range\ngsap.utils.random(-100, 100);        \u002F\u002F e.g. 42.7\ngsap.utils.random(0, 500, 5);        \u002F\u002F 0–500, snapped to nearest 5\n\n\u002F\u002F reusable function: pass true as last argument\nlet randomFn = gsap.utils.random(-200, 500, 10, true);\nrandomFn();  \u002F\u002F random value in range, snapped to 10\nrandomFn();  \u002F\u002F another random value\n\n\u002F\u002F array: pick one value at random\ngsap.utils.random([\"red\", \"blue\", \"green\"]);  \u002F\u002F \"red\", \"blue\", or \"green\"\nlet randomFromArray = gsap.utils.random([0, 100, 200], true);\nrandomFromArray();  \u002F\u002F 0, 100, or 200\n```\n\n**String form in tween vars:** use `\"random(-100, 100)\"`, `\"random(-100, 100, 5)\"`, or `\"random([0, 100, 200])\"`; GSAP evaluates it per target.\n\n```javascript\ngsap.to(\".box\", { x: \"random(-100, 100, 5)\", duration: 1 });\ngsap.to(\".item\", { backgroundColor: \"random([red, blue, green])\" });\n```\n\n### snap(snapTo, value?)\n\nSnaps a value to the nearest multiple of **snapTo**, or to the nearest value in an array of allowed values. Omit **value** to get a function: `snap(snapTo)(value)` (or `snap(snapArray)(value)`).\n\n```javascript\ngsap.utils.snap(10, 23);     \u002F\u002F 20\ngsap.utils.snap(0.25, 0.7);  \u002F\u002F 0.75\ngsap.utils.snap([0, 100, 200], 150); \u002F\u002F 100 or 200 (nearest in array)\n\nlet snapFn = gsap.utils.snap(10);\nsnapFn(23); \u002F\u002F 20\n```\n\nUse in tweens for grid or step-based animation:\n\n```javascript\ngsap.to(\".x\", { x: 200, snap: { x: 20 } });\n```\n\n### shuffle(array)\n\nReturns a new array with the same elements in random order. Use for randomizing order (e.g. stagger from \"random\" with a copy).\n\n```javascript\ngsap.utils.shuffle([1, 2, 3, 4]); \u002F\u002F e.g. [3, 1, 4, 2]\n```\n\n### distribute(config)\n\n**Returns a function** that assigns a value to each target based on its position in the array (or in a grid). Used internally for advanced staggers; use it whenever you need values spread across many elements (e.g. scale, opacity, x, delay). The returned function receives `(index, target, targets)` — either call it manually or pass the result directly into a tween; GSAP will call it per target with index, element, and array.\n\n**Config (all optional):**\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `base` | Number | Starting value. Default `0`. |\n| `amount` | Number | Total to distribute across all targets (added to base). E.g. `amount: 1` with 100 targets → 0.01 between each. Use **each** instead to set a fixed step per target. |\n| `each` | Number | Amount to add between each target (added to base). E.g. `each: 1` with 4 targets → 0, 1, 2, 3. Use **amount** instead to split a total. |\n| `from` | Number \\| String \\| Array | Where distribution starts: index, or `\"start\"`, `\"center\"`, `\"edges\"`, `\"random\"`, `\"end\"`, or ratios like `[0.25, 0.75]`. Default `0`. |\n| `grid` | String \\| Array | Use grid position instead of flat index: `[rows, columns]` (e.g. `[5, 10]`) or `\"auto\"` to detect. Omit for flat array. |\n| `axis` | String | For grid: limit to one axis (`\"x\"` or `\"y\"`). |\n| `ease` | Ease | Distribute values along an ease curve (e.g. `\"power1.inOut\"`). Default `\"none\"`. |\n\n**In a tween:** pass the result of `distribute(config)` as the property value; GSAP calls the function for each target with `(index, target, targets)`.\n\n```javascript\n\u002F\u002F Scale: middle elements 0.5, outer edges 3 (amount 2.5 distributed from center)\ngsap.to(\".class\", {\n  scale: gsap.utils.distribute({\n    base: 0.5,\n    amount: 2.5,\n    from: \"center\"\n  })\n});\n```\n\n**Manual use:** call the returned function with `(index, target, targets)` to get the value for that index.\n\n```javascript\nconst distributor = gsap.utils.distribute({\n  base: 50,\n  amount: 100,\n  from: \"center\",\n  ease: \"power1.inOut\"\n});\nconst targets = gsap.utils.toArray(\".box\");\nconst valueForIndex2 = distributor(2, targets[2], targets);\n```\n\nSee [distribute()](https:\u002F\u002Fgsap.com\u002Fdocs\u002Fv3\u002FGSAP\u002FUtilityMethods\u002Fdistribute\u002F) for more.\n\n## Units and Parsing\n\n### getUnit(value)\n\nReturns the unit string of a value (e.g. `\"px\"`, `\"%\"`, `\"deg\"`). Use when normalizing or converting values.\n\n```javascript\ngsap.utils.getUnit(\"100px\");   \u002F\u002F \"px\"\ngsap.utils.getUnit(\"50%\");     \u002F\u002F \"%\"\ngsap.utils.getUnit(42);        \u002F\u002F \"\" (unitless)\n```\n\n### unitize(value, unit)\n\nAppends a unit to a number, or returns the value as-is if it already has a unit. Use when building CSS values or tween end values.\n\n```javascript\ngsap.utils.unitize(100, \"px\");  \u002F\u002F \"100px\"\ngsap.utils.unitize(\"2rem\", \"px\"); \u002F\u002F \"2rem\" (unchanged)\n```\n\n### splitColor(color, returnHSL?)\n\nConverts a color string into an array: **[red, green, blue]** (0–255), or **[red, green, blue, alpha]** (4 elements for RGBA when alpha is present or required). Pass **true** as the second argument (**returnHSL**) to get **[hue, saturation, lightness]** or **[hue, saturation, lightness, alpha]** (HSL\u002FHSLA) instead. Works with `\"rgb()\"`, `\"rgba()\"`, `\"hsl()\"`, `\"hsla()\"`, hex, and named colors (e.g. `\"red\"`). Use when animating color components or building gradients. See [splitColor()](https:\u002F\u002Fgsap.com\u002Fdocs\u002Fv3\u002FGSAP\u002FUtilityMethods\u002FsplitColor\u002F).\n\n```javascript\ngsap.utils.splitColor(\"red\");                    \u002F\u002F [255, 0, 0]\ngsap.utils.splitColor(\"#6fb936\");                \u002F\u002F [111, 185, 54]\ngsap.utils.splitColor(\"rgba(204, 153, 51, 0.5)\"); \u002F\u002F [204, 153, 51, 0.5] (4 elements)\ngsap.utils.splitColor(\"#6fb936\", true);          \u002F\u002F [94, 55, 47] (HSL: hue, saturation, lightness)\n```\n\n## Arrays and Collections\n\n### selector(scope)\n\nReturns a scoped selector function that finds elements only within the given element (or ref). Use in components so selectors like `\".box\"` match only descendants of that component, not the whole document. Accepts a DOM element or a ref (e.g. React ref; handles `.current`).\n\n```javascript\nconst q = gsap.utils.selector(containerRef);\nq(\".box\");        \u002F\u002F array of .box elements inside container\ngsap.to(q(\".circle\"), { x: 100 });\n```\n\n### toArray(value, scope?)\n\nConverts a value to an array: selector string (scoped to element), NodeList, HTMLCollection, single element, or array. Use when passing mixed inputs to GSAP (e.g. targets) and a true array is needed.\n\n```javascript\ngsap.utils.toArray(\".item\");           \u002F\u002F array of elements\ngsap.utils.toArray(\".item\", container); \u002F\u002F scoped to container\ngsap.utils.toArray(nodeList);          \u002F\u002F [ ... ] from NodeList\n```\n\n### pipe(...functions)\n\nComposes functions: **pipe(f1, f2, f3)(value)** returns f3(f2(f1(value))). Use when applying a chain of transforms (e.g. normalize → mapRange → snap) in a tween or callback.\n\n```javascript\nconst fn = gsap.utils.pipe(\n  (v) => gsap.utils.normalize(0, 100, v),\n  (v) => gsap.utils.snap(0.1, v)\n);\nfn(50); \u002F\u002F normalized then snapped\n```\n\n### wrap(min, max, value?)\n\nWraps a value into the range min–max (inclusive min, exclusive max). Use for infinite scroll or cyclic values. Omit **value** to get a function: `wrap(min, max)(value)`.\n\n```javascript\ngsap.utils.wrap(0, 360, 370);  \u002F\u002F 10\ngsap.utils.wrap(0, 360, -10);   \u002F\u002F 350\n\nlet wrapFn = gsap.utils.wrap(0, 360);\nwrapFn(370); \u002F\u002F 10\n```\n\n### wrapYoyo(min, max, value?)\n\nWraps value in range with a yoyo (bounces at ends). Use for back-and-forth within a range. Omit **value** to get a function: `wrapYoyo(min, max)(value)`.\n\n```javascript\ngsap.utils.wrapYoyo(0, 100, 150); \u002F\u002F 50 (bounces back)\n\nlet wrapY = gsap.utils.wrapYoyo(0, 100);\nwrapY(150); \u002F\u002F 50\n```\n\n## Best practices\n\n- ✅ Omit the value argument to get a reusable function when the same range\u002Fconfig is used many times (e.g. scroll handler, tween callback): `let mapFn = gsap.utils.mapRange(0, 1, 0, 360); mapFn(progress)`.\n- ✅ Use **snap** for grid-aligned or step-based values; use **toArray** when GSAP or your code needs a real array from a selector or NodeList.\n- ✅ Use **gsap.utils.selector(scope)** in components so selectors are scoped to a container or ref.\n\n## Do Not\n\n- ❌ Assume **mapRange** \u002F **normalize** handle units; they work on numbers. Use **getUnit** \u002F **unitize** when units matter.\n- ❌ Override or rely on undocumented behavior; stick to the documented API.\n\n### Learn More\n\nhttps:\u002F\u002Fgsap.com\u002Fdocs\u002Fv3\u002FHelperFunctions\n","# gsap.utils\n\n## When to Use This Skill\n\nApply when writing or reviewing code that uses **gsap.utils** for math, array\u002Fcollection handling, unit parsing, or value mapping in animations (e.g. mapping scroll to a value, randomizing, snapping to a grid, or normalizing inputs).\n\n**Related skills:** Use with **gsap-core**, **gsap-timeline**, and **gsap-scrolltrigger** when building animations; CustomEase and other easing utilities are in **gsap-plugins**.\n\n## Overview\n\n**gsap.utils** provides pure helpers; no need to register. Use in tween vars (e.g. function-based values), in ScrollTrigger or Observer callbacks, or in any JS that drives GSAP. All are on **gsap.utils** (e.g. `gsap.utils.clamp()`).\n\n**Omitting the value: function form.** Many utils accept the value to transform as the **last** argument. If you omit that argument, the util returns a **function** that accepts the value later. Use the function form when you need to clamp, map, normalize, or snap many values with the same config (e.g. in a mousemove handler or tween callback). **Exception: random()** — pass **true** as the last argument to get a reusable function (do not omit the value); see [random()](https:\u002F\u002Fgsap.com\u002Fdocs\u002Fv3\u002FGSAP\u002FUtilityMethods\u002Frandom()).\n\n```javascript\n\u002F\u002F With value: returns the result\ngsap.utils.clamp(0, 100, 150); \u002F\u002F 100\n\n\u002F\u002F Without value: returns a function you call with the value later\nlet c = gsap.utils.clamp(0, 100);\nc(150);  \u002F\u002F 100\nc(-10);  \u002F\u002F 0\n```\n\n## Clamping and Ranges\n\n### clamp(min, max, value?)\n\nConstrains a value between min and max. Omit **value** to get a function: `clamp(min, max)(value)`.\n\n```javascript\ngsap.utils.clamp(0, 100, 150); \u002F\u002F 100\ngsap.utils.clamp(0, 100, -10); \u002F\u002F 0\n\nlet clampFn = gsap.utils.clamp(0, 100);\nclampFn(150); \u002F\u002F 100\n```\n\n### mapRange(inMin, inMax, outMin, outMax, value?)\n\nMaps a value from one range to another. Use when converting scroll position, progress (0–1), or input range to an animation range. Omit **value** to get a function: `mapRange(inMin, inMax, outMin, outMax)(value)`.\n\n```javascript\ngsap.utils.mapRange(0, 100, 0, 500, 50);  \u002F\u002F 250\ngsap.utils.mapRange(0, 1, 0, 360, 0.5);   \u002F\u002F 180 (progress to degrees)\n\nlet mapFn = gsap.utils.mapRange(0, 100, 0, 500);\nmapFn(50);  \u002F\u002F 250\n```\n\n### normalize(min, max, value?)\n\nReturns a value normalized to 0–1 for the given range. Inverse of mapping when the target range is 0–1. Omit **value** to get a function: `normalize(min, max)(value)`.\n\n```javascript\ngsap.utils.normalize(0, 100, 50);   \u002F\u002F 0.5\ngsap.utils.normalize(100, 300, 200); \u002F\u002F 0.5\n\nlet normFn = gsap.utils.normalize(0, 100);\nnormFn(50); \u002F\u002F 0.5\n```\n\n### interpolate(start, end, progress?)\n\nInterpolates between two values at a given progress (0–1). Handles numbers, colors, and objects with matching keys. Omit **progress** to get a function: `interpolate(start, end)(progress)`.\n\n```javascript\ngsap.utils.interpolate(0, 100, 0.5);       \u002F\u002F 50\ngsap.utils.interpolate(\"#ff0000\", \"#0000ff\", 0.5); \u002F\u002F mid color\ngsap.utils.interpolate({ x: 0, y: 0 }, { x: 100, y: 50 }, 0.5); \u002F\u002F { x: 50, y: 25 }\n\nlet lerp = gsap.utils.interpolate(0, 100);\nlerp(0.5); \u002F\u002F 50\n```\n\n## Random and Snap\n\n### random(minimum, maximum[, snapIncrement, returnFunction]) \u002F random(array[, returnFunction])\n\nReturns a random number in the range **minimum**–**maximum**, or a random element from an **array**. Optional **snapIncrement** snaps the result to the nearest multiple (e.g. `5` → multiples of 5). **To get a reusable function**, pass **true** as the last argument (**returnFunction**); the returned function takes no args and returns a new random value each time. This is the only util that uses `true` for the function form instead of omitting the value.\n\n```javascript\n\u002F\u002F immediate value: number in range\ngsap.utils.random(-100, 100);        \u002F\u002F e.g. 42.7\ngsap.utils.random(0, 500, 5);        \u002F\u002F 0–500, snapped to nearest 5\n\n\u002F\u002F reusable function: pass true as last argument\nlet randomFn = gsap.utils.random(-200, 500, 10, true);\nrandomFn();  \u002F\u002F random value in range, snapped to 10\nrandomFn();  \u002F\u002F another random value\n\n\u002F\u002F array: pick one value at random\ngsap.utils.random([\"red\", \"blue\", \"green\"]);  \u002F\u002F \"red\", \"blue\", or \"green\"\nlet randomFromArray = gsap.utils.random([0, 100, 200], true);\nrandomFromArray();  \u002F\u002F 0, 100, or 200\n```\n\n**String form in tween vars:** use `\"random(-100, 100)\"`, `\"random(-100, 100, 5)\"`, or `\"random([0, 100, 200])\"`; GSAP evaluates it per target.\n\n```javascript\ngsap.to(\".box\", { x: \"random(-100, 100, 5)\", duration: 1 });\ngsap.to(\".item\", { backgroundColor: \"random([red, blue, green])\" });\n```\n\n### snap(snapTo, value?)\n\nSnaps a value to the nearest multiple of **snapTo**, or to the nearest value in an array of allowed values. Omit **value** to get a function: `snap(snapTo)(value)` (or `snap(snapArray)(value)`).\n\n```javascript\ngsap.utils.snap(10, 23);     \u002F\u002F 20\ngsap.utils.snap(0.25, 0.7);  \u002F\u002F 0.75\ngsap.utils.snap([0, 100, 200], 150); \u002F\u002F 100 or 200 (nearest in array)\n\nlet snapFn = gsap.utils.snap(10);\nsnapFn(23); \u002F\u002F 20\n```\n\nUse in tweens for grid or step-based animation:\n\n```javascript\ngsap.to(\".x\", { x: 200, snap: { x: 20 } });\n```\n\n### shuffle(array)\n\nReturns a new array with the same elements in random order. Use for randomizing order (e.g. stagger from \"random\" with a copy).\n\n```javascript\ngsap.utils.shuffle([1, 2, 3, 4]); \u002F\u002F e.g. [3, 1, 4, 2]\n```\n\n### distribute(config)\n\n**Returns a function** that assigns a value to each target based on its position in the array (or in a grid). Used internally for advanced staggers; use it whenever you need values spread across many elements (e.g. scale, opacity, x, delay). The returned function receives `(index, target, targets)` — either call it manually or pass the result directly into a tween; GSAP will call it per target with index, element, and array.\n\n**Config (all optional):**\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `base` | Number | Starting value. Default `0`. |\n| `amount` | Number | Total to distribute across all targets (added to base). E.g. `amount: 1` with 100 targets → 0.01 between each. Use **each** instead to set a fixed step per target. |\n| `each` | Number | Amount to add between each target (added to base). E.g. `each: 1` with 4 targets → 0, 1, 2, 3. Use **amount** instead to split a total. |\n| `from` | Number \\| String \\| Array | Where distribution starts: index, or `\"start\"`, `\"center\"`, `\"edges\"`, `\"random\"`, `\"end\"`, or ratios like `[0.25, 0.75]`. Default `0`. |\n| `grid` | String \\| Array | Use grid position instead of flat index: `[rows, columns]` (e.g. `[5, 10]`) or `\"auto\"` to detect. Omit for flat array. |\n| `axis` | String | For grid: limit to one axis (`\"x\"` or `\"y\"`). |\n| `ease` | Ease | Distribute values along an ease curve (e.g. `\"power1.inOut\"`). Default `\"none\"`. |\n\n**In a tween:** pass the result of `distribute(config)` as the property value; GSAP calls the function for each target with `(index, target, targets)`.\n\n```javascript\n\u002F\u002F Scale: middle elements 0.5, outer edges 3 (amount 2.5 distributed from center)\ngsap.to(\".class\", {\n  scale: gsap.utils.distribute({\n    base: 0.5,\n    amount: 2.5,\n    from: \"center\"\n  })\n});\n```\n\n**Manual use:** call the returned function with `(index, target, targets)` to get the value for that index.\n\n```javascript\nconst distributor = gsap.utils.distribute({\n  base: 50,\n  amount: 100,\n  from: \"center\",\n  ease: \"power1.inOut\"\n});\nconst targets = gsap.utils.toArray(\".box\");\nconst valueForIndex2 = distributor(2, targets[2], targets);\n```\n\nSee [distribute()](https:\u002F\u002Fgsap.com\u002Fdocs\u002Fv3\u002FGSAP\u002FUtilityMethods\u002Fdistribute\u002F) for more.\n\n## Units and Parsing\n\n### getUnit(value)\n\nReturns the unit string of a value (e.g. `\"px\"`, `\"%\"`, `\"deg\"`). Use when normalizing or converting values.\n\n```javascript\ngsap.utils.getUnit(\"100px\");   \u002F\u002F \"px\"\ngsap.utils.getUnit(\"50%\");     \u002F\u002F \"%\"\ngsap.utils.getUnit(42);        \u002F\u002F \"\" (unitless)\n```\n\n### unitize(value, unit)\n\nAppends a unit to a number, or returns the value as-is if it already has a unit. Use when building CSS values or tween end values.\n\n```javascript\ngsap.utils.unitize(100, \"px\");  \u002F\u002F \"100px\"\ngsap.utils.unitize(\"2rem\", \"px\"); \u002F\u002F \"2rem\" (unchanged)\n```\n\n### splitColor(color, returnHSL?)\n\nConverts a color string into an array: **[red, green, blue]** (0–255), or **[red, green, blue, alpha]** (4 elements for RGBA when alpha is present or required). Pass **true** as the second argument (**returnHSL**) to get **[hue, saturation, lightness]** or **[hue, saturation, lightness, alpha]** (HSL\u002FHSLA) instead. Works with `\"rgb()\"`, `\"rgba()\"`, `\"hsl()\"`, `\"hsla()\"`, hex, and named colors (e.g. `\"red\"`). Use when animating color components or building gradients. See [splitColor()](https:\u002F\u002Fgsap.com\u002Fdocs\u002Fv3\u002FGSAP\u002FUtilityMethods\u002FsplitColor\u002F).\n\n```javascript\ngsap.utils.splitColor(\"red\");                    \u002F\u002F [255, 0, 0]\ngsap.utils.splitColor(\"#6fb936\");                \u002F\u002F [111, 185, 54]\ngsap.utils.splitColor(\"rgba(204, 153, 51, 0.5)\"); \u002F\u002F [204, 153, 51, 0.5] (4 elements)\ngsap.utils.splitColor(\"#6fb936\", true);          \u002F\u002F [94, 55, 47] (HSL: hue, saturation, lightness)\n```\n\n## Arrays and Collections\n\n### selector(scope)\n\nReturns a scoped selector function that finds elements only within the given element (or ref). Use in components so selectors like `\".box\"` match only descendants of that component, not the whole document. Accepts a DOM element or a ref (e.g. React ref; handles `.current`).\n\n```javascript\nconst q = gsap.utils.selector(containerRef);\nq(\".box\");        \u002F\u002F array of .box elements inside container\ngsap.to(q(\".circle\"), { x: 100 });\n```\n\n### toArray(value, scope?)\n\nConverts a value to an array: selector string (scoped to element), NodeList, HTMLCollection, single element, or array. Use when passing mixed inputs to GSAP (e.g. targets) and a true array is needed.\n\n```javascript\ngsap.utils.toArray(\".item\");           \u002F\u002F array of elements\ngsap.utils.toArray(\".item\", container); \u002F\u002F scoped to container\ngsap.utils.toArray(nodeList);          \u002F\u002F [ ... ] from NodeList\n```\n\n### pipe(...functions)\n\nComposes functions: **pipe(f1, f2, f3)(value)** returns f3(f2(f1(value))). Use when applying a chain of transforms (e.g. normalize → mapRange → snap) in a tween or callback.\n\n```javascript\nconst fn = gsap.utils.pipe(\n  (v) => gsap.utils.normalize(0, 100, v),\n  (v) => gsap.utils.snap(0.1, v)\n);\nfn(50); \u002F\u002F normalized then snapped\n```\n\n### wrap(min, max, value?)\n\nWraps a value into the range min–max (inclusive min, exclusive max). Use for infinite scroll or cyclic values. Omit **value** to get a function: `wrap(min, max)(value)`.\n\n```javascript\ngsap.utils.wrap(0, 360, 370);  \u002F\u002F 10\ngsap.utils.wrap(0, 360, -10);   \u002F\u002F 350\n\nlet wrapFn = gsap.utils.wrap(0, 360);\nwrapFn(370); \u002F\u002F 10\n```\n\n### wrapYoyo(min, max, value?)\n\nWraps value in range with a yoyo (bounces at ends). Use for back-and-forth within a range. Omit **value** to get a function: `wrapYoyo(min, max)(value)`.\n\n```javascript\ngsap.utils.wrapYoyo(0, 100, 150); \u002F\u002F 50 (bounces back)\n\nlet wrapY = gsap.utils.wrapYoyo(0, 100);\nwrapY(150); \u002F\u002F 50\n```\n\n## Best practices\n\n- ✅ Omit the value argument to get a reusable function when the same range\u002Fconfig is used many times (e.g. scroll handler, tween callback): `let mapFn = gsap.utils.mapRange(0, 1, 0, 360); mapFn(progress)`.\n- ✅ Use **snap** for grid-aligned or step-based values; use **toArray** when GSAP or your code needs a real array from a selector or NodeList.\n- ✅ Use **gsap.utils.selector(scope)** in components so selectors are scoped to a container or ref.\n\n## Do Not\n\n- ❌ Assume **mapRange** \u002F **normalize** handle units; they work on numbers. Use **getUnit** \u002F **unitize** when units matter.\n- ❌ Override or rely on undocumented behavior; stick to the documented API.\n\n### Learn More\n\nhttps:\u002F\u002Fgsap.com\u002Fdocs\u002Fv3\u002FHelperFunctions\n",{"name":5,"license":15,"description":7},"main","ea593e2a5e7b11104d9237b87890f98f16cf5ec4",".agents\u002Fskills\u002Fgsap-utils","https:\u002F\u002Fgithub.com\u002FAmon20044\u002FNetra","https:\u002F\u002Ftrynetra-one.vercel.app","https:\u002F\u002Fgithub.com\u002FAmon20044","https:\u002F\u002Famon-sharma.vercel.app","The tip of pen and my name starts from beginning to create a new beginning. ","2026-05-31 17:50:01",{"source":8,"skillName":5,"commands":34,"prompt":44,"zipAvailable":45},[35,38,41],{"tool":36,"command":37},"npx","npx skills add Amon20044\u002FNetra --skill gsap-utils",{"tool":39,"command":40},"bunx","bunx skills add Amon20044\u002FNetra --skill gsap-utils",{"tool":42,"command":43},"pnpm","pnpm dlx skills add Amon20044\u002FNetra --skill gsap-utils","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FAmon20044\u002FNetra\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fgsap-utils\u002FSKILL.md",true,[],[48,57,65,73,81,89],{"skillNo":49,"name":50,"nameZh":6,"description":51,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":52,"licenseFileUrl":53,"sourceHtmlUrl":54,"categories":55,"keywords":56,"publishedAt":19},"01M754J915QPX71N3ME2K0E57F","webapp-testing","Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.","Apache-2.0","https:\u002F\u002Fgithub.com\u002FAmon20044\u002FNetra\u002Fblob\u002Fmain\u002Fpackages\u002Fai-html-artifacts\u002Fagent-instructions\u002Fskills\u002Fwebapp-testing\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002FAmon20044\u002FNetra\u002Fblob\u002Fmain\u002Fpackages\u002Fai-html-artifacts\u002Fagent-instructions\u002Fskills\u002Fwebapp-testing\u002FSKILL.md",[],[],{"skillNo":58,"name":59,"nameZh":6,"description":60,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":52,"licenseFileUrl":61,"sourceHtmlUrl":62,"categories":63,"keywords":64,"publishedAt":19},"01M754J4SR1DP1Z2A8RM97VTTY","web-artifacts-builder","Suite of tools for creating elaborate, multi-component claude.ai HTML artifacts using modern frontend web technologies (React, Tailwind CSS, shadcn\u002Fui). Use for complex artifacts requiring state management, routing, or shadcn\u002Fui components - not for simple single-file HTML\u002FJSX artifacts.","https:\u002F\u002Fgithub.com\u002FAmon20044\u002FNetra\u002Fblob\u002Fmain\u002Fpackages\u002Fai-html-artifacts\u002Fagent-instructions\u002Fskills\u002Fweb-artifacts-builder\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002FAmon20044\u002FNetra\u002Fblob\u002Fmain\u002Fpackages\u002Fai-html-artifacts\u002Fagent-instructions\u002Fskills\u002Fweb-artifacts-builder\u002FSKILL.md",[],[],{"skillNo":66,"name":67,"nameZh":6,"description":68,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":52,"licenseFileUrl":69,"sourceHtmlUrl":70,"categories":71,"keywords":72,"publishedAt":19},"01M754GWN52K291RWE98F02RSX","theme-factory","Toolkit for styling artifacts with a theme. These artifacts can be slides, docs, reportings, HTML landing pages, etc. There are 10 pre-set themes with colors\u002Ffonts that you can apply to any artifact that has been creating, or can generate a new theme on-the-fly.","https:\u002F\u002Fgithub.com\u002FAmon20044\u002FNetra\u002Fblob\u002Fmain\u002Fpackages\u002Fai-html-artifacts\u002Fagent-instructions\u002Fskills\u002Ftheme-factory\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002FAmon20044\u002FNetra\u002Fblob\u002Fmain\u002Fpackages\u002Fai-html-artifacts\u002Fagent-instructions\u002Fskills\u002Ftheme-factory\u002FSKILL.md",[],[],{"skillNo":74,"name":75,"nameZh":6,"description":76,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":52,"licenseFileUrl":77,"sourceHtmlUrl":78,"categories":79,"keywords":80,"publishedAt":19},"01M754GRE5BMZMPDAEGPJBEY6Z","slack-gif-creator","Knowledge and utilities for creating animated GIFs optimized for Slack. Provides constraints, validation tools, and animation concepts. Use when users request animated GIFs for Slack like \"make me a GIF of X doing Y for Slack.\"","https:\u002F\u002Fgithub.com\u002FAmon20044\u002FNetra\u002Fblob\u002Fmain\u002Fpackages\u002Fai-html-artifacts\u002Fagent-instructions\u002Fskills\u002Fslack-gif-creator\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002FAmon20044\u002FNetra\u002Fblob\u002Fmain\u002Fpackages\u002Fai-html-artifacts\u002Fagent-instructions\u002Fskills\u002Fslack-gif-creator\u002FSKILL.md",[],[],{"skillNo":82,"name":83,"nameZh":6,"description":84,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":52,"licenseFileUrl":85,"sourceHtmlUrl":86,"categories":87,"keywords":88,"publishedAt":19},"01M754GJSJ2Z3DRSEAP5Z3TP5C","skill-creator","Create new skills, modify and improve existing skills, and measure skill performance. Use when users want to create a skill from scratch, edit, or optimize an existing skill, run evals to test a skill, benchmark skill performance with variance analysis, or optimize a skill's description for better triggering accuracy.","https:\u002F\u002Fgithub.com\u002FAmon20044\u002FNetra\u002Fblob\u002Fmain\u002Fpackages\u002Fai-html-artifacts\u002Fagent-instructions\u002Fskills\u002Fskill-creator\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002FAmon20044\u002FNetra\u002Fblob\u002Fmain\u002Fpackages\u002Fai-html-artifacts\u002Fagent-instructions\u002Fskills\u002Fskill-creator\u002FSKILL.md",[],[],{"skillNo":90,"name":91,"nameZh":6,"description":92,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":52,"licenseFileUrl":93,"sourceHtmlUrl":94,"categories":95,"keywords":96,"publishedAt":19},"01M754G1M19TFXBKFTNKQT9KTG","mcp-builder","Guide for creating high-quality MCP (Model Context Protocol) servers that enable LLMs to interact with external services through well-designed tools. Use when building MCP servers to integrate external APIs or services, whether in Python (FastMCP) or Node\u002FTypeScript (MCP SDK).","https:\u002F\u002Fgithub.com\u002FAmon20044\u002FNetra\u002Fblob\u002Fmain\u002Fpackages\u002Fai-html-artifacts\u002Fagent-instructions\u002Fskills\u002Fmcp-builder\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002FAmon20044\u002FNetra\u002Fblob\u002Fmain\u002Fpackages\u002Fai-html-artifacts\u002Fagent-instructions\u002Fskills\u002Fmcp-builder\u002FSKILL.md",[],[]]