@buoy-gg/shared-ui 7.0.36 → 7.0.39

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 (284) hide show
  1. package/README.md +33 -26
  2. package/floating.d.ts +1 -0
  3. package/floating.js +2 -0
  4. package/lib/commonjs/JsModal.js +16 -1
  5. package/lib/commonjs/JsModal.web.js +16 -1
  6. package/lib/commonjs/dataViewer/CyberpunkInput.js +6 -1
  7. package/lib/commonjs/dataViewer/LiveExplorer.js +28 -16
  8. package/lib/commonjs/hooks/safe-area-impl.js +1 -1
  9. package/lib/commonjs/icons/ReactQueryIcon.js +9 -161
  10. package/lib/commonjs/icons/SentryBugIcon.js +9 -171
  11. package/lib/commonjs/index.js +57 -6
  12. package/lib/commonjs/license/AccountSetup.js +56 -0
  13. package/lib/commonjs/license/AccountSetup.web.js +81 -0
  14. package/lib/commonjs/license/FeatureGate.js +10 -43
  15. package/lib/commonjs/license/FreeAccountPrompt.js +35 -12
  16. package/lib/commonjs/license/index.js +0 -6
  17. package/lib/commonjs/license/licenseModule.js +56 -36
  18. package/lib/commonjs/license/tierLimits.js +12 -63
  19. package/lib/commonjs/storage/devToolsStorageKeys.js +8 -1
  20. package/lib/commonjs/stores/BaseEventStore.js +21 -5
  21. package/lib/commonjs/stores/createToolStore.js +21 -3
  22. package/lib/commonjs/stores/floatingToolStore.js +71 -0
  23. package/lib/commonjs/stores/floatingToolStore.test.js +112 -0
  24. package/lib/commonjs/sync/toolActionRegistry.js +85 -2
  25. package/lib/commonjs/ui/backgrounds/README.md +52 -0
  26. package/lib/commonjs/ui/backgrounds/ToolBackground.js +4 -2
  27. package/lib/commonjs/ui/backgrounds/index.js +8 -1
  28. package/lib/commonjs/ui/backgrounds/registry.js +8 -0
  29. package/lib/commonjs/ui/backgrounds/variants/wormhole/motion.js +48 -0
  30. package/lib/commonjs/ui/backgrounds/variants/wormhole/textures.js +3 -0
  31. package/lib/commonjs/ui/backgrounds/variants/wormhole.js +133 -0
  32. package/lib/commonjs/ui/components/ClipboardHintBanner.js +5 -6
  33. package/lib/commonjs/ui/components/CompactRow.js +94 -74
  34. package/lib/commonjs/ui/components/DraggableHeader.js +16 -1
  35. package/lib/commonjs/ui/components/HeaderSearchButton.js +17 -4
  36. package/lib/commonjs/ui/floating/FloatingTool.js +1010 -0
  37. package/lib/commonjs/ui/floating/FloatingTool.web.js +591 -0
  38. package/lib/commonjs/ui/floating/FloatingToolHost.js +32 -0
  39. package/lib/commonjs/ui/floating/FloatingToolHost.web.js +28 -0
  40. package/lib/commonjs/ui/floating/index.js +105 -0
  41. package/lib/commonjs/ui/floating/index.web.js +105 -0
  42. package/lib/commonjs/ui/floating/onboardingConstants.js +70 -0
  43. package/lib/commonjs/ui/floating/onboardingConstants.web.js +34 -0
  44. package/lib/commonjs/ui/gameUI/constants/gameUIColors.js +3 -1
  45. package/lib/commonjs/ui/index.js +118 -2
  46. package/lib/commonjs/ui/night/nightTheme.js +10 -0
  47. package/lib/commonjs/ui/night/primitives.js +22 -5
  48. package/lib/commonjs/ui/otto/OttoSceneView.js +69 -0
  49. package/lib/commonjs/ui/otto/index.js +22 -0
  50. package/lib/commonjs/ui/otto/ottoEngine.js +10 -7
  51. package/lib/commonjs/ui/otto/ottoScenes.js +949 -0
  52. package/lib/commonjs/utils/minimalSuperJSON.js +13 -3
  53. package/lib/module/JsModal.js +16 -1
  54. package/lib/module/JsModal.web.js +16 -1
  55. package/lib/module/dataViewer/CyberpunkInput.js +6 -1
  56. package/lib/module/dataViewer/LiveExplorer.js +28 -16
  57. package/lib/module/hooks/safe-area-impl.js +1 -1
  58. package/lib/module/icons/ReactQueryIcon.js +9 -161
  59. package/lib/module/icons/SentryBugIcon.js +9 -171
  60. package/lib/module/index.js +4 -1
  61. package/lib/module/license/AccountSetup.js +52 -0
  62. package/lib/module/license/AccountSetup.web.js +77 -0
  63. package/lib/module/license/FeatureGate.js +10 -43
  64. package/lib/module/license/FreeAccountPrompt.js +35 -12
  65. package/lib/module/license/index.js +1 -1
  66. package/lib/module/license/licenseModule.js +50 -35
  67. package/lib/module/license/tierLimits.js +13 -63
  68. package/lib/module/storage/devToolsStorageKeys.js +8 -1
  69. package/lib/module/stores/BaseEventStore.js +21 -5
  70. package/lib/module/stores/createToolStore.js +21 -3
  71. package/lib/module/stores/floatingToolStore.js +61 -0
  72. package/lib/module/stores/floatingToolStore.test.js +111 -0
  73. package/lib/module/sync/toolActionRegistry.js +84 -2
  74. package/lib/module/ui/backgrounds/README.md +52 -0
  75. package/lib/module/ui/backgrounds/ToolBackground.js +4 -2
  76. package/lib/module/ui/backgrounds/index.js +2 -1
  77. package/lib/module/ui/backgrounds/registry.js +8 -0
  78. package/lib/module/ui/backgrounds/variants/wormhole/motion.js +44 -0
  79. package/lib/module/ui/backgrounds/variants/wormhole/textures.js +3 -0
  80. package/lib/module/ui/backgrounds/variants/wormhole.js +129 -0
  81. package/lib/module/ui/components/ClipboardHintBanner.js +5 -6
  82. package/lib/module/ui/components/CompactRow.js +94 -74
  83. package/lib/module/ui/components/DraggableHeader.js +16 -1
  84. package/lib/module/ui/components/HeaderSearchButton.js +17 -4
  85. package/lib/module/ui/floating/FloatingTool.js +1003 -0
  86. package/lib/module/ui/floating/FloatingTool.web.js +590 -0
  87. package/lib/module/ui/floating/FloatingToolHost.js +29 -0
  88. package/lib/module/ui/floating/FloatingToolHost.web.js +25 -0
  89. package/lib/module/ui/floating/index.js +6 -0
  90. package/lib/module/ui/floating/index.web.js +6 -0
  91. package/lib/module/ui/floating/onboardingConstants.js +64 -0
  92. package/lib/module/ui/floating/onboardingConstants.web.js +27 -0
  93. package/lib/module/ui/gameUI/constants/gameUIColors.js +3 -1
  94. package/lib/module/ui/index.js +5 -1
  95. package/lib/module/ui/night/nightTheme.js +10 -0
  96. package/lib/module/ui/night/primitives.js +22 -5
  97. package/lib/module/ui/otto/OttoSceneView.js +64 -0
  98. package/lib/module/ui/otto/index.js +3 -1
  99. package/lib/module/ui/otto/ottoEngine.js +10 -7
  100. package/lib/module/ui/otto/ottoScenes.js +942 -0
  101. package/lib/module/utils/minimalSuperJSON.js +13 -3
  102. package/lib/typescript/commonjs/JsModal.d.ts +43 -2
  103. package/lib/typescript/commonjs/JsModal.d.ts.map +1 -1
  104. package/lib/typescript/commonjs/JsModal.web.d.ts +5 -2
  105. package/lib/typescript/commonjs/JsModal.web.d.ts.map +1 -1
  106. package/lib/typescript/commonjs/dataViewer/CyberpunkInput.d.ts.map +1 -1
  107. package/lib/typescript/commonjs/dataViewer/LiveExplorer.d.ts.map +1 -1
  108. package/lib/typescript/commonjs/hooks/safe-area-impl.d.ts +1 -1
  109. package/lib/typescript/commonjs/icons/ReactQueryIcon.d.ts +1 -2
  110. package/lib/typescript/commonjs/icons/ReactQueryIcon.d.ts.map +1 -1
  111. package/lib/typescript/commonjs/icons/SentryBugIcon.d.ts +1 -2
  112. package/lib/typescript/commonjs/icons/SentryBugIcon.d.ts.map +1 -1
  113. package/lib/typescript/commonjs/index.d.ts +4 -1
  114. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  115. package/lib/typescript/commonjs/license/AccountSetup.d.ts +4 -0
  116. package/lib/typescript/commonjs/license/AccountSetup.d.ts.map +1 -0
  117. package/lib/typescript/commonjs/license/AccountSetup.web.d.ts +2 -0
  118. package/lib/typescript/commonjs/license/AccountSetup.web.d.ts.map +1 -0
  119. package/lib/typescript/commonjs/license/FeatureGate.d.ts +3 -19
  120. package/lib/typescript/commonjs/license/FeatureGate.d.ts.map +1 -1
  121. package/lib/typescript/commonjs/license/FreeAccountPrompt.d.ts +8 -11
  122. package/lib/typescript/commonjs/license/FreeAccountPrompt.d.ts.map +1 -1
  123. package/lib/typescript/commonjs/license/index.d.ts +1 -1
  124. package/lib/typescript/commonjs/license/index.d.ts.map +1 -1
  125. package/lib/typescript/commonjs/license/licenseModule.d.ts +18 -31
  126. package/lib/typescript/commonjs/license/licenseModule.d.ts.map +1 -1
  127. package/lib/typescript/commonjs/license/tierLimits.d.ts +9 -52
  128. package/lib/typescript/commonjs/license/tierLimits.d.ts.map +1 -1
  129. package/lib/typescript/commonjs/storage/devToolsStorageKeys.d.ts +6 -0
  130. package/lib/typescript/commonjs/storage/devToolsStorageKeys.d.ts.map +1 -1
  131. package/lib/typescript/commonjs/stores/BaseEventStore.d.ts.map +1 -1
  132. package/lib/typescript/commonjs/stores/createToolStore.d.ts.map +1 -1
  133. package/lib/typescript/commonjs/stores/floatingToolStore.d.ts +27 -0
  134. package/lib/typescript/commonjs/stores/floatingToolStore.d.ts.map +1 -0
  135. package/lib/typescript/commonjs/stores/floatingToolStore.test.d.ts +2 -0
  136. package/lib/typescript/commonjs/stores/floatingToolStore.test.d.ts.map +1 -0
  137. package/lib/typescript/commonjs/sync/toolActionRegistry.d.ts +4 -32
  138. package/lib/typescript/commonjs/sync/toolActionRegistry.d.ts.map +1 -1
  139. package/lib/typescript/commonjs/ui/backgrounds/ToolBackground.d.ts +7 -1
  140. package/lib/typescript/commonjs/ui/backgrounds/ToolBackground.d.ts.map +1 -1
  141. package/lib/typescript/commonjs/ui/backgrounds/index.d.ts +2 -1
  142. package/lib/typescript/commonjs/ui/backgrounds/index.d.ts.map +1 -1
  143. package/lib/typescript/commonjs/ui/backgrounds/registry.d.ts.map +1 -1
  144. package/lib/typescript/commonjs/ui/backgrounds/types.d.ts +11 -1
  145. package/lib/typescript/commonjs/ui/backgrounds/types.d.ts.map +1 -1
  146. package/lib/typescript/commonjs/ui/backgrounds/variants/wormhole/motion.d.ts +24 -0
  147. package/lib/typescript/commonjs/ui/backgrounds/variants/wormhole/motion.d.ts.map +1 -0
  148. package/lib/typescript/commonjs/ui/backgrounds/variants/wormhole/textures.d.ts +13 -0
  149. package/lib/typescript/commonjs/ui/backgrounds/variants/wormhole/textures.d.ts.map +1 -0
  150. package/lib/typescript/commonjs/ui/backgrounds/variants/wormhole.d.ts +3 -0
  151. package/lib/typescript/commonjs/ui/backgrounds/variants/wormhole.d.ts.map +1 -0
  152. package/lib/typescript/commonjs/ui/components/ClipboardHintBanner.d.ts.map +1 -1
  153. package/lib/typescript/commonjs/ui/components/CompactRow.d.ts +8 -1
  154. package/lib/typescript/commonjs/ui/components/CompactRow.d.ts.map +1 -1
  155. package/lib/typescript/commonjs/ui/components/DraggableHeader.d.ts +4 -1
  156. package/lib/typescript/commonjs/ui/components/DraggableHeader.d.ts.map +1 -1
  157. package/lib/typescript/commonjs/ui/components/HeaderSearchButton.d.ts +7 -1
  158. package/lib/typescript/commonjs/ui/components/HeaderSearchButton.d.ts.map +1 -1
  159. package/lib/typescript/commonjs/ui/floating/FloatingTool.d.ts +79 -0
  160. package/lib/typescript/commonjs/ui/floating/FloatingTool.d.ts.map +1 -0
  161. package/lib/typescript/commonjs/ui/floating/FloatingTool.web.d.ts +64 -0
  162. package/lib/typescript/commonjs/ui/floating/FloatingTool.web.d.ts.map +1 -0
  163. package/lib/typescript/commonjs/ui/floating/FloatingToolHost.d.ts +3 -0
  164. package/lib/typescript/commonjs/ui/floating/FloatingToolHost.d.ts.map +1 -0
  165. package/lib/typescript/commonjs/ui/floating/FloatingToolHost.web.d.ts +3 -0
  166. package/lib/typescript/commonjs/ui/floating/FloatingToolHost.web.d.ts.map +1 -0
  167. package/lib/typescript/commonjs/ui/floating/index.d.ts +7 -0
  168. package/lib/typescript/commonjs/ui/floating/index.d.ts.map +1 -0
  169. package/lib/typescript/commonjs/ui/floating/index.web.d.ts +7 -0
  170. package/lib/typescript/commonjs/ui/floating/index.web.d.ts.map +1 -0
  171. package/lib/typescript/commonjs/ui/floating/onboardingConstants.d.ts +30 -0
  172. package/lib/typescript/commonjs/ui/floating/onboardingConstants.d.ts.map +1 -0
  173. package/lib/typescript/commonjs/ui/floating/onboardingConstants.web.d.ts +13 -0
  174. package/lib/typescript/commonjs/ui/floating/onboardingConstants.web.d.ts.map +1 -0
  175. package/lib/typescript/commonjs/ui/gameUI/constants/gameUIColors.d.ts +2 -0
  176. package/lib/typescript/commonjs/ui/gameUI/constants/gameUIColors.d.ts.map +1 -1
  177. package/lib/typescript/commonjs/ui/index.d.ts +6 -0
  178. package/lib/typescript/commonjs/ui/index.d.ts.map +1 -1
  179. package/lib/typescript/commonjs/ui/night/nightTheme.d.ts +10 -0
  180. package/lib/typescript/commonjs/ui/night/nightTheme.d.ts.map +1 -1
  181. package/lib/typescript/commonjs/ui/night/primitives.d.ts +10 -3
  182. package/lib/typescript/commonjs/ui/night/primitives.d.ts.map +1 -1
  183. package/lib/typescript/commonjs/ui/otto/OttoSceneView.d.ts +30 -0
  184. package/lib/typescript/commonjs/ui/otto/OttoSceneView.d.ts.map +1 -0
  185. package/lib/typescript/commonjs/ui/otto/index.d.ts +2 -0
  186. package/lib/typescript/commonjs/ui/otto/index.d.ts.map +1 -1
  187. package/lib/typescript/commonjs/ui/otto/ottoEngine.d.ts +1 -1
  188. package/lib/typescript/commonjs/ui/otto/ottoEngine.d.ts.map +1 -1
  189. package/lib/typescript/commonjs/ui/otto/ottoScenes.d.ts +75 -0
  190. package/lib/typescript/commonjs/ui/otto/ottoScenes.d.ts.map +1 -0
  191. package/lib/typescript/commonjs/utils/minimalSuperJSON.d.ts.map +1 -1
  192. package/lib/typescript/module/JsModal.d.ts +43 -2
  193. package/lib/typescript/module/JsModal.d.ts.map +1 -1
  194. package/lib/typescript/module/JsModal.web.d.ts +5 -2
  195. package/lib/typescript/module/JsModal.web.d.ts.map +1 -1
  196. package/lib/typescript/module/dataViewer/CyberpunkInput.d.ts.map +1 -1
  197. package/lib/typescript/module/dataViewer/LiveExplorer.d.ts.map +1 -1
  198. package/lib/typescript/module/hooks/safe-area-impl.d.ts +1 -1
  199. package/lib/typescript/module/icons/ReactQueryIcon.d.ts +1 -2
  200. package/lib/typescript/module/icons/ReactQueryIcon.d.ts.map +1 -1
  201. package/lib/typescript/module/icons/SentryBugIcon.d.ts +1 -2
  202. package/lib/typescript/module/icons/SentryBugIcon.d.ts.map +1 -1
  203. package/lib/typescript/module/index.d.ts +4 -1
  204. package/lib/typescript/module/index.d.ts.map +1 -1
  205. package/lib/typescript/module/license/AccountSetup.d.ts +4 -0
  206. package/lib/typescript/module/license/AccountSetup.d.ts.map +1 -0
  207. package/lib/typescript/module/license/AccountSetup.web.d.ts +2 -0
  208. package/lib/typescript/module/license/AccountSetup.web.d.ts.map +1 -0
  209. package/lib/typescript/module/license/FeatureGate.d.ts +3 -19
  210. package/lib/typescript/module/license/FeatureGate.d.ts.map +1 -1
  211. package/lib/typescript/module/license/FreeAccountPrompt.d.ts +8 -11
  212. package/lib/typescript/module/license/FreeAccountPrompt.d.ts.map +1 -1
  213. package/lib/typescript/module/license/index.d.ts +1 -1
  214. package/lib/typescript/module/license/index.d.ts.map +1 -1
  215. package/lib/typescript/module/license/licenseModule.d.ts +18 -31
  216. package/lib/typescript/module/license/licenseModule.d.ts.map +1 -1
  217. package/lib/typescript/module/license/tierLimits.d.ts +9 -52
  218. package/lib/typescript/module/license/tierLimits.d.ts.map +1 -1
  219. package/lib/typescript/module/storage/devToolsStorageKeys.d.ts +6 -0
  220. package/lib/typescript/module/storage/devToolsStorageKeys.d.ts.map +1 -1
  221. package/lib/typescript/module/stores/BaseEventStore.d.ts.map +1 -1
  222. package/lib/typescript/module/stores/createToolStore.d.ts.map +1 -1
  223. package/lib/typescript/module/stores/floatingToolStore.d.ts +27 -0
  224. package/lib/typescript/module/stores/floatingToolStore.d.ts.map +1 -0
  225. package/lib/typescript/module/stores/floatingToolStore.test.d.ts +2 -0
  226. package/lib/typescript/module/stores/floatingToolStore.test.d.ts.map +1 -0
  227. package/lib/typescript/module/sync/toolActionRegistry.d.ts +4 -32
  228. package/lib/typescript/module/sync/toolActionRegistry.d.ts.map +1 -1
  229. package/lib/typescript/module/ui/backgrounds/ToolBackground.d.ts +7 -1
  230. package/lib/typescript/module/ui/backgrounds/ToolBackground.d.ts.map +1 -1
  231. package/lib/typescript/module/ui/backgrounds/index.d.ts +2 -1
  232. package/lib/typescript/module/ui/backgrounds/index.d.ts.map +1 -1
  233. package/lib/typescript/module/ui/backgrounds/registry.d.ts.map +1 -1
  234. package/lib/typescript/module/ui/backgrounds/types.d.ts +11 -1
  235. package/lib/typescript/module/ui/backgrounds/types.d.ts.map +1 -1
  236. package/lib/typescript/module/ui/backgrounds/variants/wormhole/motion.d.ts +24 -0
  237. package/lib/typescript/module/ui/backgrounds/variants/wormhole/motion.d.ts.map +1 -0
  238. package/lib/typescript/module/ui/backgrounds/variants/wormhole/textures.d.ts +13 -0
  239. package/lib/typescript/module/ui/backgrounds/variants/wormhole/textures.d.ts.map +1 -0
  240. package/lib/typescript/module/ui/backgrounds/variants/wormhole.d.ts +3 -0
  241. package/lib/typescript/module/ui/backgrounds/variants/wormhole.d.ts.map +1 -0
  242. package/lib/typescript/module/ui/components/ClipboardHintBanner.d.ts.map +1 -1
  243. package/lib/typescript/module/ui/components/CompactRow.d.ts +8 -1
  244. package/lib/typescript/module/ui/components/CompactRow.d.ts.map +1 -1
  245. package/lib/typescript/module/ui/components/DraggableHeader.d.ts +4 -1
  246. package/lib/typescript/module/ui/components/DraggableHeader.d.ts.map +1 -1
  247. package/lib/typescript/module/ui/components/HeaderSearchButton.d.ts +7 -1
  248. package/lib/typescript/module/ui/components/HeaderSearchButton.d.ts.map +1 -1
  249. package/lib/typescript/module/ui/floating/FloatingTool.d.ts +79 -0
  250. package/lib/typescript/module/ui/floating/FloatingTool.d.ts.map +1 -0
  251. package/lib/typescript/module/ui/floating/FloatingTool.web.d.ts +64 -0
  252. package/lib/typescript/module/ui/floating/FloatingTool.web.d.ts.map +1 -0
  253. package/lib/typescript/module/ui/floating/FloatingToolHost.d.ts +3 -0
  254. package/lib/typescript/module/ui/floating/FloatingToolHost.d.ts.map +1 -0
  255. package/lib/typescript/module/ui/floating/FloatingToolHost.web.d.ts +3 -0
  256. package/lib/typescript/module/ui/floating/FloatingToolHost.web.d.ts.map +1 -0
  257. package/lib/typescript/module/ui/floating/index.d.ts +7 -0
  258. package/lib/typescript/module/ui/floating/index.d.ts.map +1 -0
  259. package/lib/typescript/module/ui/floating/index.web.d.ts +7 -0
  260. package/lib/typescript/module/ui/floating/index.web.d.ts.map +1 -0
  261. package/lib/typescript/module/ui/floating/onboardingConstants.d.ts +30 -0
  262. package/lib/typescript/module/ui/floating/onboardingConstants.d.ts.map +1 -0
  263. package/lib/typescript/module/ui/floating/onboardingConstants.web.d.ts +13 -0
  264. package/lib/typescript/module/ui/floating/onboardingConstants.web.d.ts.map +1 -0
  265. package/lib/typescript/module/ui/gameUI/constants/gameUIColors.d.ts +2 -0
  266. package/lib/typescript/module/ui/gameUI/constants/gameUIColors.d.ts.map +1 -1
  267. package/lib/typescript/module/ui/index.d.ts +6 -0
  268. package/lib/typescript/module/ui/index.d.ts.map +1 -1
  269. package/lib/typescript/module/ui/night/nightTheme.d.ts +10 -0
  270. package/lib/typescript/module/ui/night/nightTheme.d.ts.map +1 -1
  271. package/lib/typescript/module/ui/night/primitives.d.ts +10 -3
  272. package/lib/typescript/module/ui/night/primitives.d.ts.map +1 -1
  273. package/lib/typescript/module/ui/otto/OttoSceneView.d.ts +30 -0
  274. package/lib/typescript/module/ui/otto/OttoSceneView.d.ts.map +1 -0
  275. package/lib/typescript/module/ui/otto/index.d.ts +2 -0
  276. package/lib/typescript/module/ui/otto/index.d.ts.map +1 -1
  277. package/lib/typescript/module/ui/otto/ottoEngine.d.ts +1 -1
  278. package/lib/typescript/module/ui/otto/ottoEngine.d.ts.map +1 -1
  279. package/lib/typescript/module/ui/otto/ottoScenes.d.ts +75 -0
  280. package/lib/typescript/module/ui/otto/ottoScenes.d.ts.map +1 -0
  281. package/lib/typescript/module/utils/minimalSuperJSON.d.ts.map +1 -1
  282. package/package.json +25 -5
  283. package/scripts/generate-wormhole-textures.cjs +261 -0
  284. package/scripts/test-wormhole-motion.cjs +59 -0
