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,318 @@
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 _Form = require("../Form/Form");
13
+ var _jsxRuntime = require("react/jsx-runtime");
14
+ 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); }
15
+ // ---------------------------------------------------------------------------
16
+ // Types
17
+ // ---------------------------------------------------------------------------
18
+
19
+ /**
20
+ * Visual state of the textarea. Mirrors the `FormField States` collection so
21
+ * MessageField slots into the same theming pipeline as FormField. The state
22
+ * is always derived from props (`isInvalid`, `isDisabled`, `isReadOnly` and
23
+ * focus) and is locked in `modes['FormField States']` — passing that key in
24
+ * `modes` is intentionally ignored to keep interactive behaviour and visual
25
+ * state in sync.
26
+ */
27
+
28
+ // ---------------------------------------------------------------------------
29
+ // Token helpers
30
+ // ---------------------------------------------------------------------------
31
+
32
+ function toNumber(value, fallback) {
33
+ if (typeof value === 'number' && Number.isFinite(value)) return value;
34
+ if (typeof value === 'string') {
35
+ const parsed = parseFloat(value);
36
+ if (Number.isFinite(parsed)) return parsed;
37
+ }
38
+ return fallback;
39
+ }
40
+ function toFontWeight(value, fallback) {
41
+ if (typeof value === 'number') return value.toString();
42
+ if (typeof value === 'string' && value.length > 0) return value;
43
+ return fallback;
44
+ }
45
+ function firstError(error) {
46
+ if (!error) return undefined;
47
+ if (Array.isArray(error)) return error[0];
48
+ return error;
49
+ }
50
+ function useMessageFieldTokens(modes) {
51
+ return (0, _react.useMemo)(() => {
52
+ const wrapperGap = toNumber((0, _figmaVariablesResolver.getVariableByName)('messageField/gap', modes), 8);
53
+ const labelColor = (0, _figmaVariablesResolver.getVariableByName)('messageField/label/foreground', modes) || '#000000';
54
+ const labelFontFamily = (0, _figmaVariablesResolver.getVariableByName)('messageField/label/fontFamily', modes) || 'JioType Var';
55
+ const labelFontSize = toNumber((0, _figmaVariablesResolver.getVariableByName)('messageField/label/fontSize', modes), 14);
56
+ const labelLineHeight = toNumber((0, _figmaVariablesResolver.getVariableByName)('messageField/label/lineHeight', modes), 17);
57
+ const labelFontWeight = toFontWeight((0, _figmaVariablesResolver.getVariableByName)('messageField/label/fontWeight', modes), '500');
58
+ const textareaBackground = (0, _figmaVariablesResolver.getVariableByName)('messageField/textarea/background', modes) || '#ffffff';
59
+ const textareaBorderColor = (0, _figmaVariablesResolver.getVariableByName)('messageField/textarea/border/color', modes) || '#b5b6b7';
60
+ const textareaBorderSize = toNumber((0, _figmaVariablesResolver.getVariableByName)('messageField/textarea/border/size', modes), 1.5);
61
+ const textareaRadius = toNumber((0, _figmaVariablesResolver.getVariableByName)('messageField/textarea/radius', modes), 8);
62
+ const textareaPadding = toNumber((0, _figmaVariablesResolver.getVariableByName)('messageField/textarea/padding', modes), 12);
63
+ const textareaHeight = toNumber((0, _figmaVariablesResolver.getVariableByName)('messageField/textarea/height', modes), 108);
64
+ const textareaGap = toNumber((0, _figmaVariablesResolver.getVariableByName)('messageField/textarea/gap', modes), 0);
65
+
66
+ // `messageField/text/foreground` is the input text color. It also
67
+ // serves as the placeholder color — in mode-aware token sets it
68
+ // resolves to a muted/idle color when empty and shifts darker via
69
+ // the `FormField States` cascade once typed-state tokens land. We
70
+ // never re-route this through another token (e.g. the counter
71
+ // color) because that conflates two semantically distinct tokens.
72
+ const inputTextColor = (0, _figmaVariablesResolver.getVariableByName)('messageField/text/foreground', modes) || '#707275';
73
+ const inputFontFamily = (0, _figmaVariablesResolver.getVariableByName)('messageField/text/fontFamily', modes) || 'JioType Var';
74
+ const inputFontSize = toNumber((0, _figmaVariablesResolver.getVariableByName)('messageField/text/fontSize', modes), 16);
75
+ const inputLineHeight = toNumber((0, _figmaVariablesResolver.getVariableByName)('messageField/text/lineHeight', modes), 21);
76
+ const inputFontWeight = toFontWeight((0, _figmaVariablesResolver.getVariableByName)('messageField/text/fontWeight', modes), '400');
77
+ const counterColor = (0, _figmaVariablesResolver.getVariableByName)('messageField/maxLength/foreground', modes) || '#24262b';
78
+ const counterFontFamily = (0, _figmaVariablesResolver.getVariableByName)('messageField/maxLength/fontFamily', modes) || 'JioType Var';
79
+ const counterFontSize = toNumber((0, _figmaVariablesResolver.getVariableByName)('messageField/maxLength/fontSize', modes), 14);
80
+ const counterLineHeight = toNumber((0, _figmaVariablesResolver.getVariableByName)('messageField/maxLength/lineHeight', modes), 18);
81
+ const counterFontWeight = toFontWeight((0, _figmaVariablesResolver.getVariableByName)('messageField/maxLength/fontWeight', modes), '400');
82
+ return {
83
+ wrapperGap,
84
+ labelColor,
85
+ labelFontFamily,
86
+ labelFontSize,
87
+ labelLineHeight,
88
+ labelFontWeight,
89
+ textareaBackground,
90
+ textareaBorderColor,
91
+ textareaBorderSize,
92
+ textareaRadius,
93
+ textareaPadding,
94
+ textareaHeight,
95
+ textareaGap,
96
+ inputTextColor,
97
+ inputFontFamily,
98
+ inputFontSize,
99
+ inputLineHeight,
100
+ inputFontWeight,
101
+ counterColor,
102
+ counterFontFamily,
103
+ counterFontSize,
104
+ counterLineHeight,
105
+ counterFontWeight
106
+ };
107
+ }, [modes]);
108
+ }
109
+
110
+ // ---------------------------------------------------------------------------
111
+ // Component
112
+ // ---------------------------------------------------------------------------
113
+
114
+ const REQUIRED_INDICATOR_COLOR = '#d93d3d';
115
+ function MessageField({
116
+ label,
117
+ placeholder,
118
+ value,
119
+ defaultValue,
120
+ onChangeText,
121
+ name,
122
+ maxLength,
123
+ showCounter,
124
+ rows,
125
+ isRequired = false,
126
+ isDisabled = false,
127
+ isInvalid = false,
128
+ isReadOnly = false,
129
+ autoFocus = false,
130
+ modes: propModes = _reactUtils.EMPTY_MODES,
131
+ style,
132
+ textareaStyle,
133
+ inputStyle,
134
+ accessibilityLabel,
135
+ accessibilityHint,
136
+ testID,
137
+ onFocus,
138
+ onBlur
139
+ }) {
140
+ const formCtx = (0, _Form.useFormContext)();
141
+ const formError = name && formCtx ? firstError(formCtx.validationErrors[name]) : undefined;
142
+ const resolvedIsInvalid = isInvalid || Boolean(formError);
143
+ const isControlled = value !== undefined;
144
+ const [uncontrolledValue, setUncontrolledValue] = (0, _react.useState)(defaultValue ?? '');
145
+ const currentValue = isControlled ? value : uncontrolledValue;
146
+ const [isFocused, setIsFocused] = (0, _react.useState)(false);
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
+ const {
158
+ modes: globalModes
159
+ } = (0, _JFSThemeProvider.useTokens)();
160
+ const baseModes = (0, _react.useMemo)(() => ({
161
+ ...globalModes,
162
+ ...propModes
163
+ }), [globalModes, propModes]);
164
+
165
+ // FormField States cascade — error > disabled > read only > active (focus)
166
+ // > idle. Always derived from props and locked into the modes object so
167
+ // consumers cannot pass `modes={{ 'FormField States': ... }}` and get out
168
+ // of sync with the component's actual interactive behaviour.
169
+ const stateMode = (0, _react.useMemo)(() => {
170
+ if (resolvedIsInvalid) return 'Error';
171
+ if (isDisabled) return 'Disabled';
172
+ if (isReadOnly) return 'Read Only';
173
+ if (isFocused) return 'Active';
174
+ return 'Idle';
175
+ }, [resolvedIsInvalid, isDisabled, isReadOnly, isFocused]);
176
+ const modes = (0, _react.useMemo)(() => ({
177
+ ...baseModes,
178
+ 'FormField States': stateMode
179
+ }), [baseModes, stateMode]);
180
+ const tokens = useMessageFieldTokens(modes);
181
+
182
+ // ---------- Event handlers ---------------------------------------------
183
+ const handleFocus = (0, _react.useCallback)(e => {
184
+ setIsFocused(true);
185
+ onFocus?.(e);
186
+ }, [onFocus]);
187
+ const handleBlur = (0, _react.useCallback)(e => {
188
+ setIsFocused(false);
189
+ onBlur?.(e);
190
+ }, [onBlur]);
191
+ const handleChangeText = (0, _react.useCallback)(next => {
192
+ if (!isControlled) {
193
+ setUncontrolledValue(next);
194
+ }
195
+ onChangeText?.(next);
196
+ if (name && formCtx) formCtx.onFieldChange(name);
197
+ }, [isControlled, onChangeText, name, formCtx]);
198
+
199
+ // ---------- Derived layout values --------------------------------------
200
+ const computedHeight = (0, _react.useMemo)(() => {
201
+ if (rows && rows > 0) {
202
+ return Math.round(rows * tokens.inputLineHeight + 2 * tokens.textareaPadding);
203
+ }
204
+ return tokens.textareaHeight;
205
+ }, [rows, tokens.inputLineHeight, tokens.textareaPadding, tokens.textareaHeight]);
206
+ const shouldShowCounter = (0, _react.useMemo)(() => {
207
+ if (showCounter === false) return false;
208
+ if (showCounter === true) return true;
209
+ return typeof maxLength === 'number';
210
+ }, [showCounter, maxLength]);
211
+ const counterText = (0, _react.useMemo)(() => {
212
+ const count = currentValue.length;
213
+ if (typeof maxLength === 'number') return `${count}/${maxLength}`;
214
+ return `${count}`;
215
+ }, [currentValue.length, maxLength]);
216
+
217
+ // ---------- Styles -----------------------------------------------------
218
+ const wrapperStyle = (0, _react.useMemo)(() => ({
219
+ gap: tokens.wrapperGap,
220
+ width: '100%'
221
+ }), [tokens.wrapperGap]);
222
+ const labelRowStyle = (0, _react.useMemo)(() => ({
223
+ flexDirection: 'row',
224
+ alignItems: 'baseline'
225
+ }), []);
226
+ const labelTextStyle = (0, _react.useMemo)(() => ({
227
+ color: tokens.labelColor,
228
+ fontFamily: tokens.labelFontFamily,
229
+ fontSize: tokens.labelFontSize,
230
+ lineHeight: tokens.labelLineHeight,
231
+ fontWeight: tokens.labelFontWeight
232
+ }), [tokens.labelColor, tokens.labelFontFamily, tokens.labelFontSize, tokens.labelLineHeight, tokens.labelFontWeight]);
233
+ const requiredIndicatorStyle = (0, _react.useMemo)(() => ({
234
+ ...labelTextStyle,
235
+ color: REQUIRED_INDICATOR_COLOR
236
+ }), [labelTextStyle]);
237
+ const textareaContainerStyle = (0, _react.useMemo)(() => ({
238
+ backgroundColor: tokens.textareaBackground,
239
+ borderColor: tokens.textareaBorderColor,
240
+ borderWidth: tokens.textareaBorderSize,
241
+ borderStyle: 'solid',
242
+ borderRadius: tokens.textareaRadius,
243
+ padding: tokens.textareaPadding,
244
+ height: computedHeight,
245
+ width: '100%',
246
+ overflow: 'hidden',
247
+ // The gap token is for content within the textarea (icons, etc.);
248
+ // we keep it so downstream layouts that pass children align.
249
+ gap: tokens.textareaGap
250
+ }), [tokens.textareaBackground, tokens.textareaBorderColor, tokens.textareaBorderSize, tokens.textareaRadius, tokens.textareaPadding, computedHeight, tokens.textareaGap]);
251
+ const inputTextStyle = (0, _react.useMemo)(() => ({
252
+ flex: 1,
253
+ color: tokens.inputTextColor,
254
+ fontFamily: tokens.inputFontFamily,
255
+ fontSize: tokens.inputFontSize,
256
+ lineHeight: tokens.inputLineHeight,
257
+ fontWeight: tokens.inputFontWeight,
258
+ padding: 0,
259
+ margin: 0,
260
+ textAlignVertical: 'top',
261
+ // Disable the default web focus ring; the textarea border
262
+ // already encodes focus state.
263
+ outlineStyle: 'none',
264
+ outlineWidth: 0,
265
+ outlineColor: 'transparent'
266
+ }), [tokens.inputTextColor, tokens.inputFontFamily, tokens.inputFontSize, tokens.inputLineHeight, tokens.inputFontWeight]);
267
+ const counterTextStyle = (0, _react.useMemo)(() => ({
268
+ color: tokens.counterColor,
269
+ fontFamily: tokens.counterFontFamily,
270
+ fontSize: tokens.counterFontSize,
271
+ lineHeight: tokens.counterLineHeight,
272
+ fontWeight: tokens.counterFontWeight,
273
+ textAlign: 'right',
274
+ width: '100%'
275
+ }), [tokens.counterColor, tokens.counterFontFamily, tokens.counterFontSize, tokens.counterLineHeight, tokens.counterFontWeight]);
276
+ const resolvedA11yLabel = accessibilityLabel || label || placeholder || 'Message field';
277
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
278
+ style: [wrapperStyle, style],
279
+ pointerEvents: isDisabled ? 'none' : 'auto',
280
+ testID: testID,
281
+ accessible: false,
282
+ children: [label != null && label !== '' && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
283
+ style: labelRowStyle,
284
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
285
+ style: labelTextStyle,
286
+ children: label
287
+ }), isRequired && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
288
+ style: requiredIndicatorStyle,
289
+ children: " *"
290
+ })]
291
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
292
+ style: [textareaContainerStyle, textareaStyle],
293
+ onPress: focusInput,
294
+ accessible: false,
295
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TextInput, {
296
+ ref: inputRef,
297
+ multiline: true,
298
+ value: currentValue,
299
+ onChangeText: handleChangeText,
300
+ onFocus: handleFocus,
301
+ onBlur: handleBlur,
302
+ placeholder: placeholder ?? '',
303
+ placeholderTextColor: tokens.inputTextColor,
304
+ editable: interactive,
305
+ maxLength: maxLength,
306
+ autoFocus: autoFocus,
307
+ accessibilityLabel: resolvedA11yLabel,
308
+ accessibilityHint: accessibilityHint,
309
+ style: [inputTextStyle, inputStyle]
310
+ })
311
+ }), shouldShowCounter && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
312
+ style: counterTextStyle,
313
+ accessibilityElementsHidden: true,
314
+ children: counterText
315
+ })]
316
+ });
317
+ }
318
+ var _default = exports.default = MessageField;
@@ -8,9 +8,20 @@ var _react = _interopRequireWildcard(require("react"));
8
8
  var _reactNative = require("react-native");
