@buoy-gg/shared-ui 7.0.32 → 7.0.34

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 (237) hide show
  1. package/lib/commonjs/JsModal.js +70 -28
  2. package/lib/commonjs/hooks/index.js +26 -0
  3. package/lib/commonjs/hooks/safe-area-impl.js +1 -1
  4. package/lib/commonjs/hooks/useChangeLog.js +55 -0
  5. package/lib/commonjs/hooks/useEventStoreEvents.js +65 -0
  6. package/lib/commonjs/hooks/usePersistedState.js +45 -10
  7. package/lib/commonjs/index.js +143 -0
  8. package/lib/commonjs/storage/definePersistedSetting.js +67 -0
  9. package/lib/commonjs/storage/devToolsStorageKeys.js +12 -0
  10. package/lib/commonjs/storage/index.js +8 -1
  11. package/lib/commonjs/stores/ChangeLog.js +197 -0
  12. package/lib/commonjs/stores/createToolStore.js +175 -0
  13. package/lib/commonjs/stores/index.js +15 -1
  14. package/lib/commonjs/sync/toolSyncAdapter.js +63 -0
  15. package/lib/commonjs/sync/wireForm.js +172 -0
  16. package/lib/commonjs/tools/defineTool.js +79 -0
  17. package/lib/commonjs/ui/components/ChangeRow.js +110 -0
  18. package/lib/commonjs/ui/components/ChipStrip.js +94 -0
  19. package/lib/commonjs/ui/components/DetailViewToggle.js +130 -0
  20. package/lib/commonjs/ui/components/DevToolsCard.js +3 -1
  21. package/lib/commonjs/ui/components/EmptyState.js +10 -2
  22. package/lib/commonjs/ui/components/EntityFilterView.js +354 -0
  23. package/lib/commonjs/ui/components/ExportPreview.js +174 -0
  24. package/lib/commonjs/ui/components/InfoRow.js +90 -0
  25. package/lib/commonjs/ui/components/ModalHeader.js +40 -7
  26. package/lib/commonjs/ui/components/Pill.js +114 -0
  27. package/lib/commonjs/ui/components/ToggleRow.js +116 -0
  28. package/lib/commonjs/ui/components/ToolEmptyState.js +154 -0
  29. package/lib/commonjs/ui/components/ToolFooter.js +204 -0
  30. package/lib/commonjs/ui/components/WindowControls.js +8 -5
  31. package/lib/commonjs/ui/components/index.js +113 -1
  32. package/lib/commonjs/ui/index.js +36 -2
  33. package/lib/commonjs/ui/listPresets.js +43 -0
  34. package/lib/commonjs/ui/night/primitives.js +3 -1
  35. package/lib/commonjs/ui/otto/OttoSprite.js +510 -0
  36. package/lib/commonjs/ui/otto/index.js +38 -0
  37. package/lib/commonjs/ui/otto/ottoEngine.js +2734 -0
  38. package/lib/commonjs/ui/otto/ottoSheet.js +191 -0
  39. package/lib/commonjs/utils/snapshotProviderKit.js +167 -0
  40. package/lib/commonjs/utils/stateTools.js +160 -0
  41. package/lib/module/JsModal.js +70 -28
  42. package/lib/module/hooks/index.js +3 -1
  43. package/lib/module/hooks/safe-area-impl.js +1 -1
  44. package/lib/module/hooks/useChangeLog.js +50 -0
  45. package/lib/module/hooks/useEventStoreEvents.js +61 -0
  46. package/lib/module/hooks/usePersistedState.js +44 -10
  47. package/lib/module/index.js +11 -1
  48. package/lib/module/storage/definePersistedSetting.js +63 -0
  49. package/lib/module/storage/devToolsStorageKeys.js +12 -0
  50. package/lib/module/storage/index.js +2 -1
  51. package/lib/module/stores/ChangeLog.js +192 -0
  52. package/lib/module/stores/createToolStore.js +171 -0
  53. package/lib/module/stores/index.js +3 -1
  54. package/lib/module/sync/toolSyncAdapter.js +58 -0
  55. package/lib/module/sync/wireForm.js +159 -0
  56. package/lib/module/tools/defineTool.js +74 -0
  57. package/lib/module/ui/components/ChangeRow.js +105 -0
  58. package/lib/module/ui/components/ChipStrip.js +91 -0
  59. package/lib/module/ui/components/DetailViewToggle.js +125 -0
  60. package/lib/module/ui/components/DevToolsCard.js +3 -1
  61. package/lib/module/ui/components/EmptyState.js +10 -2
  62. package/lib/module/ui/components/EntityFilterView.js +350 -0
  63. package/lib/module/ui/components/ExportPreview.js +169 -0
  64. package/lib/module/ui/components/InfoRow.js +86 -0
  65. package/lib/module/ui/components/ModalHeader.js +40 -7
  66. package/lib/module/ui/components/Pill.js +110 -0
  67. package/lib/module/ui/components/ToggleRow.js +112 -0
  68. package/lib/module/ui/components/ToolEmptyState.js +149 -0
  69. package/lib/module/ui/components/ToolFooter.js +196 -0
  70. package/lib/module/ui/components/WindowControls.js +8 -5
  71. package/lib/module/ui/components/index.js +13 -1
  72. package/lib/module/ui/index.js +7 -1
  73. package/lib/module/ui/listPresets.js +39 -0
  74. package/lib/module/ui/night/primitives.js +3 -1
  75. package/lib/module/ui/otto/OttoSprite.js +496 -0
  76. package/lib/module/ui/otto/index.js +20 -0
  77. package/lib/module/ui/otto/ottoEngine.js +2726 -0
  78. package/lib/module/ui/otto/ottoSheet.js +180 -0
  79. package/lib/module/utils/snapshotProviderKit.js +156 -0
  80. package/lib/module/utils/stateTools.js +154 -0
  81. package/lib/typescript/commonjs/JsModal.d.ts.map +1 -1
  82. package/lib/typescript/commonjs/hooks/index.d.ts +3 -1
  83. package/lib/typescript/commonjs/hooks/index.d.ts.map +1 -1
  84. package/lib/typescript/commonjs/hooks/safe-area-impl.d.ts +1 -1
  85. package/lib/typescript/commonjs/hooks/useChangeLog.d.ts +38 -0
  86. package/lib/typescript/commonjs/hooks/useChangeLog.d.ts.map +1 -0
  87. package/lib/typescript/commonjs/hooks/useEventStoreEvents.d.ts +25 -0
  88. package/lib/typescript/commonjs/hooks/useEventStoreEvents.d.ts.map +1 -0
  89. package/lib/typescript/commonjs/hooks/usePersistedState.d.ts +34 -5
  90. package/lib/typescript/commonjs/hooks/usePersistedState.d.ts.map +1 -1
  91. package/lib/typescript/commonjs/index.d.ts +6 -1
  92. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  93. package/lib/typescript/commonjs/storage/definePersistedSetting.d.ts +39 -0
  94. package/lib/typescript/commonjs/storage/definePersistedSetting.d.ts.map +1 -0
  95. package/lib/typescript/commonjs/storage/devToolsStorageKeys.d.ts +12 -0
  96. package/lib/typescript/commonjs/storage/devToolsStorageKeys.d.ts.map +1 -1
  97. package/lib/typescript/commonjs/storage/index.d.ts +1 -0
  98. package/lib/typescript/commonjs/storage/index.d.ts.map +1 -1
  99. package/lib/typescript/commonjs/stores/ChangeLog.d.ts +100 -0
  100. package/lib/typescript/commonjs/stores/ChangeLog.d.ts.map +1 -0
  101. package/lib/typescript/commonjs/stores/createToolStore.d.ts +92 -0
  102. package/lib/typescript/commonjs/stores/createToolStore.d.ts.map +1 -0
  103. package/lib/typescript/commonjs/stores/index.d.ts +2 -0
  104. package/lib/typescript/commonjs/stores/index.d.ts.map +1 -1
  105. package/lib/typescript/commonjs/sync/toolSyncAdapter.d.ts +66 -0
  106. package/lib/typescript/commonjs/sync/toolSyncAdapter.d.ts.map +1 -0
  107. package/lib/typescript/commonjs/sync/wireForm.d.ts +100 -0
  108. package/lib/typescript/commonjs/sync/wireForm.d.ts.map +1 -0
  109. package/lib/typescript/commonjs/tools/defineTool.d.ts +100 -0
  110. package/lib/typescript/commonjs/tools/defineTool.d.ts.map +1 -0
  111. package/lib/typescript/commonjs/ui/components/ChangeRow.d.ts +52 -0
  112. package/lib/typescript/commonjs/ui/components/ChangeRow.d.ts.map +1 -0
  113. package/lib/typescript/commonjs/ui/components/ChipStrip.d.ts +41 -0
  114. package/lib/typescript/commonjs/ui/components/ChipStrip.d.ts.map +1 -0
  115. package/lib/typescript/commonjs/ui/components/DetailViewToggle.d.ts +36 -0
  116. package/lib/typescript/commonjs/ui/components/DetailViewToggle.d.ts.map +1 -0
  117. package/lib/typescript/commonjs/ui/components/DevToolsCard.d.ts +8 -1
  118. package/lib/typescript/commonjs/ui/components/DevToolsCard.d.ts.map +1 -1
  119. package/lib/typescript/commonjs/ui/components/EmptyState.d.ts +14 -1
  120. package/lib/typescript/commonjs/ui/components/EmptyState.d.ts.map +1 -1
  121. package/lib/typescript/commonjs/ui/components/EntityFilterView.d.ts +51 -0
  122. package/lib/typescript/commonjs/ui/components/EntityFilterView.d.ts.map +1 -0
  123. package/lib/typescript/commonjs/ui/components/ExportPreview.d.ts +48 -0
  124. package/lib/typescript/commonjs/ui/components/ExportPreview.d.ts.map +1 -0
  125. package/lib/typescript/commonjs/ui/components/InfoRow.d.ts +33 -0
  126. package/lib/typescript/commonjs/ui/components/InfoRow.d.ts.map +1 -0
  127. package/lib/typescript/commonjs/ui/components/ModalHeader.d.ts +31 -1
  128. package/lib/typescript/commonjs/ui/components/ModalHeader.d.ts.map +1 -1
  129. package/lib/typescript/commonjs/ui/components/Pill.d.ts +38 -0
  130. package/lib/typescript/commonjs/ui/components/Pill.d.ts.map +1 -0
  131. package/lib/typescript/commonjs/ui/components/ToggleRow.d.ts +33 -0
  132. package/lib/typescript/commonjs/ui/components/ToggleRow.d.ts.map +1 -0
  133. package/lib/typescript/commonjs/ui/components/ToolEmptyState.d.ts +113 -0
  134. package/lib/typescript/commonjs/ui/components/ToolEmptyState.d.ts.map +1 -0
  135. package/lib/typescript/commonjs/ui/components/ToolFooter.d.ts +69 -0
  136. package/lib/typescript/commonjs/ui/components/ToolFooter.d.ts.map +1 -0
  137. package/lib/typescript/commonjs/ui/components/WindowControls.d.ts +7 -1
  138. package/lib/typescript/commonjs/ui/components/WindowControls.d.ts.map +1 -1
  139. package/lib/typescript/commonjs/ui/components/index.d.ts +11 -0
  140. package/lib/typescript/commonjs/ui/components/index.d.ts.map +1 -1
  141. package/lib/typescript/commonjs/ui/index.d.ts +2 -0
  142. package/lib/typescript/commonjs/ui/index.d.ts.map +1 -1
  143. package/lib/typescript/commonjs/ui/listPresets.d.ts +28 -0
  144. package/lib/typescript/commonjs/ui/listPresets.d.ts.map +1 -0
  145. package/lib/typescript/commonjs/ui/night/primitives.d.ts +3 -1
  146. package/lib/typescript/commonjs/ui/night/primitives.d.ts.map +1 -1
  147. package/lib/typescript/commonjs/ui/otto/OttoSprite.d.ts +103 -0
  148. package/lib/typescript/commonjs/ui/otto/OttoSprite.d.ts.map +1 -0
  149. package/lib/typescript/commonjs/ui/otto/index.d.ts +19 -0
  150. package/lib/typescript/commonjs/ui/otto/index.d.ts.map +1 -0
  151. package/lib/typescript/commonjs/ui/otto/ottoEngine.d.ts +2205 -0
  152. package/lib/typescript/commonjs/ui/otto/ottoEngine.d.ts.map +1 -0
  153. package/lib/typescript/commonjs/ui/otto/ottoSheet.d.ts +73 -0
  154. package/lib/typescript/commonjs/ui/otto/ottoSheet.d.ts.map +1 -0
  155. package/lib/typescript/commonjs/utils/snapshotProviderKit.d.ts +81 -0
  156. package/lib/typescript/commonjs/utils/snapshotProviderKit.d.ts.map +1 -0
  157. package/lib/typescript/commonjs/utils/stateTools.d.ts +44 -0
  158. package/lib/typescript/commonjs/utils/stateTools.d.ts.map +1 -0
  159. package/lib/typescript/module/JsModal.d.ts.map +1 -1
  160. package/lib/typescript/module/hooks/index.d.ts +3 -1
  161. package/lib/typescript/module/hooks/index.d.ts.map +1 -1
  162. package/lib/typescript/module/hooks/safe-area-impl.d.ts +1 -1
  163. package/lib/typescript/module/hooks/useChangeLog.d.ts +38 -0
  164. package/lib/typescript/module/hooks/useChangeLog.d.ts.map +1 -0
  165. package/lib/typescript/module/hooks/useEventStoreEvents.d.ts +25 -0
  166. package/lib/typescript/module/hooks/useEventStoreEvents.d.ts.map +1 -0
  167. package/lib/typescript/module/hooks/usePersistedState.d.ts +34 -5
  168. package/lib/typescript/module/hooks/usePersistedState.d.ts.map +1 -1
  169. package/lib/typescript/module/index.d.ts +6 -1
  170. package/lib/typescript/module/index.d.ts.map +1 -1
  171. package/lib/typescript/module/storage/definePersistedSetting.d.ts +39 -0
  172. package/lib/typescript/module/storage/definePersistedSetting.d.ts.map +1 -0
  173. package/lib/typescript/module/storage/devToolsStorageKeys.d.ts +12 -0
  174. package/lib/typescript/module/storage/devToolsStorageKeys.d.ts.map +1 -1
  175. package/lib/typescript/module/storage/index.d.ts +1 -0
  176. package/lib/typescript/module/storage/index.d.ts.map +1 -1
  177. package/lib/typescript/module/stores/ChangeLog.d.ts +100 -0
  178. package/lib/typescript/module/stores/ChangeLog.d.ts.map +1 -0
  179. package/lib/typescript/module/stores/createToolStore.d.ts +92 -0
  180. package/lib/typescript/module/stores/createToolStore.d.ts.map +1 -0
  181. package/lib/typescript/module/stores/index.d.ts +2 -0
  182. package/lib/typescript/module/stores/index.d.ts.map +1 -1
  183. package/lib/typescript/module/sync/toolSyncAdapter.d.ts +66 -0
  184. package/lib/typescript/module/sync/toolSyncAdapter.d.ts.map +1 -0
  185. package/lib/typescript/module/sync/wireForm.d.ts +100 -0
  186. package/lib/typescript/module/sync/wireForm.d.ts.map +1 -0
  187. package/lib/typescript/module/tools/defineTool.d.ts +100 -0
  188. package/lib/typescript/module/tools/defineTool.d.ts.map +1 -0
  189. package/lib/typescript/module/ui/components/ChangeRow.d.ts +52 -0
  190. package/lib/typescript/module/ui/components/ChangeRow.d.ts.map +1 -0
  191. package/lib/typescript/module/ui/components/ChipStrip.d.ts +41 -0
  192. package/lib/typescript/module/ui/components/ChipStrip.d.ts.map +1 -0
  193. package/lib/typescript/module/ui/components/DetailViewToggle.d.ts +36 -0
  194. package/lib/typescript/module/ui/components/DetailViewToggle.d.ts.map +1 -0
  195. package/lib/typescript/module/ui/components/DevToolsCard.d.ts +8 -1
  196. package/lib/typescript/module/ui/components/DevToolsCard.d.ts.map +1 -1
  197. package/lib/typescript/module/ui/components/EmptyState.d.ts +14 -1
  198. package/lib/typescript/module/ui/components/EmptyState.d.ts.map +1 -1
  199. package/lib/typescript/module/ui/components/EntityFilterView.d.ts +51 -0
  200. package/lib/typescript/module/ui/components/EntityFilterView.d.ts.map +1 -0
  201. package/lib/typescript/module/ui/components/ExportPreview.d.ts +48 -0
  202. package/lib/typescript/module/ui/components/ExportPreview.d.ts.map +1 -0
  203. package/lib/typescript/module/ui/components/InfoRow.d.ts +33 -0
  204. package/lib/typescript/module/ui/components/InfoRow.d.ts.map +1 -0
  205. package/lib/typescript/module/ui/components/ModalHeader.d.ts +31 -1
  206. package/lib/typescript/module/ui/components/ModalHeader.d.ts.map +1 -1
  207. package/lib/typescript/module/ui/components/Pill.d.ts +38 -0
  208. package/lib/typescript/module/ui/components/Pill.d.ts.map +1 -0
  209. package/lib/typescript/module/ui/components/ToggleRow.d.ts +33 -0
  210. package/lib/typescript/module/ui/components/ToggleRow.d.ts.map +1 -0
  211. package/lib/typescript/module/ui/components/ToolEmptyState.d.ts +113 -0
  212. package/lib/typescript/module/ui/components/ToolEmptyState.d.ts.map +1 -0
  213. package/lib/typescript/module/ui/components/ToolFooter.d.ts +69 -0
  214. package/lib/typescript/module/ui/components/ToolFooter.d.ts.map +1 -0
  215. package/lib/typescript/module/ui/components/WindowControls.d.ts +7 -1
  216. package/lib/typescript/module/ui/components/WindowControls.d.ts.map +1 -1
  217. package/lib/typescript/module/ui/components/index.d.ts +11 -0
  218. package/lib/typescript/module/ui/components/index.d.ts.map +1 -1
  219. package/lib/typescript/module/ui/index.d.ts +2 -0
  220. package/lib/typescript/module/ui/index.d.ts.map +1 -1
  221. package/lib/typescript/module/ui/listPresets.d.ts +28 -0
  222. package/lib/typescript/module/ui/listPresets.d.ts.map +1 -0
  223. package/lib/typescript/module/ui/night/primitives.d.ts +3 -1
  224. package/lib/typescript/module/ui/night/primitives.d.ts.map +1 -1
  225. package/lib/typescript/module/ui/otto/OttoSprite.d.ts +103 -0
  226. package/lib/typescript/module/ui/otto/OttoSprite.d.ts.map +1 -0
  227. package/lib/typescript/module/ui/otto/index.d.ts +19 -0
  228. package/lib/typescript/module/ui/otto/index.d.ts.map +1 -0
  229. package/lib/typescript/module/ui/otto/ottoEngine.d.ts +2205 -0
  230. package/lib/typescript/module/ui/otto/ottoEngine.d.ts.map +1 -0
  231. package/lib/typescript/module/ui/otto/ottoSheet.d.ts +73 -0
  232. package/lib/typescript/module/ui/otto/ottoSheet.d.ts.map +1 -0
  233. package/lib/typescript/module/utils/snapshotProviderKit.d.ts +81 -0
  234. package/lib/typescript/module/utils/snapshotProviderKit.d.ts.map +1 -0
  235. package/lib/typescript/module/utils/stateTools.d.ts +44 -0
  236. package/lib/typescript/module/utils/stateTools.d.ts.map +1 -0
  237. package/package.json +4 -4
