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.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,18 @@ All notable changes to this project are documented in this file.
4
4
 
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
6
6
 
7
+ ## [0.0.68] - 2026-04-22
8
+
9
+ ### Added
10
+
11
+ - **`Image`:** New shared raster primitive (`imageSource`, optional `ratio`, defaults to `16 / 9` so layout has a stable height without a magic `minHeight`). Supports explicit `width` + `height` to opt out of `aspectRatio` and fill a parent. Exported from the package barrel.
12
+
13
+ ### Changed
14
+
15
+ - **`MediaCard`:** Background uses the shared `Image` via `imageSource` and `ratio`; card height follows the image in normal flow (no fixed `minHeight`). Title/footer content is an `absoluteFill` overlay with `pointerEvents="box-none"`. Optional `media` escape hatch unchanged (custom node sizes itself).
16
+
17
+ ---
18
+
7
19
  ## [0.0.67] - 2026-04-22
8
20
 
9
21
  ### Fixed
@@ -35,9 +35,10 @@ function normalizeSource(imageSource) {
35
35
  * its parent (`width: '100%'`, `height: '100%'`) — same default as the
36
36
  * most common usage in this library (background media, hero images).
37
37
  */
38
+ const DEFAULT_RATIO = 16 / 9;
38
39
  function Image({
39
40
  imageSource,
40
- ratio,
41
+ ratio = DEFAULT_RATIO,
41
42
  resizeMode = 'cover',
42
43
  width,
43
44
  height,
@@ -49,15 +50,21 @@ function Image({
49
50
  }) {
50
51
  const source = (0, _react.useMemo)(() => normalizeSource(imageSource), [imageSource]);
51
52
  const layoutStyle = (0, _react.useMemo)(() => {
52
- const s = {};
53
- if (ratio != null) {
54
- s.aspectRatio = ratio;
55
- s.width = width ?? '100%';
56
- if (height != null) s.height = height;
57
- } else {
58
- s.width = width ?? '100%';
59
- s.height = height ?? '100%';
60
- }
53
+ // If the caller has fully specified width AND height, they're doing a
54
+ // non-aspect layout (e.g. "fill the parent") — respect that and skip
55
+ // `aspectRatio` so it doesn't conflict.
56
+ const isExplicitBox = width != null && height != null;
57
+ const s = {
58
+ width: width ?? '100%',
59
+ ...(isExplicitBox ? {
60
+ height: height
61
+ } : {
62
+ aspectRatio: ratio,
63
+ ...(height != null ? {
64
+ height
65
+ } : {})
66
+ })
67
+ };
61
68
  if (borderRadius != null) s.borderRadius = borderRadius;
62
69
  return s;
63
70
  }, [ratio, width, height, borderRadius]);
@@ -37,18 +37,21 @@ function MediaCard({
37
37
  style
38
38
  }) {
39
39
  const radius = parseFloat((0, _figmaVariablesResolver.getVariableByName)('cardMedia/radius', modes) || '24');
40
- const gap = parseFloat((0, _figmaVariablesResolver.getVariableByName)('cardMedia/gap', modes) || '0');
40
+
41
+ // No magic minHeight, no aspectRatio on the container. The card simply
42
+ // hugs whatever the background renders at: the <Image> sits in normal
43
+ // flow with `aspectRatio: ratio`, so its rendered height becomes the
44
+ // card's height. Header and Footer are absolutely positioned overlays
45
+ // and don't contribute to layout.
41
46
  const containerStyle = {
42
47
  borderRadius: radius,
43
- gap,
44
48
  overflow: 'hidden',
45
- position: 'relative',
46
- minHeight: 308
49
+ position: 'relative'
47
50
  };
48
51
 
49
- // `media` wins for back-compat / custom nodes; otherwise we delegate to
50
- // the shared <Image> for image-source backgrounds. All raster-rendering
51
- // concerns (URL-vs-{uri}, resizeMode, aspect-ratio) live in <Image>.
52
+ // `media` wins as an escape hatch (gradient/video/etc.). Otherwise we
53
+ // delegate to the shared <Image> for image-source backgrounds. The
54
+ // background renders in normal flow so its height drives the card.
52
55
  const background = media ?? (imageSource != null ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Image.default, {
53
56
  imageSource: imageSource,
54
57
  ratio: ratio,
@@ -62,10 +65,11 @@ function MediaCard({
62
65
  },
63
66
  children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
64
67
  style: [containerStyle, style],
65
- children: [background ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
68
+ children: [background, children != null ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
66
69
  style: _reactNative.StyleSheet.absoluteFill,
67
- children: background
68
- }) : null, children]
70
+ pointerEvents: "box-none",
71
+ children: children
72
+ }) : null]
69
73
  })
70
74
  });
71
75
  }