9
9
  var _reactNativeSvg = _interopRequireWildcard(require("react-native-svg"));
10
10
  var _figmaVariablesResolver = require("../../design-tokens/figma-variables-resolver");
11
+ var _webPlatformUtils = require("../../utils/web-platform-utils");
11
12
  var _reactUtils = require("../../utils/react-utils");
12
13
  var _jsxRuntime = require("react/jsx-runtime");
13
14
  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); }
15
+ /** Minimum touch target per iOS HIG / Material accessibility guidance. */
16
+ const MIN_TOUCH_TARGET = 44;
17
+ const IS_IOS = _reactNative.Platform.OS === 'ios';
18
+ const PRESS_DELAY = IS_IOS ? 130 : 0;
19
+ const touchTargetStyle = {
20
+ minWidth: MIN_TOUCH_TARGET,
21
+ minHeight: MIN_TOUCH_TARGET,
22
+ alignItems: 'center',
23
+ justifyContent: 'center'
24
+ };
14
25
  function resolveNavArrowTokens(modes) {
15
26
  const iconColor = (0, _figmaVariablesResolver.getVariableByName)('navArrow/icon/color', modes) || '#24262b';
16
27
  const widthToken = Number((0, _figmaVariablesResolver.getVariableByName)('navArrow/width', modes)) || 6;
@@ -51,6 +62,8 @@ function NavArrow({
51
62
  modes = _reactUtils.EMPTY_MODES,
52
63
  style,
53
64
  accessibilityLabel,
65
+ onPress,
66
+ disabled = false,
54
67
  ...rest
55
68
  }) {
56
69
  const tokens = (0, _react.useMemo)(() => resolveNavArrowTokens(modes), [modes]);
@@ -64,8 +77,7 @@ function NavArrow({
64
77
  borderRadius: tokens.borderRadius,
65
78
  backgroundColor: tokens.backgroundColor,
66
79
  alignItems: 'center',
67
- justifyContent: 'center',
68
- ...(style || {})
80
+ justifyContent: 'center'
69
81
  };
70
82
  const chevronW = isDown ? tokens.iconHeight : tokens.iconWidth;
71
83
  const chevronH = isDown ? tokens.iconWidth : tokens.iconHeight;
@@ -91,26 +103,55 @@ function NavArrow({
91
103
  svgHeight,
92
104
  points
93
105
  };
94
- }, [tokens, direction, style]);
106
+ }, [tokens, direction]);
95
107
  const defaultAccessibilityLabel = accessibilityLabel || (direction === 'Back' ? 'Go back' : direction === 'Forward' ? 'Go forward' : 'Go down');