@@ -0,0 +1,510 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.Otto = Otto;
7
+ exports.OttoMotionView = void 0;
8
+ exports.OttoPixels = OttoPixels;
9
+ exports.OttoStill = OttoStill;
10
+ Object.defineProperty(exports, "WATER_FRAMES", {
11
+ enumerable: true,
12
+ get: function () {
13
+ return _ottoSheet.WATER_FRAMES;
14
+ }
15
+ });
16
+ exports.motionUnits = motionUnits;
17
+ exports.useOttoAnchorMotion = useOttoAnchorMotion;
18
+ exports.useOttoReel = useOttoReel;
19
+ var _react = require("react");
20
+ var _reactNative = require("react-native");
21
+ var _ottoEngine = require("./ottoEngine.js");
22
+ var _ottoSheet = require("./ottoSheet.js");
23
+ var _jsxRuntime = require("react/jsx-runtime");
24
+ /**
25
+ * Otto in React Native — core APIs only, so the same file runs in Expo, in a
26
+ * bare RN CLI app, and on the web through react-native-web.
27
+ *
28
+ * <Otto state="thinking" pixelSize={4} /> the shipping sprite
29
+ * <Otto state="reel" /> plays the demo schedule
30
+ * <OttoStill pixelSize={1} /> frame 0, no clock (icons, stills)
31
+ * <OttoPixels grid={…} pixelSize={…} /> paint any frame as Views
32
+ * useOttoAnchorMotion(state, …) move a prop in lock-step with
33
+ * Otto's hands (the tool scenes)
34
+ *
35
+ * How the shipping sprite works (winner of the buoy-optimize rounds, see
36
+ * OTTO_PERF_PLAN.md): each layer of a state's animation is a STRIP of its
37
+ * distinct frames, mounted once as static Views (merged rectangles), inside
38
+ * an overflow-hidden window one frame wide. A clock slides the strip:
39
+ *
40
+ * native core `Animated` on the native driver — one looping linear timing
41
+ * mapped to strip offsets by a step interpolation
42
+ * web CSS keyframes with `step-end` timing (react-native-web's
43
+ * `animationKeyframes` style), the zero-JS path in a browser
44
+ *
45
+ * Zero JS per tick on both, no React commits, and it keeps moving while the
46
+ * JS thread is blocked — exactly when a "working" Otto is on screen. On the
47
+ * iOS sim: 60 UI / 59 JS FPS at one sprite (the page's own floor) where the
48
+ * old per-tick renderer dropped UI frames.
49
+ *
50
+ * ONE TIMEBASE. Body, water and any anchored prop derive from the same
51
+ * `units` span (see `motionUnits`) at the same duration and start in the same
52
+ * commit, so they can never drift out of phase with each other.
53
+ */
54
+
55
+ const IS_WEB = _reactNative.Platform.OS === "web";
56
+
57
+ /** Every anchor in the engine repeats within 16 ticks. */
58
+ const ANCHOR_PERIOD = 16;
59
+ /** The water wave holds each frame for 2 ticks. */
60
+ const WATER_UNITS_PER_STEP = 2;
61
+ function gcd(a, b) {
62
+ return b === 0 ? a : gcd(b, a % b);
63
+ }
64
+ function lcm(a, b) {
65
+ return a * b / gcd(a, b);
66
+ }
67
+
68
+ /**
69
+ * The tick span every layer of a state loops over. It is a common multiple of
70
+ * the body cycle and the anchor cycle, so a prop held in Otto's hand and the
71
+ * hand itself repeat together.
72
+ */
73
+ function motionUnits(state, keyline = true) {
74
+ return lcm((0, _ottoSheet.ottoSheets)(state, keyline).period, ANCHOR_PERIOD);
75
+ }
76
+
77
+ // ---------------------------------------------------------------- pixels --
78
+
79
+ /** Pure renderer: a frame → coloured run Views. Fine for stills; costly per tick. */
80
+ function OttoPixels({
81
+ grid,
82
+ pixelSize,
83
+ style
84
+ }) {
85
+ const side = _ottoEngine.OTTO_GRID * pixelSize;
86
+ const runs = (0, _ottoEngine.ottoRuns)(grid);
87
+ const spans = [];
88
+ let rowY = -1;
89
+ let rowIndex = 0;
90
+ for (const r of runs) {
91
+ if (r.y !== rowY) {
92
+ rowY = r.y;
93
+ rowIndex = 0;
94
+ }
95
+ spans.push(/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
96
+ style: {
97
+ position: "absolute",
98
+ left: r.x * pixelSize,
99
+ top: r.y * pixelSize,
100
+ width: r.w * pixelSize,
101
+ height: pixelSize,
102
+ backgroundColor: r.color
103
+ }
104
+ }, `${r.y}:${rowIndex++}`));
105
+ }
106
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
107
+ pointerEvents: "none",
108
+ style: [{
109
+ width: side,
110
+ height: side
111
+ }, style],
112
+ children: spans
113
+ });
114
+ }
115
+
116
+ // ---------------------------------------------------------------- still ---
117
+
118
+ /** Frame 0 of a state, no clock — safe on screens that must not re-render. */
119
+ function OttoStill({
120
+ state = "static",
121
+ pixelSize = 1,
122
+ water,
123
+ keyline,
124
+ style
125
+ }) {
126
+ const grid = (0, _ottoEngine.renderOttoFrame)(state, 0, {
127
+ water,
128
+ keyline
129
+ });
130
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(OttoPixels, {
131
+ grid: grid,
132
+ pixelSize: pixelSize,
133
+ style: style
134
+ });
135
+ }
136
+
137
+ // ---------------------------------------------------------------- reel ----
138
+
139
+ /**
140
+ * Walks the demo reel: which state plays now. One React state change per
141
+ * schedule entry (every few seconds), nothing per tick.
142
+ */
143
+ function useOttoReel(enabled, tickMs = 140, active = true) {
144
+ const [idx, setIdx] = (0, _react.useState)(0);
145
+ (0, _react.useEffect)(() => {
146
+ if (!enabled || !active) return;
147
+ const len = _ottoEngine.OTTO_REEL[idx % _ottoEngine.OTTO_REEL.length][1];
148
+ const id = setTimeout(() => setIdx(i => (i + 1) % _ottoEngine.OTTO_REEL.length), len * tickMs);
149
+ return () => clearTimeout(id);
150
+ }, [enabled, active, idx, tickMs]);
151
+ return _ottoEngine.OTTO_REEL[idx % _ottoEngine.OTTO_REEL.length][0];
152
+ }
153
+
154
+ // ---------------------------------------------------------------- clock ---
155
+
156
+ /** A style that moves a view through offsets in lock-step with Otto's clock. */
157
+
158
+ const EPS = 0.0001;
159
+
160
+ /**
161
+ * The layer the clock moves.
162
+ *
163
+ * On native this has to be an `Animated.View` — it carries interpolated
164
+ * values. On web the motion is a COMPILED CSS class (see `webStepStyle`), and
165
+ * `Animated.View` flattens its style prop into a fresh object, which loses the
166
+ * identity react-native-web looks the compiled rules up by; the keyframes are
167
+ * then silently dropped and the sprite sits on frame 0. So the web path takes
168
+ * a plain View, which passes the class straight through.
169
+ */
170
+ const OttoMotionView = exports.OttoMotionView = IS_WEB ? _reactNative.View : _reactNative.Animated.View;
171
+ /**
172
+ * Web keyframes, compiled once per motion pattern.
173
+ *
174
+ * react-native-web only turns `animationKeyframes` into real `@keyframes`
175
+ * rules through `StyleSheet.create` — its inline-style path drops the prop
176
+ * without a warning. Patterns repeat heavily across a page of sprites (every
177
+ * Otto shares one water wave, every state of a group shares body cycles), so
178
+ * the cache keeps the sheet small and the render cheap.
179
+ */
180
+ const webStyleCache = new Map();
181
+ function webStepStyle(offsets, unitsPerStep, units, tickMs, steps, at) {
182
+ const key = `${units}/${unitsPerStep}/${tickMs}/${offsets.map(o => `${o.x},${o.y}`).join("|")}`;
183
+ const cached = webStyleCache.get(key);
184
+ if (cached) return cached;
185
+
186
+ // Keyframe blocks skip react-native-web's style preprocessor, so the value
187
+ // has to be CSS already — an RN transform ARRAY compiles to an empty block.
188
+ const css = o => `translateX(${o.x}px) translateY(${o.y}px)`;
189
+ const keyframes = {};
190
+ for (let k = 0; k < steps; k++) {
191
+ const pct = k * unitsPerStep / units * 100;
192
+ keyframes[`${pct.toFixed(4)}%`] = {
193
+ transform: css(at(k))
194
+ };
195
+ }
196
+ keyframes["100%"] = {
197
+ transform: css(at(steps - 1))
198
+ };
199
+
200
+ // react-native-web's CSS-animation style props (not part of RN's ViewStyle).
201
+ const style = _reactNative.StyleSheet.create({
202
+ motion: {
203
+ animationKeyframes: [keyframes],
204
+ animationDuration: `${units * tickMs}ms`,
205
+ animationTimingFunction: "step-end",
206
+ animationIterationCount: "infinite",
207
+ animationFillMode: "both"
208
+ }
209
+ }).motion;
210
+ webStyleCache.set(key, style);
211
+ return style;
212
+ }
213
+
214
+ /**
215
+ * Otto's timebase: a clock that runs `units` ticks and loops.
216
+ *
217
+ * native → one `Animated.Value` on the native driver (zero JS per tick)
218
+ * web → nothing to drive; CSS keyframes carry the motion (zero JS at all)
219
+ *
220
+ * Every consumer of the SAME state builds the same `units` and duration and
221
+ * starts in the same commit, which is what keeps layers in phase.
222
+ */
223
+ function useOttoMotionClock(units, tickMs, active, restartKey) {
224
+ const value = (0, _react.useRef)(new _reactNative.Animated.Value(0)).current;
225
+ (0, _react.useEffect)(() => {
226
+ if (IS_WEB) return;
227
+ value.setValue(0);
228
+ if (!active) return;
229
+ const loop = _reactNative.Animated.loop(_reactNative.Animated.timing(value, {
230
+ toValue: units,
231
+ duration: units * tickMs,
232
+ easing: _reactNative.Easing.linear,
233
+ useNativeDriver: true,
234
+ isInteraction: false
235
+ }), {
236
+ resetBeforeIteration: true
237
+ });
238
+ loop.start();
239
+ return () => loop.stop();
240
+ }, [value, units, tickMs, active, restartKey]);
241
+ return value;
242
+ }
243
+
244
+ /**
245
+ * Turn a repeating offset pattern into a style on that clock. `offsets[k]` is
246
+ * where the view sits during tick `k·unitsPerStep`; the pattern repeats until
247
+ * `units` is filled, so patterns of different lengths share one timebase.
248
+ */
249
+ function stepStyle(value, offsets, unitsPerStep, units, tickMs, active) {
250
+ const steps = Math.max(1, Math.round(units / unitsPerStep));
251
+ const at = k => offsets[k % offsets.length] ?? {
252
+ x: 0,
253
+ y: 0
254
+ };
255
+ if (!active || offsets.length <= 1) {
256
+ const o = at(0);
257
+ return {
258
+ transform: [{
259
+ translateX: o.x
260
+ }, {
261
+ translateY: o.y
262
+ }]
263
+ };
264
+ }
265
+ if (IS_WEB) return webStepStyle(offsets, unitsPerStep, units, tickMs, steps, at);
266
+ const inputRange = [];
267
+ const xs = [];
268
+ const ys = [];
269
+ for (let k = 0; k < steps; k++) {
270
+ const o = at(k);
271
+ inputRange.push(k * unitsPerStep, (k + 1) * unitsPerStep - EPS);
272
+ xs.push(o.x, o.x);
273
+ ys.push(o.y, o.y);
274
+ }
275
+ return {
276
+ transform: [{
277
+ translateX: value.interpolate({
278
+ inputRange,
279
+ outputRange: xs,
280
+ extrapolate: "clamp"
281
+ })
282
+ }, {
283
+ translateY: value.interpolate({
284
+ inputRange,
285
+ outputRange: ys,
286
+ extrapolate: "clamp"
287
+ })
288
+ }]
289
+ };
290
+ }
291
+ /**
292
+ * Move a prop in lock-step with Otto's hands. `OTTO_ANCHORS[state]` publishes
293
+ * where the hand is each tick; this turns that into the same kind of clocked
294
+ * style the sprite itself uses, on the same timebase, so the two can't drift.
295
+ *
296
+ * Returns `null` for a state that has no anchor.
297
+ */
298
+ function useOttoAnchorMotion(state, pixelSize, tickMs = 140, active = true, keyline = true) {
299
+ const anchorFn = _ottoEngine.OTTO_ANCHORS[state];
300
+ const units = motionUnits(state, keyline);
301
+ const value = useOttoMotionClock(units, tickMs, active && !!anchorFn, state);
302
+ if (!anchorFn) return null;
303
+ const first = anchorFn(0);
304
+ const offsets = [];
305
+ for (let t = 0; t < ANCHOR_PERIOD; t++) {
306
+ const a = anchorFn(t);
307
+ offsets.push({
308
+ x: (a.x - first.x) * pixelSize,
309
+ y: (a.y - first.y) * pixelSize
310
+ });
311
+ }
312
+ return {
313
+ style: stepStyle(value, offsets, 1, units, tickMs, active),
314
+ over: first.over,
315
+ origin: {
316
+ x: first.x,
317
+ y: first.y
318
+ }
319
+ };
320
+ }
321
+
322
+ // ---------------------------------------------------------------- otto ----
323
+
324
+ /**
325
+ * The shipping sprite.
326
+ *
327
+ * Mounting is deferred on purpose. The strips are ~500 static Views for a
328
+ * typical state, and creating those is native COMMIT cost: measured at 128 ms
329
+ * for one sprite, against 28 ms for a still. A mascot almost always appears
330
+ * while something else is animating (a panel opening, a list settling), and
331
+ * 128 ms of commit dropped into that is a visible hitch.
332
+ *
333
+ * So the first commit paints `OttoStill` — frame 0, ~36 Views, the exact
334
+ * pixels the animation starts on — and the strips mount once the interaction
335
+ * has settled (an idle callback). Nothing pops, because the still IS frame 0.
336
+ * Pass `eager` when the sprite is the thing the user is waiting for.
337
+ *
338
+ * The two layers are siblings that each gate themselves with `return null`
339
+ * rather than a ternary swap, so this component's child slots never change
340
+ * shape (Fabric view-index safety).
341
+ */
342
+ function Otto({
343
+ state,
344
+ pixelSize = 8,
345
+ water = true,
346
+ keyline = true,
347
+ tickMs = 140,
348
+ active = true,
349
+ eager = false,
350
+ style
351
+ }) {
352
+ const reelState = useOttoReel(state === "reel", tickMs, active);
353
+ const resolved = state === "reel" ? reelState : state;
354
+ const side = _ottoEngine.OTTO_GRID * pixelSize;
355
+ const [mounted, setMounted] = (0, _react.useState)(eager);
356
+ (0, _react.useEffect)(() => {
357
+ if (eager || mounted) return;
358
+ // requestIdleCallback, not InteractionManager: RN 0.85 deprecates the
359
+ // latter and warns on every use, and this runs in every host we support.
360
+ // The setTimeout fallback covers runtimes without the idle callback.
361
+ const idle = globalThis.requestIdleCallback;
362
+ const cancelIdle = globalThis.cancelIdleCallback;
363
+ if (idle) {
364
+ const handle = idle(() => setMounted(true));
365
+ return () => cancelIdle?.(handle);
366
+ }
367
+ const timer = setTimeout(() => setMounted(true), 0);
368
+ return () => clearTimeout(timer);
369
+ }, [eager, mounted]);
370
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
371
+ pointerEvents: "none",
372
+ style: [{
373
+ width: side,
374
+ height: side
375
+ }, style],
376
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(OttoStillLayer, {
377
+ show: !mounted,
378
+ state: resolved,
379
+ pixelSize: pixelSize,
380
+ water: water,
381
+ keyline: keyline
382
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(OttoStrips, {
383
+ show: mounted,
384
+ state: resolved,
385
+ pixelSize: pixelSize,
386
+ water: water,
387
+ keyline: keyline,
388
+ tickMs: tickMs,
389
+ active: active
390
+ })]
391
+ });
392
+ }
393
+
394
+ /** Frame 0 while the strips are still coming. */
395
+ function OttoStillLayer({
396
+ show,
397
+ state,
398
+ pixelSize,
399
+ water,
400
+ keyline
401
+ }) {
402
+ if (!show) return null;
403
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(OttoStill, {
404
+ state: state,
405
+ pixelSize: pixelSize,
406
+ water: water,
407
+ keyline: keyline
408
+ });
409
+ }
410
+
411
+ /** The animated strips and their clock. */
412
+ function OttoStrips({
413
+ show,
414
+ state,
415
+ pixelSize,
416
+ water,
417
+ keyline,
418
+ tickMs,
419
+ active
420
+ }) {
421
+ const sheets = (0, _ottoSheet.ottoSheets)(state, keyline);
422
+ const side = _ottoEngine.OTTO_GRID * pixelSize;
423
+ const waterH = _ottoSheet.WATER_ROWS * pixelSize;
424
+ const units = lcm(sheets.period, ANCHOR_PERIOD);
425
+ const value = useOttoMotionClock(units, tickMs, active && show, state);
426
+ const bodyStyle = stepStyle(value, stripOffsets(sheets.body, side), 1, units, tickMs, active);
427
+ const waterStyle = stepStyle(value, stripOffsets(sheets.water, side), WATER_UNITS_PER_STEP, units, tickMs, active);
428
+ if (!show) return null;
429
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
430
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(StripWindow, {
431
+ top: _ottoSheet.WATER_ROW0 * pixelSize,
432
+ width: side,
433
+ height: waterH,
434
+ strip: sheets.water,
435
+ px: pixelSize,
436
+ frameW: side,
437
+ motion: waterStyle,
438
+ visible: water
439
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(StripWindow, {
440
+ top: 0,
441
+ width: side,
442
+ height: side,
443
+ strip: sheets.body,
444
+ px: pixelSize,
445
+ frameW: side,
446
+ motion: bodyStyle,
447
+ visible: true
448
+ })]
449
+ });
450
+ }
451
+ function stripOffsets(strip, frameW) {
452
+ return strip.colOf.map(c => ({
453
+ x: -c * frameW,
454
+ y: 0
455
+ }));
456
+ }
457
+ /** Pure UI: an overflow-hidden window over a strip of frames. */
458
+ function StripWindow({
459
+ top,
460
+ width,
461
+ height,
462
+ strip,
463
+ px,
464
+ frameW,
465
+ motion,
466
+ visible
467
+ }) {
468
+ const stripW = strip.frames.length * frameW;
469
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
470
+ style: {
471
+ position: "absolute",
472
+ left: 0,
473
+ top,
474
+ width,
475
+ height,
476
+ overflow: "hidden"
477
+ },
478
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(OttoMotionView, {
479
+ style: [{
480
+ width: stripW,
481
+ height
482
+ }, motion],
483
+ children: visible ? strip.frames.map((rects, i) => /*#__PURE__*/(0, _jsxRuntime.jsx)(FrameViews, {
484
+ rects: rects,
485
+ px: px,
486
+ offsetX: i * frameW
487
+ }, i)) : null
488
+ })
489
+ });
490
+ }
491
+
492
+ /** One frame as absolutely positioned rectangle Views. Static after mount. */
493
+ function FrameViews({
494
+ rects,
495
+ px,
496
+ offsetX
497
+ }) {
498
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_jsxRuntime.Fragment, {
499
+ children: rects.map((r, i) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
500
+ style: {
501
+ position: "absolute",
502
+ left: offsetX + r.x * px,
503
+ top: r.y * px,
504
+ width: r.w * px,
505
+ height: r.h * px,
506
+ backgroundColor: r.color
507
+ }
508
+ }, i))
509
+ });
510
+ }
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ var _ottoEngine = require("./ottoEngine.js");
7
+ Object.keys(_ottoEngine).forEach(function (key) {
8
+ if (key === "default" || key === "__esModule") return;
9
+ if (key in exports && exports[key] === _ottoEngine[key]) return;
10
+ Object.defineProperty(exports, key, {
11
+ enumerable: true,
12
+ get: function () {
13
+ return _ottoEngine[key];
14
+ }
15
+ });
16
+ });
17
+ var _ottoSheet = require("./ottoSheet.js");
18
+ Object.keys(_ottoSheet).forEach(function (key) {
19
+ if (key === "default" || key === "__esModule") return;
20
+ if (key in exports && exports[key] === _ottoSheet[key]) return;
21
+ Object.defineProperty(exports, key, {
22
+ enumerable: true,
23
+ get: function () {
24
+ return _ottoSheet[key];
25
+ }
26
+ });
27
+ });
28
+ var _OttoSprite = require("./OttoSprite.js");
29
+ Object.keys(_OttoSprite).forEach(function (key) {
30
+ if (key === "default" || key === "__esModule") return;
31
+ if (key in exports && exports[key] === _OttoSprite[key]) return;
32
+ Object.defineProperty(exports, key, {
33
+ enumerable: true,
34
+ get: function () {
35
+ return _OttoSprite[key];
36
+ }
37
+ });
38
+ });