jfs-components 0.0.69 → 0.0.70

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.
@@ -0,0 +1,47 @@
1
+ import { type ViewStyle, type StyleProp } from 'react-native';
2
+ export type GlassTint = 'dark' | 'light';
3
+ export interface GlassFillProps {
4
+ /**
5
+ * Visual tint of the glass surface. Maps to `BlurView`'s `blurType`
6
+ * (`'dark'` | `'light'`). The library also drives the appropriate
7
+ * `reducedTransparencyFallbackColor` from this so iOS gracefully degrades
8
+ * when "Reduce Transparency" is enabled in system accessibility settings.
9
+ */
10
+ tint?: GlassTint;
11
+ /**
12
+ * Blur strength as a 0–100 "intensity" value (kept compatible with the
13
+ * previous `expo-blur` API so consumers don't need to relearn the scale).
14
+ * Internally mapped to `@react-native-community/blur`'s `blurAmount`,
15
+ * which is roughly 0–32 on iOS / Android.
16
+ */
17
+ intensity?: number;
18
+ /**
19
+ * Token-derived color tint laid OVER the live blur (Figma `blur/minimal/background`).
20
+ * Painted as a translucent overlay so the glass keeps the design system
21
+ * color signature even when the platform blur quality varies.
22
+ */
23
+ overlayColor?: string;
24
+ /** Container style overrides. Defaults to `StyleSheet.absoluteFill`. */
25
+ style?: StyleProp<ViewStyle>;
26
+ }
27
+ /**
28
+ * Glass / frosted surface for native (iOS + Android).
29
+ *
30
+ * Why this lives in its own platform-split file:
31
+ * - `@react-native-community/blur` is a native-only module. Importing it on
32
+ * web throws because the JS shim references native components that aren't
33
+ * registered there. By using Metro's platform-extension resolution
34
+ * (`GlassFill.tsx` for native, `GlassFill.web.tsx` for web), we keep the
35
+ * web bundle free of any native-only imports.
36
+ * - Centralizes the `intensity` (0–100) -> `blurAmount` (0–32) mapping so
37
+ * callers can keep the Figma token semantics they already know.
38
+ *
39
+ * On iOS this is a real `UIVisualEffectView` (true OS-level live blur).
40
+ * On Android this uses the community blur view (RealtimeBlurView). On devices
41
+ * where realtime blur is unavailable, `reducedTransparencyFallbackColor` (and
42
+ * the explicit `overlayColor`) ensure the surface still renders as a
43
+ * translucent tinted scrim instead of disappearing.
44
+ */
45
+ declare function GlassFill({ tint, intensity, overlayColor, style, }: GlassFillProps): import("react/jsx-runtime").JSX.Element;
46
+ export default GlassFill;
47
+ //# sourceMappingURL=GlassFill.d.ts.map
@@ -0,0 +1,20 @@
1
+ import { type ViewStyle, type StyleProp } from 'react-native';
2
+ export type GlassTint = 'dark' | 'light';
3
+ export interface GlassFillProps {
4
+ tint?: GlassTint;
5
+ intensity?: number;
6
+ overlayColor?: string;
7
+ style?: StyleProp<ViewStyle>;
8
+ }
9
+ /**
10
+ * Web counterpart of `GlassFill`.
11
+ *
12
+ * `@react-native-community/blur` does not ship a web implementation, so for
13
+ * the web bundle we render a translucent `View` with `backdrop-filter: blur()`
14
+ * — which is exactly how 0.0.67 and earlier shipped the glass effect on web.
15
+ * Native bundles pick up `GlassFill.tsx` instead via Metro's platform
16
+ * resolver; the web bundle picks up this file.
17
+ */
18
+ declare function GlassFill({ tint, intensity, overlayColor, style, }: GlassFillProps): import("react/jsx-runtime").JSX.Element;
19
+ export default GlassFill;
20
+ //# sourceMappingURL=GlassFill.web.d.ts.map
@@ -83,20 +83,24 @@ export declare function Title({ children, style, modes: propModes }: {
83
83
  * Glass Footer — pinned to the bottom of the card, **always** on top of the
84
84
  * Header (`zIndex: 2`).
85
85
  *
86
- * Glass implementation (April 2026 best practice for RN/Expo):
87
- * - **iOS:** `expo-blur`'s `BlurView` renders a native `UIVisualEffectView`,
88
- * so this is a real OS-level live blur of whatever's underneath. We pick
89
- * `tint` from the Figma "Contrast Context" mode (`'dark'` / `'light'`)
90
- * and a moderate intensity that matches the Figma `blur/minimal` token.
91
- * - **Android:** the same `BlurView` with `experimentalBlurMethod="dimezisBlurView"`
92
- * enables the hardware-accelerated `RenderEffect` blur on Android 12+.
93
- * On older Android, expo-blur cleanly degrades to a tinted scrim — we
94
- * layer a subtle noise/grain overlay on top so the surface still reads
95
- * as "frosted glass" instead of a flat color.
96
- * - **Web:** `BlurView` on web is implemented as `backdrop-filter: blur()`,
97
- * which already worked in the previous version. Same component, same API.
86
+ * Glass implementation:
87
+ * - **iOS / Android:** `<GlassFill>` (this folder) wraps
88
+ * `@react-native-community/blur`'s `BlurView`. iOS gets a real
89
+ * `UIVisualEffectView` (live OS blur); Android gets the community
90
+ * `RealtimeBlurView` with a token-driven tinted scrim fallback for
91
+ * devices where realtime blur is unavailable.
92
+ * - **Web:** the platform-extension file `GlassFill.web.tsx` renders a
93
+ * translucent View with `backdrop-filter: blur()` Metro picks the
94
+ * correct file automatically, so the web bundle never imports the
95
+ * native-only blur module.
98
96
  *
99
- * Tokens still drive the tint color, blur radius and inner spacing.
97
+ * Why we don't use `expo-blur`: it requires Expo Modules autolinking on the
98
+ * consumer side (`use_expo_modules!` / `ExpoModulesPackage`), which silently
99
+ * breaks bare React Native apps that just install this library and run
100
+ * `pod install`. `@react-native-community/blur` is a regular RN native
101
+ * module — autolinking handles it with no additional setup.
102
+ *
103
+ * Tokens still drive the tint color, blur intensity and inner spacing.
100
104
  */
101
105
  export declare function Footer({ children, style, modes: propModes }: {
102
106
  children?: React.ReactNode;
@@ -4,7 +4,7 @@
4
4
  * Auto-generated from SVG files in src/icons/
5
5
  * DO NOT EDIT MANUALLY - Run "npm run icons:generate" to regenerate
6
6
  *
7
- * Generated: 2026-04-22T12:14:37.458Z
7
+ * Generated: 2026-04-23T10:31:30.721Z
8
8
  */
9
9
  export declare const iconRegistry: Record<string, {
10
10
  path: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jfs-components",
3
- "version": "0.0.69",
3
+ "version": "0.0.70",
4
4
  "description": "React Native Jio Finance Components Library",
5
5
  "author": "sunshuaiqi@gmail.com",
6
6
  "license": "MIT",
@@ -86,7 +86,6 @@
86
86
  "ajv": "^8.17.1",
87
87
  "ajv-keywords": "^5.1.0",
88
88
  "expo": "^54.0.33",
89
- "expo-blur": "~15.0.8",
90
89
  "patch-package": "^8.0.1",
91
90
  "react-native-gesture-handler": "^2.29.1",
92
91
  "react-native-reanimated": "3.18.1",
@@ -96,6 +95,7 @@
96
95
  "react-native-worklets": "0.5.1"
97
96
  },
98
97
  "peerDependencies": {
98
+ "@react-native-community/blur": ">=4.4.0",
99
99
  "react": "*",
100
100
  "react-native": "*"
101
101
  },
@@ -106,6 +106,7 @@
106
106
  "@babel/preset-react": "^7.28.5",
107
107
  "@babel/runtime": "^7.28.4",
108
108
  "@babel/traverse": "^7.28.5",
109
+ "@react-native-community/blur": "^4.4.1",
109
110
  "@react-native-community/cli": "20.0.2",
110
111
  "@react-native-community/cli-platform-android": "20.0.2",
111
112
  "@react-native-community/cli-platform-ios": "20.0.2",
@@ -0,0 +1,89 @@
1
+ import React from 'react'
2
+ import { View, StyleSheet, Platform, type ViewStyle, type StyleProp } from 'react-native'
3
+ import { BlurView } from '@react-native-community/blur'
4
+
5
+ export type GlassTint = 'dark' | 'light'
6
+
7
+ export interface GlassFillProps {
8
+ /**
9
+ * Visual tint of the glass surface. Maps to `BlurView`'s `blurType`
10
+ * (`'dark'` | `'light'`). The library also drives the appropriate
11
+ * `reducedTransparencyFallbackColor` from this so iOS gracefully degrades
12
+ * when "Reduce Transparency" is enabled in system accessibility settings.
13
+ */
14
+ tint?: GlassTint
15
+ /**
16
+ * Blur strength as a 0–100 "intensity" value (kept compatible with the
17
+ * previous `expo-blur` API so consumers don't need to relearn the scale).
18
+ * Internally mapped to `@react-native-community/blur`'s `blurAmount`,
19
+ * which is roughly 0–32 on iOS / Android.
20
+ */
21
+ intensity?: number
22
+ /**
23
+ * Token-derived color tint laid OVER the live blur (Figma `blur/minimal/background`).
24
+ * Painted as a translucent overlay so the glass keeps the design system
25
+ * color signature even when the platform blur quality varies.
26
+ */
27
+ overlayColor?: string
28
+ /** Container style overrides. Defaults to `StyleSheet.absoluteFill`. */
29
+ style?: StyleProp<ViewStyle>
30
+ }
31
+
32
+ const DEFAULT_FALLBACK_DARK = '#1414174a'
33
+ const DEFAULT_FALLBACK_LIGHT = '#ffffff66'
34
+
35
+ /**
36
+ * Glass / frosted surface for native (iOS + Android).
37
+ *
38
+ * Why this lives in its own platform-split file:
39
+ * - `@react-native-community/blur` is a native-only module. Importing it on
40
+ * web throws because the JS shim references native components that aren't
41
+ * registered there. By using Metro's platform-extension resolution
42
+ * (`GlassFill.tsx` for native, `GlassFill.web.tsx` for web), we keep the
43
+ * web bundle free of any native-only imports.
44
+ * - Centralizes the `intensity` (0–100) -> `blurAmount` (0–32) mapping so
45
+ * callers can keep the Figma token semantics they already know.
46
+ *
47
+ * On iOS this is a real `UIVisualEffectView` (true OS-level live blur).
48
+ * On Android this uses the community blur view (RealtimeBlurView). On devices
49
+ * where realtime blur is unavailable, `reducedTransparencyFallbackColor` (and
50
+ * the explicit `overlayColor`) ensure the surface still renders as a
51
+ * translucent tinted scrim instead of disappearing.
52
+ */
53
+ function GlassFill({
54
+ tint = 'dark',
55
+ intensity = 50,
56
+ overlayColor,
57
+ style,
58
+ }: GlassFillProps) {
59
+ const blurType: 'light' | 'dark' = tint === 'light' ? 'light' : 'dark'
60
+ const blurAmount = Math.max(0, Math.min(32, Math.round(intensity * 0.32)))
61
+ const fallbackColor = overlayColor ?? (tint === 'light' ? DEFAULT_FALLBACK_LIGHT : DEFAULT_FALLBACK_DARK)
62
+
63
+ return (
64
+ <View style={[StyleSheet.absoluteFill, style]} pointerEvents="none">
65
+ <BlurView
66
+ style={StyleSheet.absoluteFill}
67
+ blurType={blurType}
68
+ blurAmount={blurAmount}
69
+ reducedTransparencyFallbackColor={fallbackColor}
70
+ />
71
+ {overlayColor != null ? (
72
+ <View style={[StyleSheet.absoluteFill, { backgroundColor: overlayColor }]} />
73
+ ) : null}
74
+ {Platform.OS === 'android' ? (
75
+ <View
76
+ style={[
77
+ StyleSheet.absoluteFill,
78
+ {
79
+ backgroundColor: 'rgba(255,255,255,0.03)',
80
+ opacity: 0.6,
81
+ },
82
+ ]}
83
+ />
84
+ ) : null}
85
+ </View>
86
+ )
87
+ }
88
+
89
+ export default GlassFill
@@ -0,0 +1,53 @@
1
+ import React from 'react'
2
+ import { View, StyleSheet, type ViewStyle, type StyleProp } from 'react-native'
3
+
4
+ export type GlassTint = 'dark' | 'light'
5
+
6
+ export interface GlassFillProps {
7
+ tint?: GlassTint
8
+ intensity?: number
9
+ overlayColor?: string
10
+ style?: StyleProp<ViewStyle>
11
+ }
12
+
13
+ const DEFAULT_FALLBACK_DARK = '#1414174a'
14
+ const DEFAULT_FALLBACK_LIGHT = '#ffffff66'
15
+
16
+ /**
17
+ * Web counterpart of `GlassFill`.
18
+ *
19
+ * `@react-native-community/blur` does not ship a web implementation, so for
20
+ * the web bundle we render a translucent `View` with `backdrop-filter: blur()`
21
+ * — which is exactly how 0.0.67 and earlier shipped the glass effect on web.
22
+ * Native bundles pick up `GlassFill.tsx` instead via Metro's platform
23
+ * resolver; the web bundle picks up this file.
24
+ */
25
+ function GlassFill({
26
+ tint = 'dark',
27
+ intensity = 50,
28
+ overlayColor,
29
+ style,
30
+ }: GlassFillProps) {
31
+ // Approximate mapping: intensity 0-100 -> ~0-30px CSS blur. Keeps parity
32
+ // with the native blur strength so the component looks roughly the same
33
+ // across platforms.
34
+ const blurPx = Math.max(0, Math.min(30, Math.round(intensity * 0.3)))
35
+ const tintColor = overlayColor ?? (tint === 'light' ? DEFAULT_FALLBACK_LIGHT : DEFAULT_FALLBACK_DARK)
36
+
37
+ return (
38
+ <View
39
+ style={[
40
+ StyleSheet.absoluteFill,
41
+ { backgroundColor: tintColor },
42
+ // backdrop-filter is a web-only CSS property; ignored by RN
43
+ // on native (we never bundle this file there anyway).
44
+ // @ts-ignore web-only style
45
+ { backdropFilter: `blur(${blurPx}px)`, WebkitBackdropFilter: `blur(${blurPx}px)` },
46
+ style,
47
+ ]}
48
+ pointerEvents="none"
49
+ />
50
+ )
51
+ }
52
+
53
+ export default GlassFill
@@ -1,8 +1,8 @@
1
1
  import React, { createContext, useContext } from 'react'
2
- import { View, Text, StyleSheet, type ViewStyle, type TextStyle, type StyleProp, type ImageSourcePropType, Platform } from 'react-native'
3
- import { BlurView, type BlurTint } from 'expo-blur'
2
+ import { View, Text, StyleSheet, type ViewStyle, type TextStyle, type StyleProp, type ImageSourcePropType } from 'react-native'
4
3
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
5
4
  import Image from '../Image/Image'
5
+ import GlassFill, { type GlassTint } from './GlassFill'
6
6
  import { EMPTY_MODES } from '../../utils/react-utils'
7
7
 
8
8
  const MediaCardContext = createContext<{ modes?: Record<string, any> }>({})
@@ -162,20 +162,24 @@ export function Title({ children, style, modes: propModes }: { children?: React.
162
162
  * Glass Footer — pinned to the bottom of the card, **always** on top of the
163
163
  * Header (`zIndex: 2`).
164
164
  *
165
- * Glass implementation (April 2026 best practice for RN/Expo):
166
- * - **iOS:** `expo-blur`'s `BlurView` renders a native `UIVisualEffectView`,
167
- * so this is a real OS-level live blur of whatever's underneath. We pick
168
- * `tint` from the Figma "Contrast Context" mode (`'dark'` / `'light'`)
169
- * and a moderate intensity that matches the Figma `blur/minimal` token.
170
- * - **Android:** the same `BlurView` with `experimentalBlurMethod="dimezisBlurView"`
171
- * enables the hardware-accelerated `RenderEffect` blur on Android 12+.
172
- * On older Android, expo-blur cleanly degrades to a tinted scrim — we
173
- * layer a subtle noise/grain overlay on top so the surface still reads
174
- * as "frosted glass" instead of a flat color.
175
- * - **Web:** `BlurView` on web is implemented as `backdrop-filter: blur()`,
176
- * which already worked in the previous version. Same component, same API.
165
+ * Glass implementation:
166
+ * - **iOS / Android:** `<GlassFill>` (this folder) wraps
167
+ * `@react-native-community/blur`'s `BlurView`. iOS gets a real
168
+ * `UIVisualEffectView` (live OS blur); Android gets the community
169
+ * `RealtimeBlurView` with a token-driven tinted scrim fallback for
170
+ * devices where realtime blur is unavailable.
171
+ * - **Web:** the platform-extension file `GlassFill.web.tsx` renders a
172
+ * translucent View with `backdrop-filter: blur()` Metro picks the
173
+ * correct file automatically, so the web bundle never imports the
174
+ * native-only blur module.
177
175
  *
178
- * Tokens still drive the tint color, blur radius and inner spacing.
176
+ * Why we don't use `expo-blur`: it requires Expo Modules autolinking on the
177
+ * consumer side (`use_expo_modules!` / `ExpoModulesPackage`), which silently
178
+ * breaks bare React Native apps that just install this library and run
179
+ * `pod install`. `@react-native-community/blur` is a regular RN native
180
+ * module — autolinking handles it with no additional setup.
181
+ *
182
+ * Tokens still drive the tint color, blur intensity and inner spacing.
179
183
  */
180
184
  export function Footer({ children, style, modes: propModes }: { children?: React.ReactNode; style?: StyleProp<ViewStyle>; modes?: Record<string, any> }) {
181
185
  const context = useContext(MediaCardContext)
@@ -186,10 +190,14 @@ export function Footer({ children, style, modes: propModes }: { children?: React
186
190
  const paddingVertical = parseFloat(getVariableByName('cardMedia/footer/padding/vertical', modes) || '12')
187
191
 
188
192
  // Figma tokens:
189
- // blur/minimal/background -> tint laid over the native blur
190
- // blur/minimal -> blur radius (px). expo-blur takes a 0-100
191
- // "intensity" instead of px; we map roughly:
192
- // intensity clamp(radius * 1.7, 0, 100).
193
+ // blur/minimal/background -> tint laid over the live blur, also used
194
+ // as the iOS reduced-transparency fallback.
195
+ // blur/minimal -> blur radius (px). The community BlurView
196
+ // uses `blurAmount` (~0-32). `GlassFill`
197
+ // accepts a 0-100 "intensity" (kept compat
198
+ // with the previous expo-blur scale) and
199
+ // maps it internally — here we convert the
200
+ // token's radius to that intensity scale.
193
201
  const glassBgColor = getVariableByName('blur/minimal/background', modes) || '#1414174a'
194
202
  const blurRadius = parseFloat(getVariableByName('blur/minimal', modes) || '29')
195
203
  const intensity = Math.max(0, Math.min(100, Math.round(blurRadius * 1.7)))
@@ -197,7 +205,7 @@ export function Footer({ children, style, modes: propModes }: { children?: React
197
205
  // Pick the iOS/Android material tint from "Contrast Context" mode so the
198
206
  // glass adapts to dark/light backgrounds the same way the Figma tokens do.
199
207
  const contrast = (modes['Contrast Context'] || 'on dark') as string
200
- const tint: BlurTint = contrast === 'on light' ? 'light' : 'dark'
208
+ const tint: GlassTint = contrast === 'on light' ? 'light' : 'dark'
201
209
 
202
210
  return (
203
211
  <View
@@ -216,34 +224,7 @@ export function Footer({ children, style, modes: propModes }: { children?: React
216
224
  ]}
217
225
  pointerEvents="box-none"
218
226
  >
219
- {/* Native live blur. On Android pre-12 expo-blur falls back to a
220
- tinted scrim automatically; on web it's a backdrop-filter. */}
221
- <BlurView
222
- style={StyleSheet.absoluteFill}
223
- tint={tint}
224
- intensity={intensity}
225
- experimentalBlurMethod="dimezisBlurView"
226
- />
227
-
228
- {/* Token-driven tint laid on top of the live blur — keeps the
229
- Figma color signature regardless of platform blur quality. */}
230
- <View style={[StyleSheet.absoluteFill, { backgroundColor: glassBgColor }]} />
231
-
232
- {/* Subtle noise/grain on Android only, to compensate for the
233
- lower-fidelity blur — purely additive, no behavior change.
234
- On iOS/web the native blur already has natural texture. */}
235
- {Platform.OS === 'android' ? (
236
- <View
237
- style={[
238
- StyleSheet.absoluteFill,
239
- {
240
- backgroundColor: 'rgba(255,255,255,0.03)',
241
- opacity: 0.6,
242
- },
243
- ]}
244
- pointerEvents="none"
245
- />
246
- ) : null}
227
+ <GlassFill tint={tint} intensity={intensity} overlayColor={glassBgColor} />
247
228
 
248
229
  <View
249
230
  style={{
@@ -4,7 +4,7 @@
4
4
  * Auto-generated from SVG files in src/icons/
5
5
  * DO NOT EDIT MANUALLY - Run "npm run icons:generate" to regenerate
6
6
  *
7
- * Generated: 2026-04-22T12:14:37.458Z
7
+ * Generated: 2026-04-23T10:31:30.721Z
8
8
  */
9
9
 
10
10
  // Icon name to SVG data mapping