108
+ const webProps = (0, _webPlatformUtils.usePressableWebSupport)({
109
+ restProps: rest,
110
+ onPress,
111
+ disabled,
112
+ accessibilityLabel: defaultAccessibilityLabel
113
+ });
114
+ const chevron = /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeSvg.default, {
115
+ width: computed.svgWidth,
116
+ height: computed.svgHeight,
117
+ viewBox: `0 0 ${computed.svgWidth} ${computed.svgHeight}`,
118
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeSvg.Polyline, {
119
+ points: computed.points,
120
+ stroke: tokens.iconColor,
121
+ strokeWidth: tokens.strokeWeight,
122
+ strokeLinecap: "round",
123
+ strokeLinejoin: "round",
124
+ fill: "none"
125
+ })
126
+ });
127
+ if (onPress) {
128
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
129
+ onPress: onPress,
130
+ disabled: disabled,
131
+ accessibilityRole: "button",
132
+ accessibilityLabel: defaultAccessibilityLabel,
133
+ accessibilityState: {
134
+ disabled
135
+ },
136
+ unstable_pressDelay: PRESS_DELAY,
137
+ style: ({
138
+ pressed
139
+ }) => [touchTargetStyle, style, pressed && !disabled ? {
140
+ opacity: 0.7
141
+ } : null],
142
+ ...webProps,
143
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
144
+ style: computed.containerStyle,
145
+ children: chevron
146
+ })
147
+ });
148
+ }
96
149
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
97
- style: computed.containerStyle,
150
+ style: [computed.containerStyle, style],
98
151
  accessibilityRole: "image",
