jfs-components 0.0.67 → 0.0.68

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.
@@ -10,8 +10,12 @@ export type ImageProps = {
10
10
  imageSource?: ImageSourcePropType | string | undefined;
11
11
  /**
12
12
  * Width-to-height aspect ratio as a number, e.g. `16 / 9`, `1`, `4 / 3`.
13
- * When set, the image lays out using `aspectRatio` so it scales naturally
14
- * with whatever width it receives no need to specify height.
13
+ * Defaults to `16 / 9` so the image always has a sensible rendered height
14
+ * even when the parent has no fixed height (e.g. inside `MediaCard`,
15
+ * which hugs whatever the image renders at).
16
+ *
17
+ * Pass `ratio={null as any}` is not supported — explicitly set a number,
18
+ * or override with `width` + `height` if you need a non-aspect layout.
15
19
  *
16
20
  * Equivalent CSS: `aspect-ratio: <ratio>`.
17
21
  */
@@ -35,25 +39,6 @@ export type ImageProps = {
35
39
  accessibilityElementsHidden?: boolean | undefined;
36
40
  importantForAccessibility?: 'auto' | 'yes' | 'no' | 'no-hide-descendants' | undefined;
37
41
  };
38
- /**
39
- * `Image` — the library's standard raster image primitive.
40
- *
41
- * Why this exists:
42
- * - Gives consumers a single component for "show an image at a given aspect
43
- * ratio inside a flex container" without having to remember the
44
- * `width:'100%' / height:'100%' / resizeMode:'cover'` boilerplate.
45
- * - Centralizes URL-vs-`{uri}` normalization that several components were
46
- * re-implementing.
47
- * - Uses the same `imageSource` prop name as the rest of the library
48
- * (`Avatar`, `ProductLabel`, `CardProviderInfo`, ...) for a unified API.
49
- *
50
- * Layout rules:
51
- * - If `ratio` is provided, the image lays out with `aspectRatio: ratio`
52
- * and (unless `width` is given) fills the parent's width.
53
- * - If neither `ratio` nor explicit dimensions are given, the image fills
54
- * its parent (`width: '100%'`, `height: '100%'`) — same default as the
55
- * most common usage in this library (background media, hero images).
56
- */
57
42
  declare function Image({ imageSource, ratio, resizeMode, width, height, borderRadius, style, accessibilityLabel, accessibilityElementsHidden, importantForAccessibility, }: ImageProps): import("react/jsx-runtime").JSX.Element;
58
43
  declare const _default: React.MemoExoticComponent<typeof Image>;
59
44
  export default _default;
@@ -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-22T11:47:15.563Z
7
+ * Generated: 2026-04-22T12:06:55.739Z
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.67",
3
+ "version": "0.0.68",
4
4
  "description": "React Native Jio Finance Components Library",
5
5
  "author": "sunshuaiqi@gmail.com",
6
6
  "license": "MIT",
@@ -2,7 +2,6 @@ import React, { useMemo } from 'react'
2
2
  import {
3
3
  Image as RNImage,
4
4
  View,
5
- StyleSheet,
6
5
  type ImageSourcePropType,
7
6
  type ImageStyle,
8
7
  type StyleProp,
@@ -20,8 +19,12 @@ export type ImageProps = {
20
19
  imageSource?: ImageSourcePropType | string | undefined
21
20
  /**
22
21
  * Width-to-height aspect ratio as a number, e.g. `16 / 9`, `1`, `4 / 3`.
23
- * When set, the image lays out using `aspectRatio` so it scales naturally
24
- * with whatever width it receives no need to specify height.
22
+ * Defaults to `16 / 9` so the image always has a sensible rendered height
23
+ * even when the parent has no fixed height (e.g. inside `MediaCard`,
24
+ * which hugs whatever the image renders at).
25
+ *
26
+ * Pass `ratio={null as any}` is not supported — explicitly set a number,
27
+ * or override with `width` + `height` if you need a non-aspect layout.
25
28
  *
26
29
  * Equivalent CSS: `aspect-ratio: <ratio>`.
27
30
  */
@@ -78,9 +81,11 @@ function normalizeSource(
78
81
  * its parent (`width: '100%'`, `height: '100%'`) — same default as the
79
82
  * most common usage in this library (background media, hero images).
80
83
  */
84
+ const DEFAULT_RATIO = 16 / 9
85
+
81
86
  function Image({
82
87
  imageSource,
83
- ratio,
88
+ ratio = DEFAULT_RATIO,
84
89
  resizeMode = 'cover',
85
90
  width,
86
91
  height,
@@ -93,14 +98,15 @@ function Image({
93
98
  const source = useMemo(() => normalizeSource(imageSource), [imageSource])
94
99
 
95
100
  const layoutStyle: ImageStyle = useMemo(() => {
96
- const s: ImageStyle = {}
97
- if (ratio != null) {
98
- s.aspectRatio = ratio
99
- s.width = width ?? '100%'
100
- if (height != null) s.height = height
101
- } else {
102
- s.width = width ?? '100%'
103
- s.height = height ?? '100%'
101
+ // If the caller has fully specified width AND height, they're doing a
102
+ // non-aspect layout (e.g. "fill the parent") — respect that and skip
103
+ // `aspectRatio` so it doesn't conflict.
104
+ const isExplicitBox = width != null && height != null
105
+ const s: ImageStyle = {
106
+ width: width ?? '100%',
107
+ ...(isExplicitBox
108
+ ? { height: height as number }
109
+ : { aspectRatio: ratio, ...(height != null ? { height } : {}) }),
104
110
  }
105
111
  if (borderRadius != null) s.borderRadius = borderRadius
106
112
  return s
@@ -58,19 +58,21 @@ export function MediaCard({
58
58
  style,
59
59
  }: MediaCardProps) {
60
60
  const radius = parseFloat(getVariableByName('cardMedia/radius', modes) || '24')
61
- const gap = parseFloat(getVariableByName('cardMedia/gap', modes) || '0')
62
61
 
62
+ // No magic minHeight, no aspectRatio on the container. The card simply
63
+ // hugs whatever the background renders at: the <Image> sits in normal
64
+ // flow with `aspectRatio: ratio`, so its rendered height becomes the
65
+ // card's height. Header and Footer are absolutely positioned overlays
66
+ // and don't contribute to layout.
63
67
  const containerStyle: ViewStyle = {
64
68
  borderRadius: radius,
65
- gap,
66
69
  overflow: 'hidden',
67
70
  position: 'relative',
68
- minHeight: 308,
69
71
  }
70
72
 
71
- // `media` wins for back-compat / custom nodes; otherwise we delegate to
72
- // the shared <Image> for image-source backgrounds. All raster-rendering
73
- // concerns (URL-vs-{uri}, resizeMode, aspect-ratio) live in <Image>.
73
+ // `media` wins as an escape hatch (gradient/video/etc.). Otherwise we
74
+ // delegate to the shared <Image> for image-source backgrounds. The
75
+ // background renders in normal flow so its height drives the card.
74
76
  const background = media ?? (
75
77
  imageSource != null ? (
76
78
  <Image
@@ -86,11 +88,12 @@ export function MediaCard({
86
88
  return (
87
89
  <MediaCardContext.Provider value={{ modes }}>
88
90
  <View style={[containerStyle, style]}>
89
- {background ? (
90
- <View style={StyleSheet.absoluteFill}>{background}</View>
91
+ {background}
92
+ {children != null ? (
93
+ <View style={StyleSheet.absoluteFill} pointerEvents="box-none">
94
+ {children}
95
+ </View>
91
96
  ) : null}
92
-
93
- {children}
94
97
  </View>
95
98
  </MediaCardContext.Provider>
96
99
  )
@@ -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-22T11:47:15.563Z
7
+ * Generated: 2026-04-22T12:06:55.739Z
8
8
  */
9
9
 
10
10
  // Icon name to SVG data mapping