@@ -0,0 +1,942 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * Otto × tools — pixel scenes.
5
+ *
6
+ * One scene per dev tool: Otto in an engine pose, holding / leaning on /
7
+ * pointing at a hand-drawn PIXEL prop that stands for the tool. Everything is
8
+ * on the same 1-cell grid as the sprite, so a scene is just a bigger frame:
9
+ *
10
+ * renderOttoScene(scene, t) → W×H grid of palette keys (`.` = transparent)
11
+ * ottoSceneRuns(grid) → coloured horizontal runs for a renderer
12
+ *
13
+ * Props are ASCII art in `OTTO_SCENE_PALETTE` keys. A layer gets a one-cell
14
+ * black keyline around it (`outline`), sits over or under Otto (`over`), and
15
+ * can ride his hands (`follow` = bob with `OTTO_ANCHORS[state]`). Otto's own
16
+ * frame comes straight from `renderOttoFrame`, so the mascot is never
17
+ * redrawn here — only what he is doing with the tool.
18
+ *
19
+ * Pure, no React: the same module renders the website gallery, the export
20
+ * script and any RN still.
21
+ */
22
+ import { OTTO_ANCHORS, OTTO_GRID, OTTO_PALETTE, renderOttoFrame } from "./ottoEngine.js";
23
+
24
+ /** Sprite palette plus prop colours. `.` and space are transparent. */
25
+ export const OTTO_SCENE_PALETTE = {
26
+ ...OTTO_PALETTE,
27
+ K: "#000000",
28
+ // prop keyline
29
+ c: "#22D3EE",
30
+ // cyan
31
+ C: "#0E7490",
32
+ // cyan deep
33
+ u: "#7DD3FC",
34
+ // sky (Ask Buoy)
35
+ b: "#3B82F6",
36
+ // blue
37
+ B: "#1E3A8A",
38
+ // blue deep
39
+ y: "#FDE047",
40
+ // yellow
41
+ Y: "#F59E0B",
42
+ // amber
43
+ o: "#FB923C",
44
+ // orange
45
+ v: "#C4B5FD",
46
+ // lavender
47
+ P: "#6D28D9",
48
+ // purple deep
49
+ e: "#FB7185",
50
+ // rose
51
+ E: "#BE123C",
52
+ // rose deep
53
+ i: "#F472B6",
54
+ // pink
55
+ t: "#B07D4F",
56
+ // tan (bear)
57
+ T: "#6B4423",
58
+ // brown deep
59
+ z: "#0B1220",
60
+ // screen navy
61
+ q: "#1F2937",
62
+ // slate
63
+ Q: "#374151",
64
+ // slate light
65
+ f: "#4ADE80",
66
+ // mint (screen text, checks)
67
+ F: "#166534",
68
+ // green deep
69
+ x: "#CBD5E1",
70
+ // steel
71
+ j: "#E7C9A0",
72
+ // light tan (bear muzzle)
73
+ G: "#F6C453",
74
+ // gold (sun)
75
+ D: "#EF5B4E",
76
+ // sunset red
77
+ L: "#5DBB63",
78
+ // leaf
79
+ M: "#3D8B4F" // leaf deep
80
+ };
81
+ export const OTTO_SCENE_W = 30;
82
+ export const OTTO_SCENE_H = 24;
83
+ /** Default sprite position: feet on row 17, lamp on row 7, prop room on both sides. */
84
+ export const OTTO_SCENE_OTTO = {
85
+ x: 2,
86
+ y: 5
87
+ };
88
+ function blank(w, h) {
89
+ return Array.from({
90
+ length: h
91
+ }, () => Array(w).fill("."));
92
+ }
93
+ function filled(c) {
94
+ return !!c && c !== "." && c !== " ";
95
+ }
96
+
97
+ /** Art rows → cells, with the keyline dilation applied inside the layer. */
98
+ function layerCells(layer) {
99
+ const rows = layer.art;
100
+ const cells = [];
101
+ const has = (x, y) => y >= 0 && y < rows.length && filled(rows[y][x]);
102
+ const outline = layer.outline ?? true;
103
+ let maxW = 0;
104
+ for (const r of rows) maxW = Math.max(maxW, r.length);
105
+ for (let y = -1; y <= rows.length; y++) {
106
+ for (let x = -1; x <= maxW; x++) {
107
+ if (has(x, y)) {
108
+ cells.push([x, y, rows[y][x]]);
109
+ } else if (outline && (has(x - 1, y) || has(x + 1, y) || has(x, y - 1) || has(x, y + 1))) {
110
+ cells.push([x, y, "K"]);
111
+ }
112
+ }
113
+ }
114
+ return cells;
115
+ }
116
+ function anchorBob(state, t) {
117
+ const a = OTTO_ANCHORS[state];
118
+ if (!a) return 0;
119
+ return a(t).y - a(0).y;
120
+ }
121
+
122
+ /** The dark checker under Otto's feet — the engine's water colours, as a floor. */
123
+ function ground(x, y, t) {
124
+ return ((x - Math.floor(t / 2) + y * 5) % 7 + 7) % 7 < 2 ? "W" : "w";
125
+ }
126
+
127
+ /** One frame of a scene as a `OTTO_SCENE_W × OTTO_SCENE_H` grid of palette keys. */
128
+ export function renderOttoScene(scene, t = 0) {
129
+ const W = OTTO_SCENE_W;
130
+ const H = OTTO_SCENE_H;
131
+ const g = blank(W, H);
132
+ const ox = scene.ottoX ?? OTTO_SCENE_OTTO.x;
133
+ const oy = scene.ottoY ?? OTTO_SCENE_OTTO.y;
134
+ const put = (x, y, c) => {
135
+ if (x >= 0 && x < W && y >= 0 && y < H) g[y][x] = c;
136
+ };
137
+
138
+ // Floor: three rows under the feet (sprite rows 13–15), fading out at the ends.
139
+ if (scene.ground !== false) {
140
+ const [gx0, gx1] = scene.ground ?? [ox + 1, ox + OTTO_GRID - 2];
141
+ for (let y = 13; y < 16; y++) {
142
+ for (let x = gx0; x <= gx1; x++) {
143
+ const edge = x === gx0 || x === gx1;
144
+ if (y === 15 && (x + y) % 2) continue;
145
+ if (edge && y !== 14) continue;
146
+ put(x, oy + y, ground(x, y, t));
147
+ }
148
+ }
149
+ }
150
+ const bob = anchorBob(scene.state, t);
151
+ const paint = layer => {
152
+ const dy = layer.follow ? bob : 0;
153
+ for (const [x, y, c] of layerCells(layer)) put(layer.x + x, layer.y + y + dy, c);
154
+ };
155
+ for (const layer of scene.layers) if (!layer.over) paint(layer);
156
+ const otto = renderOttoFrame(scene.state, t, {
157
+ water: false,
158
+ keyline: true
159
+ });
160
+ for (let y = 0; y < OTTO_GRID; y++) {
161
+ for (let x = 0; x < OTTO_GRID; x++) {
162
+ const c = otto[y][x];
163
+ if (c !== ".") put(ox + x, oy + y, c);
164
+ }
165
+ }
166
+ for (const layer of scene.layers) if (layer.over) paint(layer);
167
+ return g;
168
+ }
169
+ /** Run-length encode a scene frame into coloured spans, skipping transparency. */
170
+ export function ottoSceneRuns(grid) {
171
+ const runs = [];
172
+ for (let y = 0; y < grid.length; y++) {
173
+ const row = grid[y];
174
+ let x = 0;
175
+ while (x < row.length) {
176
+ const key = row[x];
177
+ let w = 1;
178
+ while (x + w < row.length && row[x + w] === key) w++;
179
+ if (key !== ".") {
180
+ const color = OTTO_SCENE_PALETTE[key];
181
+ if (color) runs.push({
182
+ x,
183
+ y,
184
+ w,
185
+ color
186
+ });
187
+ }
188
+ x += w;
189
+ }
190
+ }
191
+ return runs;
192
+ }
193
+
194
+ /** Tight bounds of the filled cells: `[x0, y0, x1, y1]` inclusive, or null when empty. */
195
+ export function ottoSceneBounds(grid) {
196
+ let x0 = Infinity;
197
+ let y0 = Infinity;
198
+ let x1 = -1;
199
+ let y1 = -1;
200
+ for (let y = 0; y < grid.length; y++) {
201
+ for (let x = 0; x < grid[y].length; x++) {
202
+ if (grid[y][x] === ".") continue;
203
+ if (x < x0) x0 = x;
204
+ if (x > x1) x1 = x;
205
+ if (y < y0) y0 = y;
206
+ if (y > y1) y1 = y;
207
+ }
208
+ }
209
+ return x1 < 0 ? null : [x0, y0, x1, y1];
210
+ }
211
+
212
+ // ------------------------------------------------------------------ props --
213
+ //
214
+ // Drawn on the sprite's cell grid, the size of a held object (7–13 cells).
215
+ // The keyline pass draws the outline — never hand-draw `K` except for detail
216
+ // INSIDE a prop (eyes, a keyhole, an exclamation mark).
217
+
218
+ /** A `w×h` box: `fill` inside, `border` on the edge, corners cut when `round`. */
219
+ function box(w, h, fill, border = fill, round = true) {
220
+ const rows = [];
221
+ for (let y = 0; y < h; y++) {
222
+ let r = "";
223
+ for (let x = 0; x < w; x++) {
224
+ const edge = x === 0 || y === 0 || x === w - 1 || y === h - 1;
225
+ const corner = (x === 0 || x === w - 1) && (y === 0 || y === h - 1);
226
+ r += round && corner ? "." : edge ? border : fill;
227
+ }
228
+ rows.push(r);
229
+ }
230
+ return rows;
231
+ }
232
+
233
+ /** Paint `art` onto `base` at (x, y); transparent cells leave the base alone. */
234
+ function stamp(base, art, x, y) {
235
+ const out = base.map(r => r.split(""));
236
+ for (let j = 0; j < art.length; j++) {
237
+ for (let i = 0; i < art[j].length; i++) {
238
+ const c = art[j][i];
239
+ if (!filled(c)) continue;
240
+ const yy = y + j;
241
+ const xx = x + i;
242
+ if (yy < 0 || xx < 0) continue;
243
+ while (out.length <= yy) out.push([]);
244
+ while (out[yy].length <= xx) out[yy].push(".");
245
+ out[yy][xx] = c;
246
+ }
247
+ }
248
+ return out.map(r => r.join(""));
249
+ }
250
+
251
+ /** Four-point sparkle, 3×3. */
252
+ function sparkle(c) {
253
+ return [`.${c}.`, `${c}${c}${c}`, `.${c}.`];
254
+ }
255
+
256
+ /** A big sparkle, 5×5, with a bright centre. */
257
+ function star(c, centre = "l") {
258
+ return [`..${c}..`, `..${c}..`, `${c}${c}${centre}${c}${c}`, `..${c}..`, `..${c}..`];
259
+ }
260
+
261
+ /** A ring of thickness 2 on an odd `d`, in colour `c`, `fill` inside. */
262
+ function ring(d, c, fill = ".") {
263
+ const r = (d - 1) / 2;
264
+ const rows = [];
265
+ for (let y = 0; y < d; y++) {
266
+ let s = "";
267
+ for (let x = 0; x < d; x++) {
268
+ const dd = Math.hypot(x - r, y - r);
269
+ s += dd > r + 0.4 ? "." : dd > r - 1.6 ? c : fill;
270
+ }
271
+ rows.push(s);
272
+ }
273
+ return rows;
274
+ }
275
+ const NETWORK_TILE = stamp(box(13, 13, "z", "C"), ["...ccccc...", ".cc.ccc.cc.", ".c.c...c.c.", "c..c...c..c", "c..c...c..c", "ccccccccccc", "c..c...c..c", "c..c...c..c", ".c.c...c.c.", ".cc.ccc.cc.", "...ccccc..."], 1, 1);
276
+ const STORAGE_KEY = ["..yyy..", ".yYYYy.", ".yYKYy.", ".yYYYy.", "..yYy..", "..yYy..", "..yYyy.", "..yYy..", "..yYyy.", "..yYy..", "..yyy.."];
277
+ const STORAGE_SAFE = stamp(stamp(box(11, 10, "Q", "q", false), ["yyy", "yKy", "yyy", ".y."], 4, 3), ["qq.....qq"], 1, 10);
278
+
279
+ /** A filled disc of diameter `d`, one band colour per row, top to bottom. */
280
+ function disc(d, bands) {
281
+ const r = (d - 1) / 2;
282
+ const rows = [];
283
+ for (let y = 0; y < d; y++) {
284
+ let s = "";
285
+ for (let x = 0; x < d; x++) s += Math.hypot(x - r, y - r) > r + 0.4 ? "." : bands[y] ?? bands[bands.length - 1];
286
+ rows.push(s);
287
+ }
288
+ return rows;
289
+ }
290
+
291
+ /** Shift each row right by `dx(row)` — a lid seen at an angle. */
292
+ function skew(rows, dx) {
293
+ return rows.map((r, i) => ".".repeat(dx(i)) + r);
294
+ }
295
+
296
+ // Query: Otto on the beach — a palm, a sunset over the water, sunglasses and
297
+ // a laptop running React. The disc has no keyline on purpose (it is sky).
298
+ const QUERY_SUNSET = stamp(disc(13, "bppiieoDDbbbb"), [".GG.", "GGGG", "yyyy", ".GG."], 6, 2);
299
+ const QUERY_PALM = ["..LLL.....", ".LLMLL....", "LLM.LL..LL", "LM..LL.LLM", "....LLLLM.", "LLL.LLLM..", "LLMLLLLLLL", "LMM.YYMMLL", "....YY..MM", "...YY.....", "...YY.....", "..YY......", "..YY......", "..YY......"];
300
+ const QUERY_SAND = [".YYYY.....", "GGYYYYYY..", "GYYYYYYYYY", "YYYYYYYYYYY"];
301
+ const QUERY_REACT = ["..cc.cc..", ".c..c..c.", "c.cc.cc.c", "c.c.l.c.c", "c.cc.cc.c", ".c..c..c.", "..cc.cc.."];
302
+ const QUERY_LAPTOP_LID = skew(stamp(["mmmmmmmmmmm", ...Array(7).fill("11111111111")], QUERY_REACT, 1, 1), i => i < 3 ? 2 : i < 6 ? 1 : 0);
303
+ const QUERY_LAPTOP_BASE = ["KmmmmmmmmmmmmmK"];
304
+ const QUERY_SHADES = ["KKKKKKKKK", "..KKK.KKK", "..KKK.KKK"];
305
+ const QUERY_SMILE = ["K..K", ".KK."];
306
+ const QUERY_ARM = ["KK.", "ggK", "KK."];
307
+ const ENV_PANEL = (() => {
308
+ let p = box(13, 11, "z", "q", false);
309
+ for (const [row, knob, col] of [[2, "f", 7], [5, "b", 3], [8, "o", 8]]) {
310
+ p = stamp(p, ["QQQQQQQQQ"], 2, row);
311
+ p = stamp(p, [knob + knob, knob + knob, knob + knob], col, row - 1);
312
+ }
313
+ return p;
314
+ })();
315
+ const REDUX_KNOT = stamp(ring(11, "p", "z"), ["...v...", "..v.v..", ".v...v.", "v..v..v", "v.v.v.v", ".vv.vv."], 2, 2);
316
+ const ZUSTAND_BEAR = ["tt.....tt", "tTt...tTt", ".ttttttt.", "ttttttttt", "tKtttttKt", "ttttttttt", "ttjjjjjtt", "ttjjKjjtt", ".tjjjjjt."];
317
+ const JOTAI_ATOM = ["....ccc....", "...c...c...", "...c...c...", ".ccc...ccc.", "c..c...c..c", "c....y....c", "c..c...c..c", ".ccc...ccc.", "...c...c...", "...c...c...", "....ccc...."];
318
+ const TIME_MACHINE_REWIND = stamp(ring(13, "c", "z"), ["...c..c", "..cc.cc", ".ccc.ccc", "cccc.cccc", ".ccc.ccc", "..cc.cc", "...c..c"], 2, 3);
319
+ const ROUTES_PIN = ["..eee..", ".eeeee.", "eeellee", "eeellee", ".eeeee.", "..eee..", "...e...", "...e..."];
320
+ const HIGHLIGHT_ARROW = ["...y...", "..yyy..", ".yyyyy.", "yyyyyyy", "..yYy..", "..yYy..", "..yYy..", "..yYy.."];
321
+ const DEBUG_BORDER = (() => {
322
+ const w = 13;
323
+ const h = 11;
324
+ const rows = [];
325
+ for (let y = 0; y < h; y++) {
326
+ let r = "";
327
+ for (let x = 0; x < w; x++) {
328
+ const edge = x === 0 || y === 0 || x === w - 1 || y === h - 1;
329
+ const corner = (x < 2 || x > w - 3) && (y < 2 || y > h - 3);
330
+ r += corner ? "i" : edge && (x + y) % 2 === 0 ? "i" : ".";
331
+ }
332
+ rows.push(r);
333
+ }
334
+ return rows;
335
+ })();
336
+ function plane(c) {
337
+ return ["....cccc....".replace(/c/g, c), "..cccccccc..".replace(/c/g, c), "cccccccccccc".replace(/c/g, c), "..cccccccc..".replace(/c/g, c), "....cccc....".replace(/c/g, c)];
338
+ }
339
+ const IMPERSONATE_HAT = ["...qqqqqqqq...", "...qqqqqqqq...", "...qqqaaqqq...", "qqqqqqqqqqqqqq"];
340
+ const IMPERSONATE_GLASSES = ["KKKK.KKKK", "KllKKKllK", "KKKK.KKKK"];
341
+ const IMPERSONATE_STACHE = ["KKK.KKK", ".KK.KK."];
342
+ const IMPERSONATE_CARD = stamp(box(11, 8, "u", "x", false), ["zz.xxx", "zz.xx.", "...xxx"], 2, 2);
343
+ const BENCH_WATCH = stamp(stamp(ring(11, "n", "z"), ["...nnn...", "....n...."].reverse(), 1, -2), ["l", ".r", "..r"], 5, 3);
344
+ const JS_TOP_CHART = stamp(stamp(box(13, 11, "z", "q", false), [".....f.....", "....f.f....", "f..f...f..f", ".ff.....ff."], 1, 2), ["r.rr.r.rrr", "r.rr.rrrrr"], 2, 7);
345
+ const IMAGES_CARD = stamp(stamp(box(13, 9, "u", "l", false), ["..f..", ".fff.", "fffff", "ffFffff", "fFFfFFff"], 3, 3), ["yy", "yy"], 8, 2);
346
+ const ASSETS_CRATE = stamp(box(11, 9, "t", "T", false), ["llll.", "lxxll", "llll.l", "lxxxl", "llll.l", "lxxxl", "lllll"].map(r => r.slice(0, 5)), 3, 1);
347
+ const CONSOLE_MONITOR = stamp(box(13, 10, "z", "Q", false), ["f.", "ff", "f.", "..", "f.ffff", "ff", "f."], 2, 2);
348
+ const CONSOLE_STAND = ["..qq..", "..qq..", "qqqqqq"];
349
+ const CONSOLE_KEYS = ["qqqqqqqq", "qQQQQQQq", "qqqqqqqq"];
350
+ const EVENTS_LINE = (() => {
351
+ let p = ["...bbbbb...yyyyy", "...b.x.b...y.x.y", "...bx..b...yx..y", "...bbbbb...yyyyy", ".....n.......n..", ".....n.......n..", "nnnnnnnnnnnnnnnn"];
352
+ for (const [col, c] of [[0, "y"], [4, "c"], [8, "o"], [12, "p"]]) {
353
+ p = stamp(p, [c + c + c, c + c + c, c + c + c], col, 5);
354
+ }
355
+ return p;
356
+ })();
357
+ const SENTRY_SHIELD = stamp(["nnnnnnnnnnn", "nQQQQQQQQQn", "nQQQQQQQQQn", "nQQQQQQQQQn", "nQQQQQQQQQn", "nQQQQQQQQQn", "nQQQQQQQQQn", "nQQQQQQQQQn", ".nQQQQQQQn.", "..nQQQQQn..", "...nQQQn...", "....nQn....", ".....n....."], ["...r...", "..rrr..", "..rKr..", ".rrKrr.", ".rrrrr.", "rrrKrrr", "rrrrrrr"], 2, 1);
358
+ const SCENARIOS_FLOW = (() => {
359
+ let p = [];
360
+ p = stamp(p, box(7, 4, "z", "f", false), 3, 0);
361
+ p = stamp(p, ["fff"], 5, 1);
362
+ p = stamp(p, ["fff"], 5, 2);
363
+ p = stamp(p, ["n"], 6, 4);
364
+ p = stamp(p, ["nnnnnnnnn"], 2, 5);
365
+ p = stamp(p, ["n"], 2, 6);
366
+ p = stamp(p, ["n"], 10, 6);
367
+ p = stamp(p, box(5, 3, "z", "p", false), 0, 7);
368
+ p = stamp(p, ["ppp"], 1, 8);
369
+ p = stamp(p, box(5, 3, "z", "b", false), 8, 7);
370
+ p = stamp(p, ["bbb"], 9, 8);
371
+ return p;
372
+ })();
373
+ const ASK_BUOY_BUBBLE = stamp(stamp(box(13, 8, "z", "u", false), ["uu.uu.uu"], 3, 3), ["uu", "u."], 2, 8);
374
+ const TV_REMOTE_REMOTE = stamp(box(5, 9, "q", "Q", false), [".e.", "c.c", ".y.", "c.c"], 1, 1);
375
+ const TV_REMOTE_WAVES = ["...ee", "..e..", ".e.ee", ".e.e.", ".e.ee", "..e..", "...ee"];
376
+ const TV_REMOTE_SHADES = ["KKK.KKK", "KKKKKKK"];
377
+ const FOCUS_GLASS = stamp(ring(9, "n", "c"), ["l"], 3, 3);
378
+ const FOCUS_HANDLE = ["..mm", ".mm.", "mm.."];
379
+ function bracket(c, corner) {
380
+ const h = c.repeat(4);
381
+ const v = `${c}...`;
382
+ const rows = [h, v, v, v];
383
+ const flipX = r => r.split("").reverse().join("");
384
+ let out = rows;
385
+ if (corner === "tr" || corner === "br") out = out.map(flipX);
386
+ if (corner === "bl" || corner === "br") out = [...out].reverse();
387
+ return out;
388
+ }
389
+ const CAMERA_BODY = stamp(stamp(stamp(["..QQQQ"], box(13, 9, "q", "Q", false), 0, 1), ring(7, "n", "c"), 3, 2), ["yy"], 9, 3);
390
+
391
+ // ----------------------------------------------------------------- scenes --
392
+ //
393
+ // Otto sits at (2, 5): lamp on row 7, eyes on rows 11–12, palm (present) at
394
+ // (15–17, 12), arm rest (lean) on row 10, feet on row 17, floor on rows 18–20.
395
+
396
+ export const OTTO_SCENES = [{
397
+ id: "network",
398
+ name: "Network",
399
+ color: "#00D4FF",
400
+ line: "The first request, caught.",
401
+ state: "present",
402
+ layers: [{
403
+ art: NETWORK_TILE,
404
+ x: 16,
405
+ y: 1,
406
+ follow: true
407
+ }, {
408
+ art: sparkle("l"),
409
+ x: 27,
410
+ y: 1,
411
+ outline: false,
412
+ follow: true
413
+ }, {
414
+ art: ["l"],
415
+ x: 14,
416
+ y: 1,
417
+ outline: false,
418
+ follow: true
419
+ }]
420
+ }, {
421
+ id: "storage",
422
+ name: "Storage",
423
+ color: "#FFB800",
424
+ line: "Keys in, keys out, nothing lost.",
425
+ state: "present",
426
+ layers: [{
427
+ art: STORAGE_SAFE,
428
+ x: 19,
429
+ y: 7
430
+ }, {
431
+ art: STORAGE_KEY,
432
+ x: 16,
433
+ y: 1,
434
+ follow: true,
435
+ over: true
436
+ }],
437
+ ground: [3, 29]
438
+ }, {
439
+ id: "react-query",
440
+ name: "Query",
441
+ color: "#02CEE2",
442
+ line: "Ask anything, find everything.",
443
+ state: "static",
444
+ ottoX: 6,
445
+ ottoY: 3,
446
+ layers: [{
447
+ art: QUERY_SUNSET,
448
+ x: 11,
449
+ y: 0,
450
+ outline: false
451
+ }, {
452
+ art: QUERY_SAND,
453
+ x: 0,
454
+ y: 13
455
+ }, {
456
+ art: QUERY_PALM,
457
+ x: 0,
458
+ y: 0
459
+ }, {
460
+ art: QUERY_SHADES,
461
+ x: 9,
462
+ y: 8,
463
+ outline: false,
464
+ over: true
465
+ }, {
466
+ art: QUERY_SMILE,
467
+ x: 12,
468
+ y: 11,
469
+ outline: false,
470
+ over: true
471
+ }, {
472
+ art: QUERY_LAPTOP_LID,
473
+ x: 15,
474
+ y: 12,
475
+ over: true
476
+ }, {
477
+ art: QUERY_LAPTOP_BASE,
478
+ x: 13,
479
+ y: 20,
480
+ outline: false,
481
+ over: true
482
+ }, {
483
+ art: QUERY_ARM,
484
+ x: 19,
485
+ y: 10,
486
+ outline: false,
487
+ over: true
488
+ }],
489
+ ground: [2, 27]
490
+ }, {
491
+ id: "env",
492
+ name: "Env",
493
+ color: "#4AFF9F",
494
+ line: "Every variable, checked.",
495
+ state: "lean",
496
+ layers: [{
497
+ art: ENV_PANEL,
498
+ x: 16,
499
+ y: 7
500
+ }],
501
+ ground: [3, 28]
502
+ }, {
503
+ id: "redux",
504
+ name: "Redux",
505
+ color: "#764abc",
506
+ line: "One store, held close.",
507
+ state: "hug",
508
+ layers: [{
509
+ art: REDUX_KNOT,
510
+ x: 6,
511
+ y: 12,
512
+ over: true,
513
+ follow: true
514
+ }, {
515
+ art: ["e.e", "eee", ".e."],
516
+ x: 17,
517
+ y: 4,
518
+ outline: false
519
+ }, {
520
+ art: ["e.e", "eee", ".e."],
521
+ x: 21,
522
+ y: 1,
523
+ outline: false
524
+ }]
525
+ }, {
526
+ id: "zustand",
527
+ name: "Zustand",
528
+ color: "#C08552",
529
+ line: "Small stores, big possibilities.",
530
+ state: "hug",
531
+ layers: [{
532
+ art: ZUSTAND_BEAR,
533
+ x: 6,
534
+ y: 12,
535
+ over: true,
536
+ follow: true
537
+ }, {
538
+ art: ["e.e", "eee", ".e."],
539
+ x: 18,
540
+ y: 3,
541
+ outline: false
542
+ }]
543
+ }, {
544
+ id: "jotai",
545
+ name: "Jotai",
546
+ color: "#6C47FF",
547
+ line: "Atoms, one by one.",
548
+ state: "point",
549
+ layers: [{
550
+ art: JOTAI_ATOM,
551
+ x: 17,
552
+ y: 0,
553
+ follow: true
554
+ }, {
555
+ art: sparkle("y"),
556
+ x: 13,
557
+ y: 2,
558
+ outline: false
559
+ }, {
560
+ art: sparkle("y"),
561
+ x: 27,
562
+ y: 8,
563
+ outline: false
564
+ }]
565
+ }, {
566
+ id: "time-machine",
567
+ name: "Time Machine",
568
+ color: "#06B6D4",
569
+ line: "Any moment, back again.",
570
+ state: "present",
571
+ layers: [{
572
+ art: TIME_MACHINE_REWIND,
573
+ x: 16,
574
+ y: -1,
575
+ follow: true
576
+ }, {
577
+ art: ["ccc", "", ".cccc", "", "ccc"],
578
+ x: 0,
579
+ y: 9,
580
+ outline: false
581
+ }]
582
+ }, {
583
+ id: "routes",
584
+ name: "Routes",
585
+ color: "#FF9F1C",
586
+ line: "Knows where you are going.",
587
+ state: "point",
588
+ layers: [{
589
+ art: ROUTES_PIN,
590
+ x: 20,
591
+ y: 0,
592
+ follow: true
593
+ }, {
594
+ art: ["........ee", ".......e..", ".....ee...", "...ee.....", "ee........"],
595
+ x: 15,
596
+ y: 10,
597
+ outline: false
598
+ }]
599
+ }, {
600
+ id: "highlight-updates",
601
+ name: "Highlight Updates",
602
+ color: "#10B981",
603
+ line: "See every render. Catch what changed.",
604
+ state: "lift",
605
+ layers: [{
606
+ art: HIGHLIGHT_ARROW,
607
+ x: 6,
608
+ y: -1,
609
+ follow: true
610
+ }, {
611
+ art: sparkle("y"),
612
+ x: 1,
613
+ y: 0,
614
+ outline: false
615
+ }, {
616
+ art: sparkle("y"),
617
+ x: 15,
618
+ y: 1,
619
+ outline: false
620
+ }, {
621
+ art: ["l"],
622
+ x: 3,
623
+ y: 4,
624
+ outline: false
625
+ }, {
626
+ art: ["l"],
627
+ x: 14,
628
+ y: 5,
629
+ outline: false
630
+ }]
631
+ }, {
632
+ id: "debug-borders",
633
+ name: "Debug Borders",
634
+ color: "#10B981",
635
+ line: "Every box, outlined.",
636
+ state: "point",
637
+ layers: [{
638
+ art: DEBUG_BORDER,
639
+ x: 17,
640
+ y: 0,
641
+ outline: false,
642
+ follow: true
643
+ }]
644
+ }, {
645
+ id: "image-overlay",
646
+ name: "Overlay",
647
+ color: "#A855F7",
648
+ line: "Design on top, pixel for pixel.",
649
+ state: "present",
650
+ layers: [{
651
+ art: plane("P"),
652
+ x: 16,
653
+ y: 8,
654
+ follow: true
655
+ }, {
656
+ art: plane("b"),
657
+ x: 16,
658
+ y: 5,
659
+ follow: true
660
+ }, {
661
+ art: plane("c"),
662
+ x: 16,
663
+ y: 2,
664
+ follow: true
665
+ }]
666
+ }, {
667
+ id: "impersonate",
668
+ name: "Impersonate",
669
+ color: "#F59E0B",
670
+ line: "Be anyone, safely.",
671
+ state: "present",
672
+ layers: [{
673
+ art: IMPERSONATE_HAT,
674
+ x: 3,
675
+ y: 4,
676
+ over: true
677
+ }, {
678
+ art: IMPERSONATE_GLASSES,
679
+ x: 6,
680
+ y: 10,
681
+ over: true,
682
+ outline: false
683
+ }, {
684
+ art: IMPERSONATE_STACHE,
685
+ x: 7,
686
+ y: 13,
687
+ over: true,
688
+ outline: false
689
+ }, {
690
+ art: IMPERSONATE_CARD,
691
+ x: 17,
692
+ y: 3,
693
+ follow: true
694
+ }]
695
+ }, {
696
+ id: "perf-monitor",
697
+ name: "Bench",
698
+ color: "#F59E0B",
699
+ line: "Frames, counted.",
700
+ state: "present",
701
+ layers: [{
702
+ art: BENCH_WATCH,
703
+ x: 17,
704
+ y: 0,
705
+ follow: true
706
+ }, {
707
+ art: ["ccc", "", ".cccc", "", "ccc"],
708
+ x: 0,
709
+ y: 9,
710
+ outline: false
711
+ }, {
712
+ art: ["KK", "..KK"],
713
+ x: 6,
714
+ y: 9,
715
+ over: true,
716
+ outline: false
717
+ }, {
718
+ art: [".KK", "KK"],
719
+ x: 10,
720
+ y: 9,
721
+ over: true,
722
+ outline: false
723
+ }]
724
+ }, {
725
+ id: "js-top",
726
+ name: "JS Top",
727
+ color: "#F59E0B",
728
+ line: "Who is eating the thread.",
729
+ state: "debugging",
730
+ layers: [{
731
+ art: JS_TOP_CHART,
732
+ x: 18,
733
+ y: 6
734
+ }],
735
+ ground: [3, 29]
736
+ }, {
737
+ id: "images",
738
+ name: "Images",
739
+ color: "#C084FC",
740
+ line: "Every image, weighed.",
741
+ state: "present",
742
+ layers: [{
743
+ art: IMAGES_CARD,
744
+ x: 16,
745
+ y: 2,
746
+ follow: true
747
+ }, {
748
+ art: sparkle("y"),
749
+ x: 26,
750
+ y: 0,
751
+ outline: false
752
+ }, {
753
+ art: sparkle("y"),
754
+ x: 14,
755
+ y: 0,
756
+ outline: false
757
+ }]
758
+ }, {
759
+ id: "assets",
760
+ name: "Assets",
761
+ color: "#2DD4BF",
762
+ line: "What ships, and how big.",
763
+ state: "lean",
764
+ layers: [{
765
+ art: ASSETS_CRATE,
766
+ x: 16,
767
+ y: 9
768
+ }],
769
+ ground: [3, 28]
770
+ }, {
771
+ id: "console",
772
+ name: "Console",
773
+ color: "#10B981",
774
+ line: "Logs, commands, and more.",
775
+ state: "present",
776
+ layers: [{
777
+ art: CONSOLE_MONITOR,
778
+ x: 18,
779
+ y: 1
780
+ }, {
781
+ art: CONSOLE_STAND,
782
+ x: 21,
783
+ y: 11
784
+ }, {
785
+ art: CONSOLE_KEYS,
786
+ x: 15,
787
+ y: 13,
788
+ over: true
789
+ }],
790
+ ground: [3, 28]
791
+ }, {
792
+ id: "events",
793
+ name: "Events",
794
+ color: "#00D4FF",
795
+ line: "Everything in order.",
796
+ state: "present",
797
+ layers: [{
798
+ art: EVENTS_LINE,
799
+ x: 15,
800
+ y: 1,
801
+ follow: true
802
+ }]
803
+ }, {
804
+ id: "sentry",
805
+ name: "Sentry",
806
+ color: "#FF3366",
807
+ line: "Catch issues before they ship.",
808
+ state: "present",
809
+ layers: [{
810
+ art: SENTRY_SHIELD,
811
+ x: 17,
812
+ y: -1,
813
+ follow: true
814
+ }, {
815
+ art: ["KK", "..KK"],
816
+ x: 6,
817
+ y: 9,
818
+ over: true,
819
+ outline: false
820
+ }, {
821
+ art: [".KK", "KK"],
822
+ x: 10,
823
+ y: 9,
824
+ over: true,
825
+ outline: false
826
+ }]
827
+ }, {
828
+ id: "scenarios",
829
+ name: "Scenarios",
830
+ color: "#F43F5E",
831
+ line: "Set the stage, replay it.",
832
+ state: "present",
833
+ layers: [{
834
+ art: SCENARIOS_FLOW,
835
+ x: 16,
836
+ y: 0,
837
+ follow: true
838
+ }]
839
+ }, {
840
+ id: "ask-buoy",
841
+ name: "Ask Buoy",
842
+ color: "#7DD3FC",
843
+ line: "Get answers. Move faster.",
844
+ state: "wave",
845
+ layers: [{
846
+ art: ASK_BUOY_BUBBLE,
847
+ x: 16,
848
+ y: 0
849
+ }, {
850
+ art: sparkle("u"),
851
+ x: 26,
852
+ y: 10,
853
+ outline: false
854
+ }, {
855
+ art: ["u"],
856
+ x: 14,
857
+ y: 3,
858
+ outline: false
859
+ }]
860
+ }, {
861
+ id: "tv-remote",
862
+ name: "TV Remote",
863
+ color: "#FF3366",
864
+ line: "Control the app from here.",
865
+ state: "present",
866
+ layers: [{
867
+ art: TV_REMOTE_SHADES,
868
+ x: 6,
869
+ y: 11,
870
+ over: true,
871
+ outline: false
872
+ }, {
873
+ art: TV_REMOTE_REMOTE,
874
+ x: 16,
875
+ y: 5,
876
+ follow: true,
877
+ over: true
878
+ }, {
879
+ art: TV_REMOTE_WAVES,
880
+ x: 23,
881
+ y: 2,
882
+ outline: false,
883
+ follow: true
884
+ }]
885
+ }, {
886
+ id: "focus-inspector",
887
+ name: "Focus Inspector",
888
+ color: "#4ADE80",
889
+ line: "See what's focused.",
890
+ state: "present",
891
+ layers: [{
892
+ art: bracket("f", "tl"),
893
+ x: 1,
894
+ y: 1,
895
+ outline: false
896
+ }, {
897
+ art: bracket("f", "tr"),
898
+ x: 26,
899
+ y: 1,
900
+ outline: false
901
+ }, {
902
+ art: bracket("f", "bl"),
903
+ x: 1,
904
+ y: 17,
905
+ outline: false
906
+ }, {
907
+ art: bracket("f", "br"),
908
+ x: 26,
909
+ y: 17,
910
+ outline: false
911
+ }, {
912
+ art: FOCUS_GLASS,
913
+ x: 18,
914
+ y: 2,
915
+ follow: true
916
+ }, {
917
+ art: FOCUS_HANDLE,
918
+ x: 15,
919
+ y: 9,
920
+ follow: true
921
+ }]
922
+ }, {
923
+ id: "camera",
924
+ name: "Camera",
925
+ color: "#F472B6",
926
+ line: "A real feed, on the simulator.",
927
+ state: "present",
928
+ layers: [{
929
+ art: CAMERA_BODY,
930
+ x: 16,
931
+ y: 3,
932
+ follow: true
933
+ }, {
934
+ art: star("y"),
935
+ x: 25,
936
+ y: -1,
937
+ outline: false
938
+ }]
939
+ }];
940
+
941
+ /** Scene lookup by tool id. */
942
+ export const OTTO_SCENE_BY_ID = Object.fromEntries(OTTO_SCENES.map(s => [s.id, s]));