jfs-components 0.0.77 → 0.0.78

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.
Files changed (70) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/lib/commonjs/components/Accordion/Accordion.js +55 -55
  3. package/lib/commonjs/components/ActionFooter/ActionFooter.js +48 -2
  4. package/lib/commonjs/components/Checkbox/Checkbox.js +21 -9
  5. package/lib/commonjs/components/DropdownInput/DropdownInput.js +30 -16
  6. package/lib/commonjs/components/ExpandableCheckbox/ExpandableCheckbox.js +167 -0
  7. package/lib/commonjs/components/FormField/FormField.js +14 -1
  8. package/lib/commonjs/components/FullscreenModal/FullscreenModal.js +355 -0
  9. package/lib/commonjs/components/ListItem/ListItem.js +25 -10
  10. package/lib/commonjs/components/MessageField/MessageField.js +318 -0
  11. package/lib/commonjs/components/NavArrow/NavArrow.js +58 -17
  12. package/lib/commonjs/components/Stepper/Step.js +47 -60
  13. package/lib/commonjs/components/Stepper/StepLabel.js +40 -10
  14. package/lib/commonjs/components/Stepper/Stepper.js +15 -17
  15. package/lib/commonjs/components/SuggestiveSearch/SuggestiveSearch.js +487 -0
  16. package/lib/commonjs/components/TextInput/TextInput.js +16 -1
  17. package/lib/commonjs/components/Title/Title.js +10 -2
  18. package/lib/commonjs/components/index.js +28 -0
  19. package/lib/commonjs/design-tokens/Coin Variables-variables-full.json +1 -1
  20. package/lib/commonjs/icons/registry.js +1 -1
  21. package/lib/module/components/Accordion/Accordion.js +56 -56
  22. package/lib/module/components/ActionFooter/ActionFooter.js +50 -4
  23. package/lib/module/components/Checkbox/Checkbox.js +22 -10
  24. package/lib/module/components/DropdownInput/DropdownInput.js +30 -16
  25. package/lib/module/components/ExpandableCheckbox/ExpandableCheckbox.js +161 -0
  26. package/lib/module/components/FormField/FormField.js +16 -3
  27. package/lib/module/components/FullscreenModal/FullscreenModal.js +350 -0
  28. package/lib/module/components/ListItem/ListItem.js +25 -10
  29. package/lib/module/components/MessageField/MessageField.js +313 -0
  30. package/lib/module/components/NavArrow/NavArrow.js +59 -18
  31. package/lib/module/components/Stepper/Step.js +48 -61
  32. package/lib/module/components/Stepper/StepLabel.js +40 -10
  33. package/lib/module/components/Stepper/Stepper.js +15 -17
  34. package/lib/module/components/SuggestiveSearch/SuggestiveSearch.js +481 -0
  35. package/lib/module/components/TextInput/TextInput.js +17 -2
  36. package/lib/module/components/Title/Title.js +10 -2
  37. package/lib/module/components/index.js +4 -0
  38. package/lib/module/design-tokens/Coin Variables-variables-full.json +1 -1
  39. package/lib/module/icons/registry.js +1 -1
  40. package/lib/typescript/src/components/Accordion/Accordion.d.ts +14 -20
  41. package/lib/typescript/src/components/ExpandableCheckbox/ExpandableCheckbox.d.ts +63 -0
  42. package/lib/typescript/src/components/FullscreenModal/FullscreenModal.d.ts +99 -0
  43. package/lib/typescript/src/components/MessageField/MessageField.d.ts +81 -0
  44. package/lib/typescript/src/components/NavArrow/NavArrow.d.ts +10 -5
  45. package/lib/typescript/src/components/Stepper/Step.d.ts +4 -1
  46. package/lib/typescript/src/components/Stepper/StepLabel.d.ts +4 -1
  47. package/lib/typescript/src/components/Stepper/Stepper.d.ts +3 -1
  48. package/lib/typescript/src/components/SuggestiveSearch/SuggestiveSearch.d.ts +123 -0
  49. package/lib/typescript/src/components/index.d.ts +7 -3
  50. package/lib/typescript/src/icons/registry.d.ts +1 -1
  51. package/package.json +1 -1
  52. package/src/components/Accordion/Accordion.tsx +113 -73
  53. package/src/components/ActionFooter/ActionFooter.tsx +56 -4
  54. package/src/components/Checkbox/Checkbox.tsx +22 -9
  55. package/src/components/DropdownInput/DropdownInput.tsx +67 -39
  56. package/src/components/ExpandableCheckbox/ExpandableCheckbox.tsx +237 -0
  57. package/src/components/FormField/FormField.tsx +19 -3
  58. package/src/components/FullscreenModal/FullscreenModal.tsx +414 -0
  59. package/src/components/ListItem/ListItem.tsx +21 -10
  60. package/src/components/MessageField/MessageField.tsx +543 -0
  61. package/src/components/NavArrow/NavArrow.tsx +81 -17
  62. package/src/components/Stepper/Step.tsx +52 -51
  63. package/src/components/Stepper/StepLabel.tsx +46 -9
  64. package/src/components/Stepper/Stepper.tsx +20 -15
  65. package/src/components/SuggestiveSearch/SuggestiveSearch.tsx +756 -0
  66. package/src/components/TextInput/TextInput.tsx +14 -1
  67. package/src/components/Title/Title.tsx +13 -2
  68. package/src/components/index.ts +7 -3
  69. package/src/design-tokens/Coin Variables-variables-full.json +1 -1
  70. package/src/icons/registry.ts +1 -1
