jfs-components 0.0.42 → 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 (60) 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/Toast/Toast.js +93 -0
  11. package/lib/commonjs/components/Toast/ToastProvider.js +61 -0
  12. package/lib/commonjs/components/Toast/useToast.js +61 -0
  13. package/lib/commonjs/components/index.js +81 -0
  14. package/lib/commonjs/design-tokens/JFS Variables-variables-full.json +1 -1
  15. package/lib/commonjs/icons/registry.js +1 -1
  16. package/lib/module/components/Button/Button.js +14 -1
  17. package/lib/module/components/Checkbox/Checkbox.js +205 -0
  18. package/lib/module/components/MoneyValue/MoneyValue.js +81 -49
  19. package/lib/module/components/NoteInput/NoteInput.js +115 -0
  20. package/lib/module/components/NoteInput/index.js +3 -0
  21. package/lib/module/components/Numpad/Numpad.js +103 -0
  22. package/lib/module/components/StatusHero/StatusHero.js +142 -0
  23. package/lib/module/components/Tabs/TabItem.js +74 -0
  24. package/lib/module/components/Tabs/Tabs.js +78 -0
  25. package/lib/module/components/Toast/Toast.js +88 -0
  26. package/lib/module/components/Toast/ToastProvider.js +55 -0
  27. package/lib/module/components/Toast/useToast.js +54 -0
  28. package/lib/module/components/index.js +10 -1
  29. package/lib/module/design-tokens/JFS Variables-variables-full.json +1 -1
  30. package/lib/module/icons/registry.js +1 -1
  31. package/lib/typescript/src/components/Button/Button.d.ts +6 -1
  32. package/lib/typescript/src/components/Checkbox/Checkbox.d.ts +30 -0
  33. package/lib/typescript/src/components/MoneyValue/MoneyValue.d.ts +18 -26
  34. package/lib/typescript/src/components/NoteInput/NoteInput.d.ts +23 -0
  35. package/lib/typescript/src/components/NoteInput/index.d.ts +3 -0
  36. package/lib/typescript/src/components/Numpad/Numpad.d.ts +35 -0
  37. package/lib/typescript/src/components/StatusHero/StatusHero.d.ts +47 -0
  38. package/lib/typescript/src/components/Tabs/TabItem.d.ts +29 -0
  39. package/lib/typescript/src/components/Tabs/Tabs.d.ts +44 -0
  40. package/lib/typescript/src/components/Toast/Toast.d.ts +14 -0
  41. package/lib/typescript/src/components/Toast/ToastProvider.d.ts +11 -0
  42. package/lib/typescript/src/components/Toast/useToast.d.ts +24 -0
  43. package/lib/typescript/src/components/index.d.ts +9 -0
  44. package/lib/typescript/src/icons/registry.d.ts +1 -1
  45. package/package.json +1 -1
  46. package/src/components/Button/Button.tsx +14 -1
  47. package/src/components/Checkbox/Checkbox.tsx +238 -0
  48. package/src/components/MoneyValue/MoneyValue.tsx +134 -79
  49. package/src/components/NoteInput/NoteInput.tsx +146 -0
  50. package/src/components/NoteInput/index.ts +2 -0
  51. package/src/components/Numpad/Numpad.tsx +162 -0
  52. package/src/components/StatusHero/StatusHero.tsx +156 -0
  53. package/src/components/Tabs/TabItem.tsx +96 -0
  54. package/src/components/Tabs/Tabs.tsx +105 -0
  55. package/src/components/Toast/Toast.tsx +105 -0
  56. package/src/components/Toast/ToastProvider.tsx +75 -0
  57. package/src/components/Toast/useToast.ts +80 -0
  58. package/src/components/index.ts +9 -0
  59. package/src/design-tokens/JFS Variables-variables-full.json +1 -1
  60. package/src/icons/registry.ts +1 -1
