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
|
@@ -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-
|
|
7
|
+
* Generated: 2026-04-21T15:09:13.866Z
|
|
8
8
|
*/
|
|
9
9
|
export declare const iconRegistry: Record<string, {
|
|
10
10
|
path: string;
|
package/package.json
CHANGED
|
@@ -78,8 +78,16 @@ function CardCTA({
|
|
|
78
78
|
overflow: 'hidden',
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
+
// NOTE: `minWidth: 0` + explicit `flexShrink: 1` are required on native.
|
|
82
|
+
// Without them, Yoga's default `min-width: auto` clamps leftWrap to its
|
|
83
|
+
// single-line intrinsic text width, which steals all space from rightWrap
|
|
84
|
+
// and pushes the IconCapsule outside the card. See: text-not-wrapping
|
|
85
|
+
// inside flex rows on RN.
|
|
81
86
|
const leftWrapStyle: ViewStyle = {
|
|
82
87
|
flex: 3,
|
|
88
|
+
flexShrink: 1,
|
|
89
|
+
flexBasis: 0,
|
|
90
|
+
minWidth: 0,
|
|
83
91
|
paddingHorizontal: leftPaddingH,
|
|
84
92
|
paddingVertical: leftPaddingV,
|
|
85
93
|
gap: leftGap,
|
|
@@ -89,6 +97,9 @@ function CardCTA({
|
|
|
89
97
|
|
|
90
98
|
const rightWrapStyle: ViewStyle = {
|
|
91
99
|
flex: 2,
|
|
100
|
+
flexShrink: 1,
|
|
101
|
+
flexBasis: 0,
|
|
102
|
+
minWidth: 0,
|
|
92
103
|
paddingHorizontal: rightPaddingH,
|
|
93
104
|
paddingVertical: rightPaddingV,
|
|
94
105
|
alignItems: 'flex-end',
|
|
@@ -97,6 +108,8 @@ function CardCTA({
|
|
|
97
108
|
|
|
98
109
|
const textWrapStyle: ViewStyle = {
|
|
99
110
|
gap: textGap,
|
|
111
|
+
alignSelf: 'stretch',
|
|
112
|
+
minWidth: 0,
|
|
100
113
|
}
|
|
101
114
|
|
|
102
115
|
const titleStyle: TextStyle = {
|
|
@@ -279,8 +279,26 @@ export function Carousel({
|
|
|
279
279
|
|
|
280
280
|
>
|
|
281
281
|
{items.map((child, index) => {
|
|
282
|
-
|
|
282
|
+
// Strict slot box: width must be honored; never grow or shrink with
|
|
283
|
+
// content, and clip anything that misbehaves (e.g. a child whose
|
|
284
|
+
// inner flex layout would otherwise leak into the next slot on
|
|
285
|
+
// native).
|
|
286
|
+
const slotStyle: ViewStyle = {
|
|
283
287
|
width: effectiveItemWidth > 0 ? effectiveItemWidth : undefined,
|
|
288
|
+
flexGrow: 0,
|
|
289
|
+
flexShrink: 0,
|
|
290
|
+
flexBasis: effectiveItemWidth > 0 ? effectiveItemWidth : 'auto',
|
|
291
|
+
overflow: 'hidden',
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// The cloned style forces the child's outer node to also honor the
|
|
295
|
+
// slot width strictly. Without this, a child with a weird intrinsic
|
|
296
|
+
// size can render wider than the slot and visually overflow.
|
|
297
|
+
const childOverrideStyle: ViewStyle = {
|
|
298
|
+
width: effectiveItemWidth > 0 ? effectiveItemWidth : undefined,
|
|
299
|
+
maxWidth: effectiveItemWidth > 0 ? effectiveItemWidth : undefined,
|
|
300
|
+
flexGrow: 0,
|
|
301
|
+
flexShrink: 0,
|
|
284
302
|
}
|
|
285
303
|
|
|
286
304
|
// Pass modes down to children
|
|
@@ -290,12 +308,12 @@ export function Carousel({
|
|
|
290
308
|
...((child.props as any)?.modes || {}),
|
|
291
309
|
...modes,
|
|
292
310
|
},
|
|
293
|
-
style: [
|
|
311
|
+
style: [childOverrideStyle, (child.props as any)?.style],
|
|
294
312
|
})
|
|
295
313
|
: child
|
|
296
314
|
|
|
297
315
|
return (
|
|
298
|
-
<View key={index} style={
|
|
316
|
+
<View key={index} style={slotStyle}>
|
|
299
317
|
{childWithModes}
|
|
300
318
|
</View>
|
|
301
319
|
)
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import React, { useState, useMemo, useRef, useCallback } from 'react'
|
|
2
2
|
import { View, Text, Pressable, Platform, type StyleProp, type ViewStyle, type PressableStateCallbackType } from 'react-native'
|
|
3
3
|
import Animated, {
|
|
4
|
+
Easing,
|
|
4
5
|
FadeInUp,
|
|
5
6
|
FadeOutUp,
|
|
6
7
|
ReduceMotion,
|
|
7
8
|
useAnimatedStyle,
|
|
8
9
|
useSharedValue,
|
|
9
|
-
|
|
10
|
+
withTiming,
|
|
10
11
|
} from 'react-native-reanimated'
|
|
11
12
|
import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
|
|
12
13
|
import NavArrow from '../NavArrow/NavArrow'
|
|
@@ -82,7 +83,14 @@ const SLOT_GRID_MAX_COLUMNS = 4
|
|
|
82
83
|
const SLOT_GRID_STAGGER_CAP = 8
|
|
83
84
|
const SLOT_GRID_ENTER_STAGGER_MS = 35
|
|
84
85
|
const SLOT_GRID_EXIT_STAGGER_MS = 20
|
|
86
|
+
const SLOT_GRID_ENTER_DURATION_MS = 220
|
|
85
87
|
const SLOT_GRID_EXIT_DURATION_MS = 160
|
|
88
|
+
const SLOT_GRID_HEIGHT_DURATION_MS = 280
|
|
89
|
+
|
|
90
|
+
// Standard ease-out cubic curve. Calm, professional, no overshoot — matches
|
|
91
|
+
// system-style transitions. Defined once at module scope so it isn't
|
|
92
|
+
// re-allocated per render.
|
|
93
|
+
const SLOT_GRID_EASING = Easing.out(Easing.cubic)
|
|
86
94
|
|
|
87
95
|
type SlotGridProps = {
|
|
88
96
|
items: React.ReactNode[];
|
|
@@ -97,10 +105,10 @@ type SlotGridProps = {
|
|
|
97
105
|
animateExtrasFromIndex?: number;
|
|
98
106
|
/**
|
|
99
107
|
* If true, the rows container animates its height via an explicit
|
|
100
|
-
* `useSharedValue` + `
|
|
101
|
-
* inner content
|
|
102
|
-
* inside always render at their natural size
|
|
103
|
-
* during the transition. Default false.
|
|
108
|
+
* `useSharedValue` + `withTiming` (ease-out cubic, no overshoot) driven by
|
|
109
|
+
* `onLayout` measurements of the inner content, with `overflow: 'hidden'`
|
|
110
|
+
* to clip mid-animation. Cells inside always render at their natural size
|
|
111
|
+
* — they are *never* resized during the transition. Default false.
|
|
104
112
|
*/
|
|
105
113
|
animateContainerLayout?: boolean;
|
|
106
114
|
}
|
|
@@ -157,6 +165,13 @@ const SlotGrid = React.memo(function SlotGrid({
|
|
|
157
165
|
}
|
|
158
166
|
|
|
159
167
|
const containerStyle = useMemo<ViewStyle>(() => ({ gap }), [gap])
|
|
168
|
+
// Strict `width` (not `minWidth`) so every cell in every row is exactly the
|
|
169
|
+
// same size — `space-between` then distributes identical leftover into
|
|
170
|
+
// identical inter-cell gaps on every row, which keeps column N of row 1
|
|
171
|
+
// aligned with column N of rows 2/3/etc. Cells whose label is wider than
|
|
172
|
+
// `cellWidth` simply wrap their text onto more lines (taking more vertical
|
|
173
|
+
// space; the row's height grows naturally to fit the tallest cell, and the
|
|
174
|
+
// animated-height clip springs to the new total).
|
|
160
175
|
const cellStyle = useMemo<ViewStyle | undefined>(
|
|
161
176
|
() => (cellWidth !== null ? { width: cellWidth } : undefined),
|
|
162
177
|
[cellWidth]
|
|
@@ -197,8 +212,9 @@ const SlotGrid = React.memo(function SlotGrid({
|
|
|
197
212
|
// and an explicit `height` driven by a shared value.
|
|
198
213
|
// 3. The inner view reports its natural height via `onLayout`. The first
|
|
199
214
|
// measurement snaps the shared value (no first-mount animation). Every
|
|
200
|
-
// subsequent change (e.g. expand/collapse adds or removes rows)
|
|
201
|
-
// the shared value to the new natural height
|
|
215
|
+
// subsequent change (e.g. expand/collapse adds or removes rows) eases
|
|
216
|
+
// the shared value to the new natural height with a calm ease-out
|
|
217
|
+
// timing curve — no spring, no bounce, no overshoot.
|
|
202
218
|
//
|
|
203
219
|
// Visually: the container reveals/conceals content like a curtain, and the
|
|
204
220
|
// cells never deform.
|
|
@@ -213,9 +229,9 @@ const SlotGrid = React.memo(function SlotGrid({
|
|
|
213
229
|
animatedHeight.value = h
|
|
214
230
|
return
|
|
215
231
|
}
|
|
216
|
-
animatedHeight.value =
|
|
217
|
-
|
|
218
|
-
|
|
232
|
+
animatedHeight.value = withTiming(h, {
|
|
233
|
+
duration: SLOT_GRID_HEIGHT_DURATION_MS,
|
|
234
|
+
easing: SLOT_GRID_EASING,
|
|
219
235
|
reduceMotion: ReduceMotion.System,
|
|
220
236
|
})
|
|
221
237
|
},
|
|
@@ -261,11 +277,12 @@ const SlotGrid = React.memo(function SlotGrid({
|
|
|
261
277
|
reverseOrdinal,
|
|
262
278
|
SLOT_GRID_STAGGER_CAP
|
|
263
279
|
)
|
|
264
|
-
const entering = FadeInUp.
|
|
265
|
-
.
|
|
280
|
+
const entering = FadeInUp.duration(SLOT_GRID_ENTER_DURATION_MS)
|
|
281
|
+
.easing(SLOT_GRID_EASING)
|
|
266
282
|
.delay(enterStaggerSteps * SLOT_GRID_ENTER_STAGGER_MS)
|
|
267
283
|
.reduceMotion(ReduceMotion.System)
|
|
268
284
|
const exiting = FadeOutUp.duration(SLOT_GRID_EXIT_DURATION_MS)
|
|
285
|
+
.easing(SLOT_GRID_EASING)
|
|
269
286
|
.delay(exitStaggerSteps * SLOT_GRID_EXIT_STAGGER_MS)
|
|
270
287
|
.reduceMotion(ReduceMotion.System)
|
|
271
288
|
return (
|
package/src/icons/registry.ts
CHANGED