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.
Files changed (212) hide show
  1. package/README.md +41 -0
  2. package/THIRD_PARTY_NOTICES.md +65 -1
  3. package/bin/cli.mjs +264 -0
  4. package/dist/icons/abacus/abacus-icon.d.ts +5 -0
  5. package/dist/icons/abacus/abacus-icon.js +9 -0
  6. package/dist/icons/abacus/abacus-rig.d.ts +40 -0
  7. package/dist/icons/abacus/abacus-rig.js +59 -0
  8. package/dist/icons/air-conditioner/air-conditioner-icon.d.ts +5 -0
  9. package/dist/icons/air-conditioner/air-conditioner-icon.js +9 -0
  10. package/dist/icons/air-conditioner/air-conditioner-rig.d.ts +74 -0
  11. package/dist/icons/air-conditioner/air-conditioner-rig.js +110 -0
  12. package/dist/icons/barrier-gate/barrier-gate-icon.d.ts +5 -0
  13. package/dist/icons/barrier-gate/barrier-gate-icon.js +9 -0
  14. package/dist/icons/barrier-gate/barrier-gate-rig.d.ts +25 -0
  15. package/dist/icons/barrier-gate/barrier-gate-rig.js +38 -0
  16. package/dist/icons/baseball/baseball-icon.d.ts +5 -0
  17. package/dist/icons/baseball/baseball-icon.js +9 -0
  18. package/dist/icons/baseball/baseball-rig.d.ts +89 -0
  19. package/dist/icons/baseball/baseball-rig.js +140 -0
  20. package/dist/icons/basketball/basketball-icon.d.ts +5 -0
  21. package/dist/icons/basketball/basketball-icon.js +9 -0
  22. package/dist/icons/basketball/basketball-rig.d.ts +77 -0
  23. package/dist/icons/basketball/basketball-rig.js +122 -0
  24. package/dist/icons/bus-stop/bus-stop-icon.d.ts +5 -0
  25. package/dist/icons/bus-stop/bus-stop-icon.js +9 -0
  26. package/dist/icons/bus-stop/bus-stop-rig.d.ts +46 -0
  27. package/dist/icons/bus-stop/bus-stop-rig.js +76 -0
  28. package/dist/icons/butterfly/butterfly-icon.d.ts +5 -0
  29. package/dist/icons/butterfly/butterfly-icon.js +9 -0
  30. package/dist/icons/butterfly/butterfly-rig.d.ts +64 -0
  31. package/dist/icons/butterfly/butterfly-rig.js +101 -0
  32. package/dist/icons/cactus/cactus-icon.d.ts +5 -0
  33. package/dist/icons/cactus/cactus-icon.js +9 -0
  34. package/dist/icons/cactus/cactus-rig.d.ts +85 -0
  35. package/dist/icons/cactus/cactus-rig.js +137 -0
  36. package/dist/icons/capacitor/capacitor-icon.d.ts +5 -0
  37. package/dist/icons/capacitor/capacitor-icon.js +9 -0
  38. package/dist/icons/capacitor/capacitor-rig.d.ts +60 -0
  39. package/dist/icons/capacitor/capacitor-rig.js +88 -0
  40. package/dist/icons/crane/crane-icon.d.ts +5 -0
  41. package/dist/icons/crane/crane-icon.js +9 -0
  42. package/dist/icons/crane/crane-rig.d.ts +59 -0
  43. package/dist/icons/crane/crane-rig.js +90 -0
  44. package/dist/icons/cricket-bat/cricket-bat-icon.d.ts +5 -0
  45. package/dist/icons/cricket-bat/cricket-bat-icon.js +9 -0
  46. package/dist/icons/cricket-bat/cricket-bat-rig.d.ts +107 -0
  47. package/dist/icons/cricket-bat/cricket-bat-rig.js +162 -0
  48. package/dist/icons/curling-stone/curling-stone-icon.d.ts +5 -0
  49. package/dist/icons/curling-stone/curling-stone-icon.js +9 -0
  50. package/dist/icons/curling-stone/curling-stone-rig.d.ts +83 -0
  51. package/dist/icons/curling-stone/curling-stone-rig.js +124 -0
  52. package/dist/icons/elevator/elevator-icon.d.ts +5 -0
  53. package/dist/icons/elevator/elevator-icon.js +9 -0
  54. package/dist/icons/elevator/elevator-rig.d.ts +62 -0
  55. package/dist/icons/elevator/elevator-rig.js +97 -0
  56. package/dist/icons/escalator/escalator-icon.d.ts +5 -0
  57. package/dist/icons/escalator/escalator-icon.js +9 -0
  58. package/dist/icons/escalator/escalator-rig.d.ts +66 -0
  59. package/dist/icons/escalator/escalator-rig.js +103 -0
  60. package/dist/icons/excavator/excavator-icon.d.ts +5 -0
  61. package/dist/icons/excavator/excavator-icon.js +9 -0
  62. package/dist/icons/excavator/excavator-rig.d.ts +64 -0
  63. package/dist/icons/excavator/excavator-rig.js +105 -0
  64. package/dist/icons/fire-hydrant/fire-hydrant-icon.d.ts +5 -0
  65. package/dist/icons/fire-hydrant/fire-hydrant-icon.js +9 -0
  66. package/dist/icons/fire-hydrant/fire-hydrant-rig.d.ts +167 -0
  67. package/dist/icons/fire-hydrant/fire-hydrant-rig.js +250 -0
  68. package/dist/icons/football/football-icon.d.ts +5 -0
  69. package/dist/icons/football/football-icon.js +9 -0
  70. package/dist/icons/football/football-rig.d.ts +81 -0
  71. package/dist/icons/football/football-rig.js +124 -0
  72. package/dist/icons/garden-cart/garden-cart-icon.d.ts +5 -0
  73. package/dist/icons/garden-cart/garden-cart-icon.js +9 -0
  74. package/dist/icons/garden-cart/garden-cart-rig.d.ts +66 -0
  75. package/dist/icons/garden-cart/garden-cart-rig.js +104 -0
  76. package/dist/icons/gearbox/gearbox-icon.d.ts +5 -0
  77. package/dist/icons/gearbox/gearbox-icon.js +24 -0
  78. package/dist/icons/gearbox/gearbox-rig.d.ts +34 -0
  79. package/dist/icons/gearbox/gearbox-rig.js +64 -0
  80. package/dist/icons/golf/golf-icon.d.ts +5 -0
  81. package/dist/icons/golf/golf-icon.js +9 -0
  82. package/dist/icons/golf/golf-rig.d.ts +34 -0
  83. package/dist/icons/golf/golf-rig.js +56 -0
  84. package/dist/icons/grill-spatula/grill-spatula-icon.d.ts +5 -0
  85. package/dist/icons/grill-spatula/grill-spatula-icon.js +9 -0
  86. package/dist/icons/grill-spatula/grill-spatula-rig.d.ts +89 -0
  87. package/dist/icons/grill-spatula/grill-spatula-rig.js +136 -0
  88. package/dist/icons/hot-air-balloon/hot-air-balloon-icon.d.ts +5 -0
  89. package/dist/icons/hot-air-balloon/hot-air-balloon-icon.js +9 -0
  90. package/dist/icons/hot-air-balloon/hot-air-balloon-rig.d.ts +84 -0
  91. package/dist/icons/hot-air-balloon/hot-air-balloon-rig.js +133 -0
  92. package/dist/icons/iron/iron-icon.d.ts +5 -0
  93. package/dist/icons/iron/iron-icon.js +9 -0
  94. package/dist/icons/iron/iron-rig.d.ts +52 -0
  95. package/dist/icons/iron/iron-rig.js +80 -0
  96. package/dist/icons/jetpack/jetpack-icon.d.ts +5 -0
  97. package/dist/icons/jetpack/jetpack-icon.js +9 -0
  98. package/dist/icons/jetpack/jetpack-rig.d.ts +103 -0
  99. package/dist/icons/jetpack/jetpack-rig.js +157 -0
  100. package/dist/icons/ladder/ladder-icon.d.ts +5 -0
  101. package/dist/icons/ladder/ladder-icon.js +9 -0
  102. package/dist/icons/ladder/ladder-rig.d.ts +80 -0
  103. package/dist/icons/ladder/ladder-rig.js +119 -0
  104. package/dist/icons/ladle/ladle-icon.d.ts +5 -0
  105. package/dist/icons/ladle/ladle-icon.js +9 -0
  106. package/dist/icons/ladle/ladle-rig.d.ts +86 -0
  107. package/dist/icons/ladle/ladle-rig.js +135 -0
  108. package/dist/icons/mushroom/mushroom-icon.d.ts +5 -0
  109. package/dist/icons/mushroom/mushroom-icon.js +9 -0
  110. package/dist/icons/mushroom/mushroom-rig.d.ts +49 -0
  111. package/dist/icons/mushroom/mushroom-rig.js +81 -0
  112. package/dist/icons/needle-thread/needle-thread-icon.d.ts +5 -0
  113. package/dist/icons/needle-thread/needle-thread-icon.js +9 -0
  114. package/dist/icons/needle-thread/needle-thread-rig.d.ts +33 -0
  115. package/dist/icons/needle-thread/needle-thread-rig.js +59 -0
  116. package/dist/icons/oven/oven-icon.d.ts +5 -0
  117. package/dist/icons/oven/oven-icon.js +9 -0
  118. package/dist/icons/oven/oven-rig.d.ts +51 -0
  119. package/dist/icons/oven/oven-rig.js +82 -0
  120. package/dist/icons/parachute/parachute-icon.d.ts +5 -0
  121. package/dist/icons/parachute/parachute-icon.js +9 -0
  122. package/dist/icons/parachute/parachute-rig.d.ts +25 -0
  123. package/dist/icons/parachute/parachute-rig.js +45 -0
  124. package/dist/icons/pinwheel/pinwheel-icon.d.ts +5 -0
  125. package/dist/icons/pinwheel/pinwheel-icon.js +9 -0
  126. package/dist/icons/pinwheel/pinwheel-rig.d.ts +116 -0
  127. package/dist/icons/pinwheel/pinwheel-rig.js +188 -0
  128. package/dist/icons/planet/planet-icon.d.ts +5 -0
  129. package/dist/icons/planet/planet-icon.js +9 -0
  130. package/dist/icons/planet/planet-rig.d.ts +61 -0
  131. package/dist/icons/planet/planet-rig.js +91 -0
  132. package/dist/icons/pliers/pliers-icon.d.ts +5 -0
  133. package/dist/icons/pliers/pliers-icon.js +9 -0
  134. package/dist/icons/pliers/pliers-rig.d.ts +62 -0
  135. package/dist/icons/pliers/pliers-rig.js +94 -0
  136. package/dist/icons/prism/prism-icon.d.ts +5 -0
  137. package/dist/icons/prism/prism-icon.js +9 -0
  138. package/dist/icons/prism/prism-rig.d.ts +64 -0
  139. package/dist/icons/prism/prism-rig.js +101 -0
  140. package/dist/icons/roller-skate/roller-skate-icon.d.ts +5 -0
  141. package/dist/icons/roller-skate/roller-skate-icon.js +9 -0
  142. package/dist/icons/roller-skate/roller-skate-rig.d.ts +182 -0
  143. package/dist/icons/roller-skate/roller-skate-rig.js +269 -0
  144. package/dist/icons/screwdriver/screwdriver-icon.d.ts +5 -0
  145. package/dist/icons/screwdriver/screwdriver-icon.js +9 -0
  146. package/dist/icons/screwdriver/screwdriver-rig.d.ts +85 -0
  147. package/dist/icons/screwdriver/screwdriver-rig.js +133 -0
  148. package/dist/icons/scuba-mask/scuba-mask-icon.d.ts +5 -0
  149. package/dist/icons/scuba-mask/scuba-mask-icon.js +9 -0
  150. package/dist/icons/scuba-mask/scuba-mask-rig.d.ts +39 -0
  151. package/dist/icons/scuba-mask/scuba-mask-rig.js +59 -0
  152. package/dist/icons/skateboard/skateboard-icon.d.ts +5 -0
  153. package/dist/icons/skateboard/skateboard-icon.js +9 -0
  154. package/dist/icons/skateboard/skateboard-rig.d.ts +85 -0
  155. package/dist/icons/skateboard/skateboard-rig.js +133 -0
  156. package/dist/icons/snowman/snowman-icon.d.ts +5 -0
  157. package/dist/icons/snowman/snowman-icon.js +9 -0
  158. package/dist/icons/snowman/snowman-rig.d.ts +65 -0
  159. package/dist/icons/snowman/snowman-rig.js +105 -0
  160. package/dist/icons/submarine/submarine-icon.d.ts +5 -0
  161. package/dist/icons/submarine/submarine-icon.js +9 -0
  162. package/dist/icons/submarine/submarine-rig.d.ts +67 -0
  163. package/dist/icons/submarine/submarine-rig.js +105 -0
  164. package/dist/icons/teapot/teapot-icon.d.ts +5 -0
  165. package/dist/icons/teapot/teapot-icon.js +9 -0
  166. package/dist/icons/teapot/teapot-rig.d.ts +59 -0
  167. package/dist/icons/teapot/teapot-rig.js +98 -0
  168. package/dist/icons/tennis-ball/tennis-ball-icon.d.ts +5 -0
  169. package/dist/icons/tennis-ball/tennis-ball-icon.js +9 -0
  170. package/dist/icons/tennis-ball/tennis-ball-rig.d.ts +91 -0
  171. package/dist/icons/tennis-ball/tennis-ball-rig.js +135 -0
  172. package/dist/icons/traffic-light/traffic-light-icon.d.ts +5 -0
  173. package/dist/icons/traffic-light/traffic-light-icon.js +9 -0
  174. package/dist/icons/traffic-light/traffic-light-rig.d.ts +46 -0
  175. package/dist/icons/traffic-light/traffic-light-rig.js +68 -0
  176. package/dist/icons/treadmill/treadmill-icon.d.ts +5 -0
  177. package/dist/icons/treadmill/treadmill-icon.js +9 -0
  178. package/dist/icons/treadmill/treadmill-rig.d.ts +135 -0
  179. package/dist/icons/treadmill/treadmill-rig.js +193 -0
  180. package/dist/icons/ufo/ufo-icon.d.ts +5 -0
  181. package/dist/icons/ufo/ufo-icon.js +9 -0
  182. package/dist/icons/ufo/ufo-rig.d.ts +123 -0
  183. package/dist/icons/ufo/ufo-rig.js +189 -0
  184. package/dist/icons/wheel/wheel-icon.d.ts +5 -0
  185. package/dist/icons/wheel/wheel-icon.js +9 -0
  186. package/dist/icons/wheel/wheel-rig.d.ts +62 -0
  187. package/dist/icons/wheel/wheel-rig.js +122 -0
  188. package/dist/icons/whisk/whisk-icon.d.ts +5 -0
  189. package/dist/icons/whisk/whisk-icon.js +9 -0
  190. package/dist/icons/whisk/whisk-rig.d.ts +55 -0
  191. package/dist/icons/whisk/whisk-rig.js +91 -0
  192. package/dist/icons/windmill/windmill-icon.d.ts +5 -0
  193. package/dist/icons/windmill/windmill-icon.js +9 -0
  194. package/dist/icons/windmill/windmill-rig.d.ts +56 -0
  195. package/dist/icons/windmill/windmill-rig.js +93 -0
  196. package/dist/icons/wood-log/wood-log-icon.d.ts +5 -0
  197. package/dist/icons/wood-log/wood-log-icon.js +9 -0
  198. package/dist/icons/wood-log/wood-log-rig.d.ts +67 -0
  199. package/dist/icons/wood-log/wood-log-rig.js +114 -0
  200. package/dist/icons/zeppelin/zeppelin-icon.d.ts +5 -0
  201. package/dist/icons/zeppelin/zeppelin-icon.js +9 -0
  202. package/dist/icons/zeppelin/zeppelin-rig.d.ts +75 -0
  203. package/dist/icons/zeppelin/zeppelin-rig.js +121 -0
  204. package/dist/index.d.ts +50 -0
  205. package/dist/index.js +51 -0
  206. package/dist/shared/icon-colors.d.ts +50 -0
  207. package/dist/source.json +1 -0
  208. package/package.json +260 -1
  209. package/skill-data/customize/SKILL.md +55 -0
  210. package/skill-data/customize/references/motion.md +15 -0
  211. package/skill-data/customize/references/review.md +14 -0
  212. 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
@@ -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 the permission-pending notice remain. 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.
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
+ };