@wireai/activation 0.14.1 → 0.14.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,32 @@
3
3
  All notable changes to `@wireai/activation` (formerly `wireai-onboarding`).
4
4
  Historical entries below the rename keep the old package name on purpose.
5
5
 
6
+ ## [0.14.2] - 2026-08-18
7
+
8
+ **PATCH: no public surface gained, lost or renamed a member.** `SpotlightOverlay` keeps its props
9
+ and its export; `expo-blur` stays an OPTIONAL peer.
10
+
11
+ ### Fixed
12
+
13
+ - **The coachmarks subpath no longer force-imports its optional peer `expo-blur`.**
14
+ `SpotlightOverlay` did `import { BlurView } from "expo-blur"` at module scope and built its
15
+ animated blur component at module load, and `coachmarks/index.ts` re-exports the overlay with no
16
+ wildcard escape — so importing ANYTHING from `@wireai/activation/coachmarks`, even
17
+ `setCoachmarkStorage`, dragged `expo-blur` in. A host that took the peer's "optional" at its word
18
+ and skipped installing it hit a Metro resolution failure the moment it touched coachmarks, which
19
+ is why the AI Mobile Launcher tiers (and any Expo Go build) could not adopt the capability. The
20
+ peer is now resolved through a guarded lazy require with a string-literal specifier inside a
21
+ try/catch (the same shape as `icons/expoIcons.ts` / `device/appVersion.ts`), and the animated
22
+ component is built once on first render, so the subpath carries no static top-level import of the
23
+ peer.
24
+ - **Degradation, by design:** when `expo-blur` is absent the spotlight drops the frost to an
25
+ equivalent dimmed scrim. The ring, tooltip and gestures behave identically — a missing
26
+ decorative frost never blanks a tour, never crashes, never renders empty.
27
+ - `metro/index.js` `OPTIONAL_MODULES` and `tsup.config.ts` now treat `expo-blur` as a guarded
28
+ optional peer (moved off the static-peer list), so the built `dist/` collects it as optional and
29
+ the metro helper's empty-module safety net covers it for hosts that disable Metro's
30
+ `allowOptionalDependencies`.
31
+
6
32
  ## [0.14.1] - 2026-08-18
7
33
 
8
34
  Two rulings from the 0.14.0 audit, applied. Both were reproduced there and left for a decision
@@ -2,7 +2,6 @@
2
2
 
3
3
  var React3 = require('react');
4
4
  var jsxRuntime = require('react/jsx-runtime');
5
- var expoBlur = require('expo-blur');
6
5
  var reactNative = require('react-native');
7
6
  var Animated = require('react-native-reanimated');
8
7
 
@@ -11,7 +10,12 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
11
10
  var React3__default = /*#__PURE__*/_interopDefault(React3);
12
11
  var Animated__default = /*#__PURE__*/_interopDefault(Animated);
13
12
 
14
- // src/coachmarks/CoachmarkProvider.tsx
13
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
14
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
15
+ }) : x)(function(x) {
16
+ if (typeof require !== "undefined") return require.apply(this, arguments);
17
+ throw Error('Dynamic require of "' + x + '" is not supported');
18
+ });
15
19
 
16
20
  // src/features/defaults.ts
