jfs-components 0.1.2 → 0.1.8
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 +29 -0
- package/lib/commonjs/components/AmountInput/AmountInput.js +8 -5
- package/lib/commonjs/components/BenefitCard/BenefitCard.js +231 -0
- package/lib/commonjs/components/CcCard/CcCard.js +470 -0
- package/lib/commonjs/components/Checkbox/Checkbox.js +4 -3
- package/lib/commonjs/components/CheckboxItem/CheckboxItem.js +4 -3
- package/lib/commonjs/components/CompareTable/CompareTable.js +372 -0
- package/lib/commonjs/components/ComparisonBar/ComparisonBar.js +266 -0
- package/lib/commonjs/components/DropdownInput/DropdownInput.js +35 -3
- package/lib/commonjs/components/FormField/FormField.js +4 -3
- package/lib/commonjs/components/InputSearch/InputSearch.js +6 -4
- package/lib/commonjs/components/NoteInput/NoteInput.js +6 -5
- package/lib/commonjs/components/PdpCcCard/PdpCcCard.js +273 -0
- package/lib/commonjs/components/ProductMerchandisingCard/GlassFill.js +263 -0
- package/lib/commonjs/components/ProductMerchandisingCard/GlassFill.web.js +116 -0
- package/lib/commonjs/components/ProductMerchandisingCard/ProductMerchandisingCard.js +353 -0
- package/lib/commonjs/components/ProjectionMarker/ProjectionMarker.js +161 -0
- package/lib/commonjs/components/Radio/Radio.js +5 -5
- package/lib/commonjs/components/Slider/Slider.js +473 -0
- package/lib/commonjs/components/TextInput/TextInput.js +13 -8
- package/lib/commonjs/components/TextSegment/TextSegment.js +118 -0
- package/lib/commonjs/components/index.js +63 -0
- package/lib/commonjs/design-tokens/Coin Variables-variables-full.json +1 -1
- package/lib/commonjs/design-tokens/figma-modes.generated.js +38 -9
- package/lib/commonjs/icons/registry.js +1 -1
- package/lib/commonjs/utils/react-utils.js +22 -0
- package/lib/module/components/AmountInput/AmountInput.js +6 -4
- package/lib/module/components/BenefitCard/BenefitCard.js +225 -0
- package/lib/module/components/CcCard/CcCard.js +464 -0
- package/lib/module/components/Checkbox/Checkbox.js +5 -4
- package/lib/module/components/CheckboxItem/CheckboxItem.js +5 -4
- package/lib/module/components/CompareTable/CompareTable.js +367 -0
- package/lib/module/components/ComparisonBar/ComparisonBar.js +260 -0
- package/lib/module/components/DropdownInput/DropdownInput.js +36 -4
- package/lib/module/components/FormField/FormField.js +5 -4
- package/lib/module/components/InputSearch/InputSearch.js +6 -4
- package/lib/module/components/NoteInput/NoteInput.js +7 -6
- package/lib/module/components/PdpCcCard/PdpCcCard.js +267 -0
- package/lib/module/components/ProductMerchandisingCard/GlassFill.js +257 -0
- package/lib/module/components/ProductMerchandisingCard/GlassFill.web.js +111 -0
- package/lib/module/components/ProductMerchandisingCard/ProductMerchandisingCard.js +347 -0
- package/lib/module/components/ProjectionMarker/ProjectionMarker.js +156 -0
- package/lib/module/components/Radio/Radio.js +5 -4
- package/lib/module/components/Slider/Slider.js +468 -0
- package/lib/module/components/TextInput/TextInput.js +15 -10
- package/lib/module/components/TextSegment/TextSegment.js +113 -0
- package/lib/module/components/index.js +9 -0
- package/lib/module/design-tokens/Coin Variables-variables-full.json +1 -1
- package/lib/module/design-tokens/figma-modes.generated.js +38 -9
- package/lib/module/icons/registry.js +1 -1
- package/lib/module/utils/react-utils.js +21 -0
- package/lib/typescript/src/components/AmountInput/AmountInput.d.ts +3 -2
- package/lib/typescript/src/components/BenefitCard/BenefitCard.d.ts +93 -0
- package/lib/typescript/src/components/CcCard/CcCard.d.ts +137 -0
- package/lib/typescript/src/components/Checkbox/Checkbox.d.ts +3 -2
- package/lib/typescript/src/components/CheckboxItem/CheckboxItem.d.ts +2 -2
- package/lib/typescript/src/components/CompareTable/CompareTable.d.ts +88 -0
- package/lib/typescript/src/components/ComparisonBar/ComparisonBar.d.ts +118 -0
- package/lib/typescript/src/components/DropdownInput/DropdownInput.d.ts +20 -1
- package/lib/typescript/src/components/FormField/FormField.d.ts +2 -2
- package/lib/typescript/src/components/InputSearch/InputSearch.d.ts +23 -2
- package/lib/typescript/src/components/NoteInput/NoteInput.d.ts +19 -2
- package/lib/typescript/src/components/PdpCcCard/PdpCcCard.d.ts +84 -0
- package/lib/typescript/src/components/ProductMerchandisingCard/GlassFill.d.ts +56 -0
- package/lib/typescript/src/components/ProductMerchandisingCard/GlassFill.web.d.ts +27 -0
- package/lib/typescript/src/components/ProductMerchandisingCard/ProductMerchandisingCard.d.ts +81 -0
- package/lib/typescript/src/components/ProjectionMarker/ProjectionMarker.d.ts +82 -0
- package/lib/typescript/src/components/Radio/Radio.d.ts +3 -2
- package/lib/typescript/src/components/RadioButton/RadioButton.d.ts +2 -2
- package/lib/typescript/src/components/Slider/Slider.d.ts +99 -0
- package/lib/typescript/src/components/TextInput/TextInput.d.ts +9 -29
- package/lib/typescript/src/components/TextSegment/TextSegment.d.ts +100 -0
- package/lib/typescript/src/components/index.d.ts +10 -1
- package/lib/typescript/src/design-tokens/figma-modes.generated.d.ts +22 -2
- package/lib/typescript/src/icons/registry.d.ts +1 -1
- package/lib/typescript/src/utils/react-utils.d.ts +10 -0
- package/package.json +2 -1
- package/src/components/AmountInput/AmountInput.tsx +7 -5
- package/src/components/BenefitCard/BenefitCard.tsx +309 -0
- package/src/components/CcCard/CcCard.tsx +598 -0
- package/src/components/Checkbox/Checkbox.tsx +5 -4
- package/src/components/CheckboxItem/CheckboxItem.tsx +5 -4
- package/src/components/CompareTable/CompareTable.tsx +477 -0
- package/src/components/ComparisonBar/ComparisonBar.tsx +356 -0
- package/src/components/DropdownInput/DropdownInput.tsx +55 -3
- package/src/components/FormField/FormField.tsx +5 -4
- package/src/components/InputSearch/InputSearch.tsx +8 -5
- package/src/components/NoteInput/NoteInput.tsx +8 -6
- package/src/components/PdpCcCard/PdpCcCard.tsx +356 -0
- package/src/components/ProductMerchandisingCard/GlassFill.tsx +276 -0
- package/src/components/ProductMerchandisingCard/GlassFill.web.tsx +127 -0
- package/src/components/ProductMerchandisingCard/ProductMerchandisingCard.tsx +423 -0
- package/src/components/ProjectionMarker/ProjectionMarker.tsx +277 -0
- package/src/components/Radio/Radio.tsx +5 -4
- package/src/components/Slider/Slider.tsx +628 -0
- package/src/components/TextInput/TextInput.tsx +15 -11
- package/src/components/TextSegment/TextSegment.tsx +166 -0
- package/src/components/index.ts +10 -1
- package/src/design-tokens/Coin Variables-variables-full.json +1 -1
- package/src/design-tokens/figma-modes.generated.ts +38 -9
- package/src/icons/registry.ts +1 -1
- package/src/utils/react-utils.ts +23 -0
- package/lib/typescript/scripts/extract-component-tokens.d.ts +0 -9
- package/lib/typescript/scripts/generate-component-docs.d.ts +0 -9
- package/lib/typescript/scripts/generate-icon-registry.d.ts +0 -3
- package/lib/typescript/scripts/generate-mode-types.d.ts +0 -2
- package/lib/typescript/scripts/retype-modes.d.cts +0 -2
|
@@ -0,0 +1,464 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import React, { useMemo } from 'react';
|
|
4
|
+
import { View, Text, Pressable, StyleSheet } from 'react-native';
|
|
5
|
+
import { getVariableByName } from '../../design-tokens/figma-variables-resolver';
|
|
6
|
+
import { EMPTY_MODES, cloneChildrenWithModes } from '../../utils/react-utils';
|
|
7
|
+
import Badge from '../Badge/Badge';
|
|
8
|
+
import Avatar from '../Avatar/Avatar';
|
|
9
|
+
import Image from '../Image/Image';
|
|
10
|
+
import Icon from '../Icon/Icon';
|
|
11
|
+
import Title from '../Title/Title';
|
|
12
|
+
import ListItem from '../ListItem/ListItem';
|
|
13
|
+
import TextSegment from '../TextSegment/TextSegment';
|
|
14
|
+
import Button from '../Button/Button';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* A single coloured chip rendered in the card header. Each badge resolves its
|
|
18
|
+
* own design tokens through `modes`, so different appearances (brand, tonal,
|
|
19
|
+
* etc.) can sit side-by-side in the same group.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* A single benefit row in the card's list, rendered through the shared
|
|
24
|
+
* {@link ListItem} primitive (leading icon + title).
|
|
25
|
+
*/
|
|
26
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
27
|
+
/**
|
|
28
|
+
* CcCard — Figma node 5434:1992 ("Cc Card").
|
|
29
|
+
*
|
|
30
|
+
* A white, rounded credit-card product card composed entirely from the shared
|
|
31
|
+
* design-system primitives so it stays in sync with the rest of the library:
|
|
32
|
+
*
|
|
33
|
+
* - **Header** — two {@link Badge} groups (a leading group + a right-aligned
|
|
34
|
+
* trailing group), e.g. `Pre-qualified` / `Lifetime free`.
|
|
35
|
+
* - **Media** — a product `Image` + a {@link Title} (title + subtitle resolved
|
|
36
|
+
* through the `context7: Card` mode → 14px/12px).
|
|
37
|
+
* - **List** — a column of benefit {@link ListItem}s (`List Item Style:
|
|
38
|
+
* Minimal`) with leading icons.
|
|
39
|
+
* - **Nudge** — an inline upsell row: an {@link Avatar} + a {@link TextSegment}.
|
|
40
|
+
* - **Footer** — a headline + description + subtitle text block alongside a
|
|
41
|
+
* small {@link Button} (`Button / Size: S`, `AppearanceBrand: Secondary`).
|
|
42
|
+
*
|
|
43
|
+
* The {@link CcCardProps.compact} variant collapses the card to just the
|
|
44
|
+
* leading avatar slot + the footer text block (no CTA button). All defaults can
|
|
45
|
+
* be overridden via `modes`.
|
|
46
|
+
*/
|
|
47
|
+
function CcCard({
|
|
48
|
+
compact = false,
|
|
49
|
+
showHeader = true,
|
|
50
|
+
badges = DEFAULT_BADGES,
|
|
51
|
+
trailingBadges,
|
|
52
|
+
header,
|
|
53
|
+
imageSource,
|
|
54
|
+
imageWidth = 88,
|
|
55
|
+
imageHeight = 54,
|
|
56
|
+
title = 'Title',
|
|
57
|
+
subtitle = 'Subtitle',
|
|
58
|
+
media,
|
|
59
|
+
items = DEFAULT_ITEMS,
|
|
60
|
+
showNudge = true,
|
|
61
|
+
nudgeSegments = DEFAULT_NUDGE_SEGMENTS,
|
|
62
|
+
nudgeAvatarSource,
|
|
63
|
+
nudge,
|
|
64
|
+
headline = 'Headline',
|
|
65
|
+
description = 'Description',
|
|
66
|
+
footerSubtitle = 'Subtitle',
|
|
67
|
+
footer,
|
|
68
|
+
buttonLabel = 'Button',
|
|
69
|
+
onButtonPress,
|
|
70
|
+
button,
|
|
71
|
+
showButton = true,
|
|
72
|
+
onPress,
|
|
73
|
+
width = 343,
|
|
74
|
+
modes = EMPTY_MODES,
|
|
75
|
+
style,
|
|
76
|
+
accessibilityLabel
|
|
77
|
+
}) {
|
|
78
|
+
const tokens = useMemo(() => resolveTokens(modes), [modes]);
|
|
79
|
+
|
|
80
|
+
// The product title uses the card-sized type ramp (14px bold + 12px
|
|
81
|
+
// subtitle) via the `context7: Card` mode. Consumer modes still win.
|
|
82
|
+
const titleModes = useMemo(() => ({
|
|
83
|
+
context7: 'Card',
|
|
84
|
+
...modes
|
|
85
|
+
}), [modes]);
|
|
86
|
+
// List rows use the minimal style (12px / regular, no padding).
|
|
87
|
+
const listItemModes = useMemo(() => ({
|
|
88
|
+
'List Item Style': 'Minimal',
|
|
89
|
+
...modes
|
|
90
|
+
}), [modes]);
|
|
91
|
+
// The nudge avatar is the smallest size token.
|
|
92
|
+
const nudgeAvatarModes = useMemo(() => ({
|
|
93
|
+
'Avatar Size': 'XS',
|
|
94
|
+
...modes
|
|
95
|
+
}), [modes]);
|
|
96
|
+
// The CTA is the small, brand-secondary (lilac→purple) button.
|
|
97
|
+
const ctaModes = useMemo(() => ({
|
|
98
|
+
AppearanceBrand: 'Secondary',
|
|
99
|
+
'Button / Size': 'S',
|
|
100
|
+
...modes
|
|
101
|
+
}), [modes]);
|
|
102
|
+
|
|
103
|
+
// ---- Header -----------------------------------------------------------
|
|
104
|
+
const headerNode = header ? cloneChildrenWithModes(header, modes) : showHeader && (badges?.length || trailingBadges?.length) ? /*#__PURE__*/_jsxs(View, {
|
|
105
|
+
style: styles.header,
|
|
106
|
+
children: [/*#__PURE__*/_jsx(BadgeGroup, {
|
|
107
|
+
badges: badges,
|
|
108
|
+
modes: modes
|
|
109
|
+
}), trailingBadges?.length ? /*#__PURE__*/_jsx(BadgeGroup, {
|
|
110
|
+
badges: trailingBadges,
|
|
111
|
+
modes: modes
|
|
112
|
+
}) : null]
|
|
113
|
+
}) : null;
|
|
114
|
+
|
|
115
|
+
// ---- Media slot (shared by both compact + non-compact) ----------------
|
|
116
|
+
// Whatever lives in the slot is rendered identically in both variants; only
|
|
117
|
+
// the surrounding sections differ. The default is an Image driven by
|
|
118
|
+
// `imageSource`, but a consumer can pass an Avatar (or any node) via `media`.
|
|
119
|
+
const mediaSlotContent = media ? cloneChildrenWithModes(media, modes) : /*#__PURE__*/_jsx(Image, {
|
|
120
|
+
imageSource: imageSource,
|
|
121
|
+
width: imageWidth,
|
|
122
|
+
height: imageHeight,
|
|
123
|
+
borderRadius: tokens.imageRadius,
|
|
124
|
+
resizeMode: "cover",
|
|
125
|
+
accessibilityElementsHidden: true,
|
|
126
|
+
importantForAccessibility: "no"
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
// Non-compact lays the slot out in a row next to the product Title.
|
|
130
|
+
const mediaRow = /*#__PURE__*/_jsxs(View, {
|
|
131
|
+
style: styles.mediaSlot,
|
|
132
|
+
children: [mediaSlotContent, /*#__PURE__*/_jsx(View, {
|
|
133
|
+
style: styles.titleWrap,
|
|
134
|
+
children: /*#__PURE__*/_jsx(Title, {
|
|
135
|
+
title: title,
|
|
136
|
+
subtitle: subtitle,
|
|
137
|
+
textAlign: "Left",
|
|
138
|
+
modes: titleModes,
|
|
139
|
+
style: styles.titleInner
|
|
140
|
+
})
|
|
141
|
+
})]
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// ---- List -------------------------------------------------------------
|
|
145
|
+
const listNode = items.length > 0 ? /*#__PURE__*/_jsx(View, {
|
|
146
|
+
style: tokens.listGroup,
|
|
147
|
+
children: items.map((item, index) => {
|
|
148
|
+
const leading = item.leading ?? (item.icon !== null ? /*#__PURE__*/_jsx(Icon, {
|
|
149
|
+
iconName: item.icon ?? 'ic_card',
|
|
150
|
+
color: item.iconColor,
|
|
151
|
+
modes: listItemModes
|
|
152
|
+
}) : null);
|
|
153
|
+
return /*#__PURE__*/_jsx(ListItem, {
|
|
154
|
+
layout: "Horizontal",
|
|
155
|
+
navArrow: false,
|
|
156
|
+
showSupportText: false,
|
|
157
|
+
title: item.title,
|
|
158
|
+
leading: leading,
|
|
159
|
+
onPress: item.onPress,
|
|
160
|
+
modes: listItemModes
|
|
161
|
+
}, index);
|
|
162
|
+
})
|
|
163
|
+
}) : null;
|
|
164
|
+
|
|
165
|
+
// ---- Nudge ------------------------------------------------------------
|
|
166
|
+
const nudgeNode = nudge ? cloneChildrenWithModes(nudge, modes) : showNudge ? /*#__PURE__*/_jsxs(View, {
|
|
167
|
+
style: tokens.nudge,
|
|
168
|
+
children: [/*#__PURE__*/_jsx(Avatar, {
|
|
169
|
+
imageSource: nudgeAvatarSource,
|
|
170
|
+
modes: nudgeAvatarModes
|
|
171
|
+
}), /*#__PURE__*/_jsx(View, {
|
|
172
|
+
style: styles.nudgeContent,
|
|
173
|
+
children: /*#__PURE__*/_jsx(TextSegment, {
|
|
174
|
+
segments: nudgeSegments,
|
|
175
|
+
modes: modes
|
|
176
|
+
})
|
|
177
|
+
})]
|
|
178
|
+
}) : null;
|
|
179
|
+
|
|
180
|
+
// ---- Footer -----------------------------------------------------------
|
|
181
|
+
const ctaNode = button ? cloneChildrenWithModes(button, ctaModes) : /*#__PURE__*/_jsx(Button, {
|
|
182
|
+
label: buttonLabel,
|
|
183
|
+
modes: ctaModes,
|
|
184
|
+
onPress: onButtonPress
|
|
185
|
+
});
|
|
186
|
+
const footerTextBlock = footer ? cloneChildrenWithModes(footer, modes) : /*#__PURE__*/_jsxs(View, {
|
|
187
|
+
style: tokens.footerTextWrap,
|
|
188
|
+
children: [headline != null ? /*#__PURE__*/_jsx(Text, {
|
|
189
|
+
style: tokens.headline,
|
|
190
|
+
children: headline
|
|
191
|
+
}) : null, /*#__PURE__*/_jsxs(View, {
|
|
192
|
+
style: compact ? tokens.titleWrapCompact : tokens.titleWrapDefault,
|
|
193
|
+
children: [description != null ? /*#__PURE__*/_jsx(Text, {
|
|
194
|
+
style: tokens.footerTitle,
|
|
195
|
+
children: description
|
|
196
|
+
}) : null, footerSubtitle != null ? /*#__PURE__*/_jsx(Text, {
|
|
197
|
+
style: tokens.footerSubtitle,
|
|
198
|
+
children: footerSubtitle
|
|
199
|
+
}) : null]
|
|
200
|
+
})]
|
|
201
|
+
});
|
|
202
|
+
const footerNode = /*#__PURE__*/_jsxs(View, {
|
|
203
|
+
style: compact ? tokens.footerRowCompact : tokens.footerRowDefault,
|
|
204
|
+
children: [footerTextBlock, !compact && showButton ? ctaNode : null]
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
// ---- Compose ----------------------------------------------------------
|
|
208
|
+
const content = compact ? /*#__PURE__*/_jsxs(_Fragment, {
|
|
209
|
+
children: [/*#__PURE__*/_jsx(View, {
|
|
210
|
+
style: styles.compactSlot,
|
|
211
|
+
children: mediaSlotContent
|
|
212
|
+
}), footerNode]
|
|
213
|
+
}) : /*#__PURE__*/_jsxs(_Fragment, {
|
|
214
|
+
children: [headerNode, mediaRow, listNode, nudgeNode, footerNode]
|
|
215
|
+
});
|
|
216
|
+
const containerStyle = useMemo(() => ({
|
|
217
|
+
...tokens.container,
|
|
218
|
+
width
|
|
219
|
+
}), [tokens.container, width]);
|
|
220
|
+
if (onPress) {
|
|
221
|
+
return /*#__PURE__*/_jsx(Pressable, {
|
|
222
|
+
style: ({
|
|
223
|
+
pressed
|
|
224
|
+
}) => [containerStyle, pressed ? styles.pressed : null, style],
|
|
225
|
+
accessibilityRole: "button",
|
|
226
|
+
accessibilityLabel: accessibilityLabel ?? title,
|
|
227
|
+
onPress: onPress,
|
|
228
|
+
children: content
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
return /*#__PURE__*/_jsx(View, {
|
|
232
|
+
style: [containerStyle, style],
|
|
233
|
+
accessibilityLabel: accessibilityLabel,
|
|
234
|
+
children: content
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// ---------------------------------------------------------------------------
|
|
239
|
+
// BadgeGroup — internal wrapping row of badges
|
|
240
|
+
// ---------------------------------------------------------------------------
|
|
241
|
+
|
|
242
|
+
function BadgeGroup({
|
|
243
|
+
badges,
|
|
244
|
+
modes
|
|
245
|
+
}) {
|
|
246
|
+
return /*#__PURE__*/_jsx(View, {
|
|
247
|
+
style: styles.badgeGroup,
|
|
248
|
+
children: badges.map((badge, index) => {
|
|
249
|
+
const badgeModes = badge.modes ? {
|
|
250
|
+
...modes,
|
|
251
|
+
...badge.modes
|
|
252
|
+
} : modes;
|
|
253
|
+
return /*#__PURE__*/_jsx(Badge, {
|
|
254
|
+
label: badge.label,
|
|
255
|
+
modes: badgeModes,
|
|
256
|
+
style: badge.color ? {
|
|
257
|
+
backgroundColor: badge.color
|
|
258
|
+
} : undefined,
|
|
259
|
+
labelStyle: badge.labelColor ? {
|
|
260
|
+
color: badge.labelColor
|
|
261
|
+
} : undefined
|
|
262
|
+
}, index);
|
|
263
|
+
})
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// ---------------------------------------------------------------------------
|
|
268
|
+
// Tokens / static styles
|
|
269
|
+
// ---------------------------------------------------------------------------
|
|
270
|
+
|
|
271
|
+
function asNum(raw, fallback) {
|
|
272
|
+
const n = typeof raw === 'number' ? raw : parseFloat(raw);
|
|
273
|
+
return Number.isFinite(n) ? n : fallback;
|
|
274
|
+
}
|
|
275
|
+
function asStr(raw, fallback) {
|
|
276
|
+
return raw != null ? String(raw) : fallback;
|
|
277
|
+
}
|
|
278
|
+
function resolveTokens(modes) {
|
|
279
|
+
// NOTE: token names are passed as string literals DIRECTLY to
|
|
280
|
+
// getVariableByName so the `extract-component-tokens` script can statically
|
|
281
|
+
// collect them for the generated docs. Do not refactor these into a helper
|
|
282
|
+
// that receives the name as a variable.
|
|
283
|
+
const background = asStr(getVariableByName('ccCard/bg', modes), '#ffffff');
|
|
284
|
+
const borderColor = asStr(getVariableByName('ccCard/border/color', modes), '#e3e4e4');
|
|
285
|
+
const borderWidth = asNum(getVariableByName('ccCard/border/size', modes), 1);
|
|
286
|
+
const radius = asNum(getVariableByName('ccCard/radius', modes), 12);
|
|
287
|
+
const paddingHorizontal = asNum(getVariableByName('ccCard/padding/horizontal', modes), 12);
|
|
288
|
+
const paddingVertical = asNum(getVariableByName('ccCard/padding/vertical', modes), 12);
|
|
289
|
+
const gap = asNum(getVariableByName('ccCard/padding/gap', modes), 8);
|
|
290
|
+
const imageRadius = asNum(getVariableByName('image/radius', modes), 0);
|
|
291
|
+
const listGroupGap = asNum(getVariableByName('listGroup/gap', modes), 4);
|
|
292
|
+
const nudgeGap = asNum(getVariableByName('nudge/gap', modes), 6);
|
|
293
|
+
const footerGap = asNum(getVariableByName('ccCard/footer/gap', modes), 8);
|
|
294
|
+
const textWrapGap = asNum(getVariableByName('ccCard/footer/textWrap/gap', modes), 4);
|
|
295
|
+
const titleWrapGap = asNum(getVariableByName('ccCard/footer/titleWrap/gap', modes), 8);
|
|
296
|
+
const headlineColor = asStr(getVariableByName('ccCard/headline/color', modes), '#707275');
|
|
297
|
+
const headlineSize = asNum(getVariableByName('ccCard/headline/fontSize', modes), 10);
|
|
298
|
+
const headlineFamily = asStr(getVariableByName('ccCard/headline/fontFamily', modes), 'JioType Var');
|
|
299
|
+
const headlineLineHeight = asNum(getVariableByName('ccCard/headline/lineHeight', modes), 13);
|
|
300
|
+
const headlineWeight = asStr(getVariableByName('ccCard/headline/fontWeight', modes), '500');
|
|
301
|
+
const titleColor = asStr(getVariableByName('ccCard/title/color', modes), '#081007');
|
|
302
|
+
const titleSize = asNum(getVariableByName('ccCard/title/fontSize', modes), 14);
|
|
303
|
+
const titleFamily = asStr(getVariableByName('ccCard/title/fontFamily', modes), 'JioType Var');
|
|
304
|
+
const titleLineHeight = asNum(getVariableByName('ccCard/title/lineHeight', modes), 15);
|
|
305
|
+
const titleWeight = asStr(getVariableByName('ccCard/title/fontWeight', modes), '700');
|
|
306
|
+
const subtitleColor = asStr(getVariableByName('ccCard/subtitle/color', modes), '#707275');
|
|
307
|
+
const subtitleSize = asNum(getVariableByName('ccCard/subtitle/fontSize', modes), 10);
|
|
308
|
+
const subtitleFamily = asStr(getVariableByName('ccCard/subtitle/fontFamily', modes), 'JioType Var');
|
|
309
|
+
const subtitleLineHeight = asNum(getVariableByName('ccCard/subtitle/lineHeight', modes), 13);
|
|
310
|
+
const subtitleWeight = asStr(getVariableByName('ccCard/subtitle/fontWeight', modes), '500');
|
|
311
|
+
return {
|
|
312
|
+
container: {
|
|
313
|
+
backgroundColor: background,
|
|
314
|
+
borderColor,
|
|
315
|
+
borderWidth,
|
|
316
|
+
borderRadius: radius,
|
|
317
|
+
paddingHorizontal,
|
|
318
|
+
paddingVertical,
|
|
319
|
+
gap,
|
|
320
|
+
flexDirection: 'column',
|
|
321
|
+
alignItems: 'flex-start',
|
|
322
|
+
overflow: 'hidden'
|
|
323
|
+
},
|
|
324
|
+
imageRadius,
|
|
325
|
+
listGroup: {
|
|
326
|
+
alignSelf: 'stretch',
|
|
327
|
+
gap: listGroupGap
|
|
328
|
+
},
|
|
329
|
+
nudge: {
|
|
330
|
+
alignSelf: 'stretch',
|
|
331
|
+
flexDirection: 'row',
|
|
332
|
+
alignItems: 'center',
|
|
333
|
+
gap: nudgeGap
|
|
334
|
+
},
|
|
335
|
+
footerRowDefault: {
|
|
336
|
+
alignSelf: 'stretch',
|
|
337
|
+
flexDirection: 'row',
|
|
338
|
+
alignItems: 'flex-end',
|
|
339
|
+
gap: footerGap
|
|
340
|
+
},
|
|
341
|
+
footerRowCompact: {
|
|
342
|
+
alignSelf: 'stretch',
|
|
343
|
+
flexDirection: 'row',
|
|
344
|
+
alignItems: 'center'
|
|
345
|
+
},
|
|
346
|
+
footerTextWrap: {
|
|
347
|
+
flex: 1,
|
|
348
|
+
minWidth: 1,
|
|
349
|
+
alignItems: 'flex-start',
|
|
350
|
+
gap: textWrapGap
|
|
351
|
+
},
|
|
352
|
+
titleWrapDefault: {
|
|
353
|
+
flexDirection: 'row',
|
|
354
|
+
alignItems: 'flex-end',
|
|
355
|
+
gap: textWrapGap
|
|
356
|
+
},
|
|
357
|
+
titleWrapCompact: {
|
|
358
|
+
flexDirection: 'row',
|
|
359
|
+
alignItems: 'flex-end',
|
|
360
|
+
gap: titleWrapGap
|
|
361
|
+
},
|
|
362
|
+
headline: {
|
|
363
|
+
color: headlineColor,
|
|
364
|
+
fontSize: headlineSize,
|
|
365
|
+
fontFamily: headlineFamily,
|
|
366
|
+
fontWeight: headlineWeight,
|
|
367
|
+
lineHeight: Math.max(headlineLineHeight, Math.ceil(headlineSize * 1.2)),
|
|
368
|
+
includeFontPadding: false
|
|
369
|
+
},
|
|
370
|
+
footerTitle: {
|
|
371
|
+
color: titleColor,
|
|
372
|
+
fontSize: titleSize,
|
|
373
|
+
fontFamily: titleFamily,
|
|
374
|
+
fontWeight: titleWeight,
|
|
375
|
+
lineHeight: Math.max(titleLineHeight, Math.ceil(titleSize * 1.2)),
|
|
376
|
+
includeFontPadding: false
|
|
377
|
+
},
|
|
378
|
+
footerSubtitle: {
|
|
379
|
+
color: subtitleColor,
|
|
380
|
+
fontSize: subtitleSize,
|
|
381
|
+
fontFamily: subtitleFamily,
|
|
382
|
+
fontWeight: subtitleWeight,
|
|
383
|
+
lineHeight: Math.max(subtitleLineHeight, Math.ceil(subtitleSize * 1.2)),
|
|
384
|
+
includeFontPadding: false
|
|
385
|
+
}
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
const DEFAULT_BADGES = [{
|
|
389
|
+
label: 'Pre-qualified',
|
|
390
|
+
modes: {
|
|
391
|
+
AppearanceBrand: 'Tertiary'
|
|
392
|
+
},
|
|
393
|
+
labelColor: '#ffffff'
|
|
394
|
+
}, {
|
|
395
|
+
label: 'Lifetime free',
|
|
396
|
+
modes: {
|
|
397
|
+
AppearanceBrand: 'Tertiary'
|
|
398
|
+
},
|
|
399
|
+
labelColor: '#ffffff'
|
|
400
|
+
}];
|
|
401
|
+
const DEFAULT_ITEMS = [{
|
|
402
|
+
icon: 'ic_card',
|
|
403
|
+
title: '4 domestic + 2 intl. lounge access yearly'
|
|
404
|
+
}, {
|
|
405
|
+
icon: 'ic_card',
|
|
406
|
+
title: '5% cashback on dining & travel'
|
|
407
|
+
}, {
|
|
408
|
+
icon: 'ic_card',
|
|
409
|
+
title: 'No annual fee for the first year'
|
|
410
|
+
}];
|
|
411
|
+
const DEFAULT_NUDGE_SEGMENTS = [{
|
|
412
|
+
text: 'Upsell message '
|
|
413
|
+
}, {
|
|
414
|
+
text: 'JioFinance+',
|
|
415
|
+
modes: {
|
|
416
|
+
'Text Appearance': 'Primary'
|
|
417
|
+
}
|
|
418
|
+
}];
|
|
419
|
+
const styles = StyleSheet.create({
|
|
420
|
+
header: {
|
|
421
|
+
alignSelf: 'stretch',
|
|
422
|
+
flexDirection: 'row',
|
|
423
|
+
alignItems: 'flex-start',
|
|
424
|
+
justifyContent: 'space-between',
|
|
425
|
+
gap: 8
|
|
426
|
+
},
|
|
427
|
+
badgeGroup: {
|
|
428
|
+
flexDirection: 'row',
|
|
429
|
+
flexWrap: 'wrap',
|
|
430
|
+
alignItems: 'center',
|
|
431
|
+
gap: 4,
|
|
432
|
+
flexShrink: 1
|
|
433
|
+
},
|
|
434
|
+
mediaSlot: {
|
|
435
|
+
alignSelf: 'stretch',
|
|
436
|
+
flexDirection: 'row',
|
|
437
|
+
alignItems: 'center',
|
|
438
|
+
gap: 8
|
|
439
|
+
},
|
|
440
|
+
titleWrap: {
|
|
441
|
+
flex: 1,
|
|
442
|
+
minWidth: 1
|
|
443
|
+
},
|
|
444
|
+
// The shared Title falls back to 16/8 padding when its tokens resolve to 0
|
|
445
|
+
// (0 is falsy). Zero it out so the only horizontal gap to the media slot is
|
|
446
|
+
// the mediaSlot's hard-coded 8px.
|
|
447
|
+
titleInner: {
|
|
448
|
+
paddingHorizontal: 0,
|
|
449
|
+
paddingVertical: 0
|
|
450
|
+
},
|
|
451
|
+
// Compact media wrapper hugs its child so the slot sizes to the avatar /
|
|
452
|
+
// image's intrinsic dimensions instead of stretching to the card width.
|
|
453
|
+
compactSlot: {
|
|
454
|
+
alignSelf: 'flex-start'
|
|
455
|
+
},
|
|
456
|
+
nudgeContent: {
|
|
457
|
+
flex: 1,
|
|
458
|
+
minWidth: 1
|
|
459
|
+
},
|
|
460
|
+
pressed: {
|
|
461
|
+
opacity: 0.92
|
|
462
|
+
}
|
|
463
|
+
});
|
|
464
|
+
export default CcCard;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
3
|
+
import React, { forwardRef, useCallback, useEffect, useRef, useState } from 'react';
|
|
4
4
|
import { Pressable, Platform, View } from 'react-native';
|
|
5
5
|
import Svg, { Path } from 'react-native-svg';
|
|
6
6
|
import { getVariableByName } from '../../design-tokens/figma-variables-resolver';
|
|
@@ -78,7 +78,7 @@ function invisibleTouchHitSlop(checkboxSize) {
|
|
|
78
78
|
* @component
|
|
79
79
|
* @param {CheckboxProps} props
|
|
80
80
|
*/
|
|
81
|
-
function Checkbox({
|
|
81
|
+
const Checkbox = /*#__PURE__*/forwardRef(function Checkbox({
|
|
82
82
|
checked: controlledChecked,
|
|
83
83
|
defaultChecked = false,
|
|
84
84
|
onValueChange,
|
|
@@ -86,7 +86,7 @@ function Checkbox({
|
|
|
86
86
|
modes = EMPTY_MODES,
|
|
87
87
|
style,
|
|
88
88
|
accessibilityLabel
|
|
89
|
-
}) {
|
|
89
|
+
}, ref) {
|
|
90
90
|
const isControlled = controlledChecked !== undefined;
|
|
91
91
|
const [internalChecked, setInternalChecked] = useState(defaultChecked);
|
|
92
92
|
const isChecked = isControlled ? controlledChecked : internalChecked;
|
|
@@ -194,6 +194,7 @@ function Checkbox({
|
|
|
194
194
|
const markColor = disabled && isChecked ? disabledActiveMark : selectedMarkColor;
|
|
195
195
|
const hitSlop = invisibleTouchHitSlop(size);
|
|
196
196
|
return /*#__PURE__*/_jsx(Pressable, {
|
|
197
|
+
ref: ref,
|
|
197
198
|
style: [touchTargetStyle, style],
|
|
198
199
|
hitSlop: hitSlop,
|
|
199
200
|
onPress: handlePress,
|
|
@@ -221,7 +222,7 @@ function Checkbox({
|
|
|
221
222
|
})
|
|
222
223
|
})
|
|
223
224
|
});
|
|
224
|
-
}
|
|
225
|
+
});
|
|
225
226
|
function boxShadow(value) {
|
|
226
227
|
if (Platform.OS === 'web') {
|
|
227
228
|
return {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
import React, { useCallback, useState } from 'react';
|
|
3
|
+
import React, { forwardRef, useCallback, useState } from 'react';
|
|
4
4
|
import { View, Text, Pressable } from 'react-native';
|
|
5
5
|
import { getVariableByName } from '../../design-tokens/figma-variables-resolver';
|
|
6
6
|
import { EMPTY_MODES, cloneChildrenWithModes } from '../../utils/react-utils';
|
|
@@ -33,7 +33,7 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
33
33
|
* />
|
|
34
34
|
* ```
|
|
35
35
|
*/
|
|
36
|
-
function CheckboxItem({
|
|
36
|
+
const CheckboxItem = /*#__PURE__*/forwardRef(function CheckboxItem({
|
|
37
37
|
checked: controlledChecked,
|
|
38
38
|
defaultChecked = false,
|
|
39
39
|
onValueChange,
|
|
@@ -46,7 +46,7 @@ function CheckboxItem({
|
|
|
46
46
|
style,
|
|
47
47
|
labelStyle,
|
|
48
48
|
accessibilityLabel
|
|
49
|
-
}) {
|
|
49
|
+
}, ref) {
|
|
50
50
|
const isTrailing = control === 'trailing';
|
|
51
51
|
const isControlled = controlledChecked !== undefined;
|
|
52
52
|
const [internalChecked, setInternalChecked] = useState(defaultChecked);
|
|
@@ -115,6 +115,7 @@ function CheckboxItem({
|
|
|
115
115
|
children: cloneChildrenWithModes(endSlot, modes)
|
|
116
116
|
}) : null;
|
|
117
117
|
return /*#__PURE__*/_jsx(Pressable, {
|
|
118
|
+
ref: ref,
|
|
118
119
|
style: [containerStyle, style],
|
|
119
120
|
onPress: handleToggle,
|
|
120
121
|
disabled: disabled,
|
|
@@ -130,5 +131,5 @@ function CheckboxItem({
|
|
|
130
131
|
children: [checkboxNode, labelNode, endSlotNode]
|
|
131
132
|
})
|
|
132
133
|
});
|
|
133
|
-
}
|
|
134
|
+
});
|
|
134
135
|
export default CheckboxItem;
|