99
152
  accessibilityLabel: defaultAccessibilityLabel,
100
153
  ...rest,
101
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeSvg.default, {
102
- width: computed.svgWidth,
103
- height: computed.svgHeight,
104
- viewBox: `0 0 ${computed.svgWidth} ${computed.svgHeight}`,
105
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeSvg.Polyline, {
106
- points: computed.points,
107
- stroke: tokens.iconColor,
108
- strokeWidth: tokens.strokeWeight,
109
- strokeLinecap: "round",
110
- strokeLinejoin: "round",
111
- fill: "none"
112
- })
113
- })
154
+ children: chevron
114
155
  });
115
156
  }
116
157
  var _default = exports.default = /*#__PURE__*/_react.default.memo(NavArrow);
@@ -18,49 +18,45 @@ function Step({
18
18
  modes = _reactUtils.EMPTY_MODES,
19
19
  style,
20
20
  index = 0,
21
+ showLine = true,
21
22
  connectorStyle,
22
23
  title,
23
24
  supportingText,
25
+ metaText,
24
26
  subtitle = true,
27
+ meta = true,
25
28
  status = 'number'
26
29
  }) {
27
- // Container styles
28
30
  const minHeight = Number((0, _figmaVariablesResolver.getVariableByName)('steperItem/minHeight', modes)) || 52;
29
- const gap = Number((0, _figmaVariablesResolver.getVariableByName)('steperItem/gap', modes)) || 8;
30
-
31
- // Indicator dimensions and styles
32
- const indicatorSize = Number((0, _figmaVariablesResolver.getVariableByName)('stepIndicator/size', modes)) || 24;
31
+ const gap = Number((0, _figmaVariablesResolver.getVariableByName)('steperItem/gap', modes)) || 16;
32
+ const indicatorSize = Number((0, _figmaVariablesResolver.getVariableByName)('stepIndicator/size', modes)) || 36;
33
33
  const indicatorRadius = Number((0, _figmaVariablesResolver.getVariableByName)('stepIndicator/radius', modes)) || 9999;
34
- const indicatorBg = (0, _figmaVariablesResolver.getVariableByName)('stepIndicator/background', modes) || '#5c00b5';
35
- const indicatorBorderColor = (0, _figmaVariablesResolver.getVariableByName)('stepIndicator/border/color', modes) || '#5c00b5';
34
+ const indicatorBg = (0, _figmaVariablesResolver.getVariableByName)('stepIndicator/background', modes) || '#5d00b5';
35
+ const indicatorBorderColor = (0, _figmaVariablesResolver.getVariableByName)('stepIndicator/border/color', modes) || '#5d00b5';
36
36
  const indicatorBorderSize = Number((0, _figmaVariablesResolver.getVariableByName)('stepIndicator/border/size', modes)) || 1;
37
37
  const iconColor = (0, _figmaVariablesResolver.getVariableByName)('stepIndicator/icon/color', modes) || '#ffffff';
38
-
39
- // Label styles (for number)
38
+ const stepStatusSize = Number((0, _figmaVariablesResolver.getVariableByName)('stepStatus/size', modes)) || 18;
40
39
  const labelFontSize = Number((0, _figmaVariablesResolver.getVariableByName)('stepIndicator/label/fontSize', modes)) || 12;
41
40
  const labelFontFamily = (0, _figmaVariablesResolver.getVariableByName)('stepIndicator/label/fontFamily', modes) || undefined;
42
41
  const labelLineHeight = Number((0, _figmaVariablesResolver.getVariableByName)('stepIndicator/label/lineHeight', modes)) || 14;
43
42
  const labelFontWeight = (0, _figmaVariablesResolver.getVariableByName)('stepIndicator/label/fontWeight', modes) || '500';
44
-
45
- // Vertical line styles
46
43
  const lineSize = Number((0, _figmaVariablesResolver.getVariableByName)('steperItem/lineSize', modes)) || 2;
47
- const lineColor = (0, _figmaVariablesResolver.getVariableByName)('steperItem/line', modes) || '#5c00b5';
44
+ const lineColor = (0, _figmaVariablesResolver.getVariableByName)('steperItem/line', modes) || '#5d00b5';
48
45
  const badgeWrapGap = Number((0, _figmaVariablesResolver.getVariableByName)('steperItem/badgeWrap/gap', modes)) || 2;
49
46
  const containerStyle = {
50
47
  flexDirection: 'row',
51
48
  minHeight,
49
+ gap,
52
50
  ...style
53
51
  };
54
-
55
- // FIX: This wrapper should NOT expand. It should be exact width of the indicator.
56
52
  const indicatorWrapperStyle = {
57
53
  flexDirection: 'column',
58
54
  alignItems: 'center',
59
55
  width: indicatorSize,
60
56
  flexGrow: 0,
61
- // Do NOT grow
62
57
  flexShrink: 0,
63
- gap: badgeWrapGap
58
+ gap: badgeWrapGap,
59
+ alignSelf: 'stretch'
64
60
  };
65
61
  const indicatorStyle = {
66
62
  width: indicatorSize,
@@ -73,6 +69,12 @@ function Step({
73
69
  justifyContent: 'center',
74
70
  overflow: 'hidden'
75
71
  };
72
+ const stepStatusContainerStyle = {
73
+ width: stepStatusSize,
74
+ height: stepStatusSize,
75
+ alignItems: 'center',
76
+ justifyContent: 'center'
77
+ };
76
78
  const labelStyle = {
77
79
  color: iconColor,
78
80
  fontSize: labelFontSize,
@@ -81,24 +83,19 @@ function Step({
81
83
  lineHeight: labelLineHeight,
82
84
  textAlign: 'center'
83
85
  };
84
-
85
- // Combine base line style with injected connectorStyle
86
86
  const lineStyle = {
87
87
  width: lineSize,
88
88
  backgroundColor: lineColor,
89
89
  flexGrow: 1,
90
- // Line should take up remaining vertical space in this column
91
- ...connectorStyle // Allow overriding display, color, etc.
90
+ minHeight: 1,
91
+ ...connectorStyle
92
92
  };
93
-
94
- // Helper for icons
95
93
  const renderIcon = () => {
96
94
  switch (status) {
97
95
  case 'complete':
98
- // Checkmark
99
96
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeSvg.default, {
100
- width: 12,
101
- height: 12,
97
+ width: stepStatusSize,
98
+ height: stepStatusSize,
102
99
  viewBox: "0 0 24 24",
103
100
  fill: "none",
104
101
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeSvg.Path, {
@@ -110,10 +107,9 @@ function Step({
110
107
  })
111
108
  });
112
109
  case 'error':
113
- // X mark
114
110
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeSvg.default, {
115
- width: 12,
116
- height: 12,
111
+ width: stepStatusSize,
112
+ height: stepStatusSize,
117
113
  viewBox: "0 0 24 24",
118
114
  fill: "none",
119
115
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeSvg.Path, {
@@ -125,10 +121,9 @@ function Step({
125
121
  })
126
122
  });
127
123
  case 'warning':
128
- // Exclamation / Triangle
129
124
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeSvg.default, {
130
- width: 12,
131
- height: 12,
125
+ width: stepStatusSize,
126
+ height: stepStatusSize,
132
127
  viewBox: "0 0 24 24",
133
128
  fill: "none",
134
129
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeSvg.Path, {
@@ -147,46 +142,38 @@ function Step({
147
142
  });
148
143
  }
149
144
  };
150
-
151
- // Clone children to pass modes if they are StepLabel
152
- const childrenWithProps = _react.default.Children.map(children, child => {
153
- if (/*#__PURE__*/_react.default.isValidElement(child)) {
154
- return /*#__PURE__*/_react.default.cloneElement(child, {
155
- modes
156
- });
157
- }
158
- return child;
159
- });
160
-
161
- // Determine if we have content to pad
162
- // Default padding bottom to 16 if line is shown, but also respect connectorStyle display
163
- // If display is none, we probably don't want the padding bottom either.
164
- const isLineHidden = connectorStyle?.display === 'none';
165
- const contentPaddingBottom = isLineHidden ? 0 : 16;
145
+ const hasSlotChildren = _react.default.Children.count(children) > 0;
166
146
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
167
147
  style: containerStyle,
168
148
  children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
169
149
  style: indicatorWrapperStyle,
170
150
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
171
151
  style: indicatorStyle,
172
- children: renderIcon()
173
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
152
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
153
+ style: stepStatusContainerStyle,
154
+ children: renderIcon()
155
+ })
156
+ }), showLine ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
174
157
  style: lineStyle
175
- })]
176
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
177
- style: {
178
- width: gap
179
- }
158
+ }) : null]
180
159
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
181
160
  style: {
182
- flex: 1,
183
- paddingBottom: contentPaddingBottom
161
+ flex: 1
184
162
  },
185
- children: title ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_StepLabel.StepLabel, {
186
- title: title,
187
- supportingText: subtitle ? supportingText || undefined : undefined,
163
+ children: hasSlotChildren ? (0, _reactUtils.cloneChildrenWithModes)(children, modes) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_StepLabel.StepLabel, {
164
+ ...(title !== undefined ? {
165
+ title
166
+ } : {}),
167
+ ...(supportingText !== undefined ? {
168
+ supportingText
169
+ } : {}),
170
+ ...(metaText !== undefined ? {
171
+ metaText
172
+ } : {}),
173
+ subtitle: subtitle,
174
+ meta: meta,
188
175
  modes: modes
189
- }) : childrenWithProps
176
+ })
190
177
  })]
191
178
  });
192
179
  }