jfs-components 0.0.43 → 0.0.44

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 (45) hide show
  1. package/lib/commonjs/components/Button/Button.js +15 -1
  2. package/lib/commonjs/components/Checkbox/Checkbox.js +208 -0
  3. package/lib/commonjs/components/MoneyValue/MoneyValue.js +81 -49
  4. package/lib/commonjs/components/NoteInput/NoteInput.js +120 -0
  5. package/lib/commonjs/components/NoteInput/index.js +13 -0
  6. package/lib/commonjs/components/Numpad/Numpad.js +108 -0
  7. package/lib/commonjs/components/StatusHero/StatusHero.js +148 -0
  8. package/lib/commonjs/components/Tabs/TabItem.js +79 -0
  9. package/lib/commonjs/components/Tabs/Tabs.js +88 -0
  10. package/lib/commonjs/components/index.js +42 -0
  11. package/lib/commonjs/icons/registry.js +1 -1
  12. package/lib/module/components/Button/Button.js +14 -1
  13. package/lib/module/components/Checkbox/Checkbox.js +205 -0
  14. package/lib/module/components/MoneyValue/MoneyValue.js +81 -49
  15. package/lib/module/components/NoteInput/NoteInput.js +115 -0
  16. package/lib/module/components/NoteInput/index.js +3 -0
  17. package/lib/module/components/Numpad/Numpad.js +103 -0
  18. package/lib/module/components/StatusHero/StatusHero.js +142 -0
  19. package/lib/module/components/Tabs/TabItem.js +74 -0
  20. package/lib/module/components/Tabs/Tabs.js +78 -0
  21. package/lib/module/components/index.js +6 -0
  22. package/lib/module/icons/registry.js +1 -1
  23. package/lib/typescript/src/components/Button/Button.d.ts +6 -1
  24. package/lib/typescript/src/components/Checkbox/Checkbox.d.ts +30 -0
  25. package/lib/typescript/src/components/MoneyValue/MoneyValue.d.ts +18 -26
  26. package/lib/typescript/src/components/NoteInput/NoteInput.d.ts +23 -0
  27. package/lib/typescript/src/components/NoteInput/index.d.ts +3 -0
  28. package/lib/typescript/src/components/Numpad/Numpad.d.ts +35 -0
  29. package/lib/typescript/src/components/StatusHero/StatusHero.d.ts +47 -0
  30. package/lib/typescript/src/components/Tabs/TabItem.d.ts +29 -0
  31. package/lib/typescript/src/components/Tabs/Tabs.d.ts +44 -0
  32. package/lib/typescript/src/components/index.d.ts +6 -0
  33. package/lib/typescript/src/icons/registry.d.ts +1 -1
  34. package/package.json +1 -1
  35. package/src/components/Button/Button.tsx +14 -1
  36. package/src/components/Checkbox/Checkbox.tsx +238 -0
  37. package/src/components/MoneyValue/MoneyValue.tsx +134 -79
  38. package/src/components/NoteInput/NoteInput.tsx +146 -0
  39. package/src/components/NoteInput/index.ts +2 -0
  40. package/src/components/Numpad/Numpad.tsx +162 -0
  41. package/src/components/StatusHero/StatusHero.tsx +156 -0
  42. package/src/components/Tabs/TabItem.tsx +96 -0
  43. package/src/components/Tabs/Tabs.tsx +105 -0
  44. package/src/components/index.ts +6 -0
  45. package/src/icons/registry.ts +1 -1
@@ -8,7 +8,9 @@ var _react = _interopRequireWildcard(require("react"));
8
8
  var _reactNative = require("react-native");
9
9
  var _figmaVariablesResolver = require("../../design-tokens/figma-variables-resolver");
10
10
  var _webPlatformUtils = require("../../utils/web-platform-utils");
11
+ var _Icon = _interopRequireDefault(require("../../icons/Icon"));
11
12
  var _jsxRuntime = require("react/jsx-runtime");
