@buoy-gg/shared-ui 7.0.22 → 7.0.23

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 (154) hide show
  1. package/lib/commonjs/JsModal.js +39 -16
  2. package/lib/commonjs/dataViewer/JsonStringNotice.js +59 -0
  3. package/lib/commonjs/dataViewer/ThemedSplitView.js +20 -1
  4. package/lib/commonjs/dataViewer/TimestampDeltaBar.js +96 -0
  5. package/lib/commonjs/dataViewer/index.js +52 -0
  6. package/lib/commonjs/dataViewer/jsonStringValue.js +94 -0
  7. package/lib/commonjs/dataViewer/timestampDiff.js +146 -0
  8. package/lib/commonjs/hooks/safe-area-impl.js +1 -1
  9. package/lib/commonjs/index.js +50 -1
  10. package/lib/commonjs/license/FeatureGate.js +43 -10
  11. package/lib/commonjs/license/FreeAccountPrompt.js +181 -0
  12. package/lib/commonjs/license/index.js +57 -42
  13. package/lib/commonjs/license/licenseModule.js +99 -0
  14. package/lib/commonjs/license/tierLimits.js +165 -0
  15. package/lib/commonjs/ui/backgrounds/BackgroundSwitcher.js +180 -0
  16. package/lib/commonjs/ui/backgrounds/README.md +115 -0
  17. package/lib/commonjs/ui/backgrounds/ToolBackground.js +74 -0
  18. package/lib/commonjs/ui/backgrounds/backgroundStore.js +116 -0
  19. package/lib/commonjs/ui/backgrounds/index.js +70 -0
  20. package/lib/commonjs/ui/backgrounds/primitives.js +333 -0
  21. package/lib/commonjs/ui/backgrounds/registry.js +112 -0
  22. package/lib/commonjs/ui/backgrounds/rng.js +72 -0
  23. package/lib/commonjs/ui/backgrounds/types.js +1 -0
  24. package/lib/commonjs/ui/backgrounds/variants/deepField.js +351 -0
  25. package/lib/commonjs/ui/backgrounds/variants/lattice.js +579 -0
  26. package/lib/commonjs/ui/backgrounds/variants/starfield.js +210 -0
  27. package/lib/commonjs/ui/index.js +15 -3
  28. package/lib/module/JsModal.js +39 -16
  29. package/lib/module/dataViewer/JsonStringNotice.js +54 -0
  30. package/lib/module/dataViewer/ThemedSplitView.js +20 -1
  31. package/lib/module/dataViewer/TimestampDeltaBar.js +91 -0
  32. package/lib/module/dataViewer/index.js +4 -0
  33. package/lib/module/dataViewer/jsonStringValue.js +89 -0
  34. package/lib/module/dataViewer/timestampDiff.js +139 -0
  35. package/lib/module/hooks/safe-area-impl.js +1 -1
  36. package/lib/module/index.js +1 -1
  37. package/lib/module/license/FeatureGate.js +43 -10
  38. package/lib/module/license/FreeAccountPrompt.js +176 -0
  39. package/lib/module/license/index.js +5 -40
  40. package/lib/module/license/licenseModule.js +92 -0
  41. package/lib/module/license/tierLimits.js +158 -0
  42. package/lib/module/ui/backgrounds/BackgroundSwitcher.js +176 -0
  43. package/lib/module/ui/backgrounds/README.md +115 -0
  44. package/lib/module/ui/backgrounds/ToolBackground.js +70 -0
  45. package/lib/module/ui/backgrounds/backgroundStore.js +111 -0
  46. package/lib/module/ui/backgrounds/index.js +9 -0
  47. package/lib/module/ui/backgrounds/primitives.js +328 -0
  48. package/lib/module/ui/backgrounds/registry.js +105 -0
  49. package/lib/module/ui/backgrounds/rng.js +65 -0
  50. package/lib/module/ui/backgrounds/types.js +1 -0
  51. package/lib/module/ui/backgrounds/variants/deepField.js +347 -0
  52. package/lib/module/ui/backgrounds/variants/lattice.js +575 -0
  53. package/lib/module/ui/backgrounds/variants/starfield.js +206 -0
  54. package/lib/module/ui/index.js +3 -0
  55. package/lib/typescript/commonjs/JsModal.d.ts.map +1 -1
  56. package/lib/typescript/commonjs/dataViewer/JsonStringNotice.d.ts +6 -0
  57. package/lib/typescript/commonjs/dataViewer/JsonStringNotice.d.ts.map +1 -0
  58. package/lib/typescript/commonjs/dataViewer/ThemedSplitView.d.ts.map +1 -1
  59. package/lib/typescript/commonjs/dataViewer/TimestampDeltaBar.d.ts +7 -0
  60. package/lib/typescript/commonjs/dataViewer/TimestampDeltaBar.d.ts.map +1 -0
  61. package/lib/typescript/commonjs/dataViewer/index.d.ts +6 -0
  62. package/lib/typescript/commonjs/dataViewer/index.d.ts.map +1 -1
  63. package/lib/typescript/commonjs/dataViewer/jsonStringValue.d.ts +25 -0
  64. package/lib/typescript/commonjs/dataViewer/jsonStringValue.d.ts.map +1 -0
  65. package/lib/typescript/commonjs/dataViewer/timestampDiff.d.ts +55 -0
  66. package/lib/typescript/commonjs/dataViewer/timestampDiff.d.ts.map +1 -0
  67. package/lib/typescript/commonjs/hooks/safe-area-impl.d.ts +1 -1
  68. package/lib/typescript/commonjs/index.d.ts +2 -2
  69. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  70. package/lib/typescript/commonjs/license/FeatureGate.d.ts +19 -3
  71. package/lib/typescript/commonjs/license/FeatureGate.d.ts.map +1 -1
  72. package/lib/typescript/commonjs/license/FreeAccountPrompt.d.ts +23 -0
  73. package/lib/typescript/commonjs/license/FreeAccountPrompt.d.ts.map +1 -0
  74. package/lib/typescript/commonjs/license/index.d.ts +6 -15
  75. package/lib/typescript/commonjs/license/index.d.ts.map +1 -1
  76. package/lib/typescript/commonjs/license/licenseModule.d.ts +55 -0
  77. package/lib/typescript/commonjs/license/licenseModule.d.ts.map +1 -0
  78. package/lib/typescript/commonjs/license/tierLimits.d.ts +143 -0
  79. package/lib/typescript/commonjs/license/tierLimits.d.ts.map +1 -0
  80. package/lib/typescript/commonjs/ui/backgrounds/BackgroundSwitcher.d.ts +13 -0
  81. package/lib/typescript/commonjs/ui/backgrounds/BackgroundSwitcher.d.ts.map +1 -0
  82. package/lib/typescript/commonjs/ui/backgrounds/ToolBackground.d.ts +30 -0
  83. package/lib/typescript/commonjs/ui/backgrounds/ToolBackground.d.ts.map +1 -0
  84. package/lib/typescript/commonjs/ui/backgrounds/backgroundStore.d.ts +43 -0
  85. package/lib/typescript/commonjs/ui/backgrounds/backgroundStore.d.ts.map +1 -0
  86. package/lib/typescript/commonjs/ui/backgrounds/index.d.ts +7 -0
  87. package/lib/typescript/commonjs/ui/backgrounds/index.d.ts.map +1 -0
  88. package/lib/typescript/commonjs/ui/backgrounds/primitives.d.ts +106 -0
  89. package/lib/typescript/commonjs/ui/backgrounds/primitives.d.ts.map +1 -0
  90. package/lib/typescript/commonjs/ui/backgrounds/registry.d.ts +28 -0
  91. package/lib/typescript/commonjs/ui/backgrounds/registry.d.ts.map +1 -0
  92. package/lib/typescript/commonjs/ui/backgrounds/rng.d.ts +27 -0
  93. package/lib/typescript/commonjs/ui/backgrounds/rng.d.ts.map +1 -0
  94. package/lib/typescript/commonjs/ui/backgrounds/types.d.ts +14 -0
  95. package/lib/typescript/commonjs/ui/backgrounds/types.d.ts.map +1 -0
  96. package/lib/typescript/commonjs/ui/backgrounds/variants/deepField.d.ts +65 -0
  97. package/lib/typescript/commonjs/ui/backgrounds/variants/deepField.d.ts.map +1 -0
  98. package/lib/typescript/commonjs/ui/backgrounds/variants/lattice.d.ts +33 -0
  99. package/lib/typescript/commonjs/ui/backgrounds/variants/lattice.d.ts.map +1 -0
  100. package/lib/typescript/commonjs/ui/backgrounds/variants/starfield.d.ts +12 -0
  101. package/lib/typescript/commonjs/ui/backgrounds/variants/starfield.d.ts.map +1 -0
  102. package/lib/typescript/commonjs/ui/index.d.ts +1 -0
  103. package/lib/typescript/commonjs/ui/index.d.ts.map +1 -1
  104. package/lib/typescript/module/JsModal.d.ts.map +1 -1
  105. package/lib/typescript/module/dataViewer/JsonStringNotice.d.ts +6 -0
  106. package/lib/typescript/module/dataViewer/JsonStringNotice.d.ts.map +1 -0
  107. package/lib/typescript/module/dataViewer/ThemedSplitView.d.ts.map +1 -1
  108. package/lib/typescript/module/dataViewer/TimestampDeltaBar.d.ts +7 -0
  109. package/lib/typescript/module/dataViewer/TimestampDeltaBar.d.ts.map +1 -0
  110. package/lib/typescript/module/dataViewer/index.d.ts +6 -0
  111. package/lib/typescript/module/dataViewer/index.d.ts.map +1 -1
  112. package/lib/typescript/module/dataViewer/jsonStringValue.d.ts +25 -0
  113. package/lib/typescript/module/dataViewer/jsonStringValue.d.ts.map +1 -0
  114. package/lib/typescript/module/dataViewer/timestampDiff.d.ts +55 -0
  115. package/lib/typescript/module/dataViewer/timestampDiff.d.ts.map +1 -0
  116. package/lib/typescript/module/hooks/safe-area-impl.d.ts +1 -1
  117. package/lib/typescript/module/index.d.ts +2 -2
  118. package/lib/typescript/module/index.d.ts.map +1 -1
  119. package/lib/typescript/module/license/FeatureGate.d.ts +19 -3
  120. package/lib/typescript/module/license/FeatureGate.d.ts.map +1 -1
  121. package/lib/typescript/module/license/FreeAccountPrompt.d.ts +23 -0
  122. package/lib/typescript/module/license/FreeAccountPrompt.d.ts.map +1 -0
  123. package/lib/typescript/module/license/index.d.ts +6 -15
  124. package/lib/typescript/module/license/index.d.ts.map +1 -1
  125. package/lib/typescript/module/license/licenseModule.d.ts +55 -0
  126. package/lib/typescript/module/license/licenseModule.d.ts.map +1 -0
  127. package/lib/typescript/module/license/tierLimits.d.ts +143 -0
  128. package/lib/typescript/module/license/tierLimits.d.ts.map +1 -0
  129. package/lib/typescript/module/ui/backgrounds/BackgroundSwitcher.d.ts +13 -0
  130. package/lib/typescript/module/ui/backgrounds/BackgroundSwitcher.d.ts.map +1 -0
  131. package/lib/typescript/module/ui/backgrounds/ToolBackground.d.ts +30 -0
  132. package/lib/typescript/module/ui/backgrounds/ToolBackground.d.ts.map +1 -0
  133. package/lib/typescript/module/ui/backgrounds/backgroundStore.d.ts +43 -0
  134. package/lib/typescript/module/ui/backgrounds/backgroundStore.d.ts.map +1 -0
  135. package/lib/typescript/module/ui/backgrounds/index.d.ts +7 -0
  136. package/lib/typescript/module/ui/backgrounds/index.d.ts.map +1 -0
  137. package/lib/typescript/module/ui/backgrounds/primitives.d.ts +106 -0
  138. package/lib/typescript/module/ui/backgrounds/primitives.d.ts.map +1 -0
  139. package/lib/typescript/module/ui/backgrounds/registry.d.ts +28 -0
  140. package/lib/typescript/module/ui/backgrounds/registry.d.ts.map +1 -0
  141. package/lib/typescript/module/ui/backgrounds/rng.d.ts +27 -0
  142. package/lib/typescript/module/ui/backgrounds/rng.d.ts.map +1 -0
  143. package/lib/typescript/module/ui/backgrounds/types.d.ts +14 -0
  144. package/lib/typescript/module/ui/backgrounds/types.d.ts.map +1 -0
  145. package/lib/typescript/module/ui/backgrounds/variants/deepField.d.ts +65 -0
  146. package/lib/typescript/module/ui/backgrounds/variants/deepField.d.ts.map +1 -0
  147. package/lib/typescript/module/ui/backgrounds/variants/lattice.d.ts +33 -0
  148. package/lib/typescript/module/ui/backgrounds/variants/lattice.d.ts.map +1 -0
  149. package/lib/typescript/module/ui/backgrounds/variants/starfield.d.ts +12 -0
  150. package/lib/typescript/module/ui/backgrounds/variants/starfield.d.ts.map +1 -0
  151. package/lib/typescript/module/ui/index.d.ts +1 -0
  152. package/lib/typescript/module/ui/index.d.ts.map +1 -1
  153. package/package.json +4 -4
  154. package/scripts/detect-safe-area.js +0 -20