@@ -0,0 +1,108 @@
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 _IconDeletebackspace = require("../../icons/components/IconDeletebackspace");
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
+ function shuffleArray(arr) {
14
+ const shuffled = [...arr];
15
+ for (let i = shuffled.length - 1; i > 0; i--) {
16
+ const j = Math.floor(Math.random() * (i + 1));
17
+ [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
18
+ }
19
+ return shuffled;
20
+ }
21
+
22
+ /**
23
+ * Secure numpad component for the JFS finance system.
24
+ *
25
+ * Renders a 3×4 grid of digit keys (0-9), an optional decimal key, and a
26
+ * backspace key. Digit positions are shuffled by default to guard against
27
+ * keylogging and shoulder-surfing attacks on mobile devices.
28
+ *
29
+ * @component
30
+ * @param {NumpadProps} props
31
+ */
32
+ function Numpad({
33
+ modes = {},
34
+ onKeyPress,
35
+ showDecimal = true,
36
+ shuffle = true,
37
+ style,
38
+ keyStyle,
39
+ keyTextStyle
40
+ }) {
41
+ const foreground = (0, _figmaVariablesResolver.getVariableByName)('numpad/foreground', modes) ?? '#141414';
42
+ const lineHeight = (0, _figmaVariablesResolver.getVariableByName)('numpad/lineHeight', modes) ?? 32;
43
+ const fontFamily = (0, _figmaVariablesResolver.getVariableByName)('numpad/fontFamily', modes) ?? 'JioType Var';
44
+ const fontSize = (0, _figmaVariablesResolver.getVariableByName)('numpad/fontSize', modes) ?? 32;
45
+ const rowGap = (0, _figmaVariablesResolver.getVariableByName)('numpad/gridRowGap/vertical', modes) ?? 12;
46
+ const columnGap = (0, _figmaVariablesResolver.getVariableByName)('numpad/gridColumnGap/horizontal', modes) ?? 12;
47
+ const digits = (0, _react.useMemo)(() => {
48
+ const base = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'];
49
+ return shuffle ? shuffleArray(base) : base;
50
+ }, [shuffle]);
51
+ const rows = (0, _react.useMemo)(() => [digits.slice(0, 3), digits.slice(3, 6), digits.slice(6, 9), [showDecimal ? '.' : null, digits[9], 'backspace']], [digits, showDecimal]);
52
+ const handlePress = (0, _react.useCallback)(key => {
53
+ onKeyPress?.(key);
54
+ }, [onKeyPress]);
55
+ const textStyle = {
56
+ color: foreground,
57
+ fontFamily: fontFamily,
58
+ fontSize: fontSize,
59
+ lineHeight: lineHeight,
60
+ textAlign: 'center'
61
+ };
62
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
63
+ style: [{
64
+ gap: rowGap
65
+ }, style],
66
+ accessibilityRole: "none",
67
+ children: rows.map((row, rowIndex) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
68
+ style: {
69
+ flexDirection: 'row',
70
+ gap: columnGap
71
+ },
72
+ children: row.map((key, colIndex) => {
73
+ if (key === null) {
74
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
75
+ style: {
76
+ flex: 1
77
+ }
78
+ }, `empty-${colIndex}`);
79
+ }
80
+ const isBackspace = key === 'backspace';
81
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
82
+ style: ({
83
+ pressed
84
+ }) => [{
85
+ flex: 1,
86
+ justifyContent: 'center',
87
+ alignItems: 'center',
88
+ minHeight: 46
89
+ }, pressed && {
90
+ opacity: 0.4
91
+ }, keyStyle],
92
+ onPress: () => handlePress(key),
93
+ accessibilityRole: "button",
94
+ accessibilityLabel: isBackspace ? 'Backspace' : key,
95
+ children: isBackspace ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_IconDeletebackspace.IconDeletebackspace, {
96
+ width: fontSize,
97
+ height: fontSize,
98
+ fill: foreground
99
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
100
+ style: [textStyle, keyTextStyle],
101
+ children: key
102
+ })
103
+ }, `${key}-${colIndex}`);
104
+ })
105
+ }, rowIndex))
106
+ });
107
+ }
108
+ var _default = exports.default = Numpad;
@@ -0,0 +1,148 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = StatusHero;
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 _IconCapsule = _interopRequireDefault(require("../IconCapsule/IconCapsule"));
12
+ var _MoneyValue = _interopRequireDefault(require("../MoneyValue/MoneyValue"));
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
+ /**
17
+ * StatusHero component that displays a hero section for payment/transaction status screens.
18
+ *
19
+ * Contains a media slot (defaults to IconCapsule + MoneyValue) and a content area
20
+ * with an optional title and a subtitle. All visual values are resolved from Figma
21
+ * design tokens via `getVariableByName`.
22
+ *
23
+ * @component
24
+ * @example
25
+ * ```tsx
26
+ * <StatusHero
27
+ * iconName="ic_confirm"
28
+ * value="50"
29
+ * currency="INR"
30
+ * title="You're set to make payments"
31
+ * subtitle="₹50 will be auto-invested daily, stay consistent & stay golden."
32
+ * modes={{ 'Color Mode': 'Light' }}
33
+ * />
34
+ * ```
35
+ */
36
+ function StatusHero({
37
+ renderMedia,
38
+ title = "You're set to make payments",
39
+ showTitle = true,
40
+ subtitle = '₹50 will be auto-invested daily,\nstay consistent & stay golden.',
41
+ iconName = 'ic_confirm',
42
+ value = '50',
43
+ currency = 'INR',
44
+ modes: propModes = {},
45
+ style
46
+ }) {
47
+ const {
48
+ modes: globalModes
49
+ } = (0, _JFSThemeProvider.useTokens)();
50
+ const modes = {
51
+ ...globalModes,
52
+ ...propModes
53
+ };
54
+
55
+ // Container
56
+ const gap = Number((0, _figmaVariablesResolver.getVariableByName)('statusHero/gap', modes)) || 12;
57
+ const padding = Number((0, _figmaVariablesResolver.getVariableByName)('statusHero/padding', modes)) || 8;
58
+
59
+ // Media slot wrap (gap between icon and money value in default slot)
60
+ const slotWrapGap = Number((0, _figmaVariablesResolver.getVariableByName)('statusHero/slotWrap/gap', modes)) || 46;
61
+
62
+ // Content wrap
63
+ const contentWrapGap = Number((0, _figmaVariablesResolver.getVariableByName)('statusHero/contentWrap/gap', modes)) || 12;
64
+
65
+ // Title
66
+ const titleColor = (0, _figmaVariablesResolver.getVariableByName)('statusHero/title/foreground', modes) || '#0c0d10';
67
+ const titleFontSize = Number((0, _figmaVariablesResolver.getVariableByName)('statusHero/title/fontSize', modes)) || 20;
68
+ const titleFontFamily = (0, _figmaVariablesResolver.getVariableByName)('statusHero/title/fontFamily', modes) || 'System';
69
+ const titleLineHeight = Number((0, _figmaVariablesResolver.getVariableByName)('statusHero/title/lineHeight', modes)) || 22;
70
+ const titleFontWeight = (0, _figmaVariablesResolver.getVariableByName)('statusHero/title/fontWeight', modes) || '700';
71
+
72
+ // Body
73
+ const bodyColor = (0, _figmaVariablesResolver.getVariableByName)('statusHero/body/foreground', modes) || '#24262b';
74
+ const bodyFontSize = Number((0, _figmaVariablesResolver.getVariableByName)('statusHero/body/fontSize', modes)) || 14;
75
+ const bodyFontFamily = (0, _figmaVariablesResolver.getVariableByName)('statusHero/body/fontFamily', modes) || 'System';
76
+ const bodyLineHeight = Number((0, _figmaVariablesResolver.getVariableByName)('statusHero/body/lineHeight', modes)) || 17;
77
+ const bodyFontWeight = (0, _figmaVariablesResolver.getVariableByName)('statusHero/body/fontWeight', modes) || '500';
78
+ const containerStyle = {
79
+ flexDirection: 'column',
80
+ alignItems: 'center',
81
+ justifyContent: 'center',
82
+ gap,
83
+ padding
84
+ };
85
+ const defaultMediaWrapStyle = {
86
+ flexDirection: 'column',
87
+ alignItems: 'center',
88
+ gap: slotWrapGap
89
+ };
90
+ const contentWrapStyle = {
91
+ flexDirection: 'column',
92
+ alignItems: 'center',
93
+ gap: contentWrapGap
94
+ };
95
+ const titleStyle = {
96
+ color: titleColor,
97
+ fontSize: titleFontSize,
98
+ fontFamily: titleFontFamily,
99
+ lineHeight: titleLineHeight,
100
+ fontWeight: String(titleFontWeight),
101
+ textAlign: 'center'
102
+ };
103
+ const bodyStyle = {
104
+ color: bodyColor,
105
+ fontSize: bodyFontSize,
106
+ fontFamily: bodyFontFamily,
107
+ lineHeight: bodyLineHeight,
108
+ fontWeight: String(bodyFontWeight),
109
+ textAlign: 'center'
110
+ };
111
+
112
+ // Inject modes into the provided slot if it's a valid React element
113
+ const mediaContent = /*#__PURE__*/(0, _react.isValidElement)(renderMedia) ? /*#__PURE__*/(0, _react.cloneElement)(renderMedia, {
114
+ modes
115
+ }) : renderMedia;
116
+ const defaultMediaContent = /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
117
+ style: defaultMediaWrapStyle,
118
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_IconCapsule.default, {
119
+ iconName: iconName,
120
+ modes: {
121
+ ...modes,
122
+ 'Icon Capsule Size': 'L',
123
+ Emphasis: 'High',
124
+ AppearanceBrand: 'Primary'
125
+ }
126
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_MoneyValue.default, {
127
+ value: value,
128
+ currency: currency,
129
+ modes: {
130
+ ...modes,
131
+ Context3: 'Balance'
132
+ }
133
+ })]
134
+ });
135
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
136
+ style: [containerStyle, style],
137
+ children: [mediaContent ?? defaultMediaContent, /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
138
+ style: contentWrapStyle,
139
+ children: [showTitle && title ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
140
+ style: titleStyle,
141
+ children: title
142
+ }) : null, subtitle ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
143
+ style: bodyStyle,
144
+ children: subtitle
145
+ }) : null]
146
+ })]
147
+ });
148
+ }
@@ -0,0 +1,79 @@
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 _jsxRuntime = require("react/jsx-runtime");
11
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
12
+ /**
13
+ * Individual tab item used inside the Tabs container.
14
+ *
15
+ * Supports idle and active states driven by design tokens.
16
+ * When active, a bottom indicator bar is shown beneath the label.
17
+ *
18
+ * @component
19
+ * @param {TabItemProps} props
20
+ */
21
+ function TabItem({
22
+ label = 'Tab item',
23
+ active = false,
24
+ onPress,
25
+ modes = {},
26
+ style,
27
+ labelStyle,
28
+ accessibilityLabel
29
+ }) {
30
+ const paddingVertical = (0, _figmaVariablesResolver.getVariableByName)('tabItem/padding/vertical', modes) ?? 8;
31
+ const fontFamily = (0, _figmaVariablesResolver.getVariableByName)('tabItem/label/fontFamily', modes) ?? 'JioType Var';
32
+ const fontSize = (0, _figmaVariablesResolver.getVariableByName)('tabItem/label/size', modes) ?? 14;
33
+ const lineHeight = (0, _figmaVariablesResolver.getVariableByName)('tabItem/label/lineHeight', modes) ?? 17;
34
+ const idleLabelColor = (0, _figmaVariablesResolver.getVariableByName)('tabItem/idle/label/color', modes) ?? '#303338';
35
+ const activeLabelColor = (0, _figmaVariablesResolver.getVariableByName)('tabItem/active/label/color', modes) ?? '#cea15a';
36
+ const labelColor = active ? activeLabelColor : idleLabelColor;
37
+ const containerStyle = {
38
+ flexDirection: 'column',
39
+ alignItems: 'center',
40
+ justifyContent: 'center',
41
+ paddingVertical
42
+ };
43
+ const textStyle = {
44
+ color: labelColor,
45
+ fontFamily,
46
+ fontSize,
47
+ lineHeight,
48
+ fontWeight: '500'
49
+ };
50
+ const indicatorStyle = {
51
+ position: 'absolute',
52
+ bottom: 0,
53
+ left: 0,
54
+ right: 0,
55
+ height: 2,
56
+ backgroundColor: activeLabelColor,
57
+ borderRadius: 1
58
+ };
59
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Pressable, {
60
+ style: ({
61
+ pressed
62
+ }) => [containerStyle, pressed && {
63
+ opacity: 0.7
64
+ }, style],
65
+ onPress: onPress,
66
+ accessibilityRole: "tab",
67
+ accessibilityState: {
68
+ selected: active
69
+ },
70
+ accessibilityLabel: accessibilityLabel ?? label,
71
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
72
+ style: [textStyle, labelStyle],
73
+ children: label
74
+ }), active && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
75
+ style: indicatorStyle
76
+ })]
77
+ });
78
+ }
79
+ var _default = exports.default = TabItem;
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "TabItem", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _TabItem.default;
10
+ }
11
+ });
12
+ exports.default = void 0;
13
+ var _react = _interopRequireDefault(require("react"));
14
+ var _reactNative = require("react-native");
15
+ var _figmaVariablesResolver = require("../../design-tokens/figma-variables-resolver");
16
+ var _TabItem = _interopRequireDefault(require("./TabItem"));
17
+ var _jsxRuntime = require("react/jsx-runtime");
18
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
19
+ /**
20
+ * Tabs container component that lays out TabItem children horizontally.
21
+ *
22
+ * The "Tab items" slot maps to React children — each child should be a
23
+ * `<TabItem>` element. The `modes` prop is automatically forwarded to
24
+ * every TabItem child so theming is consistent.
25
+ *
26
+ * @component
27
+ * @param {TabsProps} props
28
+ *
29
+ * @example
30
+ * ```tsx
31
+ * const [activeIndex, setActiveIndex] = useState(0);
32
+ *
33
+ * <Tabs modes={{ 'Color Mode': 'Light' }}>
34
+ * <TabItem label="Tab 1" active={activeIndex === 0} onPress={() => setActiveIndex(0)} />
35
+ * <TabItem label="Tab 2" active={activeIndex === 1} onPress={() => setActiveIndex(1)} />
36
+ * <TabItem label="Tab 3" active={activeIndex === 2} onPress={() => setActiveIndex(2)} />
37
+ * </Tabs>
38
+ * ```
39
+ */
40
+ function Tabs({
41
+ children,
42
+ modes = {},
43
+ scrollable = false,
44
+ style
45
+ }) {
46
+ const gap = (0, _figmaVariablesResolver.getVariableByName)('tabs/gap', modes) ?? 16;
47
+ const paddingTop = (0, _figmaVariablesResolver.getVariableByName)('tabs/padding/top', modes) ?? 0;
48
+ const paddingBottom = (0, _figmaVariablesResolver.getVariableByName)('tabs/padding/bottom', modes) ?? 0;
49
+ const paddingLeft = (0, _figmaVariablesResolver.getVariableByName)('tabs/padding/left', modes) ?? 0;
50
+ const paddingRight = (0, _figmaVariablesResolver.getVariableByName)('tabs/padding/right', modes) ?? 0;
51
+
52
+ // Forward modes to all TabItem children
53
+ const enhancedChildren = _react.default.Children.map(children, child => {
54
+ if (/*#__PURE__*/_react.default.isValidElement(child) && child.type === _TabItem.default) {
55
+ const childElement = child;
56
+ return /*#__PURE__*/_react.default.cloneElement(childElement, {
57
+ modes: {
58
+ ...modes,
59
+ ...(childElement.props.modes ?? {})
60
+ }
61
+ });
62
+ }
63
+ return child;
64
+ });
65
+ const containerStyle = {
66
+ flexDirection: 'row',
67
+ gap,
68
+ paddingTop,
69
+ paddingBottom,
70
+ paddingLeft,
71
+ paddingRight
72
+ };
73
+ if (scrollable) {
74
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ScrollView, {
75
+ horizontal: true,
76
+ showsHorizontalScrollIndicator: false,
77
+ accessibilityRole: "tablist",
78
+ contentContainerStyle: [containerStyle, style],
79
+ children: enhancedChildren
80
+ });
81
+ }
82
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
83
+ style: [containerStyle, style],
84
+ accessibilityRole: "tablist",
85
+ children: enhancedChildren
86
+ });
87
+ }
88
+ var _default = exports.default = Tabs;
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _react = _interopRequireWildcard(require("react"));
8
+ var _reactNative = require("react-native");
9
+ var _reactNativeReanimated = _interopRequireWildcard(require("react-native-reanimated"));
10
+ var _figmaVariablesResolver = require("../../design-tokens/figma-variables-resolver");
11
+ var _useToast = require("./useToast");
12
+ var _jsxRuntime = require("react/jsx-runtime");
13
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
14
+ const ANIMATION_DURATION = 250;
15
+ function Toast({
16
+ id,
17
+ title,
18
+ timeout = 4000,
19
+ onClose,
20
+ modes = {},
21
+ placement = 'bottom',
22
+ style
23
+ }) {
24
+ const timerRef = (0, _react.useRef)(null);
25
+ (0, _react.useEffect)(() => {
26
+ if (timeout <= 0) return;
27
+ timerRef.current = setTimeout(() => (0, _useToast.closeToast)(id), timeout);
28
+ return () => {
29
+ if (timerRef.current) clearTimeout(timerRef.current);
30
+ };
31
+ }, [id, timeout]);
32
+ const backgroundColor = (0, _figmaVariablesResolver.getVariableByName)('toast/background', modes) || '#303338';
33
+ const foreground = (0, _figmaVariablesResolver.getVariableByName)('toast/foreground', modes) || '#ffffff';
34
+ const fontSize = (0, _figmaVariablesResolver.getVariableByName)('toast/fontSize', modes) || 14;
35
+ const fontFamily = (0, _figmaVariablesResolver.getVariableByName)('toast/fontFamily', modes) || undefined;
36
+ const fontWeight = (0, _figmaVariablesResolver.getVariableByName)('toast/fontWeight', modes) || '500';
37
+ const lineHeight = (0, _figmaVariablesResolver.getVariableByName)('toast/lineHeight', modes) || 18;
38
+ const radius = (0, _figmaVariablesResolver.getVariableByName)('toast/radius', modes) || 14;
39
+ const paddingHorizontal = (0, _figmaVariablesResolver.getVariableByName)('toast/padding/horizontal', modes) || 16;
40
+ const paddingVertical = (0, _figmaVariablesResolver.getVariableByName)('toast/padding/vertical', modes) || 14;
41
+ const gap = (0, _figmaVariablesResolver.getVariableByName)('toast/gap', modes) || 8;
42
+ const borderWidth = (0, _figmaVariablesResolver.getVariableByName)('toast/border/size', modes) || 1;
43
+ const borderColor = (0, _figmaVariablesResolver.getVariableByName)('toast/border/color', modes) || 'rgba(255,255,255,0.1)';
44
+ const shadowBlurPrimary = (0, _figmaVariablesResolver.getVariableByName)('toast/shadow/primary/blur', modes) || 48;
45
+ const shadowOffsetYPrimary = (0, _figmaVariablesResolver.getVariableByName)('toast/shadow/primary/offsetY', modes) || 16;
46
+ const shadowColorPrimary = (0, _figmaVariablesResolver.getVariableByName)('toast/shadow/primary/color', modes) || 'rgba(13,13,15,0.16)';
47
+ const enterAnimation = placement === 'top' ? _reactNativeReanimated.SlideInUp.duration(ANIMATION_DURATION) : _reactNativeReanimated.SlideInDown.duration(ANIMATION_DURATION);
48
+ const containerStyle = {
49
+ backgroundColor,
50
+ borderRadius: radius,
51
+ paddingHorizontal,
52
+ paddingVertical,
53
+ gap,
54
+ borderWidth,
55
+ borderColor,
56
+ shadowColor: shadowColorPrimary,
57
+ shadowOffset: {
58
+ width: 0,
59
+ height: shadowOffsetYPrimary
60
+ },
61
+ shadowOpacity: 1,
62
+ shadowRadius: shadowBlurPrimary / 2,
63
+ elevation: 8
64
+ };
65
+ const textStyle = {
66
+ color: foreground,
67
+ fontSize,
68
+ fontFamily,
69
+ fontWeight: String(fontWeight),
70
+ lineHeight
71
+ };
72
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeReanimated.default.View, {
73
+ entering: enterAnimation,
74
+ exiting: _reactNativeReanimated.FadeOut.duration(ANIMATION_DURATION),
75
+ style: [styles.toast, containerStyle, style],
76
+ accessibilityRole: "alert",
77
+ accessibilityLiveRegion: "assertive",
78
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
79
+ style: textStyle,
80
+ numberOfLines: 2,
81
+ children: title
82
+ })
83
+ });
84
+ }
85
+ const styles = _reactNative.StyleSheet.create({
86
+ toast: {
87
+ alignSelf: 'center',
88
+ maxWidth: '90%',
89
+ minWidth: 200,
90
+ overflow: 'hidden'
91
+ }
92
+ });
93
+ var _default = exports.default = Toast;
@@ -0,0 +1,61 @@
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 _reactNativeSafeAreaContext = require("react-native-safe-area-context");
10
+ var _useToast = require("./useToast");
11
+ var _Toast = _interopRequireDefault(require("./Toast"));
12
+ var _jsxRuntime = require("react/jsx-runtime");
13
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
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
+ function ToastProvider({
16
+ children,
17
+ maxVisibleToasts = 3,
18
+ placement = 'bottom',
19
+ modes
20
+ }) {
21
+ const {
22
+ toasts
23
+ } = (0, _useToast.useToast)();
24
+ const insets = (0, _reactNativeSafeAreaContext.useSafeAreaInsets)();
25
+ const visibleToasts = (0, _react.useMemo)(() => toasts.slice(-maxVisibleToasts), [toasts, maxVisibleToasts]);
26
+ const regionStyle = (0, _react.useMemo)(() => [styles.region, placement === 'top' ? {
27
+ top: insets.top + 8
28
+ } : {
29
+ bottom: insets.bottom + 8
30
+ }], [placement, insets.top, insets.bottom]);
31
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
32
+ style: styles.container,
33
+ children: [children, visibleToasts.length > 0 && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
34
+ style: regionStyle,
35
+ pointerEvents: "box-none",
36
+ children: visibleToasts.map(entry => /*#__PURE__*/(0, _jsxRuntime.jsx)(_Toast.default, {
37
+ id: entry.id,
38
+ title: entry.title,
39
+ timeout: entry.timeout,
40
+ onClose: entry.onClose,
41
+ modes: entry.modes ?? modes,
42
+ placement: placement
43
+ }, entry.id))
44
+ })]
45
+ });
46
+ }
47
+ const styles = _reactNative.StyleSheet.create({
48
+ container: {
49
+ flex: 1
50
+ },
51
+ region: {
52
+ position: 'absolute',
53
+ left: 0,
54
+ right: 0,
55
+ alignItems: 'center',
56
+ gap: 8,
57
+ zIndex: 9999,
58
+ pointerEvents: 'box-none'
59
+ }
60
+ });
61
+ var _default = exports.default = ToastProvider;
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.addToast = addToast;
7
+ exports.closeAll = closeAll;
8
+ exports.closeToast = closeToast;
9
+ exports.useToast = useToast;
10
+ var _react = require("react");
11
+ let idCounter = 0;
12
+ let toasts = [];
13
+ const listeners = new Set();
14
+ function emit() {
15
+ for (const listener of listeners) {
16
+ listener();
17
+ }
18
+ }
19
+ function getSnapshot() {
20
+ return toasts;
21
+ }
22
+ function subscribe(listener) {
23
+ listeners.add(listener);
24
+ return () => {
25
+ listeners.delete(listener);
26
+ };
27
+ }
28
+ function addToast(options) {
29
+ const id = `toast-${++idCounter}`;
30
+ const entry = {
31
+ id,
32
+ title: options.title,
33
+ timeout: options.timeout ?? 4000,
34
+ onClose: options.onClose,
35
+ modes: options.modes
36
+ };
37
+ toasts = [...toasts, entry];
38
+ emit();
39
+ return id;
40
+ }
41
+ function closeToast(id) {
42
+ const entry = toasts.find(t => t.id === id);
43
+ toasts = toasts.filter(t => t.id !== id);
44
+ emit();
45
+ entry?.onClose?.();
46
+ }
47
+ function closeAll() {
48
+ const prev = toasts;
49
+ toasts = [];
50
+ emit();
51
+ prev.forEach(t => t.onClose?.());
52
+ }
53
+ function useToast() {
54
+ const queue = (0, _react.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
55
+ return {
56
+ toasts: queue,
57
+ addToast: (0, _react.useCallback)(addToast, []),
58
+ closeToast: (0, _react.useCallback)(closeToast, []),
59
+ closeAll: (0, _react.useCallback)(closeAll, [])
60
+ };
61
+ }