@dava96/osrs-icons 1.0.16 → 1.0.17

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.
Files changed (57) hide show
  1. package/LICENSE +25 -0
  2. package/README.md +112 -26
  3. package/dist/cjs/animateCursor.d.ts +72 -0
  4. package/dist/cjs/animateCursor.d.ts.map +1 -0
  5. package/dist/cjs/animateCursor.js +94 -0
  6. package/dist/cjs/applyCursors.d.ts +1 -0
  7. package/dist/cjs/applyCursors.d.ts.map +1 -0
  8. package/dist/cjs/flip.d.ts +31 -9
  9. package/dist/cjs/flip.d.ts.map +1 -0
  10. package/dist/cjs/flip.js +53 -15
  11. package/dist/cjs/generated/icons.d.ts +1 -0
  12. package/dist/cjs/generated/icons.d.ts.map +1 -0
  13. package/dist/cjs/generated/meta.d.ts +15 -0
  14. package/dist/cjs/generated/meta.d.ts.map +1 -0
  15. package/dist/cjs/generated/meta.js +14 -0
  16. package/dist/cjs/index.d.ts +12 -0
  17. package/dist/cjs/index.d.ts.map +1 -0
  18. package/dist/cjs/index.js +14 -1
  19. package/dist/cjs/packs.d.ts +74 -100
  20. package/dist/cjs/packs.d.ts.map +1 -0
  21. package/dist/cjs/packs.js +120 -110
  22. package/dist/esm/animateCursor.d.ts +72 -0
  23. package/dist/esm/animateCursor.d.ts.map +1 -0
  24. package/dist/esm/animateCursor.js +91 -0
  25. package/dist/esm/applyCursors.d.ts +1 -0
  26. package/dist/esm/applyCursors.d.ts.map +1 -0
  27. package/dist/esm/flip.d.ts +31 -9
  28. package/dist/esm/flip.d.ts.map +1 -0
  29. package/dist/esm/flip.js +51 -13
  30. package/dist/esm/generated/icons.d.ts +1 -0
  31. package/dist/esm/generated/icons.d.ts.map +1 -0
  32. package/dist/esm/generated/meta.d.ts +15 -0
  33. package/dist/esm/generated/meta.d.ts.map +1 -0
  34. package/dist/esm/generated/meta.js +14 -0
  35. package/dist/esm/index.d.ts +12 -0
  36. package/dist/esm/index.d.ts.map +1 -0
  37. package/dist/esm/index.js +14 -1
  38. package/dist/esm/packs.d.ts +74 -100
  39. package/dist/esm/packs.d.ts.map +1 -0
  40. package/dist/esm/packs.js +120 -110
  41. package/package.json +2 -2
  42. package/dist/cjs/applyCursors_test.d.ts +0 -1
  43. package/dist/cjs/applyCursors_test.js +0 -41
  44. package/dist/cjs/flip_test.d.ts +0 -1
  45. package/dist/cjs/flip_test.js +0 -39
  46. package/dist/cjs/index_test.d.ts +0 -1
  47. package/dist/cjs/index_test.js +0 -110
  48. package/dist/cjs/packs_test.d.ts +0 -1
  49. package/dist/cjs/packs_test.js +0 -110
  50. package/dist/esm/applyCursors_test.d.ts +0 -1
  51. package/dist/esm/applyCursors_test.js +0 -36
  52. package/dist/esm/flip_test.d.ts +0 -1
  53. package/dist/esm/flip_test.js +0 -34
  54. package/dist/esm/index_test.d.ts +0 -1
  55. package/dist/esm/index_test.js +0 -105
  56. package/dist/esm/packs_test.d.ts +0 -1
  57. package/dist/esm/packs_test.js +0 -105
