weasel-icons 0.10.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -0
- package/THIRD_PARTY_NOTICES.md +65 -1
- package/bin/cli.mjs +264 -0
- package/dist/icons/abacus/abacus-icon.d.ts +5 -0
- package/dist/icons/abacus/abacus-icon.js +9 -0
- package/dist/icons/abacus/abacus-rig.d.ts +40 -0
- package/dist/icons/abacus/abacus-rig.js +59 -0
- package/dist/icons/air-conditioner/air-conditioner-icon.d.ts +5 -0
- package/dist/icons/air-conditioner/air-conditioner-icon.js +9 -0
- package/dist/icons/air-conditioner/air-conditioner-rig.d.ts +74 -0
- package/dist/icons/air-conditioner/air-conditioner-rig.js +110 -0
- package/dist/icons/barrier-gate/barrier-gate-icon.d.ts +5 -0
- package/dist/icons/barrier-gate/barrier-gate-icon.js +9 -0
- package/dist/icons/barrier-gate/barrier-gate-rig.d.ts +25 -0
- package/dist/icons/barrier-gate/barrier-gate-rig.js +38 -0
- package/dist/icons/baseball/baseball-icon.d.ts +5 -0
- package/dist/icons/baseball/baseball-icon.js +9 -0
- package/dist/icons/baseball/baseball-rig.d.ts +89 -0
- package/dist/icons/baseball/baseball-rig.js +140 -0
- package/dist/icons/basketball/basketball-icon.d.ts +5 -0
- package/dist/icons/basketball/basketball-icon.js +9 -0
- package/dist/icons/basketball/basketball-rig.d.ts +77 -0
- package/dist/icons/basketball/basketball-rig.js +122 -0
- package/dist/icons/bus-stop/bus-stop-icon.d.ts +5 -0
- package/dist/icons/bus-stop/bus-stop-icon.js +9 -0
- package/dist/icons/bus-stop/bus-stop-rig.d.ts +46 -0
- package/dist/icons/bus-stop/bus-stop-rig.js +76 -0
- package/dist/icons/butterfly/butterfly-icon.d.ts +5 -0
- package/dist/icons/butterfly/butterfly-icon.js +9 -0
- package/dist/icons/butterfly/butterfly-rig.d.ts +64 -0
- package/dist/icons/butterfly/butterfly-rig.js +101 -0
- package/dist/icons/cactus/cactus-icon.d.ts +5 -0
- package/dist/icons/cactus/cactus-icon.js +9 -0
- package/dist/icons/cactus/cactus-rig.d.ts +85 -0
- package/dist/icons/cactus/cactus-rig.js +137 -0
- package/dist/icons/capacitor/capacitor-icon.d.ts +5 -0
- package/dist/icons/capacitor/capacitor-icon.js +9 -0
- package/dist/icons/capacitor/capacitor-rig.d.ts +60 -0
- package/dist/icons/capacitor/capacitor-rig.js +88 -0
- package/dist/icons/crane/crane-icon.d.ts +5 -0
- package/dist/icons/crane/crane-icon.js +9 -0
- package/dist/icons/crane/crane-rig.d.ts +59 -0
- package/dist/icons/crane/crane-rig.js +90 -0
- package/dist/icons/cricket-bat/cricket-bat-icon.d.ts +5 -0
- package/dist/icons/cricket-bat/cricket-bat-icon.js +9 -0
- package/dist/icons/cricket-bat/cricket-bat-rig.d.ts +107 -0
- package/dist/icons/cricket-bat/cricket-bat-rig.js +162 -0
- package/dist/icons/curling-stone/curling-stone-icon.d.ts +5 -0
- package/dist/icons/curling-stone/curling-stone-icon.js +9 -0
- package/dist/icons/curling-stone/curling-stone-rig.d.ts +83 -0
- package/dist/icons/curling-stone/curling-stone-rig.js +124 -0
- package/dist/icons/elevator/elevator-icon.d.ts +5 -0
- package/dist/icons/elevator/elevator-icon.js +9 -0
- package/dist/icons/elevator/elevator-rig.d.ts +62 -0
- package/dist/icons/elevator/elevator-rig.js +97 -0
- package/dist/icons/escalator/escalator-icon.d.ts +5 -0
- package/dist/icons/escalator/escalator-icon.js +9 -0
- package/dist/icons/escalator/escalator-rig.d.ts +66 -0
- package/dist/icons/escalator/escalator-rig.js +103 -0
- package/dist/icons/excavator/excavator-icon.d.ts +5 -0
- package/dist/icons/excavator/excavator-icon.js +9 -0
- package/dist/icons/excavator/excavator-rig.d.ts +64 -0
- package/dist/icons/excavator/excavator-rig.js +105 -0
- package/dist/icons/fire-hydrant/fire-hydrant-icon.d.ts +5 -0
- package/dist/icons/fire-hydrant/fire-hydrant-icon.js +9 -0
- package/dist/icons/fire-hydrant/fire-hydrant-rig.d.ts +167 -0
- package/dist/icons/fire-hydrant/fire-hydrant-rig.js +250 -0
- package/dist/icons/football/football-icon.d.ts +5 -0
- package/dist/icons/football/football-icon.js +9 -0
- package/dist/icons/football/football-rig.d.ts +81 -0
- package/dist/icons/football/football-rig.js +124 -0
- package/dist/icons/garden-cart/garden-cart-icon.d.ts +5 -0
- package/dist/icons/garden-cart/garden-cart-icon.js +9 -0
- package/dist/icons/garden-cart/garden-cart-rig.d.ts +66 -0
- package/dist/icons/garden-cart/garden-cart-rig.js +104 -0
- package/dist/icons/gearbox/gearbox-icon.d.ts +5 -0
- package/dist/icons/gearbox/gearbox-icon.js +24 -0
- package/dist/icons/gearbox/gearbox-rig.d.ts +34 -0
- package/dist/icons/gearbox/gearbox-rig.js +64 -0
- package/dist/icons/golf/golf-icon.d.ts +5 -0
- package/dist/icons/golf/golf-icon.js +9 -0
- package/dist/icons/golf/golf-rig.d.ts +34 -0
- package/dist/icons/golf/golf-rig.js +56 -0
- package/dist/icons/grill-spatula/grill-spatula-icon.d.ts +5 -0
- package/dist/icons/grill-spatula/grill-spatula-icon.js +9 -0
- package/dist/icons/grill-spatula/grill-spatula-rig.d.ts +89 -0
- package/dist/icons/grill-spatula/grill-spatula-rig.js +136 -0
- package/dist/icons/hot-air-balloon/hot-air-balloon-icon.d.ts +5 -0
- package/dist/icons/hot-air-balloon/hot-air-balloon-icon.js +9 -0
- package/dist/icons/hot-air-balloon/hot-air-balloon-rig.d.ts +84 -0
- package/dist/icons/hot-air-balloon/hot-air-balloon-rig.js +133 -0
- package/dist/icons/iron/iron-icon.d.ts +5 -0
- package/dist/icons/iron/iron-icon.js +9 -0
- package/dist/icons/iron/iron-rig.d.ts +52 -0
- package/dist/icons/iron/iron-rig.js +80 -0
- package/dist/icons/jetpack/jetpack-icon.d.ts +5 -0
- package/dist/icons/jetpack/jetpack-icon.js +9 -0
- package/dist/icons/jetpack/jetpack-rig.d.ts +103 -0
- package/dist/icons/jetpack/jetpack-rig.js +157 -0
- package/dist/icons/ladder/ladder-icon.d.ts +5 -0
- package/dist/icons/ladder/ladder-icon.js +9 -0
- package/dist/icons/ladder/ladder-rig.d.ts +80 -0
- package/dist/icons/ladder/ladder-rig.js +119 -0
- package/dist/icons/ladle/ladle-icon.d.ts +5 -0
- package/dist/icons/ladle/ladle-icon.js +9 -0
- package/dist/icons/ladle/ladle-rig.d.ts +86 -0
- package/dist/icons/ladle/ladle-rig.js +135 -0
- package/dist/icons/mushroom/mushroom-icon.d.ts +5 -0
- package/dist/icons/mushroom/mushroom-icon.js +9 -0
- package/dist/icons/mushroom/mushroom-rig.d.ts +49 -0
- package/dist/icons/mushroom/mushroom-rig.js +81 -0
- package/dist/icons/needle-thread/needle-thread-icon.d.ts +5 -0
- package/dist/icons/needle-thread/needle-thread-icon.js +9 -0
- package/dist/icons/needle-thread/needle-thread-rig.d.ts +33 -0
- package/dist/icons/needle-thread/needle-thread-rig.js +59 -0
- package/dist/icons/oven/oven-icon.d.ts +5 -0
- package/dist/icons/oven/oven-icon.js +9 -0
- package/dist/icons/oven/oven-rig.d.ts +51 -0
- package/dist/icons/oven/oven-rig.js +82 -0
- package/dist/icons/parachute/parachute-icon.d.ts +5 -0
- package/dist/icons/parachute/parachute-icon.js +9 -0
- package/dist/icons/parachute/parachute-rig.d.ts +25 -0
- package/dist/icons/parachute/parachute-rig.js +45 -0
- package/dist/icons/pinwheel/pinwheel-icon.d.ts +5 -0
- package/dist/icons/pinwheel/pinwheel-icon.js +9 -0
- package/dist/icons/pinwheel/pinwheel-rig.d.ts +116 -0
- package/dist/icons/pinwheel/pinwheel-rig.js +188 -0
- package/dist/icons/planet/planet-icon.d.ts +5 -0
- package/dist/icons/planet/planet-icon.js +9 -0
- package/dist/icons/planet/planet-rig.d.ts +61 -0
- package/dist/icons/planet/planet-rig.js +91 -0
- package/dist/icons/pliers/pliers-icon.d.ts +5 -0
- package/dist/icons/pliers/pliers-icon.js +9 -0
- package/dist/icons/pliers/pliers-rig.d.ts +62 -0
- package/dist/icons/pliers/pliers-rig.js +94 -0
- package/dist/icons/prism/prism-icon.d.ts +5 -0
- package/dist/icons/prism/prism-icon.js +9 -0
- package/dist/icons/prism/prism-rig.d.ts +64 -0
- package/dist/icons/prism/prism-rig.js +101 -0
- package/dist/icons/roller-skate/roller-skate-icon.d.ts +5 -0
- package/dist/icons/roller-skate/roller-skate-icon.js +9 -0
- package/dist/icons/roller-skate/roller-skate-rig.d.ts +182 -0
- package/dist/icons/roller-skate/roller-skate-rig.js +269 -0
- package/dist/icons/screwdriver/screwdriver-icon.d.ts +5 -0
- package/dist/icons/screwdriver/screwdriver-icon.js +9 -0
- package/dist/icons/screwdriver/screwdriver-rig.d.ts +85 -0
- package/dist/icons/screwdriver/screwdriver-rig.js +133 -0
- package/dist/icons/scuba-mask/scuba-mask-icon.d.ts +5 -0
- package/dist/icons/scuba-mask/scuba-mask-icon.js +9 -0
- package/dist/icons/scuba-mask/scuba-mask-rig.d.ts +39 -0
- package/dist/icons/scuba-mask/scuba-mask-rig.js +59 -0
- package/dist/icons/skateboard/skateboard-icon.d.ts +5 -0
- package/dist/icons/skateboard/skateboard-icon.js +9 -0
- package/dist/icons/skateboard/skateboard-rig.d.ts +85 -0
- package/dist/icons/skateboard/skateboard-rig.js +133 -0
- package/dist/icons/snowman/snowman-icon.d.ts +5 -0
- package/dist/icons/snowman/snowman-icon.js +9 -0
- package/dist/icons/snowman/snowman-rig.d.ts +65 -0
- package/dist/icons/snowman/snowman-rig.js +105 -0
- package/dist/icons/submarine/submarine-icon.d.ts +5 -0
- package/dist/icons/submarine/submarine-icon.js +9 -0
- package/dist/icons/submarine/submarine-rig.d.ts +67 -0
- package/dist/icons/submarine/submarine-rig.js +105 -0
- package/dist/icons/teapot/teapot-icon.d.ts +5 -0
- package/dist/icons/teapot/teapot-icon.js +9 -0
- package/dist/icons/teapot/teapot-rig.d.ts +59 -0
- package/dist/icons/teapot/teapot-rig.js +98 -0
- package/dist/icons/tennis-ball/tennis-ball-icon.d.ts +5 -0
- package/dist/icons/tennis-ball/tennis-ball-icon.js +9 -0
- package/dist/icons/tennis-ball/tennis-ball-rig.d.ts +91 -0
- package/dist/icons/tennis-ball/tennis-ball-rig.js +135 -0
- package/dist/icons/traffic-light/traffic-light-icon.d.ts +5 -0
- package/dist/icons/traffic-light/traffic-light-icon.js +9 -0
- package/dist/icons/traffic-light/traffic-light-rig.d.ts +46 -0
- package/dist/icons/traffic-light/traffic-light-rig.js +68 -0
- package/dist/icons/treadmill/treadmill-icon.d.ts +5 -0
- package/dist/icons/treadmill/treadmill-icon.js +9 -0
- package/dist/icons/treadmill/treadmill-rig.d.ts +135 -0
- package/dist/icons/treadmill/treadmill-rig.js +193 -0
- package/dist/icons/ufo/ufo-icon.d.ts +5 -0
- package/dist/icons/ufo/ufo-icon.js +9 -0
- package/dist/icons/ufo/ufo-rig.d.ts +123 -0
- package/dist/icons/ufo/ufo-rig.js +189 -0
- package/dist/icons/wheel/wheel-icon.d.ts +5 -0
- package/dist/icons/wheel/wheel-icon.js +9 -0
- package/dist/icons/wheel/wheel-rig.d.ts +62 -0
- package/dist/icons/wheel/wheel-rig.js +122 -0
- package/dist/icons/whisk/whisk-icon.d.ts +5 -0
- package/dist/icons/whisk/whisk-icon.js +9 -0
- package/dist/icons/whisk/whisk-rig.d.ts +55 -0
- package/dist/icons/whisk/whisk-rig.js +91 -0
- package/dist/icons/windmill/windmill-icon.d.ts +5 -0
- package/dist/icons/windmill/windmill-icon.js +9 -0
- package/dist/icons/windmill/windmill-rig.d.ts +56 -0
- package/dist/icons/windmill/windmill-rig.js +93 -0
- package/dist/icons/wood-log/wood-log-icon.d.ts +5 -0
- package/dist/icons/wood-log/wood-log-icon.js +9 -0
- package/dist/icons/wood-log/wood-log-rig.d.ts +67 -0
- package/dist/icons/wood-log/wood-log-rig.js +114 -0
- package/dist/icons/zeppelin/zeppelin-icon.d.ts +5 -0
- package/dist/icons/zeppelin/zeppelin-icon.js +9 -0
- package/dist/icons/zeppelin/zeppelin-rig.d.ts +75 -0
- package/dist/icons/zeppelin/zeppelin-rig.js +121 -0
- package/dist/index.d.ts +50 -0
- package/dist/index.js +51 -0
- package/dist/shared/icon-colors.d.ts +50 -0
- package/dist/source.json +1 -0
- package/package.json +260 -1
- package/skill-data/customize/SKILL.md +55 -0
- package/skill-data/customize/references/motion.md +15 -0
- package/skill-data/customize/references/review.md +14 -0
- package/skills/weasel-customize/SKILL.md +18 -0
package/README.md
CHANGED
|
@@ -2,10 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
Icons that overreact beautifully. Stateful React SVG icons with smooth transitions and optional continuous behavior.
|
|
4
4
|
|
|
5
|
+
Version `0.11.0` adds an optional multi-agent customization skill and CLI with version-matched editable source.
|
|
6
|
+
|
|
5
7
|
Version `0.10.0` contains 874 icons, adding 200 across documents, collaboration, spatial tools, media, commerce, transport and characters. Existing released icons retain their APIs.
|
|
6
8
|
|
|
7
9
|
Version `0.7.0` contained 469 icons; `0.6.0` contained 265 icons.
|
|
8
10
|
|
|
11
|
+
## Version 0.12.0
|
|
12
|
+
|
|
13
|
+
Adds 50 icons, bringing the collection to 924, with three typed states for each new icon. The release includes the revised gearbox track, cricket bat, melting snowman, roller-skate braking, side-flowering cactus and flowing hydrant. The application supplies state facts; animation does not infer completion.
|
|
14
|
+
|
|
15
|
+
Representative imports include `BarrierGateIcon`, `PliersIcon`, `CraneIcon`, `ButterflyIcon`, `PrismIcon` and `WheelIcon`, available from the root or matching subpaths.
|
|
16
|
+
|
|
17
|
+
Neutral occlusion uses `--weasel-surface` (white by default). Set it to the host surface on dark or coloured backgrounds.
|
|
18
|
+
|
|
9
19
|
## Install
|
|
10
20
|
|
|
11
21
|
```sh
|
|
@@ -16,6 +26,37 @@ pnpm add weasel-icons
|
|
|
16
26
|
|
|
17
27
|
Supports React / React DOM 18.3 or 19. Motion is installed as a dependency. No stylesheet, provider, Tailwind, or Next.js dependency is required. The package is ESM with TypeScript declarations and per-icon exports.
|
|
18
28
|
|
|
29
|
+
## Customize with your coding agent
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
npm install weasel-icons
|
|
33
|
+
npx weasel-icons setup
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Choose all the agents you use: Codex, Claude Code, Antigravity IDE/App, Antigravity CLI or Cursor. Personal setup is the default and stays outside your repository. Then ask your agent: **“Use weasel-customize to add a state to my icon.”** Setup installs instructions; it does not launch an AI, share conversations or generate code by itself.
|
|
37
|
+
|
|
38
|
+
For non-interactive setup, or to add another agent later:
|
|
39
|
+
|
|
40
|
+
```sh
|
|
41
|
+
npx weasel-icons setup --agent codex,claude-code --scope user
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Use `--scope project` for a team skill checked into this app. Existing or modified skill entries are preserved. Restart/reload the agent if the skill does not appear.
|
|
45
|
+
|
|
46
|
+
The agent reads the full guide from the installed package and copies only the selected icon and its required runtime:
|
|
47
|
+
|
|
48
|
+
```sh
|
|
49
|
+
npm exec --no -- weasel-icons skills get customize
|
|
50
|
+
npm exec --no -- weasel-icons icons list refresh
|
|
51
|
+
npm exec --no -- weasel-icons icons add refresh --dir src/components/weasel
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Declare `motion` as a direct dependency when using copied source (use the dependency range from the installed `weasel-icons/package.json`). Copied TypeScript needs a compiler target of ES2015+ or downlevelIteration. Import the customized component from your local source. Other icons can keep their npm imports. Existing custom files are never overwritten; conflicting runtime versions require a separate destination. Keep the copied license notices with redistributed source.
|
|
55
|
+
|
|
56
|
+
The CLI uses bundled source and makes no network requests. It requires Node 22.13 or newer; the icon components themselves remain React 18.3/19 compatible. Personal setup paths are agent-specific: Codex `~/.agents/skills`, Claude Code `~/.claude/skills`, Antigravity IDE/App `~/.gemini/config/skills`, Antigravity CLI `~/.gemini/antigravity-cli/skills`, Cursor `~/.cursor/skills`. Project paths are `.agents/skills` for Codex/Antigravity, `.claude/skills` for Claude Code and `.cursor/skills` for Cursor.
|
|
57
|
+
|
|
58
|
+
To remove an unchanged discovery entry, run `npx weasel-icons setup --agent codex,claude-code --remove`. Modified entries and customized app source are preserved. Re-run setup to restore an entry. The detailed guide updates when the app's Weasel package is updated.
|
|
59
|
+
|
|
19
60
|
## Use
|
|
20
61
|
|
|
21
62
|
```tsx
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -111,7 +111,7 @@ The animation choreography, state behavior and state effects are independently a
|
|
|
111
111
|
|
|
112
112
|
## Website-only illustration references and brand draft
|
|
113
113
|
|
|
114
|
-
The red-panda sheet under `public/art` and its reference-derived raster cutout match [Madi / madivoid's Red Panda Spread Art Print](https://www.etsy.com/listing/1624097837/red-panda-spread-art-print-animal-art), visually checked on October 24, 2026. Reuse permission has not been obtained; the physical-print listing is not a commercial website or branding licence. The website uses three hero poses and one lower illustration from this sheet. Older dog/cat sheets remain local historical files but are not rendered; the animated SVG box-cat component has been removed. The eyes/nose/apple logo in `public/weasel-mark.svg` has newly drawn paths, but has not received copyright or trademark clearance. The requested red-panda head crop has not replaced it. The owner authorized public website use of the two red-panda files; attribution and
|
|
114
|
+
The red-panda sheet under `public/art` and its reference-derived raster cutout match [Madi / madivoid's Red Panda Spread Art Print](https://www.etsy.com/listing/1624097837/red-panda-spread-art-print-animal-art), visually checked on October 24, 2026. Reuse permission has not been obtained; the physical-print listing is not a commercial website or branding licence. The website uses three hero poses and one lower illustration from this sheet. Older dog/cat sheets remain local historical files but are not rendered; the animated SVG box-cat component has been removed. The eyes/nose/apple logo in `public/weasel-mark.svg` has newly drawn paths, but has not received copyright or trademark clearance. The requested red-panda head crop has not replaced it. The owner authorized public website use of the two red-panda files; the website retains the artist attribution and source link, while unverified permission status remains recorded in this notice. See `docs/reference-artwork.md`. These assets are not part of the npm icon package, and its MIT licence does not license the supplied illustrations.
|
|
115
115
|
|
|
116
116
|
## Motion study reference
|
|
117
117
|
|
|
@@ -120,3 +120,67 @@ The animation system was informed by the part-level motion principles demonstrat
|
|
|
120
120
|
## Website fonts
|
|
121
121
|
|
|
122
122
|
The playground self-hosts unmodified Latin WOFF2 assets for [Anton](https://github.com/google/fonts/tree/main/ofl/anton) and [DM Sans](https://github.com/google/fonts/tree/main/ofl/dmsans), distributed by Google Fonts under the SIL Open Font License 1.1. Their complete copyright and license notices are included alongside the assets at `public/fonts/anton/OFL.txt` and `public/fonts/dm-sans/OFL.txt`. These website assets are not included in the icon installation payloads.
|
|
123
|
+
|
|
124
|
+
## RapidClaims customer logo
|
|
125
|
+
|
|
126
|
+
The website-only logo at `public/brands/rapidclaims.png` is adapted from the image supplied by the project owner: its black background was removed and its white lettering changed to charcoal for the light website. On October 28, 2026, the owner confirmed permission to display it and that RapidClaims uses Weasel in its projects. RapidClaims retains its brand rights; this asset is excluded from the npm icon package and its MIT licence.
|
|
127
|
+
|
|
128
|
+
## Tabler outline additions
|
|
129
|
+
|
|
130
|
+
The new physical-object icons adapt or redraw the following [Tabler outline assets](https://github.com/tabler/tabler-icons/tree/ed177a085b652fe04ec4f37ced867c94621e7840/icons/outline), inspected at revision `ed177a085b652fe04ec4f37ced867c94621e7840`: `traffic-lights`, `barrier-block`, `elevator`, `escalator`, `air-balloon`, `parachute`, `skateboard`, `roller-skating`, `ball-basketball`, `ball-football`, `ball-baseball`, `ball-tennis`, `golf`, `teapot`, `ladle`, `whisk`, `grill-spatula`, `needle-thread`, `cactus`, `mushroom`, `snowman`, `butterfly`, `abacus`, `air-conditioning`, `automatic-gearbox`, `backhoe`, `bus-stop`, `circuit-capacitor`, `crane`, `fire-hydrant`, `garden-cart`, `ironing`, `jetpack`, `ladder`, `planet`, `prism-light`, `scuba-mask`, `treadmill`, `ufo`, `wheel`, `wood`, `submarine`, `zeppelin`, `curling`. Pivots, state topology, procedural parts and choreography are authored for Weasel. Pliers is original geometry informed by construction photographs; those photographs are not redistributed. Cricket Bat was redrawn from scratch on October 29, 2026; its current grip, blade and ball contours are original Weasel geometry. No Tabler runtime dependency is added.
|
|
131
|
+
|
|
132
|
+
```text
|
|
133
|
+
MIT License
|
|
134
|
+
|
|
135
|
+
Copyright (c) 2020-2026 Paweł Kuna
|
|
136
|
+
|
|
137
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
138
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
139
|
+
in the Software without restriction, including without limitation the rights
|
|
140
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
141
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
142
|
+
furnished to do so, subject to the following conditions:
|
|
143
|
+
|
|
144
|
+
The above copyright notice and this permission notice shall be included in all
|
|
145
|
+
copies or substantial portions of the Software.
|
|
146
|
+
|
|
147
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
148
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
149
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
150
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
151
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
152
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
153
|
+
SOFTWARE.
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Phosphor outline references
|
|
157
|
+
|
|
158
|
+
Windmill, Pinwheel, Oven and Screwdriver are redrawn as 24-unit rounded outlines from the inspected [Phosphor assets](https://github.com/phosphor-icons/core/tree/2b75f3ad12b420c9504ef05df8d2564a28f8500e/assets/regular) `windmill`, `pinwheel`, `oven` and `screwdriver` at revision `2b75f3ad12b420c9504ef05df8d2564a28f8500e`. The 256-unit filled source shapes are not used as filled Weasel bodies. No Phosphor runtime dependency is added.
|
|
159
|
+
|
|
160
|
+
```text
|
|
161
|
+
MIT License
|
|
162
|
+
|
|
163
|
+
Copyright (c) 2023 Phosphor Icons
|
|
164
|
+
|
|
165
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
166
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
167
|
+
in the Software without restriction, including without limitation the rights
|
|
168
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
169
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
170
|
+
furnished to do so, subject to the following conditions:
|
|
171
|
+
|
|
172
|
+
The above copyright notice and this permission notice shall be included in all
|
|
173
|
+
copies or substantial portions of the Software.
|
|
174
|
+
|
|
175
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
176
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
177
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
178
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
179
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
180
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
181
|
+
SOFTWARE.
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Search metadata
|
|
185
|
+
|
|
186
|
+
The website search vocabulary includes adapted tags from the same pinned Lucide revision documented above, supplemented by Weasel synonyms and related terms. The Lucide ISC and Feather notices above are retained. No metadata service is called at search time.
|
package/bin/cli.mjs
ADDED
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { lstat, mkdir, readFile, realpath, unlink, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
import { dirname, isAbsolute, join, relative, resolve, sep } from 'node:path';
|
|
5
|
+
import { createInterface } from 'node:readline/promises';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
|
|
8
|
+
const packageRoot = fileURLToPath(new URL('../', import.meta.url));
|
|
9
|
+
const manifest = JSON.parse(await readFile(join(packageRoot, 'package.json'), 'utf8'));
|
|
10
|
+
const skillName = 'weasel-customize';
|
|
11
|
+
const agents = {
|
|
12
|
+
codex: { label: 'Codex', user: '.agents/skills', project: '.agents/skills' },
|
|
13
|
+
'claude-code': { label: 'Claude Code', user: '.claude/skills', project: '.claude/skills' },
|
|
14
|
+
antigravity: {
|
|
15
|
+
label: 'Antigravity IDE / App',
|
|
16
|
+
user: '.gemini/config/skills',
|
|
17
|
+
project: '.agents/skills',
|
|
18
|
+
},
|
|
19
|
+
'antigravity-cli': {
|
|
20
|
+
label: 'Antigravity CLI',
|
|
21
|
+
user: '.gemini/antigravity-cli/skills',
|
|
22
|
+
project: '.agents/skills',
|
|
23
|
+
},
|
|
24
|
+
cursor: { label: 'Cursor', user: '.cursor/skills', project: '.cursor/skills' },
|
|
25
|
+
};
|
|
26
|
+
const help = `weasel-icons ${manifest.version}
|
|
27
|
+
|
|
28
|
+
setup Choose agents and install their discovery skill
|
|
29
|
+
setup --agent codex,claude-code --scope user
|
|
30
|
+
setup --agent codex --scope project
|
|
31
|
+
setup --agent codex --remove Remove only an unchanged Weasel discovery entry
|
|
32
|
+
skills get customize Read the installed version's customization guide
|
|
33
|
+
skills get customize <name> Read a guide reference (motion or review)
|
|
34
|
+
icons list [query] Find an icon's source name
|
|
35
|
+
icons add <name> [--dir path] Copy editable icon source and runtime into this app
|
|
36
|
+
|
|
37
|
+
Personal setup is the default. Project setup writes skill files into this repo.
|
|
38
|
+
Existing custom files are never overwritten. No network requests or AI calls.
|
|
39
|
+
`;
|
|
40
|
+
|
|
41
|
+
function parse(argv) {
|
|
42
|
+
const positional = [],
|
|
43
|
+
options = {};
|
|
44
|
+
for (let i = 0; i < argv.length; i++) {
|
|
45
|
+
const arg = argv[i];
|
|
46
|
+
if (!arg.startsWith('--')) positional.push(arg);
|
|
47
|
+
else if (['--remove', '--help', '--version'].includes(arg)) options[arg.slice(2)] = true;
|
|
48
|
+
else if (['--agent', '--scope', '--dir'].includes(arg)) {
|
|
49
|
+
if (!argv[i + 1] || argv[i + 1].startsWith('--')) throw new Error(`Missing value for ${arg}`);
|
|
50
|
+
if (options[arg.slice(2)]) throw new Error(`Repeated option ${arg}`);
|
|
51
|
+
options[arg.slice(2)] = argv[++i];
|
|
52
|
+
} else throw new Error(`Unknown option ${arg}`);
|
|
53
|
+
}
|
|
54
|
+
return { positional, options };
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async function exists(path) {
|
|
58
|
+
try {
|
|
59
|
+
return await lstat(path);
|
|
60
|
+
} catch (error) {
|
|
61
|
+
if (error.code === 'ENOENT') return null;
|
|
62
|
+
throw error;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Resolve ordinary parent symlinks (e.g. macOS /tmp), but refuse symlinks within
|
|
67
|
+
// a write target. An icon/skill destination cannot redirect writes elsewhere.
|
|
68
|
+
async function checkedTarget(root, path) {
|
|
69
|
+
const absolute = resolve(path);
|
|
70
|
+
const rel = relative(root, absolute);
|
|
71
|
+
if (rel === '..' || rel.startsWith(`..${sep}`) || isAbsolute(rel))
|
|
72
|
+
throw new Error(`Destination must stay inside ${root}`);
|
|
73
|
+
let current = root;
|
|
74
|
+
for (const segment of rel.split(sep).filter(Boolean)) {
|
|
75
|
+
current = join(current, segment);
|
|
76
|
+
const info = await exists(current);
|
|
77
|
+
if (info?.isSymbolicLink()) throw new Error(`Refusing symlink destination: ${current}`);
|
|
78
|
+
}
|
|
79
|
+
return absolute;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async function projectRoot() {
|
|
83
|
+
let directory = await realpath(process.cwd());
|
|
84
|
+
while (true) {
|
|
85
|
+
const path = join(directory, 'package.json');
|
|
86
|
+
if (await exists(path)) {
|
|
87
|
+
const project = JSON.parse(await readFile(path, 'utf8'));
|
|
88
|
+
if (project.name === manifest.name)
|
|
89
|
+
throw new Error('Run this inside your app, not the Weasel package.');
|
|
90
|
+
return directory;
|
|
91
|
+
}
|
|
92
|
+
if (dirname(directory) === directory)
|
|
93
|
+
throw new Error('Run this inside an app with a package.json.');
|
|
94
|
+
directory = dirname(directory);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async function setup(options) {
|
|
99
|
+
let selected = options.agent?.split(',').filter(Boolean);
|
|
100
|
+
let scope = options.scope ?? 'user';
|
|
101
|
+
if (!selected?.length) {
|
|
102
|
+
if (!process.stdin.isTTY)
|
|
103
|
+
throw new Error('Choose agents with --agent codex,claude-code (or run setup interactively).');
|
|
104
|
+
const prompt = createInterface({ input: process.stdin, output: process.stdout });
|
|
105
|
+
try {
|
|
106
|
+
const names = Object.keys(agents);
|
|
107
|
+
console.log('Choose every agent you use:');
|
|
108
|
+
names.forEach((name, i) => console.log(` ${i + 1}. ${agents[name].label}`));
|
|
109
|
+
const answer = await prompt.question('Numbers separated by commas: ');
|
|
110
|
+
selected = answer.split(',').map((value) => names[Number(value.trim()) - 1]);
|
|
111
|
+
if (!options.scope) {
|
|
112
|
+
const answer = (await prompt.question('Scope: personal or project? [personal] ')).trim();
|
|
113
|
+
scope = answer === 'personal' || !answer ? 'user' : answer;
|
|
114
|
+
}
|
|
115
|
+
} finally {
|
|
116
|
+
prompt.close();
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (!['user', 'project'].includes(scope)) throw new Error('Scope must be user or project.');
|
|
120
|
+
if (selected.some((name) => !Object.hasOwn(agents, name)))
|
|
121
|
+
throw new Error(`Supported agents: ${Object.keys(agents).join(', ')}`);
|
|
122
|
+
const root = scope === 'user' ? await realpath(homedir()) : await projectRoot();
|
|
123
|
+
const content = await readFile(join(packageRoot, 'skills', skillName, 'SKILL.md'), 'utf8');
|
|
124
|
+
const paths = [
|
|
125
|
+
...new Set(selected.map((name) => join(root, agents[name][scope], skillName, 'SKILL.md'))),
|
|
126
|
+
];
|
|
127
|
+
const plan = [];
|
|
128
|
+
// Preflight the entire selection before changing any agent's entry.
|
|
129
|
+
for (const path of paths) {
|
|
130
|
+
await checkedTarget(root, path);
|
|
131
|
+
const previous = await exists(path);
|
|
132
|
+
if (previous && (!previous.isFile() || (await readFile(path, 'utf8')) !== content))
|
|
133
|
+
throw new Error(
|
|
134
|
+
`Preserving an existing or modified skill: ${path}. Move it deliberately before setup; nothing was changed.`,
|
|
135
|
+
);
|
|
136
|
+
plan.push({ path, previous });
|
|
137
|
+
}
|
|
138
|
+
if (options.remove) {
|
|
139
|
+
for (const { path, previous } of plan) {
|
|
140
|
+
if (previous) await unlink(path);
|
|
141
|
+
console.log(`${previous ? 'Removed' : 'Already absent'}: ${path}`);
|
|
142
|
+
}
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
const created = [];
|
|
146
|
+
try {
|
|
147
|
+
for (const { path, previous } of plan) {
|
|
148
|
+
if (!previous) {
|
|
149
|
+
await mkdir(dirname(path), { recursive: true });
|
|
150
|
+
await checkedTarget(root, path);
|
|
151
|
+
await writeFile(path, content, { flag: 'wx' });
|
|
152
|
+
created.push(path);
|
|
153
|
+
}
|
|
154
|
+
console.log(`${previous ? 'Already installed' : 'Installed'}: ${path}`);
|
|
155
|
+
}
|
|
156
|
+
} catch (error) {
|
|
157
|
+
for (const path of created) await unlink(path);
|
|
158
|
+
throw error;
|
|
159
|
+
}
|
|
160
|
+
console.log('\nAsk your agent: Use weasel-customize to add a state to my icon.');
|
|
161
|
+
console.log('If it is not visible, start a new session or reload the agent.');
|
|
162
|
+
console.log('This installs instructions; it does not launch an AI or share chat history.');
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
async function sourceCommand(command, name, options) {
|
|
166
|
+
const source = JSON.parse(await readFile(join(packageRoot, 'dist', 'source.json'), 'utf8'));
|
|
167
|
+
if (source.version !== manifest.version)
|
|
168
|
+
throw new Error('Source and package versions do not match. Reinstall the package.');
|
|
169
|
+
if (command === 'list') {
|
|
170
|
+
for (const icon of Object.keys(source.icons)
|
|
171
|
+
.filter((icon) => icon.includes(name ?? ''))
|
|
172
|
+
.sort())
|
|
173
|
+
console.log(icon);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
if (!name || !Object.hasOwn(source.icons, name))
|
|
177
|
+
throw new Error('Unknown icon. Use: weasel-icons icons list <query>');
|
|
178
|
+
const root = await projectRoot();
|
|
179
|
+
const defaultDir = (await exists(join(root, 'src')))
|
|
180
|
+
? 'src/components/weasel'
|
|
181
|
+
: 'components/weasel';
|
|
182
|
+
const destination = await checkedTarget(root, resolve(root, options.dir ?? defaultDir));
|
|
183
|
+
if (
|
|
184
|
+
relative(root, destination)
|
|
185
|
+
.split(sep)
|
|
186
|
+
.some((part) => ['node_modules', '.git', '.agents', '.claude'].includes(part))
|
|
187
|
+
)
|
|
188
|
+
throw new Error(
|
|
189
|
+
'Choose an application source directory, outside dependencies and agent configuration.',
|
|
190
|
+
);
|
|
191
|
+
const files = new Set();
|
|
192
|
+
const visit = (path) => {
|
|
193
|
+
if (files.has(path)) return;
|
|
194
|
+
const file = source.files[path];
|
|
195
|
+
if (!file) throw new Error(`Missing bundled source: ${path}`);
|
|
196
|
+
files.add(path);
|
|
197
|
+
file.dependencies.forEach(visit);
|
|
198
|
+
};
|
|
199
|
+
source.icons[name].forEach(visit);
|
|
200
|
+
for (const file of ['LICENSE', 'THIRD_PARTY_NOTICES.md']) files.add(file);
|
|
201
|
+
const writes = [];
|
|
202
|
+
for (const file of files) {
|
|
203
|
+
const path = await checkedTarget(root, join(destination, file));
|
|
204
|
+
const content = source.files[file].content;
|
|
205
|
+
if (await exists(path)) {
|
|
206
|
+
if ((await readFile(path, 'utf8')) !== content)
|
|
207
|
+
throw new Error(
|
|
208
|
+
`Preserving customized or different-version source: ${path}. Reuse it, or choose a new --dir. Nothing was copied.`,
|
|
209
|
+
);
|
|
210
|
+
} else writes.push({ path, content });
|
|
211
|
+
}
|
|
212
|
+
const created = [];
|
|
213
|
+
try {
|
|
214
|
+
for (const { path, content } of writes) {
|
|
215
|
+
await mkdir(dirname(path), { recursive: true });
|
|
216
|
+
await checkedTarget(root, path);
|
|
217
|
+
await writeFile(path, content, { flag: 'wx' });
|
|
218
|
+
created.push(path);
|
|
219
|
+
}
|
|
220
|
+
} catch (error) {
|
|
221
|
+
for (const path of created) await unlink(path);
|
|
222
|
+
throw error;
|
|
223
|
+
}
|
|
224
|
+
console.log(`Weasel ${source.version}: ${writes.length} files copied for ${name}.`);
|
|
225
|
+
console.log(`Editable icon: ${join(destination, 'icons', name, `${name}-icon.tsx`)}`);
|
|
226
|
+
console.log(
|
|
227
|
+
'Import this local component when customizing. Existing package imports keep working.',
|
|
228
|
+
);
|
|
229
|
+
console.log(
|
|
230
|
+
'The copied source imports motion/react. Declare motion directly in your app before using it.',
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
try {
|
|
235
|
+
const { positional: args, options } = parse(process.argv.slice(2));
|
|
236
|
+
const [command, subcommand, name, ...extra] = args;
|
|
237
|
+
if (options.version) console.log(manifest.version);
|
|
238
|
+
else if (options.help || !command || command === 'help') console.log(help);
|
|
239
|
+
else if (command === 'setup' && args.length === 1) {
|
|
240
|
+
if (options.dir) throw new Error('--dir belongs to icons add.');
|
|
241
|
+
await setup(options);
|
|
242
|
+
} else if (
|
|
243
|
+
command === 'skills' &&
|
|
244
|
+
subcommand === 'get' &&
|
|
245
|
+
name === 'customize' &&
|
|
246
|
+
extra.length <= 1
|
|
247
|
+
) {
|
|
248
|
+
const reference = extra[0];
|
|
249
|
+
if (reference && !['motion', 'review'].includes(reference))
|
|
250
|
+
throw new Error('References: motion, review');
|
|
251
|
+
const path = reference
|
|
252
|
+
? `skill-data/customize/references/${reference}.md`
|
|
253
|
+
: 'skill-data/customize/SKILL.md';
|
|
254
|
+
console.log(`# Instructions for installed weasel-icons ${manifest.version}\n`);
|
|
255
|
+
console.log(await readFile(join(packageRoot, path), 'utf8'));
|
|
256
|
+
} else if (command === 'icons' && ['list', 'add'].includes(subcommand) && extra.length === 0) {
|
|
257
|
+
if (options.agent || options.scope || options.remove)
|
|
258
|
+
throw new Error('Agent options belong to setup.');
|
|
259
|
+
await sourceCommand(subcommand, name, options);
|
|
260
|
+
} else throw new Error('Unknown command. Run: weasel-icons --help');
|
|
261
|
+
} catch (error) {
|
|
262
|
+
console.error(`Weasel: ${error.message}`);
|
|
263
|
+
process.exitCode = 1;
|
|
264
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { StatefulIconProps } from "../../shared/icon-types.js";
|
|
2
|
+
import { type AbacusState } from "./abacus-rig.js";
|
|
3
|
+
export { abacusStates, type AbacusState } from "./abacus-rig.js";
|
|
4
|
+
export type AbacusIconProps = StatefulIconProps<AbacusState>;
|
|
5
|
+
export declare const AbacusIcon: import("react").NamedExoticComponent<AbacusIconProps>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { memo } from 'react';
|
|
4
|
+
import { ArticulatedIcon } from "../../shared/articulated-icon.js";
|
|
5
|
+
import { abacusArt, abacusStates } from "./abacus-rig.js";
|
|
6
|
+
export { abacusStates } from "./abacus-rig.js";
|
|
7
|
+
export const AbacusIcon = memo(function AbacusIcon(props) {
|
|
8
|
+
return _jsx(ArticulatedIcon, { art: abacusArt, states: abacusStates, ...props });
|
|
9
|
+
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export declare const abacusStates: readonly ["reset", "counting", "counted"];
|
|
2
|
+
export type AbacusState = (typeof abacusStates)[number];
|
|
3
|
+
export declare const abacusArt: {
|
|
4
|
+
readonly name: "abacus";
|
|
5
|
+
readonly parts: readonly [{
|
|
6
|
+
readonly name: "frame";
|
|
7
|
+
readonly paths: readonly ["M5 3v18", "M19 21v-18", "M3 21h18"];
|
|
8
|
+
readonly poses: readonly [{}, {}, {}];
|
|
9
|
+
}, {
|
|
10
|
+
readonly name: "rods";
|
|
11
|
+
readonly paths: readonly ["M5 7h14", "M5 15h14"];
|
|
12
|
+
readonly poses: readonly [{}, {}, {}];
|
|
13
|
+
readonly detail: true;
|
|
14
|
+
}, {
|
|
15
|
+
readonly name: "fixed-beads";
|
|
16
|
+
readonly paths: readonly ["M8 13v4", "M11 13v4", "M11 5v4", "M8 5v4"];
|
|
17
|
+
readonly poses: readonly [{}, {}, {}];
|
|
18
|
+
readonly detail: true;
|
|
19
|
+
}, {
|
|
20
|
+
readonly name: "upper-bead";
|
|
21
|
+
readonly paths: readonly ["M14 5v4"];
|
|
22
|
+
readonly poses: readonly [{}, {
|
|
23
|
+
readonly x: 1;
|
|
24
|
+
}, {
|
|
25
|
+
readonly x: 2;
|
|
26
|
+
}];
|
|
27
|
+
readonly detail: true;
|
|
28
|
+
readonly accent: true;
|
|
29
|
+
}, {
|
|
30
|
+
readonly name: "lower-bead";
|
|
31
|
+
readonly paths: readonly ["M16 13v4"];
|
|
32
|
+
readonly poses: readonly [{}, {
|
|
33
|
+
readonly x: -1.5;
|
|
34
|
+
}, {
|
|
35
|
+
readonly x: -3;
|
|
36
|
+
}];
|
|
37
|
+
readonly detail: true;
|
|
38
|
+
readonly accent: true;
|
|
39
|
+
}];
|
|
40
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// Geometry reference: https://raw.githubusercontent.com/tabler/tabler-icons/ed177a085b652fe04ec4f37ced867c94621e7840/icons/outline/abacus.svg
|
|
2
|
+
// Adaptation and motion are authored for Weasel. See THIRD_PARTY_NOTICES.md.
|
|
3
|
+
// Two horizontal rods pass through vertical beads inside a fixed frame. Two selected beads slide along the rods without passing through their neighbours.
|
|
4
|
+
// reset: Beads at reset positions
|
|
5
|
+
// counting: Selected beads partway along the rods
|
|
6
|
+
// counted: Counted positions retained
|
|
7
|
+
export const abacusStates = ['reset', 'counting', 'counted'];
|
|
8
|
+
export const abacusArt = {
|
|
9
|
+
name: 'abacus',
|
|
10
|
+
parts: [
|
|
11
|
+
{
|
|
12
|
+
name: 'frame',
|
|
13
|
+
paths: ['M5 3v18', 'M19 21v-18', 'M3 21h18'],
|
|
14
|
+
poses: [{}, {}, {}],
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
name: 'rods',
|
|
18
|
+
paths: ['M5 7h14', 'M5 15h14'],
|
|
19
|
+
poses: [{}, {}, {}],
|
|
20
|
+
detail: true,
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
name: 'fixed-beads',
|
|
24
|
+
paths: ['M8 13v4', 'M11 13v4', 'M11 5v4', 'M8 5v4'],
|
|
25
|
+
poses: [{}, {}, {}],
|
|
26
|
+
detail: true,
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: 'upper-bead',
|
|
30
|
+
paths: ['M14 5v4'],
|
|
31
|
+
poses: [
|
|
32
|
+
{},
|
|
33
|
+
{
|
|
34
|
+
x: 1,
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
x: 2,
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
detail: true,
|
|
41
|
+
accent: true,
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: 'lower-bead',
|
|
45
|
+
paths: ['M16 13v4'],
|
|
46
|
+
poses: [
|
|
47
|
+
{},
|
|
48
|
+
{
|
|
49
|
+
x: -1.5,
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
x: -3,
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
detail: true,
|
|
56
|
+
accent: true,
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { StatefulIconProps } from "../../shared/icon-types.js";
|
|
2
|
+
import { type AirConditionerState } from "./air-conditioner-rig.js";
|
|
3
|
+
export { airConditionerStates, type AirConditionerState } from "./air-conditioner-rig.js";
|
|
4
|
+
export type AirConditionerIconProps = StatefulIconProps<AirConditionerState>;
|
|
5
|
+
export declare const AirConditionerIcon: import("react").NamedExoticComponent<AirConditionerIconProps>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { memo } from 'react';
|
|
4
|
+
import { ArticulatedIcon } from "../../shared/articulated-icon.js";
|
|
5
|
+
import { airConditionerArt, airConditionerStates, } from "./air-conditioner-rig.js";
|
|
6
|
+
export { airConditionerStates } from "./air-conditioner-rig.js";
|
|
7
|
+
export const AirConditionerIcon = memo(function AirConditionerIcon(props) {
|
|
8
|
+
return _jsx(ArticulatedIcon, { art: airConditionerArt, states: airConditionerStates, ...props });
|
|
9
|
+
});
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
export declare const airConditionerStates: readonly ["off", "cooling", "heating"];
|
|
2
|
+
export type AirConditionerState = (typeof airConditionerStates)[number];
|
|
3
|
+
export declare const airConditionerArt: {
|
|
4
|
+
readonly name: "air-conditioner";
|
|
5
|
+
readonly parts: readonly [{
|
|
6
|
+
readonly name: "case";
|
|
7
|
+
readonly paths: readonly ["M3 7a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v4a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2l0 -4"];
|
|
8
|
+
readonly poses: readonly [{}, {}, {}];
|
|
9
|
+
}, {
|
|
10
|
+
readonly name: "vent";
|
|
11
|
+
readonly paths: readonly ["M7 13v-3a1 1 0 0 1 1 -1h8a1 1 0 0 1 1 1v3"];
|
|
12
|
+
readonly poses: readonly [{}, {}, {}];
|
|
13
|
+
readonly detail: true;
|
|
14
|
+
}, {
|
|
15
|
+
readonly name: "cool-air";
|
|
16
|
+
readonly paths: readonly ["M8 16a3 3 0 0 1 -3 3", "M16 16a3 3 0 0 0 3 3", "M12 16v4"];
|
|
17
|
+
readonly poses: readonly [{
|
|
18
|
+
readonly opacity: 0;
|
|
19
|
+
}, {
|
|
20
|
+
readonly opacity: 1;
|
|
21
|
+
}, {
|
|
22
|
+
readonly opacity: 0;
|
|
23
|
+
}];
|
|
24
|
+
readonly detail: true;
|
|
25
|
+
readonly accent: true;
|
|
26
|
+
readonly traceLength: 5;
|
|
27
|
+
readonly gestures: readonly [null, {
|
|
28
|
+
readonly duration: 1;
|
|
29
|
+
readonly repeatAfter: 1.5;
|
|
30
|
+
readonly loop: true;
|
|
31
|
+
readonly frames: readonly [{
|
|
32
|
+
readonly at: 0;
|
|
33
|
+
readonly draw: -0.8;
|
|
34
|
+
readonly opacity: -1;
|
|
35
|
+
}, {
|
|
36
|
+
readonly at: 0.18;
|
|
37
|
+
readonly draw: -0.6;
|
|
38
|
+
}, {
|
|
39
|
+
readonly at: 0.8;
|
|
40
|
+
}, {
|
|
41
|
+
readonly at: 1;
|
|
42
|
+
readonly opacity: -1;
|
|
43
|
+
}];
|
|
44
|
+
}, null];
|
|
45
|
+
}, {
|
|
46
|
+
readonly name: "warm-air";
|
|
47
|
+
readonly paths: readonly ["M7 17q-1 1 0 2t0 2", "M12 17q-1 1 0 2t0 2", "M17 17q-1 1 0 2t0 2"];
|
|
48
|
+
readonly poses: readonly [{
|
|
49
|
+
readonly opacity: 0;
|
|
50
|
+
}, {
|
|
51
|
+
readonly opacity: 0;
|
|
52
|
+
}, {
|
|
53
|
+
readonly opacity: 1;
|
|
54
|
+
}];
|
|
55
|
+
readonly detail: true;
|
|
56
|
+
readonly accent: true;
|
|
57
|
+
readonly gestures: readonly [null, null, {
|
|
58
|
+
readonly duration: 1.5;
|
|
59
|
+
readonly repeatAfter: 2;
|
|
60
|
+
readonly loop: true;
|
|
61
|
+
readonly frames: readonly [{
|
|
62
|
+
readonly at: 0;
|
|
63
|
+
}, {
|
|
64
|
+
readonly at: 0.28;
|
|
65
|
+
readonly y: -0.25;
|
|
66
|
+
}, {
|
|
67
|
+
readonly at: 0.65;
|
|
68
|
+
readonly y: 0.1375;
|
|
69
|
+
}, {
|
|
70
|
+
readonly at: 1;
|
|
71
|
+
}];
|
|
72
|
+
}];
|
|
73
|
+
}];
|
|
74
|
+
};
|