@@ -0,0 +1,355 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _react = _interopRequireWildcard(require("react"));
8
+ var _reactNative = require("react-native");
9
+ var _reactNativeReanimated = _interopRequireWildcard(require("react-native-reanimated"));
10
+ var _figmaVariablesResolver = require("../../design-tokens/figma-variables-resolver");
11
+ var _JFSThemeProvider = require("../../design-tokens/JFSThemeProvider");
12
+ var _reactUtils = require("../../utils/react-utils");
13
+ var _Button = _interopRequireDefault(require("../Button/Button"));
14
+ var _Disclaimer = _interopRequireDefault(require("../Disclaimer/Disclaimer"));
15
+ var _IconButton = _interopRequireDefault(require("../IconButton/IconButton"));
16
+ var _ActionFooter = _interopRequireDefault(require("../ActionFooter/ActionFooter"));
17
+ var _jsxRuntime = require("react/jsx-runtime");
18
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
19
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
20
+ // ---------------------------------------------------------------------------
21
+ // Forced modes
22
+ //
23
+ // `FullscreenModal` always themes itself with the `context5: 'Fullscreen Modal'`
24
+ // collection mode. This is what flips the section / list-item / hero text
25
+ // tokens to their white-on-dark values (see the Figma "Fullscreen Modal"
26
+ // context). It is intentionally NON-overridable: callers can pass any other
27
+ // modes (Color Mode, AppearanceBrand, …) but never context5. The frozen
28
+ // object keeps its identity stable so the token resolver's per-modes cache
29
+ // stays hot, and so `cloneChildrenWithModes` can use it as the
30
+ // always-wins `forcedModes` argument.
31
+ // ---------------------------------------------------------------------------
32
+ const FULLSCREEN_MODAL_FORCED_MODES = Object.freeze({
33
+ context5: 'Fullscreen Modal'
34
+ });
35
+
36
+ // Reanimated-driven ScrollView so the parallax handler runs on the UI thread.
37
+ // Module scope so the wrapped component identity is stable across renders.
38
+ const AnimatedScrollView = _reactNativeReanimated.default.createAnimatedComponent(_reactNative.ScrollView);
39
+
40
+ // Parallax tuning. The hero collapses by HEIGHT only as the user scrolls up —
41
+ // its full width is preserved and the media keeps a fixed aspect ratio (it is
42
+ // cropped, never scaled or squished, like a `cover` background). When no
43
+ // explicit `heroMinHeight` is given, the hero collapses to this fraction of
44
+ // its resting height.
45
+ const HERO_MIN_HEIGHT_RATIO = 0.45;
46
+
47
+ // ---------------------------------------------------------------------------
48
+ // Hero text — the eyebrow / headline / supporting / price block. Built inline
49
+ // (rather than reusing <PageHero>) so we can render BOTH a supporting
50
+ // paragraph AND a price line with the exact PageHero token gaps, and overlay
51
+ // it on the parallax media without PageHero's media/button scaffolding.
52
+ // ---------------------------------------------------------------------------
53
+
54
+ function HeroText({
55
+ eyebrow,
56
+ headline,
57
+ supportingText,
58
+ priceText,
59
+ modes
60
+ }) {
61
+ const styles = (0, _react.useMemo)(() => {
62
+ const gap = Number((0, _figmaVariablesResolver.getVariableByName)('PageHero/gap', modes)) || 16;
63
+ const textWrapGap = Number((0, _figmaVariablesResolver.getVariableByName)('PageHero/textWrap/gap', modes)) || 8;
64
+ const eyebrowStyle = {
65
+ color: (0, _figmaVariablesResolver.getVariableByName)('PageHero/eyebrow/color', modes) || '#ffffff',
66
+ fontFamily: (0, _figmaVariablesResolver.getVariableByName)('PageHero/eyebrow/fontFamily', modes) || 'System',
67
+ fontSize: Number((0, _figmaVariablesResolver.getVariableByName)('PageHero/eyebrow/fontSize', modes)) || 18,
68
+ fontWeight: String((0, _figmaVariablesResolver.getVariableByName)('PageHero/eyebrow/fontWeight', modes) || 700),
69
+ lineHeight: Number((0, _figmaVariablesResolver.getVariableByName)('PageHero/eyebrow/lineHeight', modes)) || 20,
70
+ textAlign: 'center'
71
+ };
72
+ const headlineStyle = {
73
+ color: (0, _figmaVariablesResolver.getVariableByName)('PageHero/headline/color', modes) || '#ffffff',
74
+ fontFamily: (0, _figmaVariablesResolver.getVariableByName)('PageHero/headline/fontFamily', modes) || 'System',
75
+ fontSize: Number((0, _figmaVariablesResolver.getVariableByName)('PageHero/headline/fontSize', modes)) || 29,
76
+ fontWeight: String((0, _figmaVariablesResolver.getVariableByName)('PageHero/headline/fontWeight', modes) || 900),
77
+ lineHeight: Number((0, _figmaVariablesResolver.getVariableByName)('PageHero/headline/lineHeight', modes)) || 29,
78
+ textAlign: 'center',
79
+ width: '100%'
80
+ };
81
+ const supportingTextStyle = {
82
+ color: (0, _figmaVariablesResolver.getVariableByName)('PageHero/supportingText/color', modes) || '#ffffff',
83
+ fontFamily: (0, _figmaVariablesResolver.getVariableByName)('PageHero/supportingText/fontFamily', modes) || 'System',
84
+ fontSize: Number((0, _figmaVariablesResolver.getVariableByName)('PageHero/supportingText/fontSize', modes)) || 12,
85
+ fontWeight: String((0, _figmaVariablesResolver.getVariableByName)('PageHero/supportingText/fontWeight', modes) || 500),
86
+ lineHeight: Number((0, _figmaVariablesResolver.getVariableByName)('PageHero/supportingText/lineHeight', modes)) || 16,
87
+ textAlign: 'center'
88
+ };
89
+ const priceTextStyle = {
90
+ color: (0, _figmaVariablesResolver.getVariableByName)('PageHero/body/color', modes) || '#ffffff',
91
+ fontFamily: (0, _figmaVariablesResolver.getVariableByName)('PageHero/body/fontFamily', modes) || 'System',
92
+ fontSize: Number((0, _figmaVariablesResolver.getVariableByName)('PageHero/body/fontSize', modes)) || 12,
93
+ fontWeight: String((0, _figmaVariablesResolver.getVariableByName)('PageHero/body/fontWeight', modes) || 500),
94
+ lineHeight: Number((0, _figmaVariablesResolver.getVariableByName)('PageHero/body/lineHeight', modes)) || 16,
95
+ textAlign: 'center'
96
+ };
97
+ return {
98
+ container: {
99
+ width: '100%',
100
+ alignItems: 'center',
101
+ gap
102
+ },
103
+ textWrap: {
104
+ width: '100%',
105
+ alignItems: 'center',
106
+ gap: textWrapGap
107
+ },
108
+ eyebrowStyle,
109
+ headlineStyle,
110
+ supportingTextStyle,
111
+ priceTextStyle
112
+ };
113
+ }, [modes]);
114
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
115
+ style: styles.container,
116
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
117
+ style: styles.textWrap,
118
+ children: [eyebrow ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
119
+ style: styles.eyebrowStyle,
120
+ children: eyebrow
121
+ }) : null, headline ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
122
+ style: styles.headlineStyle,
123
+ children: headline
124
+ }) : null]
125
+ }), supportingText ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
126
+ style: styles.supportingTextStyle,
127
+ children: supportingText
128
+ }) : null, priceText ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
129
+ style: styles.priceTextStyle,
130
+ children: priceText
131
+ }) : null]
132
+ });
133
+ }
134
+
135
+ /**
136
+ * FullscreenModal — a full-screen takeover surface with a parallax media hero,
137
+ * a scrollable body, a floating close button, and a sticky `ActionFooter`.
138
+ *
139
+ * The component always themes itself with `context5: 'Fullscreen Modal'`
140
+ * (non-overridable) so every nested component (Section, ListItem, Button,
141
+ * Disclaimer, …) resolves the white-on-dark "fullscreen modal" token values.
142
+ * That mode is cascaded into `children`, the footer, and the hero text via
143
+ * `cloneChildrenWithModes` / the merged `modes` object.
144
+ *
145
+ * ### Parallax
146
+ * As the user scrolls up, the hero collapses by **height only** (from
147
+ * `heroHeight` to `heroMinHeight`) — its **full width is always preserved**.
148
+ * The `heroMedia` is pinned to the top at a fixed size and `cover`-cropped by
149
+ * the collapsing clip, so it keeps a perfect aspect ratio the whole time
150
+ * (never scaled or squished). Because it collapses slower than the content
151
+ * scrolls, the media lags behind for the parallax depth cue. Disable with
152
+ * `parallax={false}`.
153
+ *
154
+ * @component
155
+ * @example
156
+ * ```tsx
157
+ * <FullscreenModal
158
+ * eyebrow="Upgrade to JioFinance+"
159
+ * headline="Get more from your money."
160
+ * supportingText="JioFinance+ is your upgraded financial experience…"
161
+ * priceText="₹999/year · ₹0 until 2027"
162
+ * heroMedia={<LottiePlayer source={hero} size={{ width: 360, height: 420 }} />}
163
+ * primaryActionLabel="Upgrade for free"
164
+ * disclaimer="By upgrading, we'll check your eligibility with Experian."
165
+ * onPrimaryAction={() => upgrade()}
166
+ * onClose={() => navigation.goBack()}
167
+ * >
168
+ * <Section title="Key Benefits" slotDirection="column" slot={…} />
169
+ * <Section title="Compare plans" slotDirection="column" slot={…} />
170
+ * </FullscreenModal>
171
+ * ```
172
+ */
173
+ function FullscreenModal({
174
+ eyebrow = 'Upgrade to JioFinance+',
175
+ headline = 'Get more from your money.',
176
+ supportingText = 'JioFinance+ is your upgraded financial experience, designed to work harder in the background so your money works smarter in real life.',
177
+ priceText = '₹999/year · ₹0 until 2027',
178
+ heroMedia,
179
+ heroHeight = 420,
180
+ heroMinHeight,
181
+ parallax = true,
182
+ showClose = true,
183
+ onClose,
184
+ closeAccessibilityLabel = 'Close',
185
+ footer,
186
+ primaryActionLabel = 'Upgrade for free',
187
+ onPrimaryAction,
188
+ disclaimer = "By upgrading, we'll check your eligibility with Experian.",
189
+ backgroundColor = '#0f0d0a',
190
+ children,
191
+ modes: propModes = _reactUtils.EMPTY_MODES,
192
+ style,
193
+ contentContainerStyle,
194
+ testID
195
+ }) {
196
+ const {
197
+ modes: globalModes
198
+ } = (0, _JFSThemeProvider.useTokens)();
199
+
200
+ // context5 is appended last so it always wins, regardless of what the
201
+ // caller (or the global theme) passes.
202
+ const modes = (0, _react.useMemo)(() => ({
203
+ ...globalModes,
204
+ ...propModes,
205
+ ...FULLSCREEN_MODAL_FORCED_MODES
206
+ }), [globalModes, propModes]);
207
+ const rootGap = Number((0, _figmaVariablesResolver.getVariableByName)('fullScreenModal/gap', modes)) || 16;
208
+ const minHeight = heroMinHeight ?? Math.round(heroHeight * HERO_MIN_HEIGHT_RATIO);
209
+ const scrollY = (0, _reactNativeReanimated.useSharedValue)(0);
210
+ const onScroll = (0, _reactNativeReanimated.useAnimatedScrollHandler)(event => {
211
+ scrollY.value = event.contentOffset.y;
212
+ });
213
+
214
+ // Collapse the hero by HEIGHT only as the user scrolls up. The clip's width
215
+ // never changes and the media inside is pinned full-size at the top, so the
216
+ // art is cropped (cover) rather than scaled or narrowed — it keeps a perfect
217
+ // aspect ratio the whole time. Pull-down (negative offset) is clamped, so the
218
+ // hero never grows past its resting height.
219
+ const heroAnimatedStyle = (0, _reactNativeReanimated.useAnimatedStyle)(() => {
220
+ const height = (0, _reactNativeReanimated.interpolate)(scrollY.value, [0, heroHeight], [heroHeight, minHeight], _reactNativeReanimated.Extrapolation.CLAMP);
221
+ return {
222
+ height
223
+ };
224
+ });
225
+ const processedHeroMedia = (0, _react.useMemo)(() => heroMedia ? (0, _reactUtils.cloneChildrenWithModes)(heroMedia, modes, FULLSCREEN_MODAL_FORCED_MODES) : null, [heroMedia, modes]);
226
+ const processedChildren = (0, _react.useMemo)(() => children ? (0, _reactUtils.cloneChildrenWithModes)(children, modes, FULLSCREEN_MODAL_FORCED_MODES) : null, [children, modes]);
227
+
228
+ // The clip is full-width and top-pinned; its height is what animates. Width
229
+ // is intentionally never animated.
230
+ const heroClipBaseStyle = (0, _react.useMemo)(() => ({
231
+ position: 'absolute',
232
+ top: 0,
233
+ left: 0,
234
+ right: 0,
235
+ overflow: 'hidden'
236
+ }), []);
237
+
238
+ // The media sits at a fixed full-size box pinned to the top of the clip, so
239
+ // the collapsing clip crops it from the bottom (cover) instead of resizing
240
+ // it. Full width, fixed height — a perfect, constant aspect ratio.
241
+ const heroMediaWrapStyle = (0, _react.useMemo)(() => ({
242
+ position: 'absolute',
243
+ top: 0,
244
+ left: 0,
245
+ right: 0,
246
+ height: heroHeight,
247
+ alignItems: 'stretch'
248
+ }), [heroHeight]);
249
+ const heroTextRegionStyle = (0, _react.useMemo)(() => ({
250
+ height: heroHeight,
251
+ justifyContent: 'flex-end',
252
+ paddingHorizontal: 16,
253
+ paddingBottom: 16
254
+ }), [heroHeight]);
255
+ const bodyStyle = (0, _react.useMemo)(() => [{
256
+ backgroundColor,
257
+ gap: rootGap,
258
+ paddingTop: rootGap,
259
+ paddingBottom: 24
260
+ }, contentContainerStyle], [backgroundColor, rootGap, contentContainerStyle]);
261
+ const heroClip = /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeReanimated.default.View, {
262
+ style: [heroClipBaseStyle, parallax ? heroAnimatedStyle : {
263
+ height: heroHeight
264
+ }],
265
+ pointerEvents: "none",
266
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
267
+ style: heroMediaWrapStyle,
268
+ children: processedHeroMedia
269
+ })
270
+ });
271
+
272
+ // Footer: a fully custom node, or the default Button + Disclaimer column.
273
+ let footerContent = null;
274
+ if (footer) {
275
+ footerContent = footer;
276
+ } else if (primaryActionLabel) {
277
+ footerContent = /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
278
+ style: footerColumnStyle,
279
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Button.default, {
280
+ label: primaryActionLabel,
281
+ modes: modes,
282
+ style: fullWidthStyle,
283
+ ...(onPrimaryAction ? {
284
+ onPress: onPrimaryAction
285
+ } : {})
286
+ }), disclaimer ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Disclaimer.default, {
287
+ disclaimer: disclaimer,
288
+ modes: modes
289
+ }) : null]
290
+ });
291
+ }
292
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
293
+ style: [rootStyle, {
294
+ backgroundColor
295
+ }, style],
296
+ testID: testID,
297
+ children: [processedHeroMedia ? heroClip : null, /*#__PURE__*/(0, _jsxRuntime.jsxs)(AnimatedScrollView, {
298
+ style: scrollViewStyle,
299
+ contentContainerStyle: scrollContentStyle,
300
+ showsVerticalScrollIndicator: false,
301
+ onScroll: onScroll,
302
+ scrollEventThrottle: 16,
303
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
304
+ style: heroTextRegionStyle,
305
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(HeroText, {
306
+ eyebrow: eyebrow,
307
+ headline: headline,
308
+ supportingText: supportingText,
309
+ priceText: priceText,
310
+ modes: modes
311
+ })
312
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
313
+ style: bodyStyle,
314
+ children: processedChildren
315
+ })]
316
+ }), footerContent ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_ActionFooter.default, {
317
+ modes: modes,
318
+ children: footerContent
319
+ }) : null, showClose ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_IconButton.default, {
320
+ iconName: "ic_close",
321
+ modes: modes,
322
+ accessibilityLabel: closeAccessibilityLabel,
323
+ style: closeButtonStyle,
324
+ ...(onClose ? {
325
+ onPress: onClose
326
+ } : {})
327
+ }) : null]
328
+ });
329
+ }
330
+
331
+ // Module-scope style constants — never re-allocated per render.
332
+ const rootStyle = {
333
+ flex: 1,
334
+ width: '100%',
335
+ position: 'relative'
336
+ };
337
+ const scrollViewStyle = {
338
+ flex: 1
339
+ };
340
+ const scrollContentStyle = {
341
+ flexGrow: 1
342
+ };
343
+ const footerColumnStyle = {
344
+ width: '100%',
345
+ gap: 8
346
+ };
347
+ const fullWidthStyle = {
348
+ width: '100%'
349
+ };
350
+ const closeButtonStyle = {
351
+ position: 'absolute',
352
+ top: 12,
353
+ right: 12
354
+ };
355
+ var _default = exports.default = FullscreenModal;
@@ -38,27 +38,42 @@ const pressedOverlayStyle = {
38
38
  // ---------------------------------------------------------------------------
39
39
 
40
40
  function resolveListItemTokens(modes) {
41
+ // Modes used to cascade into slot children (leading / supportSlot / endSlot).
42
+ // We do NOT inject an `AppearanceBrand` default here: slot content such as
43
+ // Buttons or Badges carry their own intended appearance, so forcing one onto
44
+ // them would be surprising.
41
45
  const resolvedModes = {
42
46
  ...modes,
43
47
  Context: 'ListItem'
44
48
  };
49
+
50
+ // Modes used to resolve the ListItem's OWN title + support text. Within this
51
+ // component, `AppearanceBrand` only affects `listItem/title/color` and
52
+ // `listItem/supportText/color`, so the text defaults to the "Neutral"
53
+ // appearance (in both Vertical and Horizontal layouts). A caller-supplied
54
+ // `AppearanceBrand` still wins; `Context` is always forced to 'ListItem'.
55
+ const textModes = {
56
+ AppearanceBrand: 'Neutral',
57
+ ...modes,
58
+ Context: 'ListItem'
59
+ };
45
60
  const gap = (0, _figmaVariablesResolver.getVariableByName)('listItem/gap', resolvedModes) ?? 8;
46
61
  const paddingTop = (0, _figmaVariablesResolver.getVariableByName)('listItem/padding/top', resolvedModes) ?? 0;
47
62
  const paddingBottom = (0, _figmaVariablesResolver.getVariableByName)('listItem/padding/bottom', resolvedModes) ?? 0;
48
63
  const paddingLeft = (0, _figmaVariablesResolver.getVariableByName)('listItem/padding/left', resolvedModes) ?? 0;
49
64
  const paddingRight = (0, _figmaVariablesResolver.getVariableByName)('listItem/padding/right', resolvedModes) ?? 0;
50
65
  const textWrapGap = (0, _figmaVariablesResolver.getVariableByName)('listItem/text wrap', resolvedModes) ?? 0;
51
- const titleColor = (0, _figmaVariablesResolver.getVariableByName)('listItem/title/color', resolvedModes) || '#0f0d0a';
52
- const titleFontSize = (0, _figmaVariablesResolver.getVariableByName)('listItem/title/fontSize', resolvedModes) || 14;
53
- const titleLineHeight = (0, _figmaVariablesResolver.getVariableByName)('listItem/title/lineHeight', resolvedModes) || 16;
54
- const titleFontFamily = (0, _figmaVariablesResolver.getVariableByName)('listItem/title/fontFamily', resolvedModes) || 'System';
55
- const titleFontWeightRaw = (0, _figmaVariablesResolver.getVariableByName)('listItem/title/fontWeight', resolvedModes) || 700;
66
+ const titleColor = (0, _figmaVariablesResolver.getVariableByName)('listItem/title/color', textModes) || '#0f0d0a';
67
+ const titleFontSize = (0, _figmaVariablesResolver.getVariableByName)('listItem/title/fontSize', textModes) || 14;
68
+ const titleLineHeight = (0, _figmaVariablesResolver.getVariableByName)('listItem/title/lineHeight', textModes) || 16;
69
+ const titleFontFamily = (0, _figmaVariablesResolver.getVariableByName)('listItem/title/fontFamily', textModes) || 'System';
70
+ const titleFontWeightRaw = (0, _figmaVariablesResolver.getVariableByName)('listItem/title/fontWeight', textModes) || 700;
56
71
  const titleFontWeight = typeof titleFontWeightRaw === 'number' ? titleFontWeightRaw.toString() : titleFontWeightRaw;
57
- const supportColor = (0, _figmaVariablesResolver.getVariableByName)('listItem/supportText/color', resolvedModes) || '#1f1a14';
58
- const supportFontSize = (0, _figmaVariablesResolver.getVariableByName)('listItem/supportText/fontSize', resolvedModes) || 12;
59
- const supportLineHeight = (0, _figmaVariablesResolver.getVariableByName)('listItem/supportText/lineHeight', resolvedModes) || 14;
60
- const supportFontFamily = (0, _figmaVariablesResolver.getVariableByName)('listItem/supportText/fontFamily', resolvedModes) || 'System';
61
- const supportFontWeightRaw = (0, _figmaVariablesResolver.getVariableByName)('listItem/supportText/fontWeight', resolvedModes) || 500;
72
+ const supportColor = (0, _figmaVariablesResolver.getVariableByName)('listItem/supportText/color', textModes) || '#1f1a14';
73
+ const supportFontSize = (0, _figmaVariablesResolver.getVariableByName)('listItem/supportText/fontSize', textModes) || 12;
74
+ const supportLineHeight = (0, _figmaVariablesResolver.getVariableByName)('listItem/supportText/lineHeight', textModes) || 14;
75
+ const supportFontFamily = (0, _figmaVariablesResolver.getVariableByName)('listItem/supportText/fontFamily', textModes) || 'System';
76
+ const supportFontWeightRaw = (0, _figmaVariablesResolver.getVariableByName)('listItem/supportText/fontWeight', textModes) || 500;
62
77
  const supportFontWeight = typeof supportFontWeightRaw === 'number' ? supportFontWeightRaw.toString() : supportFontWeightRaw;
63
78
  return {
64
79
  baseContainerStyle: {