17
21
  var defaultWireFeatures = Object.freeze({
@@ -90,8 +94,8 @@ var DEFAULT_TIMEOUT_MS = 4e3;
90
94
  var failOpen = async (storage, key) => {
91
95
  var _a;
92
96
  if (!storage) return defaultWireFeatures;
93
- const cached = await readCachedFeatures(storage, key);
94
- return (_a = cached == null ? void 0 : cached.features) != null ? _a : defaultWireFeatures;
97
+ const cached2 = await readCachedFeatures(storage, key);
98
+ return (_a = cached2 == null ? void 0 : cached2.features) != null ? _a : defaultWireFeatures;
95
99
  };
96
100
  var fetchWithTimeout = async (url, apiKey, timeoutMs) => {
97
101
  const controller = typeof AbortController !== "undefined" ? new AbortController() : void 0;
@@ -329,6 +333,47 @@ var useOnboardingTheme = () => {
329
333
  const ctx = React3.useContext(OnboardingThemeContext);
330
334
  return ctx != null ? ctx : mergeTheme();
331
335
  };
336
+
337
+ // src/coachmarks/expoBlur.ts
338
+ var runtimeRequire = (moduleName) => {
339
+ if (moduleName !== "expo-blur") return void 0;
340
+ if (typeof __require !== "function") return void 0;
341
+ try {
342
+ return require("expo-blur");
343
+ } catch {
344
+ return void 0;
345
+ }
346
+ };
347
+ var interop = (mod) => {
348
+ if (!mod || typeof mod !== "object") return void 0;
349
+ const ns = mod;
350
+ if (ns.BlurView) return ns;
351
+ const def = mod.default;
352
+ if (def && typeof def === "object") return def;
353
+ return ns;
354
+ };
355
+ var asComponent = (value) => {
356
+ if (typeof value === "function") return value;
357
+ if (value && typeof value === "object" && "$$typeof" in value) {
358
+ return value;
359
+ }
360
+ return void 0;
361
+ };
362
+ var cached;
363
+ var resolveBlurView = (requireModule = runtimeRequire) => {
364
+ try {
365
+ if (cached === void 0 || requireModule !== runtimeRequire) {
366
+ const resolved = interop(requireModule("expo-blur"));
367
+ const component = resolved ? asComponent(resolved.BlurView) : void 0;
368
+ if (requireModule === runtimeRequire) cached = component != null ? component : null;
369
+ return component;
370
+ }
371
+ if (cached === null) return void 0;
372
+ return cached;
373
+ } catch {
374
+ return void 0;
375
+ }
376
+ };
332
377
  var SWIPE_MS = 700;
333
378
  var TAP_MS = 320;
334
379
  var SPREAD_MS = 620;
@@ -543,7 +588,6 @@ var styles = reactNative.StyleSheet.create({
543
588
  });
544
589
  var GestureHint = React3__default.default.memo(GestureHintComponent);
545
590
  GestureHint.displayName = "GestureHint";
546
- var AnimatedBlurView = Animated__default.default.createAnimatedComponent(expoBlur.BlurView);
547
591
  var BLUR_INTENSITY = 26;
548
592
  var FADE_MS = 280;
549
593
  var RING_PADDING = 10;
@@ -565,6 +609,10 @@ var SpotlightOverlayComponent = ({
565
609
  const theme = useOnboardingTheme();
566
610
  const accent = accentColor != null ? accentColor : theme.colors.primary;
567
611
  const accentText = accentTextColor != null ? accentTextColor : theme.colors.onPrimary;
612
+ const AnimatedBlurView = React3.useMemo(() => {
613
+ const BlurView = resolveBlurView();
614
+ return BlurView ? Animated__default.default.createAnimatedComponent(BlurView) : null;
615
+ }, []);
568
616
  const showGesture = gesture !== "none" && gesture !== "tap" && gesture !== "double_tap";
569
617
  const intensity = Animated.useSharedValue(0);
570
618
  const ringScale = Animated.useSharedValue(1);
@@ -613,13 +661,23 @@ var SpotlightOverlayComponent = ({
613
661
  entering: Animated.FadeIn.duration(FADE_MS),
614
662
  exiting: Animated.FadeOut.duration(FADE_MS),
615
663
  children: [
616
- /* @__PURE__ */ jsxRuntime.jsx(
664
+ AnimatedBlurView ? /* @__PURE__ */ jsxRuntime.jsx(
617
665
  AnimatedBlurView,
618
666
  {
619
667
  tint: "dark",
620
668
  animatedProps: blurAnimatedProps,
621
669
  style: reactNative.StyleSheet.absoluteFill
622
670
  }
671
+ ) : (
672
+ // `expo-blur` absent → a plain dimmed scrim stands in for the frost. Same dark backdrop
673
+ // the tour reads against, so the ring, tooltip and gestures behave identically.
674
+ /* @__PURE__ */ jsxRuntime.jsx(
675
+ Animated__default.default.View,
676
+ {
677
+ style: [reactNative.StyleSheet.absoluteFill, styles2.scrim],
678
+ pointerEvents: "none"
679
+ }
680
+ )
623
681
  ),
624
682
  /* @__PURE__ */ jsxRuntime.jsx(
625
683
  reactNative.Pressable,
@@ -686,6 +744,11 @@ var styles2 = reactNative.StyleSheet.create({
686
744
  zIndex: 9999,
687
745
  elevation: 9999
688
746
  },
747
+ // Fallback backdrop when `expo-blur` is absent. A structural dim (not a brand token), tuned to
748
+ // read like the dark blur at BLUR_INTENSITY so the ring + tooltip keep the same contrast.
749
+ scrim: {
750
+ backgroundColor: "rgba(0, 0, 0, 0.55)"
751
+ },
689
752
  ring: {
690
753
  position: "absolute",
691
754
  borderWidth: 2.5,