jfs-components 0.0.72 → 0.0.74
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 +28 -0
- package/lib/commonjs/components/AccordionCheckbox/AccordionCheckbox.js +239 -0
- package/lib/commonjs/components/AccountCard/AccountCard.js +247 -0
- package/lib/commonjs/components/AppBar/AppBar.js +17 -11
- package/lib/commonjs/components/BrandChip/BrandChip.js +149 -0
- package/lib/commonjs/components/CardBankAccount/CardBankAccount.js +229 -0
- package/lib/commonjs/components/CardInsight/CardInsight.js +166 -0
- package/lib/commonjs/components/CheckboxGroup/CheckboxGroup.js +67 -0
- package/lib/commonjs/components/CheckboxItem/CheckboxItem.js +140 -0
- package/lib/commonjs/components/CircularProgressBar/CircularProgressBar.js +56 -9
- package/lib/commonjs/components/CoverageBarComparison/CoverageBarComparison.js +272 -0
- package/lib/commonjs/components/CoverageRing/CoverageRing.js +141 -0
- package/lib/commonjs/components/DonutChart/DonutChart.js +309 -0
- package/lib/commonjs/components/DonutChartSummary/DonutChartSummary.js +155 -0
- package/lib/commonjs/components/Dropdown/Dropdown.js +214 -0
- package/lib/commonjs/components/DropdownInput/DropdownInput.js +542 -0
- package/lib/commonjs/components/FormField/FormField.js +328 -178
- package/lib/commonjs/components/LinearMeter/LinearMeter.js +9 -28
- package/lib/commonjs/components/LinearProgress/LinearProgress.js +68 -0
- package/lib/commonjs/components/LottieIntroBlock/LottieIntroBlock.js +150 -0
- package/lib/commonjs/components/MetricLegendItem/MetricLegendItem.js +95 -0
- package/lib/commonjs/components/MonthlyStatusGrid/MonthlyStatusGrid.js +286 -0
- package/lib/commonjs/components/OTP/OTP.js +381 -37
- package/lib/commonjs/components/PageHero/PageHero.js +153 -0
- package/lib/commonjs/components/PoweredByLabel/PoweredByLabel.js +135 -0
- package/lib/commonjs/components/PoweredByLabel/finvu.png +0 -0
- package/lib/commonjs/components/ProductOverview/ProductOverview.js +147 -0
- package/lib/commonjs/components/RangeTrack/RangeTrack.js +269 -0
- package/lib/commonjs/components/SavingsGoalSummary/SavingsGoalSummary.js +181 -0
- package/lib/commonjs/components/SegmentedTrack/SegmentedTrack.js +171 -0
- package/lib/commonjs/components/StatGroup/StatGroup.js +128 -0
- package/lib/commonjs/components/StatItem/StatItem.js +65 -35
- package/lib/commonjs/components/StrengthIndicator/StrengthIndicator.js +157 -0
- package/lib/commonjs/components/SummaryTile/SummaryTile.js +150 -0
- package/lib/commonjs/components/Text/Text.js +9 -2
- package/lib/commonjs/components/Tooltip/Tooltip.js +34 -27
- package/lib/commonjs/components/index.js +231 -1
- package/lib/commonjs/design-tokens/Coin Variables-variables-full.json +1 -1
- package/lib/commonjs/icons/registry.js +1 -1
- package/lib/commonjs/utils/index.js +7 -0
- package/lib/commonjs/utils/number-utils.js +57 -0
- package/lib/module/components/AccordionCheckbox/AccordionCheckbox.js +233 -0
- package/lib/module/components/AccountCard/AccountCard.js +241 -0
- package/lib/module/components/AppBar/AppBar.js +17 -11
- package/lib/module/components/BrandChip/BrandChip.js +143 -0
- package/lib/module/components/CardBankAccount/CardBankAccount.js +223 -0
- package/lib/module/components/CardInsight/CardInsight.js +161 -0
- package/lib/module/components/CheckboxGroup/CheckboxGroup.js +62 -0
- package/lib/module/components/CheckboxItem/CheckboxItem.js +134 -0
- package/lib/module/components/CircularProgressBar/CircularProgressBar.js +56 -9
- package/lib/module/components/CoverageBarComparison/CoverageBarComparison.js +266 -0
- package/lib/module/components/CoverageRing/CoverageRing.js +136 -0
- package/lib/module/components/DonutChart/DonutChart.js +303 -0
- package/lib/module/components/DonutChartSummary/DonutChartSummary.js +150 -0
- package/lib/module/components/Dropdown/Dropdown.js +206 -0
- package/lib/module/components/DropdownInput/DropdownInput.js +536 -0
- package/lib/module/components/FormField/FormField.js +330 -180
- package/lib/module/components/LinearMeter/LinearMeter.js +9 -28
- package/lib/module/components/LinearProgress/LinearProgress.js +63 -0
- package/lib/module/components/LottieIntroBlock/LottieIntroBlock.js +144 -0
- package/lib/module/components/MetricLegendItem/MetricLegendItem.js +90 -0
- package/lib/module/components/MonthlyStatusGrid/MonthlyStatusGrid.js +281 -0
- package/lib/module/components/OTP/OTP.js +381 -38
- package/lib/module/components/PageHero/PageHero.js +147 -0
- package/lib/module/components/PoweredByLabel/PoweredByLabel.js +130 -0
- package/lib/module/components/PoweredByLabel/finvu.png +0 -0
- package/lib/module/components/ProductOverview/ProductOverview.js +142 -0
- package/lib/module/components/RangeTrack/RangeTrack.js +263 -0
- package/lib/module/components/SavingsGoalSummary/SavingsGoalSummary.js +175 -0
- package/lib/module/components/SegmentedTrack/SegmentedTrack.js +166 -0
- package/lib/module/components/StatGroup/StatGroup.js +123 -0
- package/lib/module/components/StatItem/StatItem.js +66 -36
- package/lib/module/components/StrengthIndicator/StrengthIndicator.js +152 -0
- package/lib/module/components/SummaryTile/SummaryTile.js +145 -0
- package/lib/module/components/Text/Text.js +9 -2
- package/lib/module/components/Tooltip/Tooltip.js +34 -27
- package/lib/module/components/index.js +28 -2
- package/lib/module/design-tokens/Coin Variables-variables-full.json +1 -1
- package/lib/module/icons/registry.js +1 -1
- package/lib/module/utils/index.js +2 -1
- package/lib/module/utils/number-utils.js +53 -0
- package/lib/typescript/src/components/AccordionCheckbox/AccordionCheckbox.d.ts +71 -0
- package/lib/typescript/src/components/AccountCard/AccountCard.d.ts +81 -0
- package/lib/typescript/src/components/BrandChip/BrandChip.d.ts +43 -0
- package/lib/typescript/src/components/CardBankAccount/CardBankAccount.d.ts +86 -0
- package/lib/typescript/src/components/CardInsight/CardInsight.d.ts +48 -0
- package/lib/typescript/src/components/CheckboxGroup/CheckboxGroup.d.ts +41 -0
- package/lib/typescript/src/components/CheckboxItem/CheckboxItem.d.ts +72 -0
- package/lib/typescript/src/components/CircularProgressBar/CircularProgressBar.d.ts +11 -1
- package/lib/typescript/src/components/CoverageBarComparison/CoverageBarComparison.d.ts +105 -0
- package/lib/typescript/src/components/CoverageRing/CoverageRing.d.ts +90 -0
- package/lib/typescript/src/components/DonutChart/DonutChart.d.ts +117 -0
- package/lib/typescript/src/components/DonutChartSummary/DonutChartSummary.d.ts +103 -0
- package/lib/typescript/src/components/Dropdown/Dropdown.d.ts +62 -0
- package/lib/typescript/src/components/DropdownInput/DropdownInput.d.ts +107 -0
- package/lib/typescript/src/components/FormField/FormField.d.ts +76 -19
- package/lib/typescript/src/components/LinearProgress/LinearProgress.d.ts +17 -0
- package/lib/typescript/src/components/LottieIntroBlock/LottieIntroBlock.d.ts +58 -0
- package/lib/typescript/src/components/MetricLegendItem/MetricLegendItem.d.ts +37 -0
- package/lib/typescript/src/components/MonthlyStatusGrid/MonthlyStatusGrid.d.ts +119 -0
- package/lib/typescript/src/components/OTP/OTP.d.ts +88 -2
- package/lib/typescript/src/components/PageHero/PageHero.d.ts +53 -0
- package/lib/typescript/src/components/PoweredByLabel/PoweredByLabel.d.ts +70 -0
- package/lib/typescript/src/components/ProductOverview/ProductOverview.d.ts +39 -0
- package/lib/typescript/src/components/RangeTrack/RangeTrack.d.ts +173 -0
- package/lib/typescript/src/components/SavingsGoalSummary/SavingsGoalSummary.d.ts +95 -0
- package/lib/typescript/src/components/SegmentedTrack/SegmentedTrack.d.ts +108 -0
- package/lib/typescript/src/components/StatGroup/StatGroup.d.ts +45 -0
- package/lib/typescript/src/components/StatItem/StatItem.d.ts +24 -7
- package/lib/typescript/src/components/StrengthIndicator/StrengthIndicator.d.ts +58 -0
- package/lib/typescript/src/components/SummaryTile/SummaryTile.d.ts +60 -0
- package/lib/typescript/src/components/Text/Text.d.ts +12 -2
- package/lib/typescript/src/components/Tooltip/Tooltip.d.ts +13 -2
- package/lib/typescript/src/components/index.d.ts +29 -3
- package/lib/typescript/src/icons/registry.d.ts +1 -1
- package/lib/typescript/src/utils/index.d.ts +1 -0
- package/lib/typescript/src/utils/number-utils.d.ts +29 -0
- package/package.json +1 -3
- package/src/components/AccordionCheckbox/AccordionCheckbox.tsx +323 -0
- package/src/components/AccountCard/AccountCard.tsx +376 -0
- package/src/components/AppBar/AppBar.tsx +25 -14
- package/src/components/BrandChip/BrandChip.tsx +235 -0
- package/src/components/CardBankAccount/CardBankAccount.tsx +321 -0
- package/src/components/CardInsight/CardInsight.tsx +239 -0
- package/src/components/CheckboxGroup/CheckboxGroup.tsx +86 -0
- package/src/components/CheckboxItem/CheckboxItem.tsx +209 -0
- package/src/components/CircularProgressBar/CircularProgressBar.tsx +74 -9
- package/src/components/CoverageBarComparison/CoverageBarComparison.tsx +378 -0
- package/src/components/CoverageRing/CoverageRing.tsx +225 -0
- package/src/components/DonutChart/DonutChart.tsx +503 -0
- package/src/components/DonutChartSummary/DonutChartSummary.tsx +256 -0
- package/src/components/Dropdown/Dropdown.tsx +331 -0
- package/src/components/DropdownInput/DropdownInput.tsx +819 -0
- package/src/components/FormField/FormField.tsx +542 -215
- package/src/components/LinearMeter/LinearMeter.tsx +9 -39
- package/src/components/LinearProgress/LinearProgress.tsx +92 -0
- package/src/components/LottieIntroBlock/LottieIntroBlock.tsx +202 -0
- package/src/components/MetricLegendItem/MetricLegendItem.tsx +167 -0
- package/src/components/MonthlyStatusGrid/MonthlyStatusGrid.tsx +438 -0
- package/src/components/OTP/OTP.tsx +476 -29
- package/src/components/PageHero/PageHero.tsx +200 -0
- package/src/components/PoweredByLabel/PoweredByLabel.tsx +221 -0
- package/src/components/PoweredByLabel/finvu.png +0 -0
- package/src/components/ProductOverview/ProductOverview.tsx +236 -0
- package/src/components/RangeTrack/RangeTrack.tsx +394 -0
- package/src/components/SavingsGoalSummary/SavingsGoalSummary.tsx +269 -0
- package/src/components/SegmentedTrack/SegmentedTrack.tsx +268 -0
- package/src/components/StatGroup/StatGroup.tsx +169 -0
- package/src/components/StatItem/StatItem.tsx +117 -40
- package/src/components/StrengthIndicator/StrengthIndicator.tsx +205 -0
- package/src/components/SummaryTile/SummaryTile.tsx +251 -0
- package/src/components/Text/Text.tsx +24 -3
- package/src/components/Tooltip/Tooltip.tsx +50 -25
- package/src/components/index.ts +47 -3
- package/src/design-tokens/Coin Variables-variables-full.json +1 -1
- package/src/icons/registry.ts +1 -1
- package/src/utils/index.ts +1 -0
- package/src/utils/number-utils.ts +60 -0
|
@@ -0,0 +1,135 @@
|
|
|
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 _MediaSource = _interopRequireDefault(require("../../utils/MediaSource"));
|
|
13
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
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
|
+
// Default bundled FINVU brand logo, matching the Figma reference so the
|
|
17
|
+
// component renders correctly out of the box without any image prop.
|
|
18
|
+
const DEFAULT_LOGO = require('./finvu.png');
|
|
19
|
+
const DEFAULT_LABEL = 'Powered by RBI-regulated account aggregator';
|
|
20
|
+
const DEFAULT_IMAGE_WIDTH = 33;
|
|
21
|
+
const DEFAULT_IMAGE_HEIGHT = 12;
|
|
22
|
+
const toNumber = (value, fallback) => {
|
|
23
|
+
if (typeof value === 'number') return Number.isFinite(value) ? value : fallback;
|
|
24
|
+
if (typeof value === 'string') {
|
|
25
|
+
const parsed = Number(value);
|
|
26
|
+
return Number.isFinite(parsed) ? parsed : fallback;
|
|
27
|
+
}
|
|
28
|
+
return fallback;
|
|
29
|
+
};
|
|
30
|
+
const toFontWeight = (value, fallback) => {
|
|
31
|
+
if (typeof value === 'number') return String(value);
|
|
32
|
+
if (typeof value === 'string') return value;
|
|
33
|
+
return fallback;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* `PoweredByLabel` renders the small "Powered by RBI-regulated account
|
|
38
|
+
* aggregator" badge with a trailing brand logo, used to attribute the
|
|
39
|
+
* underlying account-aggregator partner in flows such as bank-account
|
|
40
|
+
* linking and consent screens.
|
|
41
|
+
*
|
|
42
|
+
* The component is composed of:
|
|
43
|
+
*
|
|
44
|
+
* 1. A token-styled pill container (`poweredByLabel/background`,
|
|
45
|
+
* `poweredByLabel/padding/*`).
|
|
46
|
+
* 2. The disclosure copy rendered through the `poweredByLabel/*` typography
|
|
47
|
+
* tokens.
|
|
48
|
+
* 3. A configurable brand logo slot. Defaults to the bundled FINVU mark, but
|
|
49
|
+
* callers can pass any image via `imageSource` or fully replace the slot
|
|
50
|
+
* via `imageSlot`.
|
|
51
|
+
*
|
|
52
|
+
* @component
|
|
53
|
+
* @param {PoweredByLabelProps} props
|
|
54
|
+
*/
|
|
55
|
+
function PoweredByLabel({
|
|
56
|
+
label = DEFAULT_LABEL,
|
|
57
|
+
imageSource,
|
|
58
|
+
imageWidth = DEFAULT_IMAGE_WIDTH,
|
|
59
|
+
imageHeight = DEFAULT_IMAGE_HEIGHT,
|
|
60
|
+
imageSlot,
|
|
61
|
+
modes: propModes = _reactUtils.EMPTY_MODES,
|
|
62
|
+
style,
|
|
63
|
+
textStyle,
|
|
64
|
+
imageStyle,
|
|
65
|
+
accessibilityLabel
|
|
66
|
+
}) {
|
|
67
|
+
const {
|
|
68
|
+
modes: globalModes
|
|
69
|
+
} = (0, _JFSThemeProvider.useTokens)();
|
|
70
|
+
const modes = (0, _react.useMemo)(() => globalModes === _reactUtils.EMPTY_MODES && propModes === _reactUtils.EMPTY_MODES ? _reactUtils.EMPTY_MODES : {
|
|
71
|
+
...globalModes,
|
|
72
|
+
...propModes
|
|
73
|
+
}, [globalModes, propModes]);
|
|
74
|
+
const background = (0, _figmaVariablesResolver.getVariableByName)('poweredByLabel/background', modes) ?? '#f5f5f5';
|
|
75
|
+
const foreground = (0, _figmaVariablesResolver.getVariableByName)('poweredByLabel/foreground', modes) ?? '#191b1e';
|
|
76
|
+
const fontFamily = (0, _figmaVariablesResolver.getVariableByName)('poweredByLabel/fontFamily', modes) ?? 'JioType Var';
|
|
77
|
+
const fontSize = toNumber((0, _figmaVariablesResolver.getVariableByName)('poweredByLabel/fontSize', modes), 10);
|
|
78
|
+
const lineHeight = toNumber((0, _figmaVariablesResolver.getVariableByName)('poweredByLabel/lineHeight', modes), 12);
|
|
79
|
+
const fontWeight = toFontWeight((0, _figmaVariablesResolver.getVariableByName)('poweredByLabel/fontWeight', modes), '400');
|
|
80
|
+
const gap = toNumber((0, _figmaVariablesResolver.getVariableByName)('poweredByLabel/gap', modes), 10);
|
|
81
|
+
const paddingHorizontal = toNumber((0, _figmaVariablesResolver.getVariableByName)('poweredByLabel/padding/horizontal', modes), 16);
|
|
82
|
+
const paddingVertical = toNumber((0, _figmaVariablesResolver.getVariableByName)('poweredByLabel/padding/vertical', modes), 6);
|
|
83
|
+
const containerStyle = {
|
|
84
|
+
flexDirection: 'row',
|
|
85
|
+
alignItems: 'center',
|
|
86
|
+
justifyContent: 'center',
|
|
87
|
+
backgroundColor: background,
|
|
88
|
+
paddingHorizontal,
|
|
89
|
+
paddingVertical,
|
|
90
|
+
gap,
|
|
91
|
+
// Hug content horizontally so the pill does not stretch to fill the
|
|
92
|
+
// parent (matches Badge, BrandChip, etc.). Override via `style` if
|
|
93
|
+
// you want it full-width (e.g. inside a card footer).
|
|
94
|
+
alignSelf: 'flex-start'
|
|
95
|
+
};
|
|
96
|
+
const labelTextStyle = {
|
|
97
|
+
color: foreground,
|
|
98
|
+
fontFamily,
|
|
99
|
+
fontSize,
|
|
100
|
+
lineHeight,
|
|
101
|
+
fontWeight,
|
|
102
|
+
textAlign: 'center',
|
|
103
|
+
flexShrink: 1
|
|
104
|
+
};
|
|
105
|
+
const renderImage = () => {
|
|
106
|
+
if (imageSlot !== undefined && imageSlot !== null) {
|
|
107
|
+
const processed = (0, _reactUtils.cloneChildrenWithModes)(imageSlot, modes);
|
|
108
|
+
if (processed.length === 0) return null;
|
|
109
|
+
return processed.length === 1 ? processed[0] : processed;
|
|
110
|
+
}
|
|
111
|
+
const resolvedSource = imageSource ?? DEFAULT_LOGO;
|
|
112
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_MediaSource.default, {
|
|
113
|
+
source: resolvedSource,
|
|
114
|
+
width: imageWidth,
|
|
115
|
+
height: imageHeight,
|
|
116
|
+
resizeMode: "contain",
|
|
117
|
+
style: imageStyle,
|
|
118
|
+
accessibilityElementsHidden: true,
|
|
119
|
+
importantForAccessibility: "no"
|
|
120
|
+
});
|
|
121
|
+
};
|
|
122
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
123
|
+
accessibilityRole: "text",
|
|
124
|
+
accessibilityLabel: accessibilityLabel ?? label,
|
|
125
|
+
style: [containerStyle, style],
|
|
126
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
127
|
+
style: [labelTextStyle, textStyle],
|
|
128
|
+
accessibilityElementsHidden: true,
|
|
129
|
+
importantForAccessibility: "no",
|
|
130
|
+
numberOfLines: 1,
|
|
131
|
+
children: label
|
|
132
|
+
}), renderImage()]
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
var _default = exports.default = PoweredByLabel;
|
|
Binary file
|
|
@@ -0,0 +1,147 @@
|
|
|
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 _Image = _interopRequireDefault(require("../Image/Image"));
|
|
12
|
+
var _ProductLabel = _interopRequireDefault(require("../ProductLabel/ProductLabel"));
|
|
13
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
14
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
15
|
+
const DEFAULT_STATS = [{
|
|
16
|
+
value: '995',
|
|
17
|
+
label: 'Purity'
|
|
18
|
+
}, {
|
|
19
|
+
value: '3%',
|
|
20
|
+
label: 'GST'
|
|
21
|
+
}];
|
|
22
|
+
const ProductOverview = ({
|
|
23
|
+
imageSource,
|
|
24
|
+
imageRatio = 288 / 170,
|
|
25
|
+
labelImageSource,
|
|
26
|
+
label = 'Gold',
|
|
27
|
+
productName = '0.5g Gold Coin',
|
|
28
|
+
description = 'Your gold is insured from our vault to you. If lost or damaged, we’ll replace it.',
|
|
29
|
+
stats = DEFAULT_STATS,
|
|
30
|
+
modes = _reactUtils.EMPTY_MODES,
|
|
31
|
+
style,
|
|
32
|
+
children
|
|
33
|
+
}) => {
|
|
34
|
+
const padding = (0, _figmaVariablesResolver.getVariableByName)('productOverview/padding', modes) ?? 24;
|
|
35
|
+
const gap = (0, _figmaVariablesResolver.getVariableByName)('productOverview/gap', modes) ?? 12;
|
|
36
|
+
const background = (0, _figmaVariablesResolver.getVariableByName)('productOverview/background', modes) ?? '#ffffff';
|
|
37
|
+
const productNameColor = (0, _figmaVariablesResolver.getVariableByName)('productOverview/productName/color', modes) ?? '#0d0d0f';
|
|
38
|
+
const productNameFontFamily = (0, _figmaVariablesResolver.getVariableByName)('productOverview/productName/fontFamily', modes) ?? 'JioType Var';
|
|
39
|
+
const productNameFontSize = (0, _figmaVariablesResolver.getVariableByName)('productOverview/productName/fontSize', modes) ?? 26;
|
|
40
|
+
const productNameFontWeight = (0, _figmaVariablesResolver.getVariableByName)('productOverview/productName/fontWeight', modes) ?? 900;
|
|
41
|
+
const productNameLineHeight = (0, _figmaVariablesResolver.getVariableByName)('productOverview/productName/lineHeight', modes) ?? 26;
|
|
42
|
+
const descriptionColor = (0, _figmaVariablesResolver.getVariableByName)('productOverview/description/color', modes) ?? '#1a1c1f';
|
|
43
|
+
const descriptionFontFamily = (0, _figmaVariablesResolver.getVariableByName)('productOverview/description/fontFamily', modes) ?? 'JioType Var';
|
|
44
|
+
const descriptionFontSize = (0, _figmaVariablesResolver.getVariableByName)('productOverview/description/fontSize', modes) ?? 14;
|
|
45
|
+
const descriptionFontWeight = (0, _figmaVariablesResolver.getVariableByName)('productOverview/description/fontWeight', modes) ?? 500;
|
|
46
|
+
const descriptionLineHeight = (0, _figmaVariablesResolver.getVariableByName)('productOverview/description/lineHeight', modes) ?? 18.2;
|
|
47
|
+
const statGap = (0, _figmaVariablesResolver.getVariableByName)('productOverview/stat/gap', modes) ?? 2;
|
|
48
|
+
const statValueColor = (0, _figmaVariablesResolver.getVariableByName)('productOverview/stat/value/color', modes) ?? '#141414';
|
|
49
|
+
const statValueFontFamily = (0, _figmaVariablesResolver.getVariableByName)('productOverview/stat/value/fontFamily', modes) ?? 'JioType Var';
|
|
50
|
+
const statValueFontSize = (0, _figmaVariablesResolver.getVariableByName)('productOverview/stat/value/fontSize', modes) ?? 20;
|
|
51
|
+
const statValueFontWeight = (0, _figmaVariablesResolver.getVariableByName)('productOverview/stat/value/fontWeight', modes) ?? 900;
|
|
52
|
+
const statValueLineHeight = (0, _figmaVariablesResolver.getVariableByName)('productOverview/stat/value/lineHeight', modes) ?? 20;
|
|
53
|
+
const statLabelColor = productNameColor;
|
|
54
|
+
const statLabelFontFamily = (0, _figmaVariablesResolver.getVariableByName)('productOverview/stat/label/fontFamily', modes) ?? 'JioType Var';
|
|
55
|
+
const statLabelFontSize = (0, _figmaVariablesResolver.getVariableByName)('productOverview/stat/label/fontSize', modes) ?? 12;
|
|
56
|
+
const statLabelFontWeight = (0, _figmaVariablesResolver.getVariableByName)('productOverview/stat/label/fontWeight', modes) ?? 400;
|
|
57
|
+
const statLabelLineHeight = (0, _figmaVariablesResolver.getVariableByName)('productOverview/stat/label/lineHeight', modes) ?? 15.6;
|
|
58
|
+
const productNameStyle = {
|
|
59
|
+
color: productNameColor,
|
|
60
|
+
fontFamily: productNameFontFamily,
|
|
61
|
+
fontSize: productNameFontSize,
|
|
62
|
+
fontWeight: String(productNameFontWeight),
|
|
63
|
+
lineHeight: productNameLineHeight,
|
|
64
|
+
textAlign: 'center'
|
|
65
|
+
};
|
|
66
|
+
const descriptionStyle = {
|
|
67
|
+
color: descriptionColor,
|
|
68
|
+
fontFamily: descriptionFontFamily,
|
|
69
|
+
fontSize: descriptionFontSize,
|
|
70
|
+
fontWeight: String(descriptionFontWeight),
|
|
71
|
+
lineHeight: descriptionLineHeight,
|
|
72
|
+
textAlign: 'center'
|
|
73
|
+
};
|
|
74
|
+
const statValueStyle = {
|
|
75
|
+
color: statValueColor,
|
|
76
|
+
fontFamily: statValueFontFamily,
|
|
77
|
+
fontSize: statValueFontSize,
|
|
78
|
+
fontWeight: String(statValueFontWeight),
|
|
79
|
+
lineHeight: statValueLineHeight
|
|
80
|
+
};
|
|
81
|
+
const statLabelStyle = {
|
|
82
|
+
color: statLabelColor,
|
|
83
|
+
fontFamily: statLabelFontFamily,
|
|
84
|
+
fontSize: statLabelFontSize,
|
|
85
|
+
fontWeight: String(statLabelFontWeight),
|
|
86
|
+
lineHeight: statLabelLineHeight,
|
|
87
|
+
textAlign: 'center'
|
|
88
|
+
};
|
|
89
|
+
const showStats = Array.isArray(stats) && stats.length > 0;
|
|
90
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
91
|
+
style: [{
|
|
92
|
+
backgroundColor: background,
|
|
93
|
+
padding,
|
|
94
|
+
gap,
|
|
95
|
+
alignItems: 'center',
|
|
96
|
+
width: '100%'
|
|
97
|
+
}, style],
|
|
98
|
+
children: [imageSource != null && /*#__PURE__*/(0, _jsxRuntime.jsx)(_Image.default, {
|
|
99
|
+
imageSource: imageSource,
|
|
100
|
+
ratio: imageRatio,
|
|
101
|
+
resizeMode: "contain",
|
|
102
|
+
accessibilityElementsHidden: true,
|
|
103
|
+
importantForAccessibility: "no"
|
|
104
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_ProductLabel.default, {
|
|
105
|
+
label: label,
|
|
106
|
+
...(labelImageSource != null && {
|
|
107
|
+
imageSource: labelImageSource
|
|
108
|
+
}),
|
|
109
|
+
modes: modes
|
|
110
|
+
}), productName ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
111
|
+
style: productNameStyle,
|
|
112
|
+
accessibilityRole: "header",
|
|
113
|
+
children: productName
|
|
114
|
+
}) : null, description ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
115
|
+
style: descriptionStyle,
|
|
116
|
+
children: description
|
|
117
|
+
}) : null, children ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_jsxRuntime.Fragment, {
|
|
118
|
+
children: (0, _reactUtils.cloneChildrenWithModes)(children, modes)
|
|
119
|
+
}) : null, showStats && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
120
|
+
style: {
|
|
121
|
+
flexDirection: 'row',
|
|
122
|
+
alignItems: 'center',
|
|
123
|
+
justifyContent: 'space-between',
|
|
124
|
+
width: '100%'
|
|
125
|
+
},
|
|
126
|
+
children: stats.map((stat, index) => /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
127
|
+
style: {
|
|
128
|
+
flex: 1,
|
|
129
|
+
minWidth: 0,
|
|
130
|
+
alignItems: 'center',
|
|
131
|
+
gap: statGap,
|
|
132
|
+
overflow: 'hidden'
|
|
133
|
+
},
|
|
134
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
135
|
+
style: statValueStyle,
|
|
136
|
+
numberOfLines: 1,
|
|
137
|
+
children: stat.value
|
|
138
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
139
|
+
style: statLabelStyle,
|
|
140
|
+
numberOfLines: 1,
|
|
141
|
+
children: stat.label
|
|
142
|
+
})]
|
|
143
|
+
}, `${stat.label}-${index}`))
|
|
144
|
+
})]
|
|
145
|
+
});
|
|
146
|
+
};
|
|
147
|
+
var _default = exports.default = ProductOverview;
|
|
@@ -0,0 +1,269 @@
|
|
|
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 _MetricLegendItem = _interopRequireDefault(require("../MetricLegendItem/MetricLegendItem"));
|
|
13
|
+
var _SegmentedTrack = _interopRequireDefault(require("../SegmentedTrack/SegmentedTrack"));
|
|
14
|
+
var _Tabs = _interopRequireDefault(require("../Tabs/Tabs"));
|
|
15
|
+
var _TabItem = _interopRequireDefault(require("../Tabs/TabItem"));
|
|
16
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
17
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
18
|
+
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); }
|
|
19
|
+
/**
|
|
20
|
+
* One row of data inside a `RangeTrack` tab.
|
|
21
|
+
*
|
|
22
|
+
* Each item drives BOTH a `SegmentedTrack` segment and the matching
|
|
23
|
+
* `MetricLegendItem` row, so the segment color and legend indicator
|
|
24
|
+
* always share the same color by construction (same `Emphasis / DataViz`
|
|
25
|
+
* cascade as the standalone `SegmentedTrack`).
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* One tab inside a `RangeTrack`. Each tab carries its own `items`
|
|
30
|
+
* array, which is the single source of truth for both the
|
|
31
|
+
* `SegmentedTrack` segments AND the `MetricLegendItem` legend rows
|
|
32
|
+
* rendered for that tab.
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
const DEFAULT_EMPHASIS_CYCLE = ['High', 'Medium', 'Low'];
|
|
36
|
+
const DEFAULT_TABS = [{
|
|
37
|
+
label: 'Tab item',
|
|
38
|
+
items: [{
|
|
39
|
+
label: 'Large cap',
|
|
40
|
+
value: 1,
|
|
41
|
+
displayValue: '25%'
|
|
42
|
+
}, {
|
|
43
|
+
label: 'Mid cap',
|
|
44
|
+
value: 1,
|
|
45
|
+
displayValue: '25%'
|
|
46
|
+
}, {
|
|
47
|
+
label: 'Small cap',
|
|
48
|
+
value: 1,
|
|
49
|
+
displayValue: '25%'
|
|
50
|
+
}]
|
|
51
|
+
}, {
|
|
52
|
+
label: 'Tab item',
|
|
53
|
+
items: [{
|
|
54
|
+
label: 'Large cap',
|
|
55
|
+
value: 1,
|
|
56
|
+
displayValue: '25%'
|
|
57
|
+
}, {
|
|
58
|
+
label: 'Mid cap',
|
|
59
|
+
value: 1,
|
|
60
|
+
displayValue: '25%'
|
|
61
|
+
}, {
|
|
62
|
+
label: 'Small cap',
|
|
63
|
+
value: 1,
|
|
64
|
+
displayValue: '25%'
|
|
65
|
+
}]
|
|
66
|
+
}, {
|
|
67
|
+
label: 'Tab item',
|
|
68
|
+
items: [{
|
|
69
|
+
label: 'Large cap',
|
|
70
|
+
value: 1,
|
|
71
|
+
displayValue: '25%'
|
|
72
|
+
}, {
|
|
73
|
+
label: 'Mid cap',
|
|
74
|
+
value: 1,
|
|
75
|
+
displayValue: '25%'
|
|
76
|
+
}, {
|
|
77
|
+
label: 'Small cap',
|
|
78
|
+
value: 1,
|
|
79
|
+
displayValue: '25%'
|
|
80
|
+
}]
|
|
81
|
+
}];
|
|
82
|
+
const defaultEmphasisFor = index => DEFAULT_EMPHASIS_CYCLE[index % DEFAULT_EMPHASIS_CYCLE.length];
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Resolve the shared color for an item. Honors any explicit `color`
|
|
86
|
+
* override, then falls back to `dataViz/bg` for the merged mode set,
|
|
87
|
+
* then to the Figma reference value.
|
|
88
|
+
*
|
|
89
|
+
* Mirrors the cascade used by `SegmentedTrack` (per-index `Emphasis /
|
|
90
|
+
* DataViz` defaults of `High` → `Medium` → `Low`, cycling) so the
|
|
91
|
+
* pre-computed color we pass to both the segment and the legend
|
|
92
|
+
* indicator matches what the `SegmentedTrack` would have computed on
|
|
93
|
+
* its own. This is what keeps segments and legend rows in sync by
|
|
94
|
+
* construction.
|
|
95
|
+
*/
|
|
96
|
+
function resolveItemColor(parentModes, item, index) {
|
|
97
|
+
if (item.color) return item.color;
|
|
98
|
+
const itemModes = {
|
|
99
|
+
...parentModes,
|
|
100
|
+
'Emphasis / DataViz': defaultEmphasisFor(index),
|
|
101
|
+
...(item.modes || {})
|
|
102
|
+
};
|
|
103
|
+
return (0, _figmaVariablesResolver.getVariableByName)('dataViz/bg', itemModes) ?? '#cea15a';
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Resolve what to render in the legend row's right-side slot. The
|
|
108
|
+
* order of precedence is:
|
|
109
|
+
* 1. `item.displayValue` if explicitly provided (including `null` /
|
|
110
|
+
* `false`, which the underlying `MetricLegendItem` treats as
|
|
111
|
+
* "hide the value slot").
|
|
112
|
+
* 2. `formatValue(item.value)` when a parent-level formatter exists.
|
|
113
|
+
* 3. `undefined` — the value slot is hidden.
|
|
114
|
+
*/
|
|
115
|
+
function resolveLegendValue(item, formatValue) {
|
|
116
|
+
if (item.displayValue !== undefined) return item.displayValue;
|
|
117
|
+
if (formatValue) return formatValue(item.value);
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* `RangeTrack` pairs a tab row with a `SegmentedTrack` and a vertical
|
|
123
|
+
* stack of `MetricLegendItem` rows. Each tab carries its own `items`
|
|
124
|
+
* array which is the **single source of truth** for both the segments
|
|
125
|
+
* and the legend rows of that tab — every segment has exactly one
|
|
126
|
+
* legend row and they share the same color through the same
|
|
127
|
+
* `Emphasis / DataViz` cascade as the standalone `SegmentedTrack`.
|
|
128
|
+
*
|
|
129
|
+
* Switching tabs swaps the segments and the legend together so the
|
|
130
|
+
* two visualizations can never drift out of sync.
|
|
131
|
+
*
|
|
132
|
+
* The default 3-item layout per tab receives per-index
|
|
133
|
+
* `Emphasis / DataViz` defaults (item 1 → `High`, 2 → `Medium`, 3 →
|
|
134
|
+
* `Low`, then cycles). Override `Appearance / DataViz` on the parent
|
|
135
|
+
* `modes` to retheme the whole component, or set `modes` per item to
|
|
136
|
+
* remix.
|
|
137
|
+
*
|
|
138
|
+
* The component supports both **controlled** and **uncontrolled**
|
|
139
|
+
* tab selection — pass `activeTabIndex` + `onTabChange` for the
|
|
140
|
+
* controlled mode, or omit them and the component will manage the
|
|
141
|
+
* selection internally starting from `defaultActiveTabIndex`.
|
|
142
|
+
*
|
|
143
|
+
* @component
|
|
144
|
+
* @param {RangeTrackProps} props
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* ```tsx
|
|
148
|
+
* <RangeTrack
|
|
149
|
+
* tabs={[
|
|
150
|
+
* {
|
|
151
|
+
* label: 'Sectoral',
|
|
152
|
+
* items: [
|
|
153
|
+
* { label: 'Large cap', value: 50, displayValue: '50%' },
|
|
154
|
+
* { label: 'Mid cap', value: 30, displayValue: '30%' },
|
|
155
|
+
* { label: 'Small cap', value: 20, displayValue: '20%' },
|
|
156
|
+
* ],
|
|
157
|
+
* },
|
|
158
|
+
* {
|
|
159
|
+
* label: 'Geography',
|
|
160
|
+
* items: [
|
|
161
|
+
* { label: 'India', value: 70, displayValue: '70%' },
|
|
162
|
+
* { label: 'US', value: 20, displayValue: '20%' },
|
|
163
|
+
* { label: 'Other', value: 10, displayValue: '10%' },
|
|
164
|
+
* ],
|
|
165
|
+
* },
|
|
166
|
+
* ]}
|
|
167
|
+
* />
|
|
168
|
+
* ```
|
|
169
|
+
*/
|
|
170
|
+
function RangeTrack({
|
|
171
|
+
tabs,
|
|
172
|
+
formatValue,
|
|
173
|
+
activeTabIndex,
|
|
174
|
+
defaultActiveTabIndex = 0,
|
|
175
|
+
onTabChange,
|
|
176
|
+
scrollableTabs = false,
|
|
177
|
+
modes: propModes = _reactUtils.EMPTY_MODES,
|
|
178
|
+
style,
|
|
179
|
+
tabsStyle,
|
|
180
|
+
trackStyle,
|
|
181
|
+
legendStyle,
|
|
182
|
+
accessibilityLabel
|
|
183
|
+
}) {
|
|
184
|
+
const {
|
|
185
|
+
modes: globalModes
|
|
186
|
+
} = (0, _JFSThemeProvider.useTokens)();
|
|
187
|
+
const modes = {
|
|
188
|
+
...globalModes,
|
|
189
|
+
...propModes
|
|
190
|
+
};
|
|
191
|
+
const resolvedTabs = tabs && tabs.length > 0 ? tabs : DEFAULT_TABS;
|
|
192
|
+
const [internalIndex, setInternalIndex] = (0, _react.useState)(() => clampIndex(defaultActiveTabIndex, resolvedTabs.length));
|
|
193
|
+
const isControlled = activeTabIndex !== undefined;
|
|
194
|
+
const rawIndex = isControlled ? activeTabIndex : internalIndex;
|
|
195
|
+
const safeIndex = clampIndex(rawIndex, resolvedTabs.length);
|
|
196
|
+
const handleTabPress = (0, _react.useCallback)(index => {
|
|
197
|
+
const nextTab = resolvedTabs[index];
|
|
198
|
+
if (!nextTab) return;
|
|
199
|
+
if (!isControlled) setInternalIndex(index);
|
|
200
|
+
onTabChange?.(index, nextTab);
|
|
201
|
+
}, [isControlled, onTabChange, resolvedTabs]);
|
|
202
|
+
const containerGap = (0, _figmaVariablesResolver.getVariableByName)('rangeTrack/gap', modes) ?? 28;
|
|
203
|
+
// Vertical gap between legend rows is not exposed as its own token —
|
|
204
|
+
// the Figma design uses 8px between rows, mirroring the
|
|
205
|
+
// `donutChartSummary/legend/gap` default. Keep the value in step
|
|
206
|
+
// with `DonutChartSummary` so the two summary components feel
|
|
207
|
+
// cohesive when stacked.
|
|
208
|
+
const legendRowGap = 8;
|
|
209
|
+
const activeTab = resolvedTabs[safeIndex];
|
|
210
|
+
const activeItems = activeTab?.items ?? [];
|
|
211
|
+
const segments = activeItems.map((item, index) => ({
|
|
212
|
+
key: item.key ?? `segment-${index}`,
|
|
213
|
+
value: item.value,
|
|
214
|
+
color: resolveItemColor(modes, item, index),
|
|
215
|
+
accessibilityLabel: item.accessibilityLabel
|
|
216
|
+
}));
|
|
217
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
218
|
+
accessibilityRole: "summary",
|
|
219
|
+
accessibilityLabel: accessibilityLabel,
|
|
220
|
+
style: [{
|
|
221
|
+
width: '100%',
|
|
222
|
+
flexDirection: 'column',
|
|
223
|
+
alignItems: 'flex-start',
|
|
224
|
+
gap: containerGap
|
|
225
|
+
}, style],
|
|
226
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Tabs.default, {
|
|
227
|
+
modes: modes,
|
|
228
|
+
scrollable: scrollableTabs,
|
|
229
|
+
style: tabsStyle,
|
|
230
|
+
children: resolvedTabs.map((tab, index) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_TabItem.default, {
|
|
231
|
+
label: tab.label,
|
|
232
|
+
active: index === safeIndex,
|
|
233
|
+
onPress: () => handleTabPress(index),
|
|
234
|
+
accessibilityLabel: tab.accessibilityLabel ?? tab.label
|
|
235
|
+
}, tab.key ?? tab.label ?? `tab-${index}`))
|
|
236
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_SegmentedTrack.default, {
|
|
237
|
+
modes: modes,
|
|
238
|
+
segments: segments,
|
|
239
|
+
style: trackStyle,
|
|
240
|
+
accessibilityLabel: activeTab?.accessibilityLabel ?? activeTab?.label
|
|
241
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
242
|
+
style: [{
|
|
243
|
+
width: '100%',
|
|
244
|
+
flexDirection: 'column',
|
|
245
|
+
alignItems: 'flex-start',
|
|
246
|
+
gap: legendRowGap
|
|
247
|
+
}, legendStyle],
|
|
248
|
+
children: activeItems.map((item, index) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_MetricLegendItem.default, {
|
|
249
|
+
label: item.label,
|
|
250
|
+
value: resolveLegendValue(item, formatValue),
|
|
251
|
+
indicatorColor: resolveItemColor(modes, item, index),
|
|
252
|
+
modes: modes
|
|
253
|
+
}, item.key ?? `legend-${index}`))
|
|
254
|
+
})]
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Clamp a tab index into `[0, length)`. Negative or out-of-bounds
|
|
260
|
+
* values fall back to `0` to avoid rendering an undefined tab.
|
|
261
|
+
*/
|
|
262
|
+
function clampIndex(index, length) {
|
|
263
|
+
if (length <= 0) return 0;
|
|
264
|
+
if (!Number.isFinite(index)) return 0;
|
|
265
|
+
if (index < 0) return 0;
|
|
266
|
+
if (index >= length) return length - 1;
|
|
267
|
+
return Math.floor(index);
|
|
268
|
+
}
|
|
269
|
+
var _default = exports.default = RangeTrack;
|