@@ -0,0 +1,351 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.DeepFieldTunable = exports.DeepField = void 0;
7
+ var _react = require("react");
8
+ var _reactNative = require("react-native");
9
+ var _absoluteFill = require("../../../utils/absoluteFill.js");
10
+ var _primitives = require("../primitives.js");
11
+ var _rng = require("../rng.js");
12
+ var _jsxRuntime = require("react/jsx-runtime");
13
+ /**
14
+ * Deep Field — a faithful port of the Everlights `ParallaxDriftBackground`.
15
+ *
16
+ * The sibling `Starfield` preset is a cheap approximation of the same idea: 99
17
+ * stars quantised into five depth bands. This one reproduces the original's
18
+ * field exactly — same seed, same generator call order, same 160 stars, same
19
+ * `z = zNear + zSpan·√rnd()` far-plane bias, same sizes, brightnesses, palette
20
+ * and drift. Drop the constants below into the Skia version and you get the
21
+ * same sky.
22
+ *
23
+ * WHAT COULDN'T COME ACROSS 1:1, and what was done instead:
24
+ *
25
+ * - **Continuous per-star speed.** The original runs a worklet per star, so
26
+ * every one of the 160 drifts at its own `drift/z`. Here a distinct speed
27
+ * means a distinct animated node, so SPEED (and only speed) is quantised
28
+ * into 18 bands — banded uniformly in 1/z, which is what speed is
29
+ * proportional to, so the steps are even. Size, brightness, colour and
30
+ * twinkle phase all stay per-star and exact, and those are the properties
31
+ * the eye actually reads as depth.
32
+ *
33
+ * - **The soft bulb sprite.** The original bakes one 64px sprite (blurred halo
34
+ * at r=6/α.30 over a blurred core at r=4/α1) and stamps it at `dia`. That is
35
+ * why stars stay fine points even at dia=20 — the lit core is only ~13% of
36
+ * the stamp. There is no blur primitive here, so each star is a small solid
37
+ * core at that same 13%, and the nearer ones get one or two concentric
38
+ * discs standing in for the halo. Far stars end up a single ~1px dot, which
39
+ * is what the sprite renders them as anyway.
40
+ *
41
+ * - **Additive blending.** `blendMode="plus"` becomes ordinary alpha
42
+ * compositing. Over a near-black base the two agree except where stars
43
+ * overlap, which at this density is rare.
44
+ *
45
+ * It costs roughly twice the cheap Starfield — see `registry.tsx` — which is
46
+ * the whole reason both are in the catalogue.
47
+ */
48
+
49
+ // ---------------------------------------------------------------------------
50
+ // The original's shipping constants, verbatim.
51
+ // ---------------------------------------------------------------------------
52
+ const COUNT = 160;
53
+ const DRIFT = 0.016; // horizontal travel/sec at z=1, as a fraction of width
54
+ const BASE_DIA = 5; // sprite diameter px at z=1
55
+ const Z_NEAR = 0.25;
56
+ const Z_FAR = 1.0;
57
+ const Z_SPAN = Z_FAR - Z_NEAR;
58
+ const MAX_DIA = BASE_DIA / Z_NEAR;
59
+ const TWINKLE = 0.08;
60
+
61
+ /** The classic white/blue mix — `[r,g,b]` 0..1 in the original. */
62
+ const PALETTE = ["#FFFFFF", "#B3D9FF", "#8CB3FF"];
63
+
64
+ /** The backdrop the field sits on — also what `opaque` mode flattens against. */
65
+ const BASE_COLOR = "#050609";
66
+
67
+ /**
68
+ * Default speed bands. 18 is the point where stepping stops being visible:
69
+ * adjacent bands differ by ~6% in speed, well under what reads as a seam. The
70
+ * bench route sweeps this, since it is the main lever on cost.
71
+ */
72
+ const BAND_COUNT = 18;
73
+ /** Twinkle groups — bands are round-robined across these. */
74
+ const TWINKLE_GROUPS = 4;
75
+ const TWINKLE_MS = [4200, 4900, 5600, 6300];
76
+
77
+ /** How the ±8% brightness wobble is applied. */
78
+
79
+ /** How many concentric discs stand in for the sprite's blurred halo. */
80
+
81
+ /**
82
+ * The original field, regenerated.
83
+ *
84
+ * The generator order matters as much as the seed: the source pulls fx, fy, z
85
+ * and tw off ONE mulberry32 stream per star, so drawing them in any other order
86
+ * — four separate `scatter()` calls, say — gives a different sky from the same
87
+ * seed. Built once at module load.
88
+ */
89
+ function buildField(count) {
90
+ const rnd = (0, _rng.mulberry32)((0x5747 ^ count) >>> 0);
91
+ const stars = [];
92
+ for (let i = 0; i < count; i++) {
93
+ const fx = rnd();
94
+ const fy = rnd();
95
+ // Bias toward the far plane so close, fast streaks stay sparse.
96
+ const z = Z_NEAR + Z_SPAN * Math.sqrt(rnd());
97
+ const tw = rnd() * Math.PI * 2;
98
+ const dia = Math.min(BASE_DIA / z, MAX_DIA);
99
+ const near = (Z_FAR - z) / Z_SPAN; // 0 far → 1 near
100
+ stars.push({
101
+ fx,
102
+ fy,
103
+ z,
104
+ tw,
105
+ // 0.15·dia ≈ the sprite's lit core (r=4 of 64, blurred), with a 1.1px
106
+ // floor so the farthest stars still land on a pixel.
107
+ core: Math.max(1.1, dia * 0.15),
108
+ halo: dia * 0.3,
109
+ haloDiscs: z < 0.45 ? 2 : z < 0.7 ? 1 : 0,
110
+ alpha: 0.2 + 0.8 * near,
111
+ color: PALETTE[Math.floor((tw * 0.5 + 0.5) * PALETTE.length) % PALETTE.length]
112
+ });
113
+ }
114
+ return stars;
115
+ }
116
+
117
+ /**
118
+ * Fields by star count, built on demand.
119
+ *
120
+ * 160 is the real preset. The larger counts exist for AMPLIFIED benchmarking:
121
+ * at 160 the difference between two rendering structures is ~2 CPU points,
122
+ * which on real hardware sits under a noise floor several times that — so the
123
+ * variants are compared at a scale where the difference is unmistakable, and
124
+ * the structure that wins there is the one worth shipping at 160.
125
+ *
126
+ * Note the seed is `0x5747 ^ count`, exactly as the original does it, so each
127
+ * count is its own field rather than a prefix of a bigger one. That is fine
128
+ * here: only the 160 field has to match Everlights.
129
+ */
130
+ const fieldCache = new Map();
131
+ function getField(count) {
132
+ const cached = fieldCache.get(count);
133
+ if (cached) return cached;
134
+ const built = buildField(count);
135
+ fieldCache.set(count, built);
136
+ return built;
137
+ }
138
+ const FIELD = getField(COUNT);
139
+
140
+ /**
141
+ * Bucket by 1/z (∝ speed) rather than by z, so the bands are evenly spaced in
142
+ * the quantity being quantised. Each band carries its member stars and the
143
+ * speed of its centre. Cached per count — the bench route asks for several.
144
+ */
145
+ const bandCache = new Map();
146
+ function buildBands(count, starCount) {
147
+ const key = `${count}:${starCount}`;
148
+ const cached = bandCache.get(key);
149
+ if (cached) return cached;
150
+ const field = getField(starCount);
151
+ const invNear = 1 / Z_NEAR; // 4
152
+ const invFar = 1 / Z_FAR; // 1
153
+ const span = invNear - invFar;
154
+ const buckets = Array.from({
155
+ length: count
156
+ }, () => []);
157
+ for (const star of field) {
158
+ const t = (1 / star.z - invFar) / span;
159
+ const idx = Math.min(count - 1, Math.max(0, Math.floor(t * count)));
160
+ buckets[idx].push(star);
161
+ }
162
+ const bands = buckets.map((stars, i) => ({
163
+ stars,
164
+ // z at the band's centre, back out of the 1/z bucketing.
165
+ z: 1 / (invFar + (i + 0.5) / count * span)
166
+ }));
167
+ bandCache.set(key, bands);
168
+ return bands;
169
+ }
170
+ const DeepBand = /*#__PURE__*/(0, _react.memo)(function DeepBand({
171
+ bands,
172
+ index,
173
+ width,
174
+ height,
175
+ animated,
176
+ raster,
177
+ halo,
178
+ opaque,
179
+ drift,
180
+ opacity
181
+ }) {
182
+ const band = bands[index];
183
+ // One full width of travel takes z / DRIFT seconds, exactly as in the
184
+ // original's `phase = fx - t·(drift/z)`.
185
+ const driftValue = (0, _primitives.useLoop)(band.z / DRIFT * 1000, animated && drift);
186
+ const translateX = driftValue.interpolate({
187
+ inputRange: [0, 1],
188
+ outputRange: [0, -width]
189
+ });
190
+ // Over a known backdrop an opaque colour is pixel-identical to the
191
+ // translucent one — the GPU just skips the blend.
192
+ const paint = (color, alpha) => opaque ? (0, _rng.flattenOver)(color, alpha, BASE_COLOR) : (0, _rng.withAlpha)(color, alpha);
193
+ const parts = [];
194
+ for (let i = 0; i < band.stars.length; i++) {
195
+ const star = band.stars[i];
196
+ const y = star.fy * height;
197
+ const discs = halo === "none" ? 0 : halo === "flat" ? star.haloDiscs > 0 ? 1 : 0 : star.haloDiscs;
198
+ // Drawn twice, one width apart, so the layer tiles seamlessly when the
199
+ // loop snaps back to 0.
200
+ for (let copy = 0; copy < 2; copy++) {
201
+ const x = star.fx * width + copy * width;
202
+ const key = `${i}-${copy}`;
203
+ for (let h = 0; h < discs; h++) {
204
+ const d = star.halo * (h === 0 ? 1 : 0.6);
205
+ parts.push(/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
206
+ style: {
207
+ position: "absolute",
208
+ left: x - d / 2,
209
+ top: y - d / 2,
210
+ width: d,
211
+ height: d,
212
+ borderRadius: d / 2,
213
+ // The sprite's halo is α.30 of the core; scaled by the star's own
214
+ // depth brightness like everything else.
215
+ backgroundColor: paint(star.color, star.alpha * 0.3)
216
+ }
217
+ }, `${key}-h${h}`));
218
+ }
219
+ parts.push(/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
220
+ style: {
221
+ position: "absolute",
222
+ left: x - star.core / 2,
223
+ top: y - star.core / 2,
224
+ width: star.core,
225
+ height: star.core,
226
+ borderRadius: star.core / 2,
227
+ backgroundColor: paint(star.color, star.alpha)
228
+ }
229
+ }, key));
230
+ }
231
+ }
232
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Animated.View, {
233
+ style: [{
234
+ position: "absolute",
235
+ left: 0,
236
+ top: 0,
237
+ width: width * 2,
238
+ height
239
+ },
240
+ // Fused mode puts the wobble on THIS layer instead of a wrapper above
241
+ // it, so the twinkle costs no extra composited surface.
242
+ opacity ? {
243
+ opacity,
244
+ transform: [{
245
+ translateX
246
+ }]
247
+ } : {
248
+ transform: [{
249
+ translateX
250
+ }]
251
+ }],
252
+ pointerEvents: "none",
253
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_primitives.RasterLayer, {
254
+ raster: raster,
255
+ style: {
256
+ width: width * 2,
257
+ height
258
+ },
259
+ children: parts
260
+ })
261
+ });
262
+ });
263
+
264
+ /**
265
+ * The four wobble values. The original wobbles each star by
266
+ * `1 + 0.08·sin(t·3 + tw)`; per-star that would be 160 nodes, so bands are
267
+ * round-robined across four pulses at slightly different periods — same ±8%
268
+ * amplitude, and the differing periods keep the sky from pulsing as a unit.
269
+ *
270
+ * Fixed count, called unconditionally, so hook order never varies with props.
271
+ */
272
+ function useTwinkles(animated, enabled) {
273
+ const a = (0, _primitives.usePulse)(TWINKLE_MS[0], animated && enabled);
274
+ const b = (0, _primitives.usePulse)(TWINKLE_MS[1], animated && enabled);
275
+ const c = (0, _primitives.usePulse)(TWINKLE_MS[2], animated && enabled);
276
+ const d = (0, _primitives.usePulse)(TWINKLE_MS[3], animated && enabled);
277
+ const range = {
278
+ inputRange: [0, 1],
279
+ outputRange: [1 - TWINKLE, 1]
280
+ };
281
+ return [a.interpolate(range), b.interpolate(range), c.interpolate(range), d.interpolate(range)];
282
+ }
283
+ /**
284
+ * The tunable body. `DeepField` below is this with the shipping defaults; the
285
+ * bench route (`example-dev-build/app/bg-bench.tsx`) drives the knobs so every
286
+ * measured variant is this exact code, not a copy of it.
287
+ */
288
+ const DeepFieldTunable = exports.DeepFieldTunable = /*#__PURE__*/(0, _react.memo)(function DeepFieldTunable({
289
+ width,
290
+ height,
291
+ animated,
292
+ bandCount = BAND_COUNT,
293
+ raster = true,
294
+ twinkle = "group",
295
+ halo = "full",
296
+ opaque = false,
297
+ drift = true,
298
+ starCount = COUNT
299
+ }) {
300
+ const bands = buildBands(bandCount, starCount);
301
+ const twinkles = useTwinkles(animated, twinkle !== "off");
302
+ const bandViews = [];
303
+ for (let i = 0; i < bandCount; i++) {
304
+ bandViews.push(/*#__PURE__*/(0, _jsxRuntime.jsx)(DeepBand, {
305
+ bands: bands,
306
+ index: i,
307
+ width: width,
308
+ height: height,
309
+ animated: animated,
310
+ raster: raster,
311
+ halo: halo,
312
+ opaque: opaque,
313
+ drift: drift,
314
+ opacity: twinkle === "fused" ? twinkles[i % TWINKLE_GROUPS] : undefined
315
+ }, i));
316
+ }
317
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
318
+ style: _absoluteFill.absoluteFill,
319
+ pointerEvents: "none",
320
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_primitives.Base, {
321
+ color: BASE_COLOR
322
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_primitives.RadialGlow, {
323
+ size: width * 1.7,
324
+ color: "#1E3A8A",
325
+ alpha: 0.16,
326
+ rings: 8,
327
+ falloff: 2.1,
328
+ style: {
329
+ position: "absolute",
330
+ left: -width * 0.35,
331
+ top: -width
332
+ }
333
+ }), twinkle === "group" ?
334
+ // Group mode: one full-screen Animated.View per pulse, each wrapping
335
+ // its share of the bands. Costs four extra composited surfaces.
336
+ Array.from({
337
+ length: TWINKLE_GROUPS
338
+ }, (_, g) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Animated.View, {
339
+ style: [_absoluteFill.absoluteFill, {
340
+ opacity: twinkles[g]
341
+ }],
342
+ pointerEvents: "none",
343
+ children: bandViews.filter((_, i) => i % TWINKLE_GROUPS === g)
344
+ }, g)) : bandViews]
345
+ });
346
+ });
347
+ const DeepField = exports.DeepField = /*#__PURE__*/(0, _react.memo)(function DeepField(props) {
348
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(DeepFieldTunable, {
349
+ ...props
350
+ });
351
+ });