13
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
12
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); }
13
15
  /**
14
16
  * Button component that maps directly to the Figma design using design tokens.
@@ -35,6 +37,7 @@ function Button({
35
37
  renderContent,
36
38
  leading,
37
39
  trailing,
40
+ icon,
38
41
  modes = {},
39
42
  onPress,
40
43
  disabled = false,
@@ -60,6 +63,8 @@ function Button({
60
63
  const lineHeight = (0, _figmaVariablesResolver.getVariableByName)('button/lineHeight', modes) || 19;
61
64
  const fontSize = (0, _figmaVariablesResolver.getVariableByName)('button/fontSize', modes) || 16;
62
65
  const textColor = (0, _figmaVariablesResolver.getVariableByName)('button/foreground', modes) || '#0f0d0a';
66
+ const iconColor = (0, _figmaVariablesResolver.getVariableByName)('button/icon/color', modes) ?? textColor;
67
+ const iconSize = (0, _figmaVariablesResolver.getVariableByName)('button/icon/size', modes) ?? 18;
63
68
  const baseLabelTextStyle = {
64
69
  color: textColor,
65
70
  fontFamily,
@@ -185,7 +190,16 @@ function Button({
185
190
  children: [leading ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
186
191
  style: leadingAccessoryStyle,
187
192
  children: leading
188
- }) : null, content, trailing ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
193
+ }) : null, content, icon ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
194
+ style: trailingAccessoryStyle,
195
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Icon.default, {
196
+ name: icon,
197
+ size: iconSize,
198
+ color: iconColor,
199
+ accessibilityElementsHidden: true,
200
+ importantForAccessibility: "no"
201
+ })
202
+ }) : trailing ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
189
203
  style: trailingAccessoryStyle,
190
204
  children: trailing
191
205
  }) : null]
@@ -0,0 +1,208 @@
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 _reactNativeSvg = _interopRequireWildcard(require("react-native-svg"));
10
+ var _figmaVariablesResolver = require("../../design-tokens/figma-variables-resolver");
11
+ var _jsxRuntime = require("react/jsx-runtime");
12
+ 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); }
13
+ /**
14
+ * Tracks whether the last user interaction was a keyboard event (Tab).
15
+ * Capture-phase document listeners fire before any element-level handlers,
16
+ * so the flag is always up-to-date when onFocus runs.
17
+ */function useFocusVisible() {
18
+ const [isFocusVisible, setIsFocusVisible] = (0, _react.useState)(false);
19
+ const hadKeyboardEventRef = (0, _react.useRef)(false);
20
+ (0, _react.useEffect)(() => {
21
+ if (_reactNative.Platform.OS !== 'web' || typeof document === 'undefined') return;
22
+ const onKeyDown = e => {
23
+ if (e.key === 'Tab') hadKeyboardEventRef.current = true;
24
+ };
25
+ const onPointerDown = () => {
26
+ hadKeyboardEventRef.current = false;
27
+ };
28
+ document.addEventListener('keydown', onKeyDown, true);
29
+ document.addEventListener('mousedown', onPointerDown, true);
30
+ document.addEventListener('touchstart', onPointerDown, true);
31
+ return () => {
32
+ document.removeEventListener('keydown', onKeyDown, true);
33
+ document.removeEventListener('mousedown', onPointerDown, true);
34
+ document.removeEventListener('touchstart', onPointerDown, true);
35
+ };
36
+ }, []);
37
+ const onFocus = (0, _react.useCallback)(() => {
38
+ if (hadKeyboardEventRef.current) setIsFocusVisible(true);
39
+ }, []);
40
+ const onBlur = (0, _react.useCallback)(() => {
41
+ setIsFocusVisible(false);
42
+ }, []);
43
+ return {
44
+ isFocusVisible,
45
+ focusHandlers: {
46
+ onFocus,
47
+ onBlur
48
+ }
49
+ };
50
+ }
51
+ /**
52
+ * Checkbox component that maps directly to the Figma design using design tokens.
53
+ *
54
+ * Supports 8 visual states: Idle, Hover, Focus, Selected, Selected Hover,
55
+ * Focus Selected, Disabled, and Disabled Active. All styling is driven by
56
+ * design tokens with optional mode overrides.
57
+ *
58
+ * @component
59
+ * @param {CheckboxProps} props
60
+ */
61
+ function Checkbox({
62
+ checked: controlledChecked,
63
+ defaultChecked = false,
64
+ onValueChange,
65
+ disabled = false,
66
+ modes = {},
67
+ style,
68
+ accessibilityLabel
69
+ }) {
70
+ const isControlled = controlledChecked !== undefined;
71
+ const [internalChecked, setInternalChecked] = (0, _react.useState)(defaultChecked);
72
+ const isChecked = isControlled ? controlledChecked : internalChecked;
73
+ const [isHovered, setIsHovered] = (0, _react.useState)(false);
74
+ const {
75
+ isFocusVisible,
76
+ focusHandlers
77
+ } = useFocusVisible();
78
+ const size = (0, _figmaVariablesResolver.getVariableByName)('checkbox/size', modes) ?? 18;
79
+ const radius = (0, _figmaVariablesResolver.getVariableByName)('checkbox/radius', modes) ?? 4;
80
+ const strokeWidth = (0, _figmaVariablesResolver.getVariableByName)('strokeWidth', modes) ?? 1;
81
+ const idleStroke = (0, _figmaVariablesResolver.getVariableByName)('checkbox/idle/stroke/color', modes) ?? '#666666';
82
+ const hoverFill = (0, _figmaVariablesResolver.getVariableByName)('checkbox/hover/fill/color', modes) ?? 'rgba(0,0,0,0.1)';
83
+ const hoverStroke = (0, _figmaVariablesResolver.getVariableByName)('checkbox/hover/stroke/color', modes) ?? '#666666';
84
+ const hoverRing = (0, _figmaVariablesResolver.getVariableByName)('checkbox/hoverRing', modes) ?? 4;
85
+ const hoverShadow = (0, _figmaVariablesResolver.getVariableByName)('hover/boxShadow', modes) ?? 'rgba(0,0,0,0.1)';
86
+ const selectedFill = (0, _figmaVariablesResolver.getVariableByName)('checkbox/selected/fill/color', modes) ?? '#cea15a';
87
+ const selectedStroke = (0, _figmaVariablesResolver.getVariableByName)('checkbox/selected/stroke/color', modes) ?? '#0d0d0d';
88
+ const selectedMarkColor = (0, _figmaVariablesResolver.getVariableByName)('checkbox/selected/mark/color', modes) ?? '#0f0d0a';
89
+ const focusFill = (0, _figmaVariablesResolver.getVariableByName)('checkbox/focus/fill/color', modes) ?? '#ffffff';
90
+ const focusStroke = (0, _figmaVariablesResolver.getVariableByName)('checkbox/focus/stroke/color', modes) ?? '#666666';
91
+ const focusShadowColor = (0, _figmaVariablesResolver.getVariableByName)('checkbox/focus/shadow/color', modes) ?? '#12fc2e';
92
+ const focusSpread = (0, _figmaVariablesResolver.getVariableByName)('checkbox/focus/spread/effect', modes) ?? 2;
93
+ const disabledStroke = (0, _figmaVariablesResolver.getVariableByName)('checkbox/disabled/stroke/color', modes) ?? '#999999';
94
+ const disabledActiveBg = (0, _figmaVariablesResolver.getVariableByName)('checkbox/disabledActive/background/color', modes) ?? '#f6d19a';
95
+ const disabledActiveBorder = (0, _figmaVariablesResolver.getVariableByName)('checkbox/disabledActive/border/color', modes) ?? '#f6d19a';
96
+ const disabledActiveMark = (0, _figmaVariablesResolver.getVariableByName)('checkbox/disabledActive/mark/color', modes) ?? '#474d54';
97
+ const selectedHoverShadow = (0, _figmaVariablesResolver.getVariableByName)('selected/hover/boxShadow', modes) ?? 'rgba(0,0,0,0.1)';
98
+ const hoverShadowSize = (0, _figmaVariablesResolver.getVariableByName)('hover/boxShadow/size', modes) ?? 4;
99
+ const handlePress = (0, _react.useCallback)(() => {
100
+ if (disabled) return;
101
+ const next = !isChecked;
102
+ if (!isControlled) {
103
+ setInternalChecked(next);
104
+ }
105
+ onValueChange?.(next);
106
+ }, [disabled, isChecked, isControlled, onValueChange]);
107
+ const resolveStyle = () => {
108
+ const base = {
109
+ width: size,
110
+ height: size,
111
+ borderRadius: radius,
112
+ borderWidth: strokeWidth,
113
+ alignItems: 'center',
114
+ justifyContent: 'center',
115
+ overflow: 'hidden'
116
+ };
117
+ if (disabled && isChecked) {
118
+ return {
119
+ ...base,
120
+ backgroundColor: disabledActiveBg,
121
+ borderColor: disabledActiveBorder
122
+ };
123
+ }
124
+ if (disabled) {
125
+ return {
126
+ ...base,
127
+ borderColor: disabledStroke
128
+ };
129
+ }
130
+ if (isChecked && isFocusVisible) {
131
+ return {
132
+ ...base,
133
+ backgroundColor: selectedFill,
134
+ borderColor: selectedStroke,
135
+ ...boxShadow(`0px 0px 0px ${focusSpread}px ${focusShadowColor}`)
136
+ };
137
+ }
138
+ if (isChecked && isHovered) {
139
+ return {
140
+ ...base,
141
+ backgroundColor: selectedFill,
142
+ borderColor: selectedStroke,
143
+ ...boxShadow(`0px 0px 0px ${hoverShadowSize}px ${selectedHoverShadow}`)
144
+ };
145
+ }
146
+ if (isChecked) {
147
+ return {
148
+ ...base,
149
+ backgroundColor: selectedFill,
150
+ borderColor: selectedStroke
151
+ };
152
+ }
153
+ if (isFocusVisible) {
154
+ return {
155
+ ...base,
156
+ backgroundColor: focusFill,
157
+ borderColor: focusStroke,
158
+ ...boxShadow(`0px 0px 0px ${focusSpread}px ${focusShadowColor}`)
159
+ };
160
+ }
161
+ if (isHovered) {
162
+ return {
163
+ ...base,
164
+ backgroundColor: hoverFill,
165
+ borderColor: hoverStroke,
166
+ ...boxShadow(`0px 0px 0px ${hoverRing}px ${hoverShadow}`)
167
+ };
168
+ }
169
+ return {
170
+ ...base,
171
+ borderColor: idleStroke
172
+ };
173
+ };
174
+ const markColor = disabled && isChecked ? disabledActiveMark : selectedMarkColor;
175
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
176
+ style: [resolveStyle(), style],
177
+ onPress: handlePress,
178
+ disabled: disabled,
179
+ onHoverIn: () => setIsHovered(true),
180
+ onHoverOut: () => setIsHovered(false),
181
+ ...focusHandlers,
182
+ accessibilityRole: "checkbox",
183
+ accessibilityState: {
184
+ checked: isChecked,
185
+ disabled
186
+ },
187
+ accessibilityLabel: accessibilityLabel,
188
+ children: isChecked && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeSvg.default, {
189
+ width: 12,
190
+ height: 9,
191
+ viewBox: "0 0 12 9",
192
+ fill: "none",
193
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeSvg.Path, {
194
+ d: "M4.00091 8.66939C3.91321 8.6699 3.82628 8.65309 3.74509 8.61991C3.6639 8.58673 3.59006 8.53785 3.52779 8.47606L0.195972 5.14273C0.0704931 5.01719 -1.86978e-09 4.84693 0 4.66939C1.86978e-09 4.49186 0.0704931 4.3216 0.195972 4.19606C0.321451 4.07053 0.491636 4 0.66909 4C0.846544 4 1.01673 4.07053 1.14221 4.19606L4.00091 7.06273L10.8578 0.196061C10.9833 0.0705253 11.1535 0 11.3309 0C11.5084 0 11.6785 0.0705253 11.804 0.196061C11.9295 0.321597 12 0.49186 12 0.669394C12 0.846929 11.9295 1.01719 11.804 1.14273L4.47403 8.47606C4.41176 8.53785 4.33792 8.58673 4.25673 8.61991C4.17554 8.65309 4.08861 8.6699 4.00091 8.66939Z",
195
+ fill: markColor
196
+ })
197
+ })
198
+ });
199
+ }
200
+ function boxShadow(value) {
201
+ if (_reactNative.Platform.OS === 'web') {
202
+ return {
203
+ boxShadow: value
204
+ };
205
+ }
206
+ return {};
207
+ }
208
+ var _default = exports.default = Checkbox;
@@ -4,11 +4,11 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
- var _react = _interopRequireDefault(require("react"));
7
+ var _react = _interopRequireWildcard(require("react"));
8
8
  var _reactNative = require("react-native");