package/LICENSE ADDED
@@ -0,0 +1,25 @@
1
+ Attribution — NonCommercial — ShareAlike 3.0 Unported
2
+ (CC BY-NC-SA 3.0)
3
+
4
+ Full licence text: https://creativecommons.org/licenses/by-nc-sa/3.0/legalcode
5
+
6
+ You are free to:
7
+
8
+ Share — copy and redistribute the material in any medium or format.
9
+ Adapt — remix, transform, and build upon the material.
10
+
11
+ Under the following terms:
12
+
13
+ Attribution — You must give appropriate credit, provide a link to
14
+ the licence, and indicate if changes were made.
15
+
16
+ NonCommercial — You may not use the material for commercial purposes.
17
+
18
+ ShareAlike — If you remix, transform, or build upon the material, you
19
+ must distribute your contributions under the same licence.
20
+
21
+ ---
22
+
23
+ This project is not affiliated with Jagex Ltd.
24
+ OSRS icons are sourced from the Old School RuneScape Wiki and are the
25
+ property of Jagex / the Wiki contributors.
package/README.md CHANGED
@@ -8,12 +8,47 @@ Designed for easy integration with modern web apps, with full tree-shaking suppo
8
8
  [![license](https://img.shields.io/npm/l/@dava96/osrs-icons)](./LICENSE)
9
9
  [![GitHub stars](https://img.shields.io/github/stars/Dava96/osrs-icons)](https://github.com/Dava96/osrs-icons)
10
10
 
11
+ 📖 **[Browse icons & build packs →](https://dava96.github.io/osrs-icons/)**
12
+
13
+ ## Table of Contents
14
+
15
+ - [Installation](#installation)
16
+ - [Quick Start](#quick-start)
17
+ - [Usage](#usage)
18
+ - [CSS Cursor](#css-cursor-tree-shaking-supported)
19
+ - [As an Image](#as-an-image)
20
+ - [Icon Discovery](#icon-discovery)
21
+ - [CDN (No Build Step)](#cdn-usage-no-build-step)
22
+ - [Cursor Packs](#cursor-packs)
23
+ - [Utilities](#utilities)
24
+ - [flipCursor](#flip-cursor)
25
+ - [applyCursors](#apply-cursors)
26
+ - [errorCursor](#error-cursor-)
27
+ - [API Reference](#api-reference)
28
+ - [Browser Compatibility](#browser-compatibility)
29
+ - [How It Works](#how-it-works)
30
+ - [Contributing](#contributing)
31
+ - [License](#license)
32
+
11
33
  ## Installation
12
34
 
13
35
  ```bash
14
36
  npm install @dava96/osrs-icons
15
37
  ```
16
38
 
39
+ ## Quick Start
40
+
41
+ ```tsx
42
+ import { abyssalWhip } from '@dava96/osrs-icons';
43
+
44
+ // As a cursor
45
+ <div style={{ cursor: abyssalWhip }}>Hover me!</div>;
46
+
47
+ // As an image
48
+ import { toDataUrl } from '@dava96/osrs-icons';
49
+ <img src={toDataUrl(abyssalWhip)} alt="Abyssal Whip" />;
50
+ ```
51
+
17
52
  ## Usage
18
53
 
19
54
  ### CSS Cursor (Tree-Shaking Supported)
@@ -38,7 +73,7 @@ Use the `toDataUrl` helper to extract the raw data URL for use outside of CSS:
38
73
  import { abyssalWhip, dragonScimitar, toDataUrl } from '@dava96/osrs-icons';
39
74
 
40
75
  // Single icon
41
- <img src={toDataUrl(abyssalWhip)} alt="Abyssal Whip" />
76
+ <img src={toDataUrl(abyssalWhip)} alt="Abyssal Whip" />;
42
77
 
43
78
  // Multiple icons at once
44
79
  const urls = toDataUrl({
@@ -57,10 +92,12 @@ Browse all available icons programmatically with `iconNames`, or restrict values
57
92
  import { iconNames, type IconName } from '@dava96/osrs-icons';
58
93
 
59
94
  // Search / autocomplete
60
- const results = iconNames.filter(name => name.includes('dragon'));
95
+ const results = iconNames.filter((name) => name.includes('dragon'));
61
96
 
62
97
  // Type-safe icon references
63
- function setCustomCursor(name: IconName) { /* ... */ }
98
+ function setCustomCursor(name: IconName) {
99
+ /* ... */
100
+ }
64
101
  ```
65
102
 
66
103
  ### CDN Usage (No Build Step)
@@ -70,52 +107,52 @@ You can use the package directly in the browser via ESM.sh:
70
107
  ```html
71
108
  <script type="module">
72
109
  import { AbyssalWhip } from 'https://esm.sh/@dava96/osrs-icons';
73
-
110
+
74
111
  document.body.style.cursor = AbyssalWhip;
75
112
  </script>
76
113
  ```
77
114
 
78
- ### Cursor Packs
115
+ ## Cursor Packs
79
116
 
80
117
  Pre-built thematic icon groups — each pack groups related icons by their in-game state:
81
118
 
82
119
  ```ts
83
- import { sharkPack, dragonDaggerPack, bucketPack } from '@dava96/osrs-icons';
84
-
85
- // Fish: raw → cooked → burnt
86
- element.style.cursor = sharkPack.cooked;
120
+ import { runePack, bucketPack, coinsPack } from '@dava96/osrs-icons';
87
121
 
88
- // Dragon dagger: base poisoned p+ → p++
89
- element.style.cursor = dragonDaggerPack.poisonedPlusPlus;
122
+ // Rune pack all 10 F2P runes
123
+ element.style.cursor = runePack.air;
90
124
 
91
125
  // Bucket fill progression — great for loading states
92
126
  const stages = bucketPack.stages; // [empty, 1/5, 2/5, 3/5, 4/5, full]
93
- const index = Math.min(Math.floor(progress / 100 * stages.length), stages.length - 1);
127
+ const index = Math.min(Math.floor((progress / 100) * stages.length), stages.length - 1);
94
128
  element.style.cursor = stages[index];
95
129
  ```
96
130
 
97
131
  **Available packs:**
98
132
 
99
- | Pack | Keys |
100
- |------|------|
101
- | `sharkPack` | `raw`, `cooked`, `burnt` |
102
- | `herringPack` | `raw`, `cooked`, `burnt`, `error` |
103
- | `anglerfishPack` | `raw`, `cooked`, `burnt` |
104
- | `dragonDaggerPack` | `base`, `poisoned`, `poisonedPlus`, `poisonedPlusPlus` |
105
- | `goldPack` | `ore`, `bar` |
106
- | `ironPack` | `ore`, `bar` |
107
- | `coinsPack` | `_1` to `_10000` + `stages[]` |
108
- | `bucketPack` | `empty` to `full` + `stages[]` |
133
+ | Pack | Keys |
134
+ | ------------ | ----------------------------------------------------------------------------------------------- |
135
+ | `coinsPack` | `_1` to `_10000` + `stages[]` |
136
+ | `bucketPack` | `empty` to `full` + `stages[]` |
137
+ | `runePack` | `air`, `fire`, `water`, `earth`, `chaos`, `mind`, `death`, `law`, `nature`, `body` + `stages[]` |
138
+
139
+ ## Utilities
109
140
 
110
141
  ### Flip Cursor
111
142
 
112
- Many OSRS icons face right, but cursors typically point left. Flip any icon horizontally at runtime:
143
+ Many OSRS icons face right, but cursors typically point left. Flip one icon, an array, or an entire pack:
113
144
 
114
145
  ```ts
115
- import { abyssalWhip, flipCursor } from '@dava96/osrs-icons';
146
+ import { abyssalWhip, runePack, flipCursor } from '@dava96/osrs-icons';
116
147
 
148
+ // Single icon
117
149
  const leftFacing = await flipCursor(abyssalWhip);
118
- document.body.style.cursor = leftFacing;
150
+
151
+ // Array of icons
152
+ const [flippedAir, flippedFire] = await flipCursor([runePack.air, runePack.fire]);
153
+
154
+ // Entire pack — flips all values and stages in one call
155
+ const flippedRunes = await flipCursor(runePack);
119
156
  ```
120
157
 
121
158
  Results are cached internally — flipping the same icon twice returns instantly. Browser-only (uses Canvas API); returns the original value in Node.js/SSR.
@@ -154,6 +191,45 @@ import { errorCursor } from '@dava96/osrs-icons';
154
191
  element.style.cursor = errorCursor;
155
192
  ```
156
193
 
194
+ ## API Reference
195
+
196
+ ### Types
197
+
198
+ | Type | Description |
199
+ | --------------- | ------------------------------------------------------------------------------------------ |
200
+ | `IconName` | Union of all valid icon name strings (for type-safe references) |
201
+ | `CursorMapping` | `Partial<Record<CursorState, string>>` — maps CSS cursor states to icon values |
202
+ | `CursorState` | `'default' \| 'pointer' \| 'wait' \| 'text' \| 'move' \| ...` — standard CSS cursor states |
203
+
204
+ ### Functions
205
+
206
+ | Function | Signature | Description |
207
+ | -------------- | ------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
208
+ | `toDataUrl` | `(cursor: string) → string` | Extracts the raw `data:image/png;base64,...` URL from a CSS cursor value |
209
+ | `toDataUrl` | `(cursors: Record<K, string>) → Record<K, string>` | Batch version — extracts URLs from multiple cursor values |
210
+ | `flipCursor` | `(cursor: string) → Promise<string>` | Horizontally flips a cursor icon at runtime via Canvas API. Cached. Browser-only. |
211
+ | `applyCursors` | `(mapping: CursorMapping, target?: HTMLElement) → () => void` | Injects a `<style>` tag mapping cursor states to OSRS icons. Returns a cleanup function. |
212
+
213
+ ### Constants
214
+
215
+ | Export | Type | Description |
216
+ | ------------- | ------------------------ | ---------------------------------------------------------- |
217
+ | `iconNames` | `readonly string[]` | Array of all available icon name strings |
218
+ | `errorCursor` | `string` | Semantic alias for `redHerring` |
219
+ | `*Pack` | `Record<string, string>` | Pre-built cursor packs (see [Cursor Packs](#cursor-packs)) |
220
+
221
+ ## Browser Compatibility
222
+
223
+ | Feature | Browser | Node.js / SSR |
224
+ | -------------- | ---------------------- | ------------------------- |
225
+ | Icon imports | ✅ All | ✅ All |
226
+ | `toDataUrl` | ✅ All | ✅ All |
227
+ | `applyCursors` | ✅ All modern | ⚠️ Returns no-op cleanup |
228
+ | `flipCursor` | ✅ Canvas API required | ⚠️ Returns original value |
229
+ | Cursor packs | ✅ All | ✅ All |
230
+
231
+ All features are SSR-safe — browser-only features degrade gracefully in Node.js environments by returning safe fallback values.
232
+
157
233
  ## How It Works
158
234
 
159
235
  The build script fetches every inventory sprite (~17,400 icons) from the
@@ -162,9 +238,19 @@ compresses them as palette PNGs, and generates a TypeScript file of named export
162
238
 
163
239
  Each icon is a small ~32×32 pixel sprite, base64-encoded inline — no external assets to host.
164
240
 
241
+ ### Package Output
242
+
243
+ | Format | Path | Use |
244
+ | ------ | --------------------- | ------------------------------------ |
245
+ | ESM | `dist/esm/index.js` | `import` (bundlers, modern browsers) |
246
+ | CJS | `dist/cjs/index.js` | `require()` (Node.js, legacy) |
247
+ | Types | `dist/cjs/index.d.ts` | TypeScript definitions |
248
+
249
+ The package has `"sideEffects": false` for optimal tree-shaking in Webpack, Rollup, Vite, and esbuild.
250
+
165
251
  ## Contributing
166
252
 
167
- See [CONTRIBUTING.md](./CONTRIBUTING.md) for details on updating icons and publishing new versions.
253
+ See [CONTRIBUTING.md](./CONTRIBUTING.md) for details on local development, updating icons, and publishing new versions.
168
254
 
169
255
  ## License
170
256
 
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Options for {@link animateCursor}.
3
+ */
4
+ export interface AnimateCursorOptions {
5
+ /**
6
+ * Total duration of one full animation cycle in milliseconds.
7
+ * Each frame occupies `duration / frames.length` of the cycle.
8
+ *
9
+ * @default 1000
10
+ */
11
+ duration?: number;
12
+ /**
13
+ * Element to scope the animated cursor to.
14
+ * When omitted the cursor animates on the entire page (`*`).
15
+ */
16
+ target?: HTMLElement;
17
+ /**
18
+ * How many times the cycle should repeat.
19
+ * Use `Infinity` (the default) for a continuous loop.
20
+ *
21
+ * @default Infinity
22
+ */
23
+ iterations?: number;
24
+ }
25
+ /**
26
+ * Animates a cursor by cycling through an ordered array of OSRS icon
27
+ * strings using a pure‑CSS `@keyframes` rule.
28
+ *
29
+ * Each frame is assigned an equal slice of the total `duration` and
30
+ * transitions are **discrete** (`step-end`), producing a clean
31
+ * frame‑by‑frame sprite animation — no JavaScript timers required.
32
+ *
33
+ * **Browser‑only** — in non‑browser environments (Node / SSR) this
34
+ * is a no‑op that returns an empty cleanup function.
35
+ *
36
+ * @param frames - An ordered array of CSS cursor strings (≥ 2).
37
+ * @param options - Optional configuration for duration, target, and iterations.
38
+ * @returns A cleanup function that removes the injected styles and
39
+ * stops the animation.
40
+ *
41
+ * @throws {Error} If fewer than 2 frames are provided.
42
+ *
43
+ * @example
44
+ * ```ts
45
+ * import {
46
+ * coins1, coins2, coins3, coins4, coins5,
47
+ * animateCursor,
48
+ * } from '@dava96/osrs-icons';
49
+ *
50
+ * // Animate a growing coin stack on the whole page
51
+ * const stop = animateCursor(
52
+ * [coins1, coins2, coins3, coins4, coins5],
53
+ * { duration: 1200 },
54
+ * );
55
+ *
56
+ * // Later, stop the animation and clean up
57
+ * stop();
58
+ * ```
59
+ *
60
+ * @example
61
+ * ```ts
62
+ * import { lobsterRaw, lobsterCooked, lobsterBurnt, animateCursor } from '@dava96/osrs-icons';
63
+ *
64
+ * // Scope to a specific element, play 3 times
65
+ * const stop = animateCursor(
66
+ * [lobsterRaw, lobsterCooked, lobsterBurnt],
67
+ * { duration: 900, target: document.getElementById('cooking')!, iterations: 3 },
68
+ * );
69
+ * ```
70
+ */
71
+ export declare function animateCursor(frames: string[], options?: AnimateCursorOptions): () => void;
72
+ //# sourceMappingURL=animateCursor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"animateCursor.d.ts","sourceRoot":"","sources":["../../src/animateCursor.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;OAGG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;IAErB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE,oBAAyB,GAAG,MAAM,IAAI,CAiD9F"}
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.animateCursor = animateCursor;
4
+ /**
5
+ * Animates a cursor by cycling through an ordered array of OSRS icon
6
+ * strings using a pure‑CSS `@keyframes` rule.
7
+ *
8
+ * Each frame is assigned an equal slice of the total `duration` and
9
+ * transitions are **discrete** (`step-end`), producing a clean
10
+ * frame‑by‑frame sprite animation — no JavaScript timers required.
11
+ *
12
+ * **Browser‑only** — in non‑browser environments (Node / SSR) this
13
+ * is a no‑op that returns an empty cleanup function.
14
+ *
15
+ * @param frames - An ordered array of CSS cursor strings (≥ 2).
16
+ * @param options - Optional configuration for duration, target, and iterations.
17
+ * @returns A cleanup function that removes the injected styles and
18
+ * stops the animation.
19
+ *
20
+ * @throws {Error} If fewer than 2 frames are provided.
21
+ *
22
+ * @example
23
+ * ```ts
24
+ * import {
25
+ * coins1, coins2, coins3, coins4, coins5,
26
+ * animateCursor,
27
+ * } from '@dava96/osrs-icons';
28
+ *
29
+ * // Animate a growing coin stack on the whole page
30
+ * const stop = animateCursor(
31
+ * [coins1, coins2, coins3, coins4, coins5],
32
+ * { duration: 1200 },
33
+ * );
34
+ *
35
+ * // Later, stop the animation and clean up
36
+ * stop();
37
+ * ```
38
+ *
39
+ * @example
40
+ * ```ts
41
+ * import { lobsterRaw, lobsterCooked, lobsterBurnt, animateCursor } from '@dava96/osrs-icons';
42
+ *
43
+ * // Scope to a specific element, play 3 times
44
+ * const stop = animateCursor(
45
+ * [lobsterRaw, lobsterCooked, lobsterBurnt],
46
+ * { duration: 900, target: document.getElementById('cooking')!, iterations: 3 },
47
+ * );
48
+ * ```
49
+ */
50
+ function animateCursor(frames, options = {}) {
51
+ if (frames.length < 2) {
52
+ throw new Error(`animateCursor requires at least 2 frames, received ${frames.length}.`);
53
+ }
54
+ if (typeof document === 'undefined') {
55
+ return () => { };
56
+ }
57
+ const { duration = 1000, target, iterations = Infinity } = options;
58
+ const animationName = generateAnimationName();
59
+ const scopeId = `${animationName}-scope`;
60
+ const selector = target ? `[data-osrs-anim-id="${scopeId}"]` : '*';
61
+ if (target) {
62
+ target.setAttribute('data-osrs-anim-id', scopeId);
63
+ }
64
+ const keyframeSteps = frames
65
+ .map((cursorValue, index) => {
66
+ const percentage = ((index / frames.length) * 100).toFixed(2);
67
+ return ` ${percentage}% { cursor: ${cursorValue}; }`;
68
+ })
69
+ .join('\n');
70
+ const iterationCount = iterations === Infinity ? 'infinite' : String(iterations);
71
+ const css = [
72
+ `@keyframes ${animationName} {`,
73
+ keyframeSteps,
74
+ '}',
75
+ `${selector} {`,
76
+ ` animation: ${animationName} ${duration}ms step-end ${iterationCount};`,
77
+ '}',
78
+ ].join('\n');
79
+ const styleElement = document.createElement('style');
80
+ styleElement.textContent = css;
81
+ styleElement.setAttribute('data-osrs-animate', 'true');
82
+ document.head.appendChild(styleElement);
83
+ return () => {
84
+ styleElement.remove();
85
+ if (target) {
86
+ target.removeAttribute('data-osrs-anim-id');
87
+ }
88
+ };
89
+ }
90
+ /** Generates a short unique ID for animation scoping. */
91
+ let animCounter = 0;
92
+ function generateAnimationName() {
93
+ return `osrs-anim-${++animCounter}-${Date.now().toString(36)}`;
94
+ }
@@ -61,3 +61,4 @@ export type CursorMapping = Partial<Record<CursorState, string>>;
61
61
  * ```
62
62
  */
63
63
  export declare function applyCursors(mapping: CursorMapping, target?: HTMLElement): () => void;
64
+ //# sourceMappingURL=applyCursors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"applyCursors.d.ts","sourceRoot":"","sources":["../../src/applyCursors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,MAAM,WAAW,GACnB,SAAS,GACT,SAAS,GACT,MAAM,GACN,MAAM,GACN,MAAM,GACN,WAAW,GACX,MAAM,GACN,UAAU,GACV,aAAa,GACb,MAAM,GACN,UAAU,GACV,MAAM,GACN,MAAM,GACN,OAAO,GACP,SAAS,GACT,YAAY,GACZ,YAAY,GACZ,UAAU,GACV,UAAU,GACV,UAAU,GACV,UAAU,GACV,SAAS,GACT,UAAU,CAAC;AAEf;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;AAEjE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,aAAa,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,MAAM,IAAI,CA6BrF"}
@@ -1,33 +1,55 @@
1
1
  /**
2
- * Horizontally flips a CSS cursor icon so it points in the opposite direction.
2
+ * Horizontally flips CSS cursor icons so they point in the opposite direction.
3
3
  *
4
4
  * Many OSRS inventory icons face right, but cursor conventions typically
5
5
  * expect left-facing images. This helper mirrors the embedded base64 PNG
6
- * using the Canvas API and returns a new, ready-to-use CSS cursor string.
6
+ * using the Canvas API and returns new, ready-to-use CSS cursor strings.
7
7
  *
8
8
  * Results are cached internally — flipping the same icon twice returns
9
9
  * the cached value instantly.
10
10
  *
11
11
  * **Browser-only** — requires the Canvas API. In non-browser environments
12
- * (Node.js, SSR) the original cursor string is returned unchanged.
12
+ * (Node.js, SSR) the original cursor strings are returned unchanged.
13
13
  *
14
- * @param cursorValue - A CSS cursor string (e.g. `url('data:image/png;base64,...'), auto`).
15
- * @returns A promise that resolves to a new cursor string with the image flipped.
14
+ * Supports three input shapes:
15
+ * - **Single string** returns a single flipped string.
16
+ * - **Array of strings** → returns an array of flipped strings (same order).
17
+ * - **Record of strings** → returns a record with the same keys, values flipped.
18
+ * Perfect for flipping an entire pack in one call.
16
19
  *
17
20
  * @example
18
21
  * ```ts
19
22
  * import { abyssalWhip, flipCursor } from '@dava96/osrs-icons';
20
23
  *
21
- * const leftFacingWhip = await flipCursor(abyssalWhip);
22
- * document.body.style.cursor = leftFacingWhip;
24
+ * // Single icon
25
+ * const flipped = await flipCursor(abyssalWhip);
26
+ * document.body.style.cursor = flipped;
23
27
  * ```
24
28
  *
25
29
  * @example
26
30
  * ```ts
27
- * import { dragonDaggerPack, flipCursor } from '@dava96/osrs-icons';
31
+ * import { coinsPack, flipCursor } from '@dava96/osrs-icons';
28
32
  *
29
33
  * // Flip an entire pack
30
- * const flippedDagger = await flipCursor(dragonDaggerPack.base);
34
+ * const flippedPack = await flipCursor(coinsPack);
35
+ * // flippedPack._1, flippedPack._2, ... are all flipped
36
+ * // flippedPack.stages is a flipped array
37
+ * ```
38
+ *
39
+ * @example
40
+ * ```ts
41
+ * import { airRune, fireRune, flipCursor } from '@dava96/osrs-icons';
42
+ *
43
+ * // Flip an array of cursors
44
+ * const [flippedAir, flippedFire] = await flipCursor([airRune, fireRune]);
31
45
  * ```
32
46
  */
47
+ /** Flip a single CSS cursor string. */
33
48
  export declare function flipCursor(cursorValue: string): Promise<string>;
49
+ /** Flip an array of CSS cursor strings, preserving order. */
50
+ export declare function flipCursor(cursorValues: readonly string[]): Promise<string[]>;
51
+ /** Flip every string value in a record (e.g. a pack object), preserving keys. */
52
+ export declare function flipCursor<T extends Record<string, unknown>>(pack: T): Promise<{
53
+ [K in keyof T]: T[K] extends string ? string : T[K] extends readonly string[] ? string[] : T[K];
54
+ }>;
55
+ //# sourceMappingURL=flip.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flip.d.ts","sourceRoot":"","sources":["../../src/flip.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAUH,uCAAuC;AACvC,wBAAsB,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;AAEvE,6DAA6D;AAC7D,wBAAsB,UAAU,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;AAErF,iFAAiF;AACjF,wBAAsB,UAAU,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChE,IAAI,EAAE,CAAC,GACN,OAAO,CAAC;KACR,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;CAChG,CAAC,CAAC"}
package/dist/cjs/flip.js CHANGED
@@ -1,46 +1,86 @@
1
1
  "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.flipCursor = flipCursor;
4
2
  /**
5
- * Horizontally flips a CSS cursor icon so it points in the opposite direction.
3
+ * Horizontally flips CSS cursor icons so they point in the opposite direction.
6
4
  *
7
5
  * Many OSRS inventory icons face right, but cursor conventions typically
8
6
  * expect left-facing images. This helper mirrors the embedded base64 PNG
9
- * using the Canvas API and returns a new, ready-to-use CSS cursor string.
7
+ * using the Canvas API and returns new, ready-to-use CSS cursor strings.
10
8
  *
11
9
  * Results are cached internally — flipping the same icon twice returns
12
10
  * the cached value instantly.
13
11
  *
14
12
  * **Browser-only** — requires the Canvas API. In non-browser environments
15
- * (Node.js, SSR) the original cursor string is returned unchanged.
13
+ * (Node.js, SSR) the original cursor strings are returned unchanged.
16
14
  *
17
- * @param cursorValue - A CSS cursor string (e.g. `url('data:image/png;base64,...'), auto`).
18
- * @returns A promise that resolves to a new cursor string with the image flipped.
15
+ * Supports three input shapes:
16
+ * - **Single string** returns a single flipped string.
17
+ * - **Array of strings** → returns an array of flipped strings (same order).
18
+ * - **Record of strings** → returns a record with the same keys, values flipped.
19
+ * Perfect for flipping an entire pack in one call.
19
20
  *
20
21
  * @example
21
22
  * ```ts
22
23
  * import { abyssalWhip, flipCursor } from '@dava96/osrs-icons';
23
24
  *
24
- * const leftFacingWhip = await flipCursor(abyssalWhip);
25
- * document.body.style.cursor = leftFacingWhip;
25
+ * // Single icon
26
+ * const flipped = await flipCursor(abyssalWhip);
27
+ * document.body.style.cursor = flipped;
26
28
  * ```
27
29
  *
28
30
  * @example
29
31
  * ```ts
30
- * import { dragonDaggerPack, flipCursor } from '@dava96/osrs-icons';
32
+ * import { coinsPack, flipCursor } from '@dava96/osrs-icons';
31
33
  *
32
34
  * // Flip an entire pack
33
- * const flippedDagger = await flipCursor(dragonDaggerPack.base);
35
+ * const flippedPack = await flipCursor(coinsPack);
36
+ * // flippedPack._1, flippedPack._2, ... are all flipped
37
+ * // flippedPack.stages is a flipped array
38
+ * ```
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * import { airRune, fireRune, flipCursor } from '@dava96/osrs-icons';
43
+ *
44
+ * // Flip an array of cursors
45
+ * const [flippedAir, flippedFire] = await flipCursor([airRune, fireRune]);
34
46
  * ```
35
47
  */
36
- async function flipCursor(cursorValue) {
48
+ Object.defineProperty(exports, "__esModule", { value: true });
49
+ exports.flipCursor = flipCursor;
50
+ /** Matches `url('...')` in a CSS cursor value. Precompiled to avoid re-creation per call. */
51
+ const FLIP_URL_REGEX = /url\('(.*?)'\)/;
52
+ /** Internal cache to avoid re-processing the same icon. */
53
+ const flipCache = new Map();
54
+ // ── Implementation ─────────────────────────────────────────────────
55
+ async function flipCursor(input) {
56
+ if (typeof input === 'string') {
57
+ return flipSingleCursor(input);
58
+ }
59
+ if (Array.isArray(input)) {
60
+ return Promise.all(input.map(flipSingleCursor));
61
+ }
62
+ const entries = Object.entries(input);
63
+ const flippedEntries = await Promise.all(entries.map(async ([key, value]) => {
64
+ if (typeof value === 'string') {
65
+ return [key, await flipSingleCursor(value)];
66
+ }
67
+ if (Array.isArray(value) && value.every((v) => typeof v === 'string')) {
68
+ return [key, await Promise.all(value.map(flipSingleCursor))];
69
+ }
70
+ return [key, value];
71
+ }));
72
+ return Object.fromEntries(flippedEntries);
73
+ }
74
+ // ── Internal helpers ───────────────────────────────────────────────
75
+ /** Flips a single CSS cursor string, using the cache. */
76
+ async function flipSingleCursor(cursorValue) {
37
77
  if (flipCache.has(cursorValue)) {
38
78
  return flipCache.get(cursorValue);
39
79
  }
40
80
  if (typeof document === 'undefined') {
41
81
  return cursorValue;
42
82
  }
43
- const dataUrlMatch = cursorValue.match(/url\('(.*?)'\)/);
83
+ const dataUrlMatch = cursorValue.match(FLIP_URL_REGEX);
44
84
  if (!dataUrlMatch) {
45
85
  return cursorValue;
46
86
  }
@@ -50,8 +90,6 @@ async function flipCursor(cursorValue) {
50
90
  flipCache.set(cursorValue, flippedCursor);
51
91
  return flippedCursor;
52
92
  }
53
- /** Internal cache to avoid re-processing the same icon. */
54
- const flipCache = new Map();
55
93
  /**
56
94
  * Loads a data URL into an off-screen canvas, mirrors it horizontally,
57
95
  * and returns the flipped image as a new data URL.
@@ -17413,3 +17413,4 @@ export declare const zurielsStaff = "url('data:image/png;base64,iVBORw0KGgoAAAAN
17413
17413
  export declare const zurielsStaffLastManStanding = "url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB0AAAAeCAMAAADn2eWTAAAAulBMVEVMaXFsZGRdV1dYUlJnYGBza2tOSUgAAAFIQ0NMRkZbVVV5cXCEenpqYmI8NzdWUFBjXFs5NDSJYF1dNzWkcm9UMC50Q0KFTkqKUU6JgH8/OjpwaWlFQEBQLiyHUExUTU2PVVGTZWNnPTpxQj99V1VkOjl/SkhmMi5hOTeMUlB5SEVXNDB2OjdzOTVcPz1CPT1MJCI1MDBmbmZye3JITkh2RkOU2sS75thboIx807mK1sBwxaxrvaWP2MLZgia+AAAAAXRSTlMAQObYZgAAAAlwSFlzAAALEwAACxMBAJqcGAAAAKxJREFUeNp902cCgyAMBWCU6lPr1qrde++973+t9gBJ+PsRHgRQih2AEvD15BgK9++HUWQ4394P0IEoytOFzkWaZpV2jqRi2AByNymqK8FYAeVh959C1k6Rx3tgQcfOJts1MKKPg56eb5aDLqNGNAbAoc03GJbLNx91CeFIlRJaEgYS1niEiIaEcdQSlvXckHti8Jt2wmHbt0w2FGbgCTvSdodHs++E0r3w3+kHfw4LUj07+AMAAAAASUVORK5CYII='), auto";
17414
17414
  export declare const zurielsStaffBh = "url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB0AAAAeCAMAAADn2eWTAAAAulBMVEVMaXFsZGRdV1dYUlJnYGBza2tOSUgAAAFIQ0NMRkZbVVV5cXCEenpqYmI8NzdWUFBjXFs5NDSJYF1dNzWkcm9UMC50Q0KFTkqKUU6JgH8/OjpwaWlFQEBQLiyHUExUTU2PVVGTZWNnPTpxQj99V1VkOjl/SkhmMi5hOTeMUlB5SEVXNDB2OjdzOTVcPz1CPT1MJCI1MDBmbmZye3JITkh2RkOU2sS75thboIx807mK1sBwxaxrvaWP2MLZgia+AAAAAXRSTlMAQObYZgAAAAlwSFlzAAALEwAACxMBAJqcGAAAAKxJREFUeNp902cCgyAMBWCU6lPr1qrde++973+t9gBJ+PsRHgRQih2AEvD15BgK9++HUWQ4394P0IEoytOFzkWaZpV2jqRi2AByNymqK8FYAeVh959C1k6Rx3tgQcfOJts1MKKPg56eb5aDLqNGNAbAoc03GJbLNx91CeFIlRJaEgYS1niEiIaEcdQSlvXckHti8Jt2wmHbt0w2FGbgCTvSdodHs++E0r3w3+kHfw4LUj07+AMAAAAASUVORK5CYII='), auto";
17415
17415
  export declare const zurielsStaffBhinactive = "url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB0AAAAeCAMAAADn2eWTAAAAsVBMVEVMaXFFQEA5NDQ3IB0oJiZjXFtMRkYAAAEyLi5UTU15SEVhOTdhWlpqYmI1MDBza2ssKipYUlJCPT1bVVU/OjpRSkpMLCpIKihmMi6VZ2V4VFE8NzdWUFBIQ0MkIiJOSUh5cXB/Skh2RkNUMC5dNzVuQD1xQj9nSEZALCqAWFZnPTo/JCRUKCY0GBh0Q0JVW1UgHR1kbGQ0OTRxx65uwahDdmdWmYWW2sZvw6tcoo5mtJ6pW+hyAAAAAXRSTlMAQObYZgAAAAlwSFlzAAALEwAACxMBAJqcGAAAAK9JREFUeNp901cCgyAMBmBU9K9oa7VaR4fde+/2/gerB0jCCw8fISGAUuwAlICPH8dQeH9ejCLH9f59gk6I4HS+0XlRVbnx7Aup2DpAmerABARjB6yOm2YJGdtHmWk0E5l2uS72wJw+DmbWoTBTh9FesgDAoc03GG6Hbz7aEqIlRUoYShhL6PMIEUMJh6OusG090NwTQzRJxhy6keuxSZHFllCRlwoV+ZatpXvhv9Mfx6IK2oVBcCAAAAAASUVORK5CYII='), auto";
17416
+ //# sourceMappingURL=icons.d.ts.map