jfs-components 0.0.78 → 0.0.84
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 +11 -0
- package/lib/commonjs/components/AppBar/AppBar.js +56 -6
- package/lib/commonjs/components/Attached/Attached.js +183 -0
- package/lib/commonjs/components/Card/Card.js +25 -2
- package/lib/commonjs/components/Checkbox/Checkbox.js +18 -2
- package/lib/commonjs/components/Drawer/Drawer.js +6 -1
- package/lib/commonjs/components/DropdownInput/DropdownInput.js +30 -6
- package/lib/commonjs/components/ExpandableCheckbox/ExpandableCheckbox.js +17 -11
- package/lib/commonjs/components/FormField/FormField.js +1 -14
- package/lib/commonjs/components/FullscreenModal/FullscreenModal.js +9 -7
- package/lib/commonjs/components/ListItem/ListItem.js +26 -24
- package/lib/commonjs/components/MessageField/MessageField.js +1 -13
- package/lib/commonjs/components/PaymentFeedback/PaymentFeedback.js +12 -9
- package/lib/commonjs/components/PlanComparisonCard/PlanComparisonCard.js +237 -0
- package/lib/commonjs/components/Slot/Slot.js +73 -0
- package/lib/commonjs/components/Spinner/Spinner.js +217 -0
- package/lib/commonjs/components/TextInput/TextInput.js +33 -18
- package/lib/commonjs/components/index.js +28 -0
- package/lib/commonjs/icons/components/IconArrowdown.js +19 -0
- package/lib/commonjs/icons/components/IconArrowup.js +19 -0
- package/lib/commonjs/icons/components/IconChevrondowncircle.js +19 -0
- package/lib/commonjs/icons/components/IconChevronleftcircle.js +19 -0
- package/lib/commonjs/icons/components/IconChevronrightcircle.js +19 -0
- package/lib/commonjs/icons/components/IconChevronupcircle.js +19 -0
- package/lib/commonjs/icons/components/IconOsnavback.js +19 -0
- package/lib/commonjs/icons/components/IconOsnavcenter.js +19 -0
- package/lib/commonjs/icons/components/IconOsnavhome.js +19 -0
- package/lib/commonjs/icons/components/IconOsnavtask.js +19 -0
- package/lib/commonjs/icons/components/IconSignin.js +19 -0
- package/lib/commonjs/icons/components/IconSignout.js +19 -0
- package/lib/commonjs/icons/components/index.js +132 -0
- package/lib/commonjs/icons/registry.js +2 -2
- package/lib/module/components/AppBar/AppBar.js +56 -6
- package/lib/module/components/Attached/Attached.js +178 -0
- package/lib/module/components/Card/Card.js +25 -2
- package/lib/module/components/Checkbox/Checkbox.js +18 -2
- package/lib/module/components/Drawer/Drawer.js +6 -1
- package/lib/module/components/DropdownInput/DropdownInput.js +30 -6
- package/lib/module/components/ExpandableCheckbox/ExpandableCheckbox.js +17 -11
- package/lib/module/components/FormField/FormField.js +3 -16
- package/lib/module/components/FullscreenModal/FullscreenModal.js +9 -7
- package/lib/module/components/ListItem/ListItem.js +26 -24
- package/lib/module/components/MessageField/MessageField.js +3 -15
- package/lib/module/components/PaymentFeedback/PaymentFeedback.js +13 -9
- package/lib/module/components/PlanComparisonCard/PlanComparisonCard.js +234 -0
- package/lib/module/components/Slot/Slot.js +68 -0
- package/lib/module/components/Spinner/Spinner.js +212 -0
- package/lib/module/components/TextInput/TextInput.js +34 -19
- package/lib/module/components/index.js +4 -0
- package/lib/module/icons/components/IconArrowdown.js +12 -0
- package/lib/module/icons/components/IconArrowup.js +12 -0
- package/lib/module/icons/components/IconChevrondowncircle.js +12 -0
- package/lib/module/icons/components/IconChevronleftcircle.js +12 -0
- package/lib/module/icons/components/IconChevronrightcircle.js +12 -0
- package/lib/module/icons/components/IconChevronupcircle.js +12 -0
- package/lib/module/icons/components/IconOsnavback.js +12 -0
- package/lib/module/icons/components/IconOsnavcenter.js +12 -0
- package/lib/module/icons/components/IconOsnavhome.js +12 -0
- package/lib/module/icons/components/IconOsnavtask.js +12 -0
- package/lib/module/icons/components/IconSignin.js +12 -0
- package/lib/module/icons/components/IconSignout.js +12 -0
- package/lib/module/icons/components/index.js +12 -0
- package/lib/module/icons/registry.js +2 -2
- package/lib/typescript/src/components/AppBar/AppBar.d.ts +12 -1
- package/lib/typescript/src/components/Attached/Attached.d.ts +64 -0
- package/lib/typescript/src/components/Card/Card.d.ts +9 -2
- package/lib/typescript/src/components/DropdownInput/DropdownInput.d.ts +3 -2
- package/lib/typescript/src/components/ListItem/ListItem.d.ts +16 -6
- package/lib/typescript/src/components/PaymentFeedback/PaymentFeedback.d.ts +5 -1
- package/lib/typescript/src/components/PlanComparisonCard/PlanComparisonCard.d.ts +66 -0
- package/lib/typescript/src/components/Slot/Slot.d.ts +52 -0
- package/lib/typescript/src/components/Spinner/Spinner.d.ts +45 -0
- package/lib/typescript/src/components/index.d.ts +4 -0
- package/lib/typescript/src/icons/components/IconArrowdown.d.ts +3 -0
- package/lib/typescript/src/icons/components/IconArrowup.d.ts +3 -0
- package/lib/typescript/src/icons/components/IconChevrondowncircle.d.ts +3 -0
- package/lib/typescript/src/icons/components/IconChevronleftcircle.d.ts +3 -0
- package/lib/typescript/src/icons/components/IconChevronrightcircle.d.ts +3 -0
- package/lib/typescript/src/icons/components/IconChevronupcircle.d.ts +3 -0
- package/lib/typescript/src/icons/components/IconOsnavback.d.ts +3 -0
- package/lib/typescript/src/icons/components/IconOsnavcenter.d.ts +3 -0
- package/lib/typescript/src/icons/components/IconOsnavhome.d.ts +3 -0
- package/lib/typescript/src/icons/components/IconOsnavtask.d.ts +3 -0
- package/lib/typescript/src/icons/components/IconSignin.d.ts +3 -0
- package/lib/typescript/src/icons/components/IconSignout.d.ts +3 -0
- package/lib/typescript/src/icons/components/index.d.ts +12 -0
- package/lib/typescript/src/icons/registry.d.ts +1 -1
- package/package.json +3 -2
- package/src/components/AppBar/AppBar.tsx +79 -12
- package/src/components/Attached/Attached.tsx +237 -0
- package/src/components/Card/Card.tsx +28 -1
- package/src/components/Checkbox/Checkbox.tsx +14 -2
- package/src/components/Drawer/Drawer.tsx +4 -0
- package/src/components/DropdownInput/DropdownInput.tsx +54 -20
- package/src/components/ExpandableCheckbox/ExpandableCheckbox.tsx +13 -9
- package/src/components/FormField/FormField.tsx +3 -19
- package/src/components/FullscreenModal/FullscreenModal.tsx +6 -3
- package/src/components/ListItem/ListItem.tsx +42 -25
- package/src/components/MessageField/MessageField.tsx +3 -18
- package/src/components/PaymentFeedback/PaymentFeedback.tsx +15 -8
- package/src/components/PlanComparisonCard/PlanComparisonCard.tsx +316 -0
- package/src/components/Slot/Slot.tsx +91 -0
- package/src/components/Spinner/Spinner.tsx +273 -0
- package/src/components/TextInput/TextInput.tsx +37 -19
- package/src/components/index.ts +4 -0
- package/src/icons/components/IconArrowdown.tsx +11 -0
- package/src/icons/components/IconArrowup.tsx +11 -0
- package/src/icons/components/IconChevrondowncircle.tsx +11 -0
- package/src/icons/components/IconChevronleftcircle.tsx +11 -0
- package/src/icons/components/IconChevronrightcircle.tsx +11 -0
- package/src/icons/components/IconChevronupcircle.tsx +11 -0
- package/src/icons/components/IconOsnavback.tsx +11 -0
- package/src/icons/components/IconOsnavcenter.tsx +11 -0
- package/src/icons/components/IconOsnavhome.tsx +11 -0
- package/src/icons/components/IconOsnavtask.tsx +11 -0
- package/src/icons/components/IconSignin.tsx +11 -0
- package/src/icons/components/IconSignout.tsx +11 -0
- package/src/icons/components/index.ts +12 -0
- package/src/icons/registry.ts +49 -1
|
@@ -7,7 +7,6 @@ exports.default = void 0;
|
|
|
7
7
|
var _react = _interopRequireWildcard(require("react"));
|
|
8
8
|
var _reactNative = require("react-native");
|
|
9
9
|
var _figmaVariablesResolver = require("../../design-tokens/figma-variables-resolver");
|
|
10
|
-
var _IconCapsule = _interopRequireDefault(require("../IconCapsule/IconCapsule"));
|
|
11
10
|
var _NavArrow = _interopRequireDefault(require("../NavArrow/NavArrow"));
|
|
12
11
|
var _webPlatformUtils = require("../../utils/web-platform-utils");
|
|
13
12
|
var _reactUtils = require("../../utils/react-utils");
|
|
@@ -21,9 +20,10 @@ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r
|
|
|
21
20
|
const IS_IOS = _reactNative.Platform.OS === 'ios';
|
|
22
21
|
const PRESS_DELAY = IS_IOS ? 130 : 0;
|
|
23
22
|
|
|
24
|
-
// Forced modes for the
|
|
25
|
-
// overridden by external modes. Frozen so identity is stable across
|
|
26
|
-
|
|
23
|
+
// Forced modes for the leading/trailing slots — `Context: 'ListItem'` can
|
|
24
|
+
// never be overridden by external modes. Frozen so identity is stable across
|
|
25
|
+
// renders. Applied to both slots so they cascade modes identically.
|
|
26
|
+
const SLOT_FORCED_MODES = Object.freeze({
|
|
27
27
|
Context: 'ListItem'
|
|
28
28
|
});
|
|
29
29
|
|
|
@@ -38,7 +38,7 @@ const pressedOverlayStyle = {
|
|
|
38
38
|
// ---------------------------------------------------------------------------
|
|
39
39
|
|
|
40
40
|
function resolveListItemTokens(modes) {
|
|
41
|
-
// Modes used to cascade into slot children (leading / supportSlot /
|
|
41
|
+
// Modes used to cascade into slot children (leading / supportSlot / trailing).
|
|
42
42
|
// We do NOT inject an `AppearanceBrand` default here: slot content such as
|
|
43
43
|
// Buttons or Badges carry their own intended appearance, so forcing one onto
|
|
44
44
|
// them would be surprising.
|
|
@@ -137,9 +137,11 @@ const verticalSupportTextOverride = {
|
|
|
137
137
|
* - **design-token driven styling** via `getVariableByName` and `modes`
|
|
138
138
|
*
|
|
139
139
|
* Wherever the Figma layer name contains "Slot", this component exposes a
|
|
140
|
-
* dedicated React "slot" prop
|
|
140
|
+
* dedicated React "slot" prop. The leading and trailing edges share a
|
|
141
|
+
* symmetric `leading` / `trailing` slot API:
|
|
142
|
+
* - Slot "leading" → `leading`
|
|
141
143
|
* - Slot "support text" → `supportSlot`
|
|
142
|
-
* - Slot "
|
|
144
|
+
* - Slot "trailing" → `trailing`
|
|
143
145
|
*
|
|
144
146
|
* @component
|
|
145
147
|
* @param {Object} props
|
|
@@ -147,9 +149,9 @@ const verticalSupportTextOverride = {
|
|
|
147
149
|
* @param {string} [props.title='Title'] - Primary title used in the horizontal layout.
|
|
148
150
|
* @param {string} [props.supportText='Support Text'] - Support text used in both layouts when `supportSlot` is not provided.
|
|
149
151
|
* @param {boolean} [props.showSupportText=true] - Toggles rendering of the support text in Horizontal layout.
|
|
150
|
-
* @param {React.ReactNode} [props.leading] - Optional leading
|
|
152
|
+
* @param {React.ReactNode|null} [props.leading] - Optional leading slot. Omitted or `null` renders nothing.
|
|
151
153
|
* @param {React.ReactNode} [props.supportSlot] - Optional custom slot used instead of the default support text block.
|
|
152
|
-
* @param {React.ReactNode} [props.
|
|
154
|
+
* @param {React.ReactNode} [props.trailing] - Optional trailing slot (Figma Slot "trailing"). Horizontal layout only.
|
|
153
155
|
* @param {boolean} [props.navArrow=true] - Whether to show NavArrow on the far right (Horizontal layout only).
|
|
154
156
|
* @param {Object} [props.modes={}] - Modes object passed to `getVariableByName` for all design tokens.
|
|
155
157
|
* @param {Function} [props.onPress] - When provided, the entire item becomes pressable (navigation variant).
|
|
@@ -178,6 +180,7 @@ function ListItemImpl({
|
|
|
178
180
|
showSupportText = true,
|
|
179
181
|
leading,
|
|
180
182
|
supportSlot,
|
|
183
|
+
trailing,
|
|
181
184
|
endSlot,
|
|
182
185
|
navArrow = true,
|
|
183
186
|
modes = _reactUtils.EMPTY_MODES,
|
|
@@ -215,13 +218,9 @@ function ListItemImpl({
|
|
|
215
218
|
// Process leading slot to pass modes to children. Memoized on
|
|
216
219
|
// (leading, resolvedModes) so a parent re-render doesn't re-walk the tree.
|
|
217
220
|
const leadingElement = (0, _react.useMemo)(() => {
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
modes: tokens.resolvedModes,
|
|
222
|
-
accessibilityLabel: undefined
|
|
223
|
-
});
|
|
224
|
-
}
|
|
221
|
+
if (leading == null) return null;
|
|
222
|
+
const processed = (0, _reactUtils.cloneChildrenWithModes)(_react.default.Children.toArray(leading), tokens.resolvedModes, SLOT_FORCED_MODES);
|
|
223
|
+
if (processed.length === 0) return null;
|
|
225
224
|
return processed.length === 1 ? processed[0] : processed;
|
|
226
225
|
}, [leading, tokens.resolvedModes]);
|
|
227
226
|
const processedSupportSlot = (0, _react.useMemo)(() => {
|
|
@@ -229,11 +228,14 @@ function ListItemImpl({
|
|
|
229
228
|
const processed = (0, _reactUtils.cloneChildrenWithModes)(_react.default.Children.toArray(supportSlot), tokens.resolvedModes);
|
|
230
229
|
return processed.length === 1 ? processed[0] : processed;
|
|
231
230
|
}, [supportSlot, tokens.resolvedModes]);
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
231
|
+
|
|
232
|
+
// `trailing` wins; `endSlot` is the deprecated alias kept for back-compat.
|
|
233
|
+
const trailingContent = trailing ?? endSlot;
|
|
234
|
+
const processedTrailing = (0, _react.useMemo)(() => {
|
|
235
|
+
if (!trailingContent) return null;
|
|
236
|
+
const processed = (0, _reactUtils.cloneChildrenWithModes)(_react.default.Children.toArray(trailingContent), tokens.resolvedModes, SLOT_FORCED_MODES);
|
|
235
237
|
return processed.length === 1 ? processed[0] : processed;
|
|
236
|
-
}, [
|
|
238
|
+
}, [trailingContent, tokens.resolvedModes]);
|
|
237
239
|
const renderSupportContent = () => {
|
|
238
240
|
if (processedSupportSlot) return processedSupportSlot;
|
|
239
241
|
|
|
@@ -268,7 +270,7 @@ function ListItemImpl({
|
|
|
268
270
|
if (layout === 'Horizontal') {
|
|
269
271
|
const innerContent = /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
270
272
|
style: innerContentStyleArray,
|
|
271
|
-
children: [leadingElement, /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
273
|
+
children: [leadingElement ?? null, /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
272
274
|
style: {
|
|
273
275
|
flex: 1,
|
|
274
276
|
minWidth: 1,
|
|
@@ -279,9 +281,9 @@ function ListItemImpl({
|
|
|
279
281
|
numberOfLines: 1,
|
|
280
282
|
children: title
|
|
281
283
|
}), showSupportText && renderSupportContent()]
|
|
282
|
-
}),
|
|
284
|
+
}), processedTrailing ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
283
285
|
style: tokens.trailingWrapperStyle,
|
|
284
|
-
children:
|
|
286
|
+
children: processedTrailing
|
|
285
287
|
}) : null, navArrow && /*#__PURE__*/(0, _jsxRuntime.jsx)(_NavArrow.default, {
|
|
286
288
|
direction: "Forward",
|
|
287
289
|
modes: tokens.resolvedModes
|
|
@@ -315,7 +317,7 @@ function ListItemImpl({
|
|
|
315
317
|
// Vertical layout — icon on top, support text/slot below
|
|
316
318
|
const verticalContent = /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
317
319
|
style: verticalContentStyleArray,
|
|
318
|
-
children: [leadingElement, renderSupportContent()]
|
|
320
|
+
children: [leadingElement ?? null, renderSupportContent()]
|
|
319
321
|
});
|
|
320
322
|
if (onPress) {
|
|
321
323
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
|
|
@@ -145,15 +145,6 @@ function MessageField({
|
|
|
145
145
|
const currentValue = isControlled ? value : uncontrolledValue;
|
|
146
146
|
const [isFocused, setIsFocused] = (0, _react.useState)(false);
|
|
147
147
|
const interactive = !isDisabled && !isReadOnly;
|
|
148
|
-
|
|
149
|
-
// Ref to the native textarea so tapping anywhere in the (padded) textarea
|
|
150
|
-
// container focuses it on the FIRST tap, fixing the Android "two taps to
|
|
151
|
-
// open the keyboard" issue.
|
|
152
|
-
const inputRef = (0, _react.useRef)(null);
|
|
153
|
-
const focusInput = (0, _react.useCallback)(() => {
|
|
154
|
-
if (!interactive) return;
|
|
155
|
-
inputRef.current?.focus();
|
|
156
|
-
}, [interactive]);
|
|
157
148
|
const {
|
|
158
149
|
modes: globalModes
|
|
159
150
|
} = (0, _JFSThemeProvider.useTokens)();
|
|
@@ -288,12 +279,9 @@ function MessageField({
|
|
|
288
279
|
style: requiredIndicatorStyle,
|
|
289
280
|
children: " *"
|
|
290
281
|
})]
|
|
291
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.
|
|
282
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
292
283
|
style: [textareaContainerStyle, textareaStyle],
|
|
293
|
-
onPress: focusInput,
|
|
294
|
-
accessible: false,
|
|
295
284
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TextInput, {
|
|
296
|
-
ref: inputRef,
|
|
297
285
|
multiline: true,
|
|
298
286
|
value: currentValue,
|
|
299
287
|
onChangeText: handleChangeText,
|
|
@@ -4,7 +4,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = PaymentFeedback;
|
|
7
|
-
var _react =
|
|
7
|
+
var _react = _interopRequireDefault(require("react"));
|
|
8
8
|
var _reactNative = require("react-native");
|
|
9
9
|
var _figmaVariablesResolver = require("../../design-tokens/figma-variables-resolver");
|
|
10
10
|
var _JFSThemeProvider = require("../../design-tokens/JFSThemeProvider");
|
|
@@ -12,11 +12,10 @@ var _IconCapsule = _interopRequireDefault(require("../IconCapsule/IconCapsule"))
|
|
|
12
12
|
var _reactUtils = require("../../utils/react-utils");
|
|
13
13
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
14
14
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
15
|
-
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); }
|
|
16
15
|
function PaymentFeedback({
|
|
17
16
|
title = '₹50,000',
|
|
18
17
|
subtitle = 'Payment successful',
|
|
19
|
-
body
|
|
18
|
+
body,
|
|
20
19
|
details = '18 March 2025, 4:15 pm\nTransaction ID: TXN121466784',
|
|
21
20
|
showDetails = true,
|
|
22
21
|
iconName = 'ic_confirm',
|
|
@@ -103,17 +102,21 @@ function PaymentFeedback({
|
|
|
103
102
|
fontWeight: String(detailsFontWeight),
|
|
104
103
|
textAlign: 'center'
|
|
105
104
|
};
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
105
|
+
|
|
106
|
+
// Cascade modes into a custom media slot (per the modes-cascade convention);
|
|
107
|
+
// any modes the consumer set on the slot child still take precedence.
|
|
108
|
+
const mediaContent = renderMedia != null ? (0, _reactUtils.cloneChildrenWithModes)(renderMedia, modes) : null;
|
|
109
109
|
const defaultMedia = /*#__PURE__*/(0, _jsxRuntime.jsx)(_IconCapsule.default, {
|
|
110
|
-
iconName: iconName
|
|
110
|
+
iconName: iconName
|
|
111
|
+
// `positive` is the default; consumers override the capsule color by
|
|
112
|
+
// passing `AppearanceSystem` (or any other mode) via the `modes` prop.
|
|
113
|
+
,
|
|
111
114
|
modes: {
|
|
115
|
+
AppearanceSystem: 'positive',
|
|
112
116
|
...modes,
|
|
113
117
|
'Icon Capsule Size': 'L',
|
|
114
118
|
Emphasis: 'High',
|
|
115
|
-
'Semantic Intent': 'System'
|
|
116
|
-
AppearanceSystem: 'positive'
|
|
119
|
+
'Semantic Intent': 'System'
|
|
117
120
|
}
|
|
118
121
|
});
|
|
119
122
|
const detailLines = details?.split('\n') ?? [];
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _react = _interopRequireDefault(require("react"));
|
|
8
|
+
var _reactNative = require("react-native");
|
|
9
|
+
var _figmaVariablesResolver = require("../../design-tokens/figma-variables-resolver");
|
|
10
|
+
var _reactUtils = require("../../utils/react-utils");
|
|
11
|
+
var _Icon = _interopRequireDefault(require("../../icons/Icon"));
|
|
12
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
13
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
14
|
+
/** Figma grid: label column 1.8fr, each plan column 1fr. */const LABEL_COLUMN_FR = 1.8;
|
|
15
|
+
const PLAN_COLUMN_FR = 1;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* A single plan column header (the label column has no header of its own).
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Value rendered inside a plan cell.
|
|
23
|
+
* - `string` / `number` → rendered as value text.
|
|
24
|
+
* - `false` → renders the muted "not available" cross icon.
|
|
25
|
+
* - any React node → rendered as-is (e.g. a `Badge`, `MoneyValue`, icon…).
|
|
26
|
+
* - `null` / `undefined` / `true` → empty cell.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
const DEFAULT_COLUMNS = [{
|
|
30
|
+
label: 'Your plan'
|
|
31
|
+
}, {
|
|
32
|
+
label: 'JioFinance+',
|
|
33
|
+
brand: true
|
|
34
|
+
}];
|
|
35
|
+
const DEFAULT_ROWS = [{
|
|
36
|
+
label: 'JioPoints multiplier',
|
|
37
|
+
values: ['1x', '1.25x']
|
|
38
|
+
}, {
|
|
39
|
+
label: 'Cashback',
|
|
40
|
+
showInfo: true,
|
|
41
|
+
values: [false, 'Upto ₹5000']
|
|
42
|
+
}, {
|
|
43
|
+
label: 'Bonus JioGold',
|
|
44
|
+
showInfo: true,
|
|
45
|
+
values: [false, '1%']
|
|
46
|
+
}];
|
|
47
|
+
|
|
48
|
+
/** Keeps every text layer on a single line. */
|
|
49
|
+
const NO_WRAP_TEXT = {
|
|
50
|
+
flexShrink: 0,
|
|
51
|
+
...(_reactNative.Platform.OS === 'web' ? {
|
|
52
|
+
whiteSpace: 'nowrap'
|
|
53
|
+
} : {})
|
|
54
|
+
};
|
|
55
|
+
const labelColumnStyle = {
|
|
56
|
+
flex: LABEL_COLUMN_FR,
|
|
57
|
+
minWidth: 0
|
|
58
|
+
};
|
|
59
|
+
const planColumnStyle = {
|
|
60
|
+
flex: PLAN_COLUMN_FR,
|
|
61
|
+
minWidth: 0,
|
|
62
|
+
alignItems: 'center'
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* PlanComparisonCard renders a compact comparison table that pits the user's
|
|
67
|
+
* current plan against one or more alternative plans across a set of feature
|
|
68
|
+
* rows. Implementation of Figma node `4498:2968` (`PlanComparisonCard`).
|
|
69
|
+
*
|
|
70
|
+
* Columns use a 1.8fr / 1fr flex ratio (label vs plan), matching the Figma grid.
|
|
71
|
+
*
|
|
72
|
+
* @component
|
|
73
|
+
*/
|
|
74
|
+
function PlanComparisonCard({
|
|
75
|
+
columns = DEFAULT_COLUMNS,
|
|
76
|
+
rows = DEFAULT_ROWS,
|
|
77
|
+
modes = _reactUtils.EMPTY_MODES,
|
|
78
|
+
style
|
|
79
|
+
}) {
|
|
80
|
+
const gap = (0, _figmaVariablesResolver.getVariableByName)('planComparisonCard/gap', modes) ?? 16;
|
|
81
|
+
const headerFg = (0, _figmaVariablesResolver.getVariableByName)('planComparisonCard/header/fg', modes) ?? '#ffffff';
|
|
82
|
+
const headerBrandFg = (0, _figmaVariablesResolver.getVariableByName)('planComparisonCard/header/brand/fg', modes) ?? '#cea15a';
|
|
83
|
+
const headerFontSize = (0, _figmaVariablesResolver.getVariableByName)('planComparisonCard/header/fontSize', modes) ?? 14;
|
|
84
|
+
const headerFontFamily = (0, _figmaVariablesResolver.getVariableByName)('planComparisonCard/header/fontFamily', modes) ?? 'JioType Var';
|
|
85
|
+
const headerLineHeight = (0, _figmaVariablesResolver.getVariableByName)('planComparisonCard/header/lineHeight', modes) ?? 18;
|
|
86
|
+
const headerFontWeight = (0, _figmaVariablesResolver.getVariableByName)('planComparisonCard/header/fontWeight', modes) ?? '500';
|
|
87
|
+
const tableBackground = (0, _figmaVariablesResolver.getVariableByName)('planComparisonCard/tableRow/background', modes) ?? '#141414';
|
|
88
|
+
const tableRadius = (0, _figmaVariablesResolver.getVariableByName)('planComparisonCard/tableRow/radius', modes) ?? 16;
|
|
89
|
+
const tableBorderSize = (0, _figmaVariablesResolver.getVariableByName)('planComparisonCard/tableRow/border/size', modes) ?? 1;
|
|
90
|
+
const tableBorderColor = (0, _figmaVariablesResolver.getVariableByName)('planComparisonCard/tableRow/border/color', modes) ?? '#1e1a14';
|
|
91
|
+
const cellPadding = (0, _figmaVariablesResolver.getVariableByName)('planComparisonCard/tableCell/padding', modes) ?? 12;
|
|
92
|
+
const cellGap = (0, _figmaVariablesResolver.getVariableByName)('planComparisonCard/tableCell/gap', modes) ?? 2;
|
|
93
|
+
const cellMinHeight = (0, _figmaVariablesResolver.getVariableByName)('planComparisonCard/tableCell/height', modes) ?? 46;
|
|
94
|
+
const cellBorderSize = (0, _figmaVariablesResolver.getVariableByName)('planComparisonCard/tableCell/border/size', modes) ?? 1;
|
|
95
|
+
const cellBorderColor = (0, _figmaVariablesResolver.getVariableByName)('planComparisonCard/tableCell/border/color', modes) ?? '#1e1a14';
|
|
96
|
+
const labelColor = (0, _figmaVariablesResolver.getVariableByName)('planComparisonCard/tableCell/label/color', modes) ?? '#ffffff';
|
|
97
|
+
const labelDisabledColor = (0, _figmaVariablesResolver.getVariableByName)('planComparisonCard/tableCell/label/disabled/color', modes) ?? '#91949c';
|
|
98
|
+
const labelFontSize = (0, _figmaVariablesResolver.getVariableByName)('planComparisonCard/tableCell/label/fontSize', modes) ?? 12;
|
|
99
|
+
const labelFontFamily = (0, _figmaVariablesResolver.getVariableByName)('planComparisonCard/tableCell/label/fontFamily', modes) ?? 'JioType Var';
|
|
100
|
+
const labelLineHeight = (0, _figmaVariablesResolver.getVariableByName)('planComparisonCard/tableCell/label/lineHeight', modes) ?? 16;
|
|
101
|
+
const labelFontWeight = (0, _figmaVariablesResolver.getVariableByName)('planComparisonCard/tableCell/label/fontWeight', modes) ?? '400';
|
|
102
|
+
const valueColor = (0, _figmaVariablesResolver.getVariableByName)('planComparisonCard/tableCell/value/color', modes) ?? '#ffffff';
|
|
103
|
+
const valueFontSize = (0, _figmaVariablesResolver.getVariableByName)('planComparisonCard/tableCell/value/fontSize', modes) ?? 12;
|
|
104
|
+
const valueFontFamily = (0, _figmaVariablesResolver.getVariableByName)('planComparisonCard/tableCell/value/fontFamily', modes) ?? 'JioType Var';
|
|
105
|
+
const valueLineHeight = (0, _figmaVariablesResolver.getVariableByName)('planComparisonCard/tableCell/value/lineHeight', modes) ?? 16;
|
|
106
|
+
const valueFontWeight = (0, _figmaVariablesResolver.getVariableByName)('planComparisonCard/tableCell/value/fontWeight', modes) ?? '500';
|
|
107
|
+
const iconColor = (0, _figmaVariablesResolver.getVariableByName)('planComparisonCard/icon/color', modes) ?? '#ffffff';
|
|
108
|
+
const iconSize = (0, _figmaVariablesResolver.getVariableByName)('planComparisonCard/icon/size', modes) ?? 16;
|
|
109
|
+
const toWeight = w => typeof w === 'number' ? `${w}` : w;
|
|
110
|
+
const headerTextStyle = {
|
|
111
|
+
...NO_WRAP_TEXT,
|
|
112
|
+
fontFamily: headerFontFamily,
|
|
113
|
+
fontSize: headerFontSize,
|
|
114
|
+
lineHeight: headerLineHeight,
|
|
115
|
+
fontWeight: toWeight(headerFontWeight),
|
|
116
|
+
textAlign: 'center'
|
|
117
|
+
};
|
|
118
|
+
const labelTextStyle = {
|
|
119
|
+
...NO_WRAP_TEXT,
|
|
120
|
+
color: labelColor,
|
|
121
|
+
fontFamily: labelFontFamily,
|
|
122
|
+
fontSize: labelFontSize,
|
|
123
|
+
lineHeight: labelLineHeight,
|
|
124
|
+
fontWeight: toWeight(labelFontWeight)
|
|
125
|
+
};
|
|
126
|
+
const valueTextStyle = {
|
|
127
|
+
...NO_WRAP_TEXT,
|
|
128
|
+
color: valueColor,
|
|
129
|
+
fontFamily: valueFontFamily,
|
|
130
|
+
fontSize: valueFontSize,
|
|
131
|
+
lineHeight: valueLineHeight,
|
|
132
|
+
fontWeight: toWeight(valueFontWeight),
|
|
133
|
+
textAlign: 'center'
|
|
134
|
+
};
|
|
135
|
+
const rowStyle = {
|
|
136
|
+
flexDirection: 'row',
|
|
137
|
+
width: '100%'
|
|
138
|
+
};
|
|
139
|
+
const labelCellStyle = {
|
|
140
|
+
flexDirection: 'row',
|
|
141
|
+
alignItems: 'center',
|
|
142
|
+
gap: cellGap,
|
|
143
|
+
padding: cellPadding,
|
|
144
|
+
minHeight: cellMinHeight
|
|
145
|
+
};
|
|
146
|
+
const valueCellStyle = {
|
|
147
|
+
flexDirection: 'row',
|
|
148
|
+
alignItems: 'center',
|
|
149
|
+
justifyContent: 'center',
|
|
150
|
+
padding: cellPadding,
|
|
151
|
+
minHeight: cellMinHeight,
|
|
152
|
+
width: '100%'
|
|
153
|
+
};
|
|
154
|
+
const renderValue = (value, cellKey) => {
|
|
155
|
+
if (value === false) {
|
|
156
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Icon.default, {
|
|
157
|
+
name: "ic_close",
|
|
158
|
+
size: iconSize,
|
|
159
|
+
color: labelDisabledColor
|
|
160
|
+
}, cellKey);
|
|
161
|
+
}
|
|
162
|
+
if (value === null || value === undefined || value === true) {
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
if (typeof value === 'string' || typeof value === 'number') {
|
|
166
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
167
|
+
style: valueTextStyle,
|
|
168
|
+
children: value
|
|
169
|
+
}, cellKey);
|
|
170
|
+
}
|
|
171
|
+
return (0, _reactUtils.cloneChildrenWithModes)(value, modes);
|
|
172
|
+
};
|
|
173
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
174
|
+
style: [{
|
|
175
|
+
gap,
|
|
176
|
+
width: '100%'
|
|
177
|
+
}, style],
|
|
178
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
179
|
+
style: rowStyle,
|
|
180
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
181
|
+
style: labelColumnStyle
|
|
182
|
+
}), columns.map((column, index) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
183
|
+
style: planColumnStyle,
|
|
184
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
185
|
+
style: [headerTextStyle, {
|
|
186
|
+
color: column.brand ? headerBrandFg : headerFg
|
|
187
|
+
}],
|
|
188
|
+
children: column.label
|
|
189
|
+
})
|
|
190
|
+
}, column.label ?? index))]
|
|
191
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
192
|
+
style: {
|
|
193
|
+
width: '100%',
|
|
194
|
+
backgroundColor: tableBackground,
|
|
195
|
+
borderWidth: tableBorderSize,
|
|
196
|
+
borderColor: tableBorderColor,
|
|
197
|
+
borderRadius: tableRadius,
|
|
198
|
+
overflow: 'hidden'
|
|
199
|
+
},
|
|
200
|
+
children: rows.map((row, rowIndex) => {
|
|
201
|
+
const isLast = rowIndex === rows.length - 1;
|
|
202
|
+
const showInfo = row.showInfo || row.onInfoPress != null;
|
|
203
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
204
|
+
style: [rowStyle, {
|
|
205
|
+
borderBottomWidth: isLast ? 0 : cellBorderSize,
|
|
206
|
+
borderBottomColor: cellBorderColor
|
|
207
|
+
}],
|
|
208
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
209
|
+
style: [labelColumnStyle, labelCellStyle],
|
|
210
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
211
|
+
style: labelTextStyle,
|
|
212
|
+
children: row.label
|
|
213
|
+
}), showInfo && (row.onInfoPress ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
|
|
214
|
+
onPress: row.onInfoPress,
|
|
215
|
+
accessibilityRole: "button",
|
|
216
|
+
accessibilityLabel: `More information about ${row.label}`,
|
|
217
|
+
hitSlop: 8,
|
|
218
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Icon.default, {
|
|
219
|
+
name: "ic_info",
|
|
220
|
+
size: iconSize,
|
|
221
|
+
color: iconColor
|
|
222
|
+
})
|
|
223
|
+
}) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_Icon.default, {
|
|
224
|
+
name: "ic_info",
|
|
225
|
+
size: iconSize,
|
|
226
|
+
color: iconColor
|
|
227
|
+
}))]
|
|
228
|
+
}), columns.map((column, colIndex) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
229
|
+
style: [planColumnStyle, valueCellStyle],
|
|
230
|
+
children: renderValue(row.values?.[colIndex], `${rowIndex}-${colIndex}`)
|
|
231
|
+
}, column.label ?? colIndex))]
|
|
232
|
+
}, row.key ?? `${row.label}-${rowIndex}`);
|
|
233
|
+
})
|
|
234
|
+
})]
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
var _default = exports.default = PlanComparisonCard;
|
|
@@ -0,0 +1,73 @@
|
|
|
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 _figmaVariablesResolver = require("../../design-tokens/figma-variables-resolver");
|
|
10
|
+
var _JFSThemeProvider = require("../../design-tokens/JFSThemeProvider");
|
|
11
|
+
var _reactUtils = require("../../utils/react-utils");
|
|
12
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
13
|
+
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); }
|
|
14
|
+
/**
|
|
15
|
+
* Slot — a token-driven layout container for grouped slot content.
|
|
16
|
+
*
|
|
17
|
+
* Use `Slot` instead of a raw `View` when you need a vertical or horizontal
|
|
18
|
+
* stack with design-token gap spacing and automatic `modes` propagation to
|
|
19
|
+
* children. Typical usage is nesting a column of actions inside a
|
|
20
|
+
* direction-locked parent such as `ActionFooter`:
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```tsx
|
|
24
|
+
* <ActionFooter modes={modes}>
|
|
25
|
+
* <Slot layoutDirection="vertical" modes={modes}>
|
|
26
|
+
* <Button label="Continue" modes={primaryModes} />
|
|
27
|
+
* <Disclaimer disclaimer="Terms apply." modes={modes} />
|
|
28
|
+
* </Slot>
|
|
29
|
+
* </ActionFooter>
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
function Slot({
|
|
33
|
+
children,
|
|
34
|
+
layoutDirection = 'vertical',
|
|
35
|
+
alignCrossAxis,
|
|
36
|
+
justifyMainAxis,
|
|
37
|
+
modes: propModes = _reactUtils.EMPTY_MODES,
|
|
38
|
+
style,
|
|
39
|
+
...rest
|
|
40
|
+
}) {
|
|
41
|
+
const {
|
|
42
|
+
modes: globalModes
|
|
43
|
+
} = (0, _JFSThemeProvider.useTokens)();
|
|
44
|
+
const modes = (0, _react.useMemo)(() => ({
|
|
45
|
+
...globalModes,
|
|
46
|
+
...propModes
|
|
47
|
+
}), [globalModes, propModes]);
|
|
48
|
+
const {
|
|
49
|
+
containerStyle,
|
|
50
|
+
processedChildren
|
|
51
|
+
} = (0, _react.useMemo)(() => {
|
|
52
|
+
const gap = (0, _figmaVariablesResolver.getVariableByName)('slot/gap', modes) ?? 8;
|
|
53
|
+
const isHorizontal = layoutDirection === 'horizontal';
|
|
54
|
+
const container = {
|
|
55
|
+
flexDirection: isHorizontal ? 'row' : 'column',
|
|
56
|
+
alignItems: alignCrossAxis ?? (isHorizontal ? 'flex-start' : 'stretch'),
|
|
57
|
+
justifyContent: justifyMainAxis ?? (isHorizontal ? 'center' : undefined),
|
|
58
|
+
alignSelf: 'stretch',
|
|
59
|
+
gap
|
|
60
|
+
};
|
|
61
|
+
const processed = children ? (0, _reactUtils.cloneChildrenWithModes)(children, modes) : null;
|
|
62
|
+
return {
|
|
63
|
+
containerStyle: container,
|
|
64
|
+
processedChildren: processed
|
|
65
|
+
};
|
|
66
|
+
}, [children, modes, layoutDirection, alignCrossAxis, justifyMainAxis]);
|
|
67
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
68
|
+
style: [containerStyle, style],
|
|
69
|
+
...rest,
|
|
70
|
+
children: processedChildren
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
var _default = exports.default = /*#__PURE__*/_react.default.memo(Slot);
|