9
9
  var _figmaVariablesResolver = require("../../design-tokens/figma-variables-resolver");
10
10
  var _jsxRuntime = require("react/jsx-runtime");
11
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
11
+ 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); }
12
12
  // Map of common ISO 4217 currency codes to display symbols
13
13
  const CURRENCY_SYMBOLS = {
14
14
  INR: '₹',
@@ -46,34 +46,20 @@ const CURRENCY_SYMBOLS = {
46
46
  /**
47
47
  * MoneyValue component that mirrors the Figma MoneyValue design.
48
48
  *
49
- * The styling is fully resolved from Figma design tokens using `getVariableByName`
50
- * and an optional `modes` configuration, consistent with other components in this library.
49
+ * The styling is fully resolved from Figma design tokens using `getVariableByName`.
50
+ * Supports separate typography scaling for currency and value.
51
51
  *
52
- * Currency can be provided either as a symbol (e.g. "₹") or as an ISO code
53
- * (e.g. "INR", "USD"). When an ISO code is provided, it will be mapped to the
54
- * appropriate symbol, with special care to support INR and other major currencies.
55
- *
56
- * Negative values are auto-detected from the value prop (e.g., -500 or "-500").
57
- * The `negative` prop can be used to explicitly override this behavior.
58
- *
59
- * @component
60
- * @param {Object} props
61
- * @param {string|number} [props.value="500"] - Monetary value to display. Negative values are auto-detected.
62
- * @param {string} [props.currency="₹"] - Currency symbol or ISO code (e.g. "INR").
63
- * @param {boolean} [props.negative] - Explicitly override negative display. If undefined, auto-detects from value.
64
- * @param {Object} [props.modes={}] - Modes object passed directly to `getVariableByName`.
65
- * Example: {"MoneyValue / Theme": "Default"}
66
- * @param {Object} [props.style] - Optional container style overrides.
67
- * @param {Object} [props.valueStyle] - Optional value text style overrides.
68
- * @param {Object} [props.currencyStyle] - Optional currency text style overrides.
69
- * @param {Object} [props.negativeSignStyle] - Optional negative sign text style overrides.
70
- * @param {string} [props.accessibilityLabel] - Accessibility label for screen readers. If not provided, generates from value and currency
71
- * @param {string} [props.accessibilityHint] - Additional accessibility hint for screen readers
52
+ * To make this component editable without coupling it to a Numpad component,
53
+ * use the `onPress` prop and manage the data state in the parent layer. When
54
+ * the `focused` prop is provided to this component, it will display a natural
55
+ * blinking text cursor.
72
56
  */
73
57
  function MoneyValue({
74
58
  value = '500',
75
59
  currency = '₹',
76
60
  negative,
61
+ focused = false,
62
+ hidden = false,
77
63
  modes = {},
78
64
  style,
79
65
  valueStyle,
@@ -81,13 +67,14 @@ function MoneyValue({
81
67
  negativeSignStyle,
82
68
  accessibilityLabel,
83
69
  accessibilityHint,
70
+ onPress,
84
71
  ...rest
85
72
  }) {
86
73
  // Auto-detect negative from value and compute display value
87
74
  const {
88
75
  isNegative,
89
76
  displayValue
90
- } = _react.default.useMemo(() => {
77
+ } = (0, _react.useMemo)(() => {
91
78
  const stringValue = String(value);
92
79
  const trimmed = stringValue.trim();
93
80
  const valueIsNegative = trimmed.startsWith('-') || typeof value === 'number' && value < 0;
@@ -98,62 +85,107 @@ function MoneyValue({
98
85
  // Use explicit negative prop if provided, otherwise use auto-detected
99
86
  const showNegative = negative !== undefined ? negative : valueIsNegative;
100
87
  return {
101
- isNegative: showNegative,
102
- displayValue: absoluteValue
88
+ isNegative: hidden ? false : showNegative,
89
+ displayValue: hidden ? '•••' : absoluteValue
103
90
  };
104
- }, [value, negative]);
91
+ }, [value, negative, hidden]);
105
92
 
106
93
  // Resolve typography and layout tokens from Figma
107
94
  const textColor = (0, _figmaVariablesResolver.getVariableByName)('moneyValue/text/color', modes) || '#0f0d0a';
108
- const fontSize = (0, _figmaVariablesResolver.getVariableByName)('moneyValue/supportText/fontSize', modes) || 14;
109
- const lineHeight = (0, _figmaVariablesResolver.getVariableByName)('moneyValue/supportText/lineHeight', modes) || 18;
110
- const fontWeightValue = (0, _figmaVariablesResolver.getVariableByName)('moneyValue/supportText/fontWeight', modes) || 500;
95
+ const currencyFontSize = (0, _figmaVariablesResolver.getVariableByName)('moneyValue/currency/fontSize', modes) || 14;
96
+ const currencyLineHeight = (0, _figmaVariablesResolver.getVariableByName)('moneyValue/currency/lineHeight', modes) || 18;
97
+ const valueFontSize = (0, _figmaVariablesResolver.getVariableByName)('moneyValue/value/fontSize', modes) || 14;
98
+ const valueLineHeight = (0, _figmaVariablesResolver.getVariableByName)('moneyValue/value/lineHeight', modes) || 18;
99
+ const fontWeightValue = (0, _figmaVariablesResolver.getVariableByName)('moneyValue/fontWeight', modes) || 500;
111
100
  const fontWeight = typeof fontWeightValue === 'number' ? fontWeightValue.toString() : fontWeightValue;
112
- const fontFamily = (0, _figmaVariablesResolver.getVariableByName)('moneyValue/supportText/fontFamily', modes) || 'System';
101
+ const fontFamily = (0, _figmaVariablesResolver.getVariableByName)('moneyValue/fontFamily', modes) || 'System';
113
102
  const gap = (0, _figmaVariablesResolver.getVariableByName)('moneyValue/gap', modes) || 4;
114
103
 
115
104
  // Resolve currency to a symbol, supporting both symbols and ISO codes
116
- const resolvedCurrency = _react.default.useMemo(() => {
105
+ const resolvedCurrency = (0, _react.useMemo)(() => {
117
106
  if (!currency) return '';
118
107
  const upper = currency.toUpperCase ? currency.toUpperCase() : currency;
119
108
  return upper in CURRENCY_SYMBOLS ? CURRENCY_SYMBOLS[upper] : currency;
120
109
  }, [currency]);
121
- const baseTextStyle = {
110
+ const currencyTextStyle = {
111
+ color: textColor,
112
+ fontSize: currencyFontSize,
113
+ lineHeight: currencyLineHeight,
114
+ fontWeight: fontWeight,
115
+ fontFamily: fontFamily
116
+ };
117
+ const valueTextStyle = {
122
118
  color: textColor,
123
- fontSize,
124
- lineHeight,
125
- fontWeight,
126
- fontFamily
119
+ fontSize: valueFontSize,
120
+ lineHeight: valueLineHeight,
121
+ fontWeight: fontWeight,
122
+ fontFamily: fontFamily
127
123
  };
128
124
  const containerStyle = {
129
125
  flexDirection: 'row',
130
126
  alignItems: 'center',
131
- gap
127
+ gap: gap
132
128
  };
133
129
 
134
- // Generate default accessibility label from value and currency
135
- const defaultAccessibilityLabel = accessibilityLabel || `${isNegative ? 'negative ' : ''}${resolvedCurrency} ${displayValue}`;
136
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
130
+ // Blinking cursor animation
131
+ const cursorOpacity = (0, _react.useRef)(new _reactNative.Animated.Value(0)).current;
132
+ (0, _react.useEffect)(() => {
133
+ if (focused) {
134
+ const animation = _reactNative.Animated.loop(_reactNative.Animated.sequence([_reactNative.Animated.timing(cursorOpacity, {
135
+ toValue: 1,
136
+ duration: 400,
137
+ useNativeDriver: true
138
+ }), _reactNative.Animated.timing(cursorOpacity, {
139
+ toValue: 0,
140
+ duration: 400,
141
+ useNativeDriver: true
142
+ })]));
143
+ animation.start();
144
+ return () => {
145
+ animation.stop();
146
+ cursorOpacity.setValue(0);
147
+ };
148
+ } else {
149
+ cursorOpacity.setValue(0);
150
+ }
151
+ }, [focused, cursorOpacity]);
152
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Pressable, {
137
153
  style: [containerStyle, style],
138
154
  accessibilityRole: "text",
139
155
  accessibilityLabel: undefined,
140
156
  accessibilityHint: accessibilityHint,
157
+ onPress: onPress,
158
+ disabled: !onPress,
141
159
  ...rest,
142
160
  children: [isNegative && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
143
- style: [baseTextStyle, negativeSignStyle],
161
+ style: [currencyTextStyle, negativeSignStyle],
144
162
  accessibilityElementsHidden: true,
145
163
  importantForAccessibility: "no",
146
164
  children: "-"
147
165
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
148
- style: [baseTextStyle, currencyStyle],
166
+ style: [currencyTextStyle, currencyStyle],
149
167
  accessibilityElementsHidden: true,
150
168
  importantForAccessibility: "no",
151
169
  children: resolvedCurrency
152
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
153
- style: [baseTextStyle, valueStyle],
154
- accessibilityElementsHidden: true,
155
- importantForAccessibility: "no",
156
- children: displayValue
170
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
171
+ style: {
172
+ flexDirection: 'row',
173
+ alignItems: 'center'
174
+ },
175
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
176
+ style: [valueTextStyle, valueStyle],
177
+ accessibilityElementsHidden: true,
178
+ importantForAccessibility: "no",
179
+ children: displayValue
180
+ }), focused && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Animated.View, {
181
+ style: {
182
+ opacity: cursorOpacity,
183
+ width: 2,
184
+ height: valueFontSize * 1.1,
185
+ backgroundColor: textColor,
186
+ marginLeft: 2
187
+ }
188
+ })]
157
189
  })]
158
190
  });
159
191
  }
@@ -0,0 +1,120 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = NoteInput;
7
+ var _react = _interopRequireWildcard(require("react"));
8
+ var _reactNative = require("react-native");
9
+ var _figmaVariablesResolver = require("../../design-tokens/figma-variables-resolver");
10
+ var _jsxRuntime = require("react/jsx-runtime");
11
+ 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); }
12
+ /**
13
+ * NoteInput component representing an interactive "Add note" badge style field.
14
+ * Allows the user to click, clears the placeholder text, and shows a blinking cursor when focused.
15
+ */
16
+ function NoteInput({
17
+ value = '',
18
+ placeholder = 'Add note',
19
+ onChangeText,
20
+ modes = {},
21
+ style,
22
+ textStyle,
23
+ state: explicitState,
24
+ onFocus,
25
+ onBlur,
26
+ ...rest
27
+ }) {
28
+ const [internalFocused, setInternalFocused] = (0, _react.useState)(false);
29
+ const inputRef = (0, _react.useRef)(null);
30
+
31
+ // Resolve tokens from Figma Design
32
+ const foreground = (0, _figmaVariablesResolver.getVariableByName)('noteInput/foreground', modes) || '#0d0d0f';
33
+ const fontSize = (0, _figmaVariablesResolver.getVariableByName)('noteInput/fontSize', modes) || 14;
34
+ const fontFamily = (0, _figmaVariablesResolver.getVariableByName)('noteInput/fontFamily', modes) || 'JioType Var';
35
+ const lineHeight = (0, _figmaVariablesResolver.getVariableByName)('noteInput/lineHeight', modes) || 16;
36
+ const fontWeightRaw = (0, _figmaVariablesResolver.getVariableByName)('noteInput/fontWeight', modes) || 700;
37
+ const fontWeight = typeof fontWeightRaw === 'number' ? fontWeightRaw.toString() : fontWeightRaw;
38
+ const gap = (0, _figmaVariablesResolver.getVariableByName)('noteInput/gap', modes) || 0; // 4 in some files, 0 in context
39
+ const paddingHorizontal = (0, _figmaVariablesResolver.getVariableByName)('noteInput/padding/horizontal', modes) || 17;
40
+ const paddingVertical = (0, _figmaVariablesResolver.getVariableByName)('noteInput/padding/vertical', modes) || 9;
41
+ const radius = (0, _figmaVariablesResolver.getVariableByName)('noteInput/radius', modes) || 999;
42
+ const borderSize = (0, _figmaVariablesResolver.getVariableByName)('noteInput/border/size', modes) || 1;
43
+ const background = (0, _figmaVariablesResolver.getVariableByName)('noteInput/background', modes) || '#ebebed';
44
+ const borderColor = (0, _figmaVariablesResolver.getVariableByName)('noteInput/border/color', modes) || 'rgba(255,255,255,0)';
45
+ const containerStyle = {
46
+ flexDirection: 'row',
47
+ alignItems: 'center',
48
+ justifyContent: 'center',
49
+ paddingHorizontal: paddingHorizontal,
50
+ paddingVertical: paddingVertical,
51
+ borderRadius: radius,
52
+ backgroundColor: background,
53
+ borderWidth: borderSize,
54
+ borderColor: borderColor,
55
+ gap: gap,
56
+ // Add specific width when editing if requested by Figma design logic, though flex fits content generically
57
+ alignSelf: 'flex-start'
58
+ };
59
+ const baseTextStyle = {
60
+ color: foreground,
61
+ fontSize: fontSize,
62
+ fontFamily: fontFamily,
63
+ lineHeight: lineHeight,
64
+ fontWeight: fontWeight,
65
+ padding: 0,
66
+ margin: 0,
67
+ minHeight: lineHeight
68
+ };
69
+ const handleFocus = e => {
70
+ setInternalFocused(true);
71
+ if (onFocus) onFocus(e);
72
+ };
73
+ const handleBlur = e => {
74
+ setInternalFocused(false);
75
+ if (onBlur) onBlur(e);
76
+ };
77
+ const handlePress = () => {
78
+ inputRef.current?.focus();
79
+ };
80
+
81
+ // Blinking cursor setup for custom UI representation if we were drawing it natively.
82
+ // We use RNTextInput's native cursor, but we can style it or ensure it's visible.
83
+
84
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
85
+ style: [containerStyle, style],
86
+ onPress: handlePress,
87
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
88
+ style: {
89
+ position: 'relative',
90
+ justifyContent: 'center'
91
+ },
92
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
93
+ style: [baseTextStyle, textStyle, {
94
+ opacity: 0
95
+ }],
96
+ accessibilityElementsHidden: true,
97
+ importantForAccessibility: "no",
98
+ children: internalFocused ? value || ' ' : value || placeholder
99
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TextInput, {
100
+ ref: inputRef,
101
+ value: value,
102
+ onChangeText: onChangeText,
103
+ placeholder: internalFocused ? '' : placeholder,
104
+ placeholderTextColor: foreground,
105
+ onFocus: handleFocus,
106
+ onBlur: handleBlur,
107
+ selectionColor: foreground,
108
+ style: [baseTextStyle, {
109
+ position: 'absolute',
110
+ left: 0,
111
+ right: 0,
112
+ top: 0,
113
+ bottom: 0,
114
+ outlineStyle: 'none'
115
+ }, textStyle],
116
+ ...rest
117
+ })]
118
+ })
119
+ });
120
+ }
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "default", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _NoteInput.default;
10
+ }
11
+ });
12
+ var _NoteInput = _interopRequireDefault(require("./NoteInput"));
13
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }