@oxyhq/bloom 0.51.0 → 0.51.1

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 (54) hide show
  1. package/lib/commonjs/frosted-icon-button/shared.js +1 -1
  2. package/lib/commonjs/tab-bar/surface-solid.js +43 -0
  3. package/lib/commonjs/tab-bar/surface-solid.js.map +1 -0
  4. package/lib/commonjs/tab-bar/surface.js +5 -42
  5. package/lib/commonjs/tab-bar/surface.js.map +1 -1
  6. package/lib/commonjs/tab-bar/surface.native.js +65 -8
  7. package/lib/commonjs/tab-bar/surface.native.js.map +1 -1
  8. package/lib/module/frosted-icon-button/shared.js +1 -1
  9. package/lib/module/tab-bar/surface-solid.js +37 -0
  10. package/lib/module/tab-bar/surface-solid.js.map +1 -0
  11. package/lib/module/tab-bar/surface.js +10 -23
  12. package/lib/module/tab-bar/surface.js.map +1 -1
  13. package/lib/module/tab-bar/surface.native.js +68 -9
  14. package/lib/module/tab-bar/surface.native.js.map +1 -1
  15. package/lib/typescript/commonjs/benefit-list/types.d.ts +2 -1
  16. package/lib/typescript/commonjs/benefit-list/types.d.ts.map +1 -1
  17. package/lib/typescript/commonjs/fab/types.d.ts +4 -2
  18. package/lib/typescript/commonjs/fab/types.d.ts.map +1 -1
  19. package/lib/typescript/commonjs/frosted-icon-button/shared.d.ts +1 -1
  20. package/lib/typescript/commonjs/frosted-icon-button/types.d.ts +2 -1
  21. package/lib/typescript/commonjs/frosted-icon-button/types.d.ts.map +1 -1
  22. package/lib/typescript/commonjs/tab-bar/surface-solid.d.ts +6 -0
  23. package/lib/typescript/commonjs/tab-bar/surface-solid.d.ts.map +1 -0
  24. package/lib/typescript/commonjs/tab-bar/surface.d.ts +28 -5
  25. package/lib/typescript/commonjs/tab-bar/surface.d.ts.map +1 -1
  26. package/lib/typescript/commonjs/tab-bar/surface.native.d.ts.map +1 -1
  27. package/lib/typescript/commonjs/tab-bar/types.d.ts +6 -3
  28. package/lib/typescript/commonjs/tab-bar/types.d.ts.map +1 -1
  29. package/lib/typescript/module/benefit-list/types.d.ts +2 -1
  30. package/lib/typescript/module/benefit-list/types.d.ts.map +1 -1
  31. package/lib/typescript/module/fab/types.d.ts +4 -2
  32. package/lib/typescript/module/fab/types.d.ts.map +1 -1
  33. package/lib/typescript/module/frosted-icon-button/shared.d.ts +1 -1
  34. package/lib/typescript/module/frosted-icon-button/types.d.ts +2 -1
  35. package/lib/typescript/module/frosted-icon-button/types.d.ts.map +1 -1
  36. package/lib/typescript/module/tab-bar/surface-solid.d.ts +6 -0
  37. package/lib/typescript/module/tab-bar/surface-solid.d.ts.map +1 -0
  38. package/lib/typescript/module/tab-bar/surface.d.ts +28 -5
  39. package/lib/typescript/module/tab-bar/surface.d.ts.map +1 -1
  40. package/lib/typescript/module/tab-bar/surface.native.d.ts.map +1 -1
  41. package/lib/typescript/module/tab-bar/types.d.ts +6 -3
  42. package/lib/typescript/module/tab-bar/types.d.ts.map +1 -1
  43. package/package.json +2 -8
  44. package/src/__tests__/TabBarGlassFallback.test.tsx +234 -0
  45. package/src/__tests__/TabBarWebFork.test.ts +46 -0
  46. package/src/__tests__/icon-references.test.ts +243 -0
  47. package/src/benefit-list/types.ts +2 -1
  48. package/src/fab/types.ts +4 -2
  49. package/src/frosted-icon-button/shared.ts +1 -1
  50. package/src/frosted-icon-button/types.ts +2 -1
  51. package/src/tab-bar/surface-solid.tsx +40 -0
  52. package/src/tab-bar/surface.native.tsx +77 -15
  53. package/src/tab-bar/surface.tsx +10 -29
  54. package/src/tab-bar/types.ts +6 -3
