@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.
- package/LICENSE +25 -0
- package/README.md +112 -26
- package/dist/cjs/animateCursor.d.ts +72 -0
- package/dist/cjs/animateCursor.d.ts.map +1 -0
- package/dist/cjs/animateCursor.js +94 -0
- package/dist/cjs/applyCursors.d.ts +1 -0
- package/dist/cjs/applyCursors.d.ts.map +1 -0
- package/dist/cjs/flip.d.ts +31 -9
- package/dist/cjs/flip.d.ts.map +1 -0
- package/dist/cjs/flip.js +53 -15
- package/dist/cjs/generated/icons.d.ts +1 -0
- package/dist/cjs/generated/icons.d.ts.map +1 -0
- package/dist/cjs/generated/meta.d.ts +15 -0
- package/dist/cjs/generated/meta.d.ts.map +1 -0
- package/dist/cjs/generated/meta.js +14 -0
- package/dist/cjs/index.d.ts +12 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +14 -1
- package/dist/cjs/packs.d.ts +74 -100
- package/dist/cjs/packs.d.ts.map +1 -0
- package/dist/cjs/packs.js +120 -110
- package/dist/esm/animateCursor.d.ts +72 -0
- package/dist/esm/animateCursor.d.ts.map +1 -0
- package/dist/esm/animateCursor.js +91 -0
- package/dist/esm/applyCursors.d.ts +1 -0
- package/dist/esm/applyCursors.d.ts.map +1 -0
- package/dist/esm/flip.d.ts +31 -9
- package/dist/esm/flip.d.ts.map +1 -0
- package/dist/esm/flip.js +51 -13
- package/dist/esm/generated/icons.d.ts +1 -0
- package/dist/esm/generated/icons.d.ts.map +1 -0
- package/dist/esm/generated/meta.d.ts +15 -0
- package/dist/esm/generated/meta.d.ts.map +1 -0
- package/dist/esm/generated/meta.js +14 -0
- package/dist/esm/index.d.ts +12 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +14 -1
- package/dist/esm/packs.d.ts +74 -100
- package/dist/esm/packs.d.ts.map +1 -0
- package/dist/esm/packs.js +120 -110
- package/package.json +2 -2
- package/dist/cjs/applyCursors_test.d.ts +0 -1
- package/dist/cjs/applyCursors_test.js +0 -41
- package/dist/cjs/flip_test.d.ts +0 -1
- package/dist/cjs/flip_test.js +0 -39
- package/dist/cjs/index_test.d.ts +0 -1
- package/dist/cjs/index_test.js +0 -110
- package/dist/cjs/packs_test.d.ts +0 -1
- package/dist/cjs/packs_test.js +0 -110
- package/dist/esm/applyCursors_test.d.ts +0 -1
- package/dist/esm/applyCursors_test.js +0 -36
- package/dist/esm/flip_test.d.ts +0 -1
- package/dist/esm/flip_test.js +0 -34
- package/dist/esm/index_test.d.ts +0 -1
- package/dist/esm/index_test.js +0 -105
- package/dist/esm/packs_test.d.ts +0 -1
- 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)
|
|
9
9
|
[](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
|
-
|
|
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 {
|
|
84
|
-
|
|
85
|
-
// Fish: raw → cooked → burnt
|
|
86
|
-
element.style.cursor = sharkPack.cooked;
|
|
120
|
+
import { runePack, bucketPack, coinsPack } from '@dava96/osrs-icons';
|
|
87
121
|
|
|
88
|
-
//
|
|
89
|
-
element.style.cursor =
|
|
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
|
|
100
|
-
|
|
101
|
-
| `
|
|
102
|
-
| `
|
|
103
|
-
| `
|
|
104
|
-
|
|
105
|
-
|
|
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
|
|
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
|
-
|
|
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
|
+
}
|
|
@@ -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"}
|
package/dist/cjs/flip.d.ts
CHANGED
|
@@ -1,33 +1,55 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Horizontally flips
|
|
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
|
|
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
|
|
12
|
+
* (Node.js, SSR) the original cursor strings are returned unchanged.
|
|
13
13
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
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
|
-
*
|
|
22
|
-
*
|
|
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 {
|
|
31
|
+
* import { coinsPack, flipCursor } from '@dava96/osrs-icons';
|
|
28
32
|
*
|
|
29
33
|
* // Flip an entire pack
|
|
30
|
-
* const
|
|
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
|
|
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
|
|
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
|
|
13
|
+
* (Node.js, SSR) the original cursor strings are returned unchanged.
|
|
16
14
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
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
|
-
*
|
|
25
|
-
*
|
|
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 {
|
|
32
|
+
* import { coinsPack, flipCursor } from '@dava96/osrs-icons';
|
|
31
33
|
*
|
|
32
34
|
* // Flip an entire pack
|
|
33
|
-
* const
|
|
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
|
-
|
|
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(
|
|
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
|