jfs-components 0.0.65 → 0.0.66
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/lib/commonjs/components/CardCTA/CardCTA.js +15 -1
- package/lib/commonjs/components/Carousel/Carousel.js +22 -4
- package/lib/commonjs/components/Section/Section.js +22 -7
- package/lib/commonjs/icons/registry.js +1 -1
- package/lib/module/components/CardCTA/CardCTA.js +15 -1
- package/lib/module/components/Carousel/Carousel.js +22 -4
- package/lib/module/components/Section/Section.js +23 -8
- package/lib/module/icons/registry.js +1 -1
- package/lib/typescript/src/icons/registry.d.ts +1 -1
- package/package.json +1 -1
- package/src/components/CardCTA/CardCTA.tsx +13 -0
- package/src/components/Carousel/Carousel.tsx +21 -3
- package/src/components/Section/Section.tsx +29 -12
- package/src/icons/registry.ts +1 -1
|
@@ -56,8 +56,17 @@ function CardCTA({
|
|
|
56
56
|
flexDirection: 'row',
|
|
57
57
|
overflow: 'hidden'
|
|
58
58
|
};
|
|
59
|
+
|
|
60
|
+
// NOTE: `minWidth: 0` + explicit `flexShrink: 1` are required on native.
|
|
61
|
+
// Without them, Yoga's default `min-width: auto` clamps leftWrap to its
|
|
62
|
+
// single-line intrinsic text width, which steals all space from rightWrap
|
|
63
|
+
// and pushes the IconCapsule outside the card. See: text-not-wrapping
|
|
64
|
+
// inside flex rows on RN.
|
|
59
65
|
const leftWrapStyle = {
|
|
60
66
|
flex: 3,
|
|
67
|
+
flexShrink: 1,
|
|
68
|
+
flexBasis: 0,
|
|
69
|
+
minWidth: 0,
|
|
61
70
|
paddingHorizontal: leftPaddingH,
|
|
62
71
|
paddingVertical: leftPaddingV,
|
|
63
72
|
gap: leftGap,
|
|
@@ -66,13 +75,18 @@ function CardCTA({
|
|
|
66
75
|
};
|
|
67
76
|
const rightWrapStyle = {
|
|
68
77
|
flex: 2,
|
|
78
|
+
flexShrink: 1,
|
|
79
|
+
flexBasis: 0,
|
|
80
|
+
minWidth: 0,
|
|
69
81
|
paddingHorizontal: rightPaddingH,
|
|
70
82
|
paddingVertical: rightPaddingV,
|
|
71
83
|
alignItems: 'flex-end',
|
|
72
84
|
justifyContent: 'flex-start'
|
|
73
85
|
};
|
|
74
86
|
const textWrapStyle = {
|
|
75
|
-
gap: textGap
|
|
87
|
+
gap: textGap,
|
|
88
|
+
alignSelf: 'stretch',
|
|
89
|
+
minWidth: 0
|
|
76
90
|
};
|
|
77
91
|
const titleStyle = {
|
|
78
92
|
color: titleColor,
|
|
@@ -181,8 +181,26 @@ export function Carousel({
|
|
|
181
181
|
onScrollBeginDrag: handleScrollBeginDrag,
|
|
182
182
|
onScrollEndDrag: handleScrollEndDrag,
|
|
183
183
|
children: items.map((child, index) => {
|
|
184
|
-
|
|
185
|
-
|
|
184
|
+
// Strict slot box: width must be honored; never grow or shrink with
|
|
185
|
+
// content, and clip anything that misbehaves (e.g. a child whose
|
|
186
|
+
// inner flex layout would otherwise leak into the next slot on
|
|
187
|
+
// native).
|
|
188
|
+
const slotStyle = {
|
|
189
|
+
width: effectiveItemWidth > 0 ? effectiveItemWidth : undefined,
|
|
190
|
+
flexGrow: 0,
|
|
191
|
+
flexShrink: 0,
|
|
192
|
+
flexBasis: effectiveItemWidth > 0 ? effectiveItemWidth : 'auto',
|
|
193
|
+
overflow: 'hidden'
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
// The cloned style forces the child's outer node to also honor the
|
|
197
|
+
// slot width strictly. Without this, a child with a weird intrinsic
|
|
198
|
+
// size can render wider than the slot and visually overflow.
|
|
199
|
+
const childOverrideStyle = {
|
|
200
|
+
width: effectiveItemWidth > 0 ? effectiveItemWidth : undefined,
|
|
201
|
+
maxWidth: effectiveItemWidth > 0 ? effectiveItemWidth : undefined,
|
|
202
|
+
flexGrow: 0,
|
|
203
|
+
flexShrink: 0
|
|
186
204
|
};
|
|
187
205
|
|
|
188
206
|
// Pass modes down to children
|
|
@@ -191,10 +209,10 @@ export function Carousel({
|
|
|
191
209
|
...(child.props?.modes || {}),
|
|
192
210
|
...modes
|
|
193
211
|
},
|
|
194
|
-
style: [
|
|
212
|
+
style: [childOverrideStyle, child.props?.style]
|
|
195
213
|
}) : child;
|
|
196
214
|
return /*#__PURE__*/_jsx(View, {
|
|
197
|
-
style:
|
|
215
|
+
style: slotStyle,
|
|
198
216
|
children: childWithModes
|
|
199
217
|
}, index);
|
|
200
218
|
})
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import React, { useState, useMemo, useRef, useCallback } from 'react';
|
|
4
4
|
import { View, Text, Pressable, Platform } from 'react-native';
|
|
5
|
-
import Animated, { FadeInUp, FadeOutUp, ReduceMotion, useAnimatedStyle, useSharedValue,
|
|
5
|
+
import Animated, { Easing, FadeInUp, FadeOutUp, ReduceMotion, useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated';
|
|
6
6
|
import { getVariableByName } from '../../design-tokens/figma-variables-resolver';
|
|
7
7
|
import NavArrow from '../NavArrow/NavArrow';
|
|
8
8
|
import IconCapsule from '../IconCapsule/IconCapsule';
|
|
@@ -85,7 +85,14 @@ const SLOT_GRID_MAX_COLUMNS = 4;
|
|
|
85
85
|
const SLOT_GRID_STAGGER_CAP = 8;
|
|
86
86
|
const SLOT_GRID_ENTER_STAGGER_MS = 35;
|
|
87
87
|
const SLOT_GRID_EXIT_STAGGER_MS = 20;
|
|
88
|
+
const SLOT_GRID_ENTER_DURATION_MS = 220;
|
|
88
89
|
const SLOT_GRID_EXIT_DURATION_MS = 160;
|
|
90
|
+
const SLOT_GRID_HEIGHT_DURATION_MS = 280;
|
|
91
|
+
|
|
92
|
+
// Standard ease-out cubic curve. Calm, professional, no overshoot — matches
|
|
93
|
+
// system-style transitions. Defined once at module scope so it isn't
|
|
94
|
+
// re-allocated per render.
|
|
95
|
+
const SLOT_GRID_EASING = Easing.out(Easing.cubic);
|
|
89
96
|
const slotGridRowFlowStyle = {
|
|
90
97
|
flexDirection: 'row',
|
|
91
98
|
justifyContent: 'space-between'
|
|
@@ -131,6 +138,13 @@ const SlotGrid = /*#__PURE__*/React.memo(function SlotGrid({
|
|
|
131
138
|
const containerStyle = useMemo(() => ({
|
|
132
139
|
gap
|
|
133
140
|
}), [gap]);
|
|
141
|
+
// Strict `width` (not `minWidth`) so every cell in every row is exactly the
|
|
142
|
+
// same size — `space-between` then distributes identical leftover into
|
|
143
|
+
// identical inter-cell gaps on every row, which keeps column N of row 1
|
|
144
|
+
// aligned with column N of rows 2/3/etc. Cells whose label is wider than
|
|
145
|
+
// `cellWidth` simply wrap their text onto more lines (taking more vertical
|
|
146
|
+
// space; the row's height grows naturally to fit the tallest cell, and the
|
|
147
|
+
// animated-height clip springs to the new total).
|
|
134
148
|
const cellStyle = useMemo(() => cellWidth !== null ? {
|
|
135
149
|
width: cellWidth
|
|
136
150
|
} : undefined, [cellWidth]);
|
|
@@ -164,8 +178,9 @@ const SlotGrid = /*#__PURE__*/React.memo(function SlotGrid({
|
|
|
164
178
|
// and an explicit `height` driven by a shared value.
|
|
165
179
|
// 3. The inner view reports its natural height via `onLayout`. The first
|
|
166
180
|
// measurement snaps the shared value (no first-mount animation). Every
|
|
167
|
-
// subsequent change (e.g. expand/collapse adds or removes rows)
|
|
168
|
-
// the shared value to the new natural height
|
|
181
|
+
// subsequent change (e.g. expand/collapse adds or removes rows) eases
|
|
182
|
+
// the shared value to the new natural height with a calm ease-out
|
|
183
|
+
// timing curve — no spring, no bounce, no overshoot.
|
|
169
184
|
//
|
|
170
185
|
// Visually: the container reveals/conceals content like a curtain, and the
|
|
171
186
|
// cells never deform.
|
|
@@ -179,9 +194,9 @@ const SlotGrid = /*#__PURE__*/React.memo(function SlotGrid({
|
|
|
179
194
|
animatedHeight.value = h;
|
|
180
195
|
return;
|
|
181
196
|
}
|
|
182
|
-
animatedHeight.value =
|
|
183
|
-
|
|
184
|
-
|
|
197
|
+
animatedHeight.value = withTiming(h, {
|
|
198
|
+
duration: SLOT_GRID_HEIGHT_DURATION_MS,
|
|
199
|
+
easing: SLOT_GRID_EASING,
|
|
185
200
|
reduceMotion: ReduceMotion.System
|
|
186
201
|
});
|
|
187
202
|
}, [animatedHeight]);
|
|
@@ -205,8 +220,8 @@ const SlotGrid = /*#__PURE__*/React.memo(function SlotGrid({
|
|
|
205
220
|
const enterStaggerSteps = Math.min(extraOrdinal, SLOT_GRID_STAGGER_CAP);
|
|
206
221
|
const reverseOrdinal = Math.max(0, extrasCount - 1 - extraOrdinal);
|
|
207
222
|
const exitStaggerSteps = Math.min(reverseOrdinal, SLOT_GRID_STAGGER_CAP);
|
|
208
|
-
const entering = FadeInUp.
|
|
209
|
-
const exiting = FadeOutUp.duration(SLOT_GRID_EXIT_DURATION_MS).delay(exitStaggerSteps * SLOT_GRID_EXIT_STAGGER_MS).reduceMotion(ReduceMotion.System);
|
|
223
|
+
const entering = FadeInUp.duration(SLOT_GRID_ENTER_DURATION_MS).easing(SLOT_GRID_EASING).delay(enterStaggerSteps * SLOT_GRID_ENTER_STAGGER_MS).reduceMotion(ReduceMotion.System);
|
|
224
|
+
const exiting = FadeOutUp.duration(SLOT_GRID_EXIT_DURATION_MS).easing(SLOT_GRID_EASING).delay(exitStaggerSteps * SLOT_GRID_EXIT_STAGGER_MS).reduceMotion(ReduceMotion.System);
|
|
210
225
|
return /*#__PURE__*/_jsx(Animated.View, {
|
|
211
226
|
entering: entering,
|
|
212
227
|
exiting: exiting,
|