@@ -97,7 +97,7 @@ function resolveFrostedPalette(colors, isDark) {
97
97
  * Inject `color` as the icon's `fill` — but only as a FALLBACK: if the caller
98
98
  * already set an explicit `fill` on the icon element, it wins and the node is
99
99
  * returned untouched. Bloom icons resolve their paint as `fill ?? style.color`,
100
- * so a bare `<Icons.X />` gets the theme-aware color for free while an
100
+ * so any bare Bloom icon element gets the theme-aware color for free while an
101
101
  * explicitly-colored icon is never overridden. Non-element children (plain
102
102
  * text/strings) pass through unchanged.
103
103
  */
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.SolidTabBarSurface = SolidTabBarSurface;
7
+ var _reactNative = require("react-native");
8
+ var _reactNativeReanimated = _interopRequireDefault(require("react-native-reanimated"));
9
+ var _jsxRuntime = require("react/jsx-runtime");
10
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
11
+ /**
12
+ * Ported from expo-glass-tabs v0.1.1 — src/glass-tab-bar.tsx
13
+ * (MIT © 2026 David Mokos). See the top-level NOTICE.
14
+ *
15
+ * The tab bar's NON-GLASS capsule surface: a plain animated view filled with the
16
+ * theme's near-opaque fallback. Android, pre-iOS-26 devices and any build without
17
+ * a usable `expo-glass-effect` all paint this.
18
+ *
19
+ * It lives in its own module because TWO variants render it and one of them
20
+ * cannot reach the other: Metro resolves a bare `./surface` to
21
+ * `surface.native.tsx` no matter which file asks, so `surface.native.tsx`
22
+ * importing its neutral sibling for the fallback would import ITSELF. A name with
23
+ * no platform variants resolves to this one file everywhere — which is the whole
24
+ * point, so please do not fold it back into `surface.tsx`.
25
+ */
26
+
27
+ function SolidTabBarSurface({
28
+ theme,
29
+ style
30
+ }) {
31
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeReanimated.default.View, {
32
+ style: [_reactNative.StyleSheet.absoluteFill, styles.surface, {
33
+ backgroundColor: theme.solidFallback
34
+ }, style]
35
+ });
36
+ }
37
+ SolidTabBarSurface.displayName = 'SolidTabBarSurface';
38
+ const styles = _reactNative.StyleSheet.create({
39
+ surface: {
40
+ borderCurve: 'continuous'
41
+ }
42
+ });
43
+ //# sourceMappingURL=surface-solid.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_reactNative","require","_reactNativeReanimated","_interopRequireDefault","_jsxRuntime","e","__esModule","default","SolidTabBarSurface","theme","style","jsx","View","StyleSheet","absoluteFill","styles","surface","backgroundColor","solidFallback","displayName","create","borderCurve"],"sourceRoot":"../../../src","sources":["tab-bar/surface-solid.tsx"],"mappings":";;;;;;AAeA,IAAAA,YAAA,GAAAC,OAAA;AACA,IAAAC,sBAAA,GAAAC,sBAAA,CAAAF,OAAA;AAA+C,IAAAG,WAAA,GAAAH,OAAA;AAAA,SAAAE,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAhB/C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAMO,SAASG,kBAAkBA,CAAC;EAAEC,KAAK;EAAEC;AAA0B,CAAC,EAAE;EACvE,oBACE,IAAAN,WAAA,CAAAO,GAAA,EAACT,sBAAA,CAAAK,OAAQ,CAACK,IAAI;IACZF,KAAK,EAAE,CACLG,uBAAU,CAACC,YAAY,EACvBC,MAAM,CAACC,OAAO,EACd;MAAEC,eAAe,EAAER,KAAK,CAACS;IAAc,CAAC,EACxCR,KAAK;EACL,CACH,CAAC;AAEN;AAEAF,kBAAkB,CAACW,WAAW,GAAG,oBAAoB;AAErD,MAAMJ,MAAM,GAAGF,uBAAU,CAACO,MAAM,CAAC;EAC/BJ,OAAO,EAAE;IACPK,WAAW,EAAE;EACf;AACF,CAAC,CAAC","ignoreList":[]}
@@ -3,48 +3,11 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.TabBarSurface = TabBarSurface;
7
- var _reactNative = require("react-native");
8
- var _reactNativeReanimated = _interopRequireDefault(require("react-native-reanimated"));
9
- var _jsxRuntime = require("react/jsx-runtime");
10
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
11
- /**
12
- * Ported from expo-glass-tabs v0.1.1 — src/glass-tab-bar.tsx
13
- * (MIT © 2026 David Mokos). See the top-level NOTICE.
14
- *
15
- * NEUTRAL default variant of the tab bar's capsule surface: a plain animated
16
- * view filled with the theme's solid fallback.
17
- *
18
- * This is the file resolved by everything that does NOT do React Native's
19
- * platform-extension resolution — a consumer's `tsc` (which follows Bloom's
20
- * `"react-native"` source export condition) and any non-Metro bundler reading
21
- * the published `lib/`. It therefore imports NOTHING platform-specific:
22
- * `expo-glass-effect` is native-only, and a static import of it from a file a
23
- * web bundler or a consumer's type-checker resolves would break module
24
- * resolution outright. Same three-way split, for the same reason, as
25
- * `theme/native-root-vars{,.native,.web}.ts`.
26
- *
27
- * The variants — all three implement `TabBarSurfaceProps` exactly, so the entry
28
- * modules can swap them freely:
29
- * - `surface.native.tsx` — iOS/Android (Metro), real `UIGlassEffect` glass;
30
- * - `surface.web.tsx` — web, a CSS `backdrop-filter`;
31
- * - this file — everywhere else, the opaque fallback.
32
- */
33
-
34
- function TabBarSurface({
35
- theme,
36
- style
37
- }) {
38
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeReanimated.default.View, {
39
- style: [_reactNative.StyleSheet.absoluteFill, styles.surface, {
40
- backgroundColor: theme.solidFallback
41
- }, style]
42
- });
43
- }
44
- TabBarSurface.displayName = 'TabBarSurface';
45
- const styles = _reactNative.StyleSheet.create({
46
- surface: {
47
- borderCurve: 'continuous'
6
+ Object.defineProperty(exports, "TabBarSurface", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _surfaceSolid.SolidTabBarSurface;
48
10
  }
49
11
  });
12
+ var _surfaceSolid = require("./surface-solid.js");
50
13
  //# sourceMappingURL=surface.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["_reactNative","require","_reactNativeReanimated","_interopRequireDefault","_jsxRuntime","e","__esModule","default","TabBarSurface","theme","style","jsx","View","StyleSheet","absoluteFill","styles","surface","backgroundColor","solidFallback","displayName","create","borderCurve"],"sourceRoot":"../../../src","sources":["tab-bar/surface.tsx"],"mappings":";;;;;;AAsBA,IAAAA,YAAA,GAAAC,OAAA;AACA,IAAAC,sBAAA,GAAAC,sBAAA,CAAAF,OAAA;AAA+C,IAAAG,WAAA,GAAAH,OAAA;AAAA,SAAAE,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAvB/C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAMO,SAASG,aAAaA,CAAC;EAAEC,KAAK;EAAEC;AAA0B,CAAC,EAAE;EAClE,oBACE,IAAAN,WAAA,CAAAO,GAAA,EAACT,sBAAA,CAAAK,OAAQ,CAACK,IAAI;IACZF,KAAK,EAAE,CACLG,uBAAU,CAACC,YAAY,EACvBC,MAAM,CAACC,OAAO,EACd;MAAEC,eAAe,EAAER,KAAK,CAACS;IAAc,CAAC,EACxCR,KAAK;EACL,CACH,CAAC;AAEN;AAEAF,aAAa,CAACW,WAAW,GAAG,eAAe;AAE3C,MAAMJ,MAAM,GAAGF,uBAAU,CAACO,MAAM,CAAC;EAC/BJ,OAAO,EAAE;IACPK,WAAW,EAAE;EACf;AACF,CAAC,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["_surfaceSolid","require"],"sourceRoot":"../../../src","sources":["tab-bar/surface.tsx"],"mappings":";;;;;;;;;;;AA2BA,IAAAA,aAAA,GAAAC,OAAA","ignoreList":[]}
@@ -7,13 +7,15 @@ exports.TabBarSurface = TabBarSurface;
7
7
  var _expoGlassEffect = require("expo-glass-effect");
8
8
  var _reactNative = require("react-native");
9
9
  var _reactNativeReanimated = _interopRequireDefault(require("react-native-reanimated"));
10
+ var _surfaceSolid = require("./surface-solid.js");
10
11
  var _jsxRuntime = require("react/jsx-runtime");
11
12
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
12
13
  /**
13
14
  * Ported from expo-glass-tabs v0.1.1 — src/glass-tab-bar.tsx
14
15
  * (MIT © 2026 David Mokos). See the top-level NOTICE.
15
16
  *
16
- * NATIVE variant of the tab bar's capsule surface — real liquid glass.
17
+ * NATIVE variant of the tab bar's capsule surface — real liquid glass, degrading
18
+ * to the solid surface whenever the glass is not actually usable.
17
19
  *
18
20
  * `expo-glass-effect` is imported STATICALLY and this file is the only place it
19
21
  * appears: Metro selects `.native` on iOS/Android, so the import never reaches
@@ -25,15 +27,71 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
25
27
  *
26
28
  * `isLiquidGlassAvailable()` is false on Android and pre-iOS-26, where the
27
29
  * package's `GlassView` has no material to render; those platforms get the same
28
- * opaque fallback the neutral variant paints.
30
+ * opaque fallback the neutral variant paints. "Installed" is not "usable"
31
+ * though, and BOTH remaining hazards sit at MODULE scope, which is why neither
32
+ * can be handled by a branch inside the component:
33
+ *
34
+ * 1. THE NATIVE MODULE. On iOS `isLiquidGlassAvailable()` resolves
35
+ * `ExpoGlassEffect` through `requireNativeModule`, which THROWS
36
+ * `Cannot find native module …` by contract when that module is not in the
37
+ * binary. For these apps it is a normal deploy state rather than a
38
+ * misconfiguration: an OTA JS update can land on a binary built before the
39
+ * package was linked, while the JS side always resolves because expo-router
40
+ * depends on it. Unguarded, the throw escapes render and takes down the whole
41
+ * screen the bar is on.
42
+ * 2. THE EXPORTS. `Animated.createAnimatedComponent(GlassView)` runs at IMPORT
43
+ * time, so a tree that resolves the specifier to something without
44
+ * `GlassView` hands React an `undefined` element type before any render
45
+ * happens.
46
+ *
47
+ * `isGlassEffectAPIAvailable()` is upstream's own third condition: on some iOS 26
48
+ * betas `UIGlassEffect` is missing and touching `GlassView` crashes NATIVELY,
49
+ * below JS (expo/expo#40911). It first shipped in expo-glass-effect 0.1.9, which is
50
+ * exactly why the peer floor is `>=0.1.9`: this file imports the symbol STATICALLY,
51
+ * and a floor predating it would be the same incoherence as declaring a
52
+ * statically-imported package optional. The `typeof` guard below is still not
53
+ * redundant — a peer range only WARNS, so a consumer can resolve an older copy
54
+ * anyway. A missing probe therefore means "not applicable", never "unavailable";
55
+ * reading it the other way would delete the glass look from every working device.
56
+ *
57
+ * Everything that fails routes to the SAME solid surface Android already paints —
58
+ * the intended fallback path, not a new one.
29
59
  */
30
60
 
31
- const AnimatedGlassView = _reactNativeReanimated.default.createAnimatedComponent(_expoGlassEffect.GlassView);
61
+ /**
62
+ * The animated glass view, or `null` when the package did not deliver the two
63
+ * exports this file needs. Built once, and guarded HERE rather than in the
64
+ * component because `createAnimatedComponent` runs on import (hazard 2 above).
65
+ */const AnimatedGlassView = Boolean(_expoGlassEffect.GlassView) && typeof _expoGlassEffect.isLiquidGlassAvailable === 'function' ? _reactNativeReanimated.default.createAnimatedComponent(_expoGlassEffect.GlassView) : null;
66
+
67
+ /** Memo for {@link glassIsUsable} — the answer cannot change within a session. */
68
+ let glassUsable;
69
+
70
+ /**
71
+ * Whether this build can really render glass. Probed once: the native lookup
72
+ * behind it is not free, and on the failing path it throws.
73
+ *
74
+ * The `catch` reports rather than swallows. A bar that silently painted itself
75
+ * opaque on every iOS device would be far more expensive to find than one warning
76
+ * line, and reaching this branch always means a real, fixable packaging mistake.
77
+ * Warning exactly once falls out of the memo — the body runs at most one time.
78
+ */
79
+ function glassIsUsable() {
80
+ if (glassUsable !== undefined) return glassUsable;
81
+ try {
82
+ glassUsable = (0, _expoGlassEffect.isLiquidGlassAvailable)() && (typeof _expoGlassEffect.isGlassEffectAPIAvailable !== 'function' || (0, _expoGlassEffect.isGlassEffectAPIAvailable)());
83
+ } catch (error) {
84
+ glassUsable = false;
85
+ // eslint-disable-next-line no-console
86
+ console.warn('[Bloom] TabBar: expo-glass-effect could not report liquid-glass availability, ' + 'so the bar is painting its solid surface. Install expo-glass-effect and ' + 'rebuild the native app to get the glass capsule.', error);
87
+ }
88
+ return glassUsable;
89
+ }
32
90
  function TabBarSurface({
33
91
  theme,
34
92
  style
35
93
  }) {
36
- if ((0, _expoGlassEffect.isLiquidGlassAvailable)()) {
94
+ if (AnimatedGlassView !== null && glassIsUsable()) {
37
95
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(AnimatedGlassView, {
38
96
  glassEffectStyle: "regular",
39
97
  style: [_reactNative.StyleSheet.absoluteFill, styles.surface, {
@@ -41,10 +99,9 @@ function TabBarSurface({
41
99
  }, style]
42
100
  });
43
101
  }
44
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeReanimated.default.View, {
45
- style: [_reactNative.StyleSheet.absoluteFill, styles.surface, {
46
- backgroundColor: theme.solidFallback
47
- }, style]
102
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_surfaceSolid.SolidTabBarSurface, {
103
+ theme: theme,
104
+ style: style
48
105
  });
49
106
  }
50
107
  TabBarSurface.displayName = 'TabBarSurface';
@@ -1 +1 @@
1
- {"version":3,"names":["_expoGlassEffect","require","_reactNative","_reactNativeReanimated","_interopRequireDefault","_jsxRuntime","e","__esModule","default","AnimatedGlassView","Animated","createAnimatedComponent","GlassView","TabBarSurface","theme","style","isLiquidGlassAvailable","jsx","glassEffectStyle","StyleSheet","absoluteFill","styles","surface","backgroundColor","glassTint","View","solidFallback","displayName","create","borderCurve"],"sourceRoot":"../../../src","sources":["tab-bar/surface.native.tsx"],"mappings":";;;;;;AAkBA,IAAAA,gBAAA,GAAAC,OAAA;AACA,IAAAC,YAAA,GAAAD,OAAA;AACA,IAAAE,sBAAA,GAAAC,sBAAA,CAAAH,OAAA;AAA+C,IAAAI,WAAA,GAAAJ,OAAA;AAAA,SAAAG,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AApB/C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAOA,MAAMG,iBAAiB,GAAGC,8BAAQ,CAACC,uBAAuB,CAACC,0BAAS,CAAC;AAE9D,SAASC,aAAaA,CAAC;EAAEC,KAAK;EAAEC;AAA0B,CAAC,EAAE;EAClE,IAAI,IAAAC,uCAAsB,EAAC,CAAC,EAAE;IAC5B,oBACE,IAAAX,WAAA,CAAAY,GAAA,EAACR,iBAAiB;MAChBS,gBAAgB,EAAC,SAAS;MAC1BH,KAAK,EAAE,CACLI,uBAAU,CAACC,YAAY,EACvBC,MAAM,CAACC,OAAO,EACd;QAAEC,eAAe,EAAET,KAAK,CAACU;MAAU,CAAC,EACpCT,KAAK;IACL,CACH,CAAC;EAEN;EAEA,oBACE,IAAAV,WAAA,CAAAY,GAAA,EAACd,sBAAA,CAAAK,OAAQ,CAACiB,IAAI;IACZV,KAAK,EAAE,CACLI,uBAAU,CAACC,YAAY,EACvBC,MAAM,CAACC,OAAO,EACd;MAAEC,eAAe,EAAET,KAAK,CAACY;IAAc,CAAC,EACxCX,KAAK;EACL,CACH,CAAC;AAEN;AAEAF,aAAa,CAACc,WAAW,GAAG,eAAe;AAE3C,MAAMN,MAAM,GAAGF,uBAAU,CAACS,MAAM,CAAC;EAC/BN,OAAO,EAAE;IACPO,WAAW,EAAE;EACf;AACF,CAAC,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["_expoGlassEffect","require","_reactNative","_reactNativeReanimated","_interopRequireDefault","_surfaceSolid","_jsxRuntime","e","__esModule","default","AnimatedGlassView","Boolean","GlassView","isLiquidGlassAvailable","Animated","createAnimatedComponent","glassUsable","glassIsUsable","undefined","isGlassEffectAPIAvailable","error","console","warn","TabBarSurface","theme","style","jsx","glassEffectStyle","StyleSheet","absoluteFill","styles","surface","backgroundColor","glassTint","SolidTabBarSurface","displayName","create","borderCurve"],"sourceRoot":"../../../src","sources":["tab-bar/surface.native.tsx"],"mappings":";;;;;;AA+CA,IAAAA,gBAAA,GAAAC,OAAA;AACA,IAAAC,YAAA,GAAAD,OAAA;AACA,IAAAE,sBAAA,GAAAC,sBAAA,CAAAH,OAAA;AAGA,IAAAI,aAAA,GAAAJ,OAAA;AAAqD,IAAAK,WAAA,GAAAL,OAAA;AAAA,SAAAG,uBAAAG,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AApDrD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAQA;AACA;AACA;AACA;AACA,GACA,MAAMG,iBAAiB,GACrBC,OAAO,CAACC,0BAAS,CAAC,IAAI,OAAOC,uCAAsB,KAAK,UAAU,GAC9DC,8BAAQ,CAACC,uBAAuB,CAACH,0BAAS,CAAC,GAC3C,IAAI;;AAEV;AACA,IAAII,WAAgC;;AAEpC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASC,aAAaA,CAAA,EAAY;EAChC,IAAID,WAAW,KAAKE,SAAS,EAAE,OAAOF,WAAW;EAEjD,IAAI;IACFA,WAAW,GACT,IAAAH,uCAAsB,EAAC,CAAC,KACvB,OAAOM,0CAAyB,KAAK,UAAU,IAAI,IAAAA,0CAAyB,EAAC,CAAC,CAAC;EACpF,CAAC,CAAC,OAAOC,KAAK,EAAE;IACdJ,WAAW,GAAG,KAAK;IACnB;IACAK,OAAO,CAACC,IAAI,CACV,gFAAgF,GAC9E,0EAA0E,GAC1E,kDAAkD,EACpDF,KACF,CAAC;EACH;EAEA,OAAOJ,WAAW;AACpB;AAEO,SAASO,aAAaA,CAAC;EAAEC,KAAK;EAAEC;AAA0B,CAAC,EAAE;EAClE,IAAIf,iBAAiB,KAAK,IAAI,IAAIO,aAAa,CAAC,CAAC,EAAE;IACjD,oBACE,IAAAX,WAAA,CAAAoB,GAAA,EAAChB,iBAAiB;MAChBiB,gBAAgB,EAAC,SAAS;MAC1BF,KAAK,EAAE,CACLG,uBAAU,CAACC,YAAY,EACvBC,MAAM,CAACC,OAAO,EACd;QAAEC,eAAe,EAAER,KAAK,CAACS;MAAU,CAAC,EACpCR,KAAK;IACL,CACH,CAAC;EAEN;EAEA,oBAAO,IAAAnB,WAAA,CAAAoB,GAAA,EAACrB,aAAA,CAAA6B,kBAAkB;IAACV,KAAK,EAAEA,KAAM;IAACC,KAAK,EAAEA;EAAM,CAAE,CAAC;AAC3D;AAEAF,aAAa,CAACY,WAAW,GAAG,eAAe;AAE3C,MAAML,MAAM,GAAGF,uBAAU,CAACQ,MAAM,CAAC;EAC/BL,OAAO,EAAE;IACPM,WAAW,EAAE;EACf;AACF,CAAC,CAAC","ignoreList":[]}
@@ -92,7 +92,7 @@ export function resolveFrostedPalette(colors, isDark) {
92
92
  * Inject `color` as the icon's `fill` — but only as a FALLBACK: if the caller
93
93
  * already set an explicit `fill` on the icon element, it wins and the node is
94
94
  * returned untouched. Bloom icons resolve their paint as `fill ?? style.color`,
95
- * so a bare `<Icons.X />` gets the theme-aware color for free while an
95
+ * so any bare Bloom icon element gets the theme-aware color for free while an
96
96
  * explicitly-colored icon is never overridden. Non-element children (plain
97
97
  * text/strings) pass through unchanged.
98
98
  */
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * Ported from expo-glass-tabs v0.1.1 — src/glass-tab-bar.tsx
5
+ * (MIT © 2026 David Mokos). See the top-level NOTICE.
6
+ *
7
+ * The tab bar's NON-GLASS capsule surface: a plain animated view filled with the
8
+ * theme's near-opaque fallback. Android, pre-iOS-26 devices and any build without
9
+ * a usable `expo-glass-effect` all paint this.
10
+ *
11
+ * It lives in its own module because TWO variants render it and one of them
12
+ * cannot reach the other: Metro resolves a bare `./surface` to
13
+ * `surface.native.tsx` no matter which file asks, so `surface.native.tsx`
14
+ * importing its neutral sibling for the fallback would import ITSELF. A name with
15
+ * no platform variants resolves to this one file everywhere — which is the whole
16
+ * point, so please do not fold it back into `surface.tsx`.
17
+ */
18
+ import { StyleSheet } from 'react-native';
19
+ import Animated from 'react-native-reanimated';
20
+ import { jsx as _jsx } from "react/jsx-runtime";
21
+ export function SolidTabBarSurface({
22
+ theme,
23
+ style
24
+ }) {
25
+ return /*#__PURE__*/_jsx(Animated.View, {
26
+ style: [StyleSheet.absoluteFill, styles.surface, {
27
+ backgroundColor: theme.solidFallback
28
+ }, style]
29
+ });
30
+ }
31
+ SolidTabBarSurface.displayName = 'SolidTabBarSurface';
32
+ const styles = StyleSheet.create({
33
+ surface: {
34
+ borderCurve: 'continuous'
35
+ }
36
+ });
37
+ //# sourceMappingURL=surface-solid.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["StyleSheet","Animated","jsx","_jsx","SolidTabBarSurface","theme","style","View","absoluteFill","styles","surface","backgroundColor","solidFallback","displayName","create","borderCurve"],"sourceRoot":"../../../src","sources":["tab-bar/surface-solid.tsx"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASA,UAAU,QAAQ,cAAc;AACzC,OAAOC,QAAQ,MAAM,yBAAyB;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAI/C,OAAO,SAASC,kBAAkBA,CAAC;EAAEC,KAAK;EAAEC;AAA0B,CAAC,EAAE;EACvE,oBACEH,IAAA,CAACF,QAAQ,CAACM,IAAI;IACZD,KAAK,EAAE,CACLN,UAAU,CAACQ,YAAY,EACvBC,MAAM,CAACC,OAAO,EACd;MAAEC,eAAe,EAAEN,KAAK,CAACO;IAAc,CAAC,EACxCN,KAAK;EACL,CACH,CAAC;AAEN;AAEAF,kBAAkB,CAACS,WAAW,GAAG,oBAAoB;AAErD,MAAMJ,MAAM,GAAGT,UAAU,CAACc,MAAM,CAAC;EAC/BJ,OAAO,EAAE;IACPK,WAAW,EAAE;EACf;AACF,CAAC,CAAC","ignoreList":[]}
@@ -4,8 +4,7 @@
4
4
  * Ported from expo-glass-tabs v0.1.1 — src/glass-tab-bar.tsx
5
5
  * (MIT © 2026 David Mokos). See the top-level NOTICE.
6
6
  *
7
- * NEUTRAL default variant of the tab bar's capsule surface: a plain animated
8
- * view filled with the theme's solid fallback.
7
+ * NEUTRAL default variant of the tab bar's capsule surface: the non-glass one.
9
8
  *
10
9
  * This is the file resolved by everything that does NOT do React Native's
11
10
  * platform-extension resolution — a consumer's `tsc` (which follows Bloom's
@@ -16,29 +15,17 @@
16
15
  * resolution outright. Same three-way split, for the same reason, as
17
16
  * `theme/native-root-vars{,.native,.web}.ts`.
18
17
  *
18
+ * The surface itself lives in `surface-solid.tsx`, because `surface.native.tsx`
19
+ * renders it as its own fallback and cannot import this file to get it — Metro
20
+ * resolves `./surface` back to `surface.native.tsx`, i.e. to itself. This module's
21
+ * job is to give that one implementation the name every entry module imports.
22
+ *
19
23
  * The variants — all three implement `TabBarSurfaceProps` exactly, so the entry
20
24
  * modules can swap them freely:
21
- * - `surface.native.tsx` — iOS/Android (Metro), real `UIGlassEffect` glass;
25
+ * - `surface.native.tsx` — iOS/Android (Metro), real `UIGlassEffect` glass, with
26
+ * the solid surface as its fallback;
22
27
  * - `surface.web.tsx` — web, a CSS `backdrop-filter`;
23
- * - this file — everywhere else, the opaque fallback.
28
+ * - this file — everywhere else, the opaque fallback alone.
24
29
  */
25
- import { StyleSheet } from 'react-native';
26
- import Animated from 'react-native-reanimated';
27
- import { jsx as _jsx } from "react/jsx-runtime";
28
- export function TabBarSurface({
29
- theme,
30
- style
31
- }) {
32
- return /*#__PURE__*/_jsx(Animated.View, {
33
- style: [StyleSheet.absoluteFill, styles.surface, {
34
- backgroundColor: theme.solidFallback
35
- }, style]
36
- });
37
- }
38
- TabBarSurface.displayName = 'TabBarSurface';
39
- const styles = StyleSheet.create({
40
- surface: {
41
- borderCurve: 'continuous'
42
- }
43
- });
30
+ export { SolidTabBarSurface as TabBarSurface } from "./surface-solid.js";
44
31
  //# sourceMappingURL=surface.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["StyleSheet","Animated","jsx","_jsx","TabBarSurface","theme","style","View","absoluteFill","styles","surface","backgroundColor","solidFallback","displayName","create","borderCurve"],"sourceRoot":"../../../src","sources":["tab-bar/surface.tsx"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASA,UAAU,QAAQ,cAAc;AACzC,OAAOC,QAAQ,MAAM,yBAAyB;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAI/C,OAAO,SAASC,aAAaA,CAAC;EAAEC,KAAK;EAAEC;AAA0B,CAAC,EAAE;EAClE,oBACEH,IAAA,CAACF,QAAQ,CAACM,IAAI;IACZD,KAAK,EAAE,CACLN,UAAU,CAACQ,YAAY,EACvBC,MAAM,CAACC,OAAO,EACd;MAAEC,eAAe,EAAEN,KAAK,CAACO;IAAc,CAAC,EACxCN,KAAK;EACL,CACH,CAAC;AAEN;AAEAF,aAAa,CAACS,WAAW,GAAG,eAAe;AAE3C,MAAMJ,MAAM,GAAGT,UAAU,CAACc,MAAM,CAAC;EAC/BJ,OAAO,EAAE;IACPK,WAAW,EAAE;EACf;AACF,CAAC,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["SolidTabBarSurface","TabBarSurface"],"sourceRoot":"../../../src","sources":["tab-bar/surface.tsx"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASA,kBAAkB,IAAIC,aAAa,QAAQ,oBAAiB","ignoreList":[]}
@@ -4,7 +4,8 @@
4
4
  * Ported from expo-glass-tabs v0.1.1 — src/glass-tab-bar.tsx
5
5
  * (MIT © 2026 David Mokos). See the top-level NOTICE.
6
6
  *
7
- * NATIVE variant of the tab bar's capsule surface — real liquid glass.
7
+ * NATIVE variant of the tab bar's capsule surface — real liquid glass, degrading
8
+ * to the solid surface whenever the glass is not actually usable.
8
9
  *
9
10
  * `expo-glass-effect` is imported STATICALLY and this file is the only place it
10
11
  * appears: Metro selects `.native` on iOS/Android, so the import never reaches
@@ -16,18 +17,77 @@
16
17
  *
17
18
  * `isLiquidGlassAvailable()` is false on Android and pre-iOS-26, where the
18
19
  * package's `GlassView` has no material to render; those platforms get the same
19
- * opaque fallback the neutral variant paints.
20
+ * opaque fallback the neutral variant paints. "Installed" is not "usable"
21
+ * though, and BOTH remaining hazards sit at MODULE scope, which is why neither
22
+ * can be handled by a branch inside the component:
23
+ *
24
+ * 1. THE NATIVE MODULE. On iOS `isLiquidGlassAvailable()` resolves
25
+ * `ExpoGlassEffect` through `requireNativeModule`, which THROWS
26
+ * `Cannot find native module …` by contract when that module is not in the
27
+ * binary. For these apps it is a normal deploy state rather than a
28
+ * misconfiguration: an OTA JS update can land on a binary built before the
29
+ * package was linked, while the JS side always resolves because expo-router
30
+ * depends on it. Unguarded, the throw escapes render and takes down the whole
31
+ * screen the bar is on.
32
+ * 2. THE EXPORTS. `Animated.createAnimatedComponent(GlassView)` runs at IMPORT
33
+ * time, so a tree that resolves the specifier to something without
34
+ * `GlassView` hands React an `undefined` element type before any render
35
+ * happens.
36
+ *
37
+ * `isGlassEffectAPIAvailable()` is upstream's own third condition: on some iOS 26
38
+ * betas `UIGlassEffect` is missing and touching `GlassView` crashes NATIVELY,
39
+ * below JS (expo/expo#40911). It first shipped in expo-glass-effect 0.1.9, which is
40
+ * exactly why the peer floor is `>=0.1.9`: this file imports the symbol STATICALLY,
41
+ * and a floor predating it would be the same incoherence as declaring a
42
+ * statically-imported package optional. The `typeof` guard below is still not
43
+ * redundant — a peer range only WARNS, so a consumer can resolve an older copy
44
+ * anyway. A missing probe therefore means "not applicable", never "unavailable";
45
+ * reading it the other way would delete the glass look from every working device.
46
+ *
47
+ * Everything that fails routes to the SAME solid surface Android already paints —
48
+ * the intended fallback path, not a new one.
20
49
  */
21
- import { GlassView, isLiquidGlassAvailable } from 'expo-glass-effect';
50
+ import { GlassView, isGlassEffectAPIAvailable, isLiquidGlassAvailable } from 'expo-glass-effect';
22
51
  import { StyleSheet } from 'react-native';
23
52
  import Animated from 'react-native-reanimated';
53
+ import { SolidTabBarSurface } from "./surface-solid.js";
54
+
55
+ /**
56
+ * The animated glass view, or `null` when the package did not deliver the two
57
+ * exports this file needs. Built once, and guarded HERE rather than in the
58
+ * component because `createAnimatedComponent` runs on import (hazard 2 above).
59
+ */
24
60
  import { jsx as _jsx } from "react/jsx-runtime";
25
- const AnimatedGlassView = Animated.createAnimatedComponent(GlassView);
61
+ const AnimatedGlassView = Boolean(GlassView) && typeof isLiquidGlassAvailable === 'function' ? Animated.createAnimatedComponent(GlassView) : null;
62
+
63
+ /** Memo for {@link glassIsUsable} — the answer cannot change within a session. */
64
+ let glassUsable;
65
+
66
+ /**
67
+ * Whether this build can really render glass. Probed once: the native lookup
68
+ * behind it is not free, and on the failing path it throws.
69
+ *
70
+ * The `catch` reports rather than swallows. A bar that silently painted itself
71
+ * opaque on every iOS device would be far more expensive to find than one warning
72
+ * line, and reaching this branch always means a real, fixable packaging mistake.
73
+ * Warning exactly once falls out of the memo — the body runs at most one time.
74
+ */
75
+ function glassIsUsable() {
76
+ if (glassUsable !== undefined) return glassUsable;
77
+ try {
78
+ glassUsable = isLiquidGlassAvailable() && (typeof isGlassEffectAPIAvailable !== 'function' || isGlassEffectAPIAvailable());
79
+ } catch (error) {
80
+ glassUsable = false;
81
+ // eslint-disable-next-line no-console
82
+ console.warn('[Bloom] TabBar: expo-glass-effect could not report liquid-glass availability, ' + 'so the bar is painting its solid surface. Install expo-glass-effect and ' + 'rebuild the native app to get the glass capsule.', error);
83
+ }
84
+ return glassUsable;
85
+ }
26
86
  export function TabBarSurface({
27
87
  theme,
28
88
  style
29
89
  }) {
30
- if (isLiquidGlassAvailable()) {
90
+ if (AnimatedGlassView !== null && glassIsUsable()) {
31
91
  return /*#__PURE__*/_jsx(AnimatedGlassView, {
32
92
  glassEffectStyle: "regular",
33
93
  style: [StyleSheet.absoluteFill, styles.surface, {
@@ -35,10 +95,9 @@ export function TabBarSurface({
35
95
  }, style]
36
96
  });
37
97
  }
38
- return /*#__PURE__*/_jsx(Animated.View, {
39
- style: [StyleSheet.absoluteFill, styles.surface, {
40
- backgroundColor: theme.solidFallback
41
- }, style]
98
+ return /*#__PURE__*/_jsx(SolidTabBarSurface, {
99
+ theme: theme,
100
+ style: style
42
101
  });
43
102
  }
44
103
  TabBarSurface.displayName = 'TabBarSurface';
@@ -1 +1 @@
1
- {"version":3,"names":["GlassView","isLiquidGlassAvailable","StyleSheet","Animated","jsx","_jsx","AnimatedGlassView","createAnimatedComponent","TabBarSurface","theme","style","glassEffectStyle","absoluteFill","styles","surface","backgroundColor","glassTint","View","solidFallback","displayName","create","borderCurve"],"sourceRoot":"../../../src","sources":["tab-bar/surface.native.tsx"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASA,SAAS,EAAEC,sBAAsB,QAAQ,mBAAmB;AACrE,SAASC,UAAU,QAAQ,cAAc;AACzC,OAAOC,QAAQ,MAAM,yBAAyB;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAI/C,MAAMC,iBAAiB,GAAGH,QAAQ,CAACI,uBAAuB,CAACP,SAAS,CAAC;AAErE,OAAO,SAASQ,aAAaA,CAAC;EAAEC,KAAK;EAAEC;AAA0B,CAAC,EAAE;EAClE,IAAIT,sBAAsB,CAAC,CAAC,EAAE;IAC5B,oBACEI,IAAA,CAACC,iBAAiB;MAChBK,gBAAgB,EAAC,SAAS;MAC1BD,KAAK,EAAE,CACLR,UAAU,CAACU,YAAY,EACvBC,MAAM,CAACC,OAAO,EACd;QAAEC,eAAe,EAAEN,KAAK,CAACO;MAAU,CAAC,EACpCN,KAAK;IACL,CACH,CAAC;EAEN;EAEA,oBACEL,IAAA,CAACF,QAAQ,CAACc,IAAI;IACZP,KAAK,EAAE,CACLR,UAAU,CAACU,YAAY,EACvBC,MAAM,CAACC,OAAO,EACd;MAAEC,eAAe,EAAEN,KAAK,CAACS;IAAc,CAAC,EACxCR,KAAK;EACL,CACH,CAAC;AAEN;AAEAF,aAAa,CAACW,WAAW,GAAG,eAAe;AAE3C,MAAMN,MAAM,GAAGX,UAAU,CAACkB,MAAM,CAAC;EAC/BN,OAAO,EAAE;IACPO,WAAW,EAAE;EACf;AACF,CAAC,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["GlassView","isGlassEffectAPIAvailable","isLiquidGlassAvailable","StyleSheet","Animated","SolidTabBarSurface","jsx","_jsx","AnimatedGlassView","Boolean","createAnimatedComponent","glassUsable","glassIsUsable","undefined","error","console","warn","TabBarSurface","theme","style","glassEffectStyle","absoluteFill","styles","surface","backgroundColor","glassTint","displayName","create","borderCurve"],"sourceRoot":"../../../src","sources":["tab-bar/surface.native.tsx"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASA,SAAS,EAAEC,yBAAyB,EAAEC,sBAAsB,QAAQ,mBAAmB;AAChG,SAASC,UAAU,QAAQ,cAAc;AACzC,OAAOC,QAAQ,MAAM,yBAAyB;AAG9C,SAASC,kBAAkB,QAAQ,oBAAiB;;AAEpD;AACA;AACA;AACA;AACA;AAJA,SAAAC,GAAA,IAAAC,IAAA;AAKA,MAAMC,iBAAiB,GACrBC,OAAO,CAACT,SAAS,CAAC,IAAI,OAAOE,sBAAsB,KAAK,UAAU,GAC9DE,QAAQ,CAACM,uBAAuB,CAACV,SAAS,CAAC,GAC3C,IAAI;;AAEV;AACA,IAAIW,WAAgC;;AAEpC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASC,aAAaA,CAAA,EAAY;EAChC,IAAID,WAAW,KAAKE,SAAS,EAAE,OAAOF,WAAW;EAEjD,IAAI;IACFA,WAAW,GACTT,sBAAsB,CAAC,CAAC,KACvB,OAAOD,yBAAyB,KAAK,UAAU,IAAIA,yBAAyB,CAAC,CAAC,CAAC;EACpF,CAAC,CAAC,OAAOa,KAAK,EAAE;IACdH,WAAW,GAAG,KAAK;IACnB;IACAI,OAAO,CAACC,IAAI,CACV,gFAAgF,GAC9E,0EAA0E,GAC1E,kDAAkD,EACpDF,KACF,CAAC;EACH;EAEA,OAAOH,WAAW;AACpB;AAEA,OAAO,SAASM,aAAaA,CAAC;EAAEC,KAAK;EAAEC;AAA0B,CAAC,EAAE;EAClE,IAAIX,iBAAiB,KAAK,IAAI,IAAII,aAAa,CAAC,CAAC,EAAE;IACjD,oBACEL,IAAA,CAACC,iBAAiB;MAChBY,gBAAgB,EAAC,SAAS;MAC1BD,KAAK,EAAE,CACLhB,UAAU,CAACkB,YAAY,EACvBC,MAAM,CAACC,OAAO,EACd;QAAEC,eAAe,EAAEN,KAAK,CAACO;MAAU,CAAC,EACpCN,KAAK;IACL,CACH,CAAC;EAEN;EAEA,oBAAOZ,IAAA,CAACF,kBAAkB;IAACa,KAAK,EAAEA,KAAM;IAACC,KAAK,EAAEA;EAAM,CAAE,CAAC;AAC3D;AAEAF,aAAa,CAACS,WAAW,GAAG,eAAe;AAE3C,MAAMJ,MAAM,GAAGnB,UAAU,CAACwB,MAAM,CAAC;EAC/BJ,OAAO,EAAE;IACPK,WAAW,EAAE;EACf;AACF,CAAC,CAAC","ignoreList":[]}
@@ -3,7 +3,8 @@ import type { StyleProp, TextStyle, ViewStyle } from 'react-native';
3
3
  export interface BenefitRowProps {
4
4
  /**
5
5
  * Leading icon — rendered inside a rounded `fill-secondary` square. Pass a
6
- * Bloom icon element (e.g. `<Icons.Lock size="sm" />`) or any node.
6
+ * Bloom icon element (e.g. `<Icons.Lock_Stroke2_Corner0_Rounded size="sm" />`,
7
+ * suffix included — there is no shortened alias) or any node.
7
8
  */
8
9
  icon: ReactNode;
9
10
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/benefit-list/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEpE,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,IAAI,EAAE,SAAS,CAAC;IAChB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,sEAAsE;IACtE,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8CAA8C;IAC9C,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,6CAA6C;IAC7C,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,gBAAgB;IAC/B,oEAAoE;IACpE,QAAQ,EAAE,SAAS,CAAC;IACpB,wCAAwC;IACxC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+CAA+C;IAC/C,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAC9B"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/benefit-list/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEpE,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,IAAI,EAAE,SAAS,CAAC;IAChB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,sEAAsE;IACtE,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8CAA8C;IAC9C,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,6CAA6C;IAC7C,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,gBAAgB;IAC/B,oEAAoE;IACpE,QAAQ,EAAE,SAAS,CAAC;IACpB,wCAAwC;IACxC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+CAA+C;IAC/C,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAC9B"}
@@ -53,8 +53,10 @@ export interface FabProps {
53
53
  onPress?: () => void;
54
54
  /**
55
55
  * The icon to render inside the FAB. Typically a Bloom icon element
56
- * (`<Icons.Plus .../>`). For an icon-only FAB this is the whole content; for
57
- * the extended variant it sits to the left of the `label`.
56
+ * (`<Icons.PlusLarge_Stroke2_Corner0_Rounded />` icon exports carry their full
57
+ * style and corner suffix, and there is no shortened alias). For an icon-only
58
+ * FAB this is the whole content; for the extended variant it sits to the left of
59
+ * the `label`.
58
60
  *
59
61
  * `children` is accepted as an alias/override of `icon` for ergonomics — if
60
62
  * both are given, `icon` wins and `children` is ignored.
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/fab/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEpE;;;;;;;;GAQG;AACH,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC;AAE7D;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEnD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,MAAM,YAAY,GACpB,cAAc,GACd,aAAa,GACb,WAAW,GACX,UAAU,GACV,QAAQ,CAAC;AAEb,MAAM,WAAW,QAAQ;IACvB,qBAAqB;IACrB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IAErB;;;;;;;OAOG;IACH,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAE3B;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,OAAO,CAAC,EAAE,UAAU,CAAC;IACrB;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAExB;;;;OAIG;IACH,SAAS,CAAC,EAAE,YAAY,CAAC;IAEzB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,yEAAyE;IACzE,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,8CAA8C;IAC9C,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,8CAA8C;IAC9C,UAAU,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAClC,8CAA8C;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAUhB,wDAAwD;IACxD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;IAC/D,mEAAmE;IACnE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4CAA4C;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kCAAkC;IAClC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,6DAA6D;IAC7D,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;CACtC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/fab/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEpE;;;;;;;;GAQG;AACH,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC;AAE7D;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEnD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,MAAM,YAAY,GACpB,cAAc,GACd,aAAa,GACb,WAAW,GACX,UAAU,GACV,QAAQ,CAAC;AAEb,MAAM,WAAW,QAAQ;IACvB,qBAAqB;IACrB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IAErB;;;;;;;;;OASG;IACH,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAE3B;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,OAAO,CAAC,EAAE,UAAU,CAAC;IACrB;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAExB;;;;OAIG;IACH,SAAS,CAAC,EAAE,YAAY,CAAC;IAEzB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,yEAAyE;IACzE,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,8CAA8C;IAC9C,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,8CAA8C;IAC9C,UAAU,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAClC,8CAA8C;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAUhB,wDAAwD;IACxD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;IAC/D,mEAAmE;IACnE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4CAA4C;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kCAAkC;IAClC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,6DAA6D;IAC7D,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;CACtC"}
@@ -52,7 +52,7 @@ export declare function resolveFrostedPalette(colors: ThemeColors, isDark: boole
52
52
  * Inject `color` as the icon's `fill` — but only as a FALLBACK: if the caller
53
53
  * already set an explicit `fill` on the icon element, it wins and the node is
54
54
  * returned untouched. Bloom icons resolve their paint as `fill ?? style.color`,
55
- * so a bare `<Icons.X />` gets the theme-aware color for free while an
55
+ * so any bare Bloom icon element gets the theme-aware color for free while an
56
56
  * explicitly-colored icon is never overridden. Non-element children (plain
57
57
  * text/strings) pass through unchanged.
58
58
  */
@@ -15,7 +15,8 @@ export interface FrostedIconButtonProps {
15
15
  onPress?: () => void;
16
16
  /**
17
17
  * The icon to render, centered inside the circle. Typically a Bloom icon
18
- * element (`<Icons.ArrowLeft… />`). If the icon does not set its own `fill`,
18
+ * element (`<Icons.ArrowLeft_Stroke2_Corner0_Rounded />` icon exports carry
19
+ * their full style and corner suffix). If the icon does not set its own `fill`,
19
20
  * the button injects the theme-aware icon color (foreground when frosted,
20
21
  * `primaryForeground` when `active`) as a fallback so a bare icon is colored
21
22
  * correctly out of the box; an explicit `fill` on the icon always wins.
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/frosted-icon-button/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzD;;;;;;;;;GASG;AACH,MAAM,MAAM,qBAAqB,GAAG,IAAI,GAAG,IAAI,CAAC;AAEhD,MAAM,WAAW,sBAAsB;IACrC,qBAAqB;IACrB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IAErB;;;;;;;;OAQG;IACH,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAE3B;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;OAGG;IACH,IAAI,CAAC,EAAE,qBAAqB,GAAG,MAAM,CAAC;IAEtC,4EAA4E;IAC5E,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,8CAA8C;IAC9C,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,8CAA8C;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,OAAO,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAUvE,wDAAwD;IACxD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;IAC/D,mEAAmE;IACnE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4CAA4C;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kCAAkC;IAClC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,6DAA6D;IAC7D,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;CACtC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/frosted-icon-button/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzD;;;;;;;;;GASG;AACH,MAAM,MAAM,qBAAqB,GAAG,IAAI,GAAG,IAAI,CAAC;AAEhD,MAAM,WAAW,sBAAsB;IACrC,qBAAqB;IACrB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IAErB;;;;;;;;;OASG;IACH,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAE3B;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;OAGG;IACH,IAAI,CAAC,EAAE,qBAAqB,GAAG,MAAM,CAAC;IAEtC,4EAA4E;IAC5E,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,8CAA8C;IAC9C,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,8CAA8C;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,OAAO,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAUvE,wDAAwD;IACxD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;IAC/D,mEAAmE;IACnE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4CAA4C;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kCAAkC;IAClC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,6DAA6D;IAC7D,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;CACtC"}
@@ -0,0 +1,6 @@
1
+ import type { TabBarSurfaceProps } from './shared';
2
+ export declare function SolidTabBarSurface({ theme, style }: TabBarSurfaceProps): import("react/jsx-runtime").JSX.Element;
3
+ export declare namespace SolidTabBarSurface {
4
+ var displayName: string;
5
+ }
6
+ //# sourceMappingURL=surface-solid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surface-solid.d.ts","sourceRoot":"","sources":["../../../../src/tab-bar/surface-solid.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAEnD,wBAAgB,kBAAkB,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,kBAAkB,2CAWtE;yBAXe,kBAAkB"}
@@ -1,6 +1,29 @@
1
- import type { TabBarSurfaceProps } from './shared';
2
- export declare function TabBarSurface({ theme, style }: TabBarSurfaceProps): import("react/jsx-runtime").JSX.Element;
3
- export declare namespace TabBarSurface {
4
- var displayName: string;
5
- }
1
+ /**
2
+ * Ported from expo-glass-tabs v0.1.1 src/glass-tab-bar.tsx
3
+ * (MIT © 2026 David Mokos). See the top-level NOTICE.
4
+ *
5
+ * NEUTRAL default variant of the tab bar's capsule surface: the non-glass one.
6
+ *
7
+ * This is the file resolved by everything that does NOT do React Native's
8
+ * platform-extension resolution — a consumer's `tsc` (which follows Bloom's
9
+ * `"react-native"` source export condition) and any non-Metro bundler reading
10
+ * the published `lib/`. It therefore imports NOTHING platform-specific:
11
+ * `expo-glass-effect` is native-only, and a static import of it from a file a
12
+ * web bundler or a consumer's type-checker resolves would break module
13
+ * resolution outright. Same three-way split, for the same reason, as
14
+ * `theme/native-root-vars{,.native,.web}.ts`.
15
+ *
16
+ * The surface itself lives in `surface-solid.tsx`, because `surface.native.tsx`
17
+ * renders it as its own fallback and cannot import this file to get it — Metro
18
+ * resolves `./surface` back to `surface.native.tsx`, i.e. to itself. This module's
19
+ * job is to give that one implementation the name every entry module imports.
20
+ *
21
+ * The variants — all three implement `TabBarSurfaceProps` exactly, so the entry
22
+ * modules can swap them freely:
23
+ * - `surface.native.tsx` — iOS/Android (Metro), real `UIGlassEffect` glass, with
24
+ * the solid surface as its fallback;
25
+ * - `surface.web.tsx` — web, a CSS `backdrop-filter`;
26
+ * - this file — everywhere else, the opaque fallback alone.
27
+ */
28
+ export { SolidTabBarSurface as TabBarSurface } from './surface-solid';
6
29
  //# sourceMappingURL=surface.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"surface.d.ts","sourceRoot":"","sources":["../../../../src/tab-bar/surface.tsx"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAEnD,wBAAgB,aAAa,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,kBAAkB,2CAWjE;yBAXe,aAAa"}
1
+ {"version":3,"file":"surface.d.ts","sourceRoot":"","sources":["../../../../src/tab-bar/surface.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,EAAE,kBAAkB,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"surface.native.d.ts","sourceRoot":"","sources":["../../../../src/tab-bar/surface.native.tsx"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAInD,wBAAgB,aAAa,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,kBAAkB,2CAyBjE;yBAzBe,aAAa"}
1
+ {"version":3,"file":"surface.native.d.ts","sourceRoot":"","sources":["../../../../src/tab-bar/surface.native.tsx"],"names":[],"mappings":"AAmDA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AA8CnD,wBAAgB,aAAa,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,kBAAkB,2CAgBjE;yBAhBe,aAAa"}
@@ -18,9 +18,12 @@ export type TabBarItem = {
18
18
  /** Text under the icon; fades out and is clipped when the bar minimizes. */
19
19
  label: string;
20
20
  /**
21
- * The glyph, as a Bloom icon element (`<Icons.Home />`) or any node. This is
22
- * the primary icon API same convention as `Tabs`/`TabsTrigger` and
23
- * `FrostedIconButton`. The bar renders it TWICE (an inactive layer with the
21
+ * The glyph, as a Bloom icon element (`<Icons.Home_Stroke2_Corner0_Rounded />`)
22
+ * or any node. Every `@oxyhq/bloom/icons` export carries its full style and
23
+ * corner suffix; a shortened `Home` is not an export, and a name that does not
24
+ * exist is simply `undefined`, which React then rejects as an invalid element
25
+ * type. This is the primary icon API — same convention as `Tabs`/`TabsTrigger`
26
+ * and `FrostedIconButton`. The bar renders it TWICE (an inactive layer with the
24
27
  * active layer crossfading on top), injecting the layer's tint as the icon's
25
28
  * `fill` unless the element already sets one.
26
29
  */