@bacon-pos/ui 0.10.0 → 0.11.0

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 (62) hide show
  1. package/lib/commonjs/components/Alert/Alert.js +137 -0
  2. package/lib/commonjs/components/Alert/Alert.js.map +1 -0
  3. package/lib/commonjs/components/Alert/Alert.stories.js +104 -0
  4. package/lib/commonjs/components/Alert/Alert.stories.js.map +1 -0
  5. package/lib/commonjs/components/Alert/Alert.test.js +62 -0
  6. package/lib/commonjs/components/Alert/Alert.test.js.map +1 -0
  7. package/lib/commonjs/components/Alert/index.js +13 -0
  8. package/lib/commonjs/components/Alert/index.js.map +1 -0
  9. package/lib/commonjs/components/StatTile/StatTile.js +94 -0
  10. package/lib/commonjs/components/StatTile/StatTile.js.map +1 -0
  11. package/lib/commonjs/components/StatTile/StatTile.stories.js +100 -0
  12. package/lib/commonjs/components/StatTile/StatTile.stories.js.map +1 -0
  13. package/lib/commonjs/components/StatTile/StatTile.test.js +49 -0
  14. package/lib/commonjs/components/StatTile/StatTile.test.js.map +1 -0
  15. package/lib/commonjs/components/StatTile/index.js +13 -0
  16. package/lib/commonjs/components/StatTile/index.js.map +1 -0
  17. package/lib/commonjs/components/index.js +53 -31
  18. package/lib/commonjs/components/index.js.map +1 -1
  19. package/lib/module/components/Alert/Alert.js +133 -0
  20. package/lib/module/components/Alert/Alert.js.map +1 -0
  21. package/lib/module/components/Alert/Alert.stories.js +100 -0
  22. package/lib/module/components/Alert/Alert.stories.js.map +1 -0
  23. package/lib/module/components/Alert/Alert.test.js +62 -0
  24. package/lib/module/components/Alert/Alert.test.js.map +1 -0
  25. package/lib/module/components/Alert/index.js +4 -0
  26. package/lib/module/components/Alert/index.js.map +1 -0
  27. package/lib/module/components/StatTile/StatTile.js +90 -0
  28. package/lib/module/components/StatTile/StatTile.js.map +1 -0
  29. package/lib/module/components/StatTile/StatTile.stories.js +96 -0
  30. package/lib/module/components/StatTile/StatTile.stories.js.map +1 -0
  31. package/lib/module/components/StatTile/StatTile.test.js +49 -0
  32. package/lib/module/components/StatTile/StatTile.test.js.map +1 -0
  33. package/lib/module/components/StatTile/index.js +4 -0
  34. package/lib/module/components/StatTile/index.js.map +1 -0
  35. package/lib/module/components/index.js +2 -0
  36. package/lib/module/components/index.js.map +1 -1
  37. package/lib/typescript/commonjs/components/Alert/Alert.d.ts +41 -0
  38. package/lib/typescript/commonjs/components/Alert/Alert.d.ts.map +1 -0
  39. package/lib/typescript/commonjs/components/Alert/index.d.ts +3 -0
  40. package/lib/typescript/commonjs/components/Alert/index.d.ts.map +1 -0
  41. package/lib/typescript/commonjs/components/StatTile/StatTile.d.ts +31 -0
  42. package/lib/typescript/commonjs/components/StatTile/StatTile.d.ts.map +1 -0
  43. package/lib/typescript/commonjs/components/StatTile/index.d.ts +3 -0
  44. package/lib/typescript/commonjs/components/StatTile/index.d.ts.map +1 -0
  45. package/lib/typescript/commonjs/components/index.d.ts +2 -0
  46. package/lib/typescript/commonjs/components/index.d.ts.map +1 -1
  47. package/lib/typescript/module/components/Alert/Alert.d.ts +41 -0
  48. package/lib/typescript/module/components/Alert/Alert.d.ts.map +1 -0
  49. package/lib/typescript/module/components/Alert/index.d.ts +3 -0
  50. package/lib/typescript/module/components/Alert/index.d.ts.map +1 -0
  51. package/lib/typescript/module/components/StatTile/StatTile.d.ts +31 -0
  52. package/lib/typescript/module/components/StatTile/StatTile.d.ts.map +1 -0
  53. package/lib/typescript/module/components/StatTile/index.d.ts +3 -0
  54. package/lib/typescript/module/components/StatTile/index.d.ts.map +1 -0
  55. package/lib/typescript/module/components/index.d.ts +2 -0
  56. package/lib/typescript/module/components/index.d.ts.map +1 -1
  57. package/package.json +1 -1
  58. package/src/components/Alert/Alert.tsx +132 -0
  59. package/src/components/Alert/index.ts +2 -0
  60. package/src/components/StatTile/StatTile.tsx +98 -0
  61. package/src/components/StatTile/index.ts +2 -0
  62. package/src/components/index.ts +2 -0
@@ -0,0 +1,132 @@
1
+ import { type ReactNode } from 'react';
2
+ import { Pressable, View, type StyleProp, type ViewStyle } from 'react-native';
3
+ import { useTheme, type Theme } from '../../theme';
4
+ import { palette } from '../../theme/palette';
5
+ import { Icon } from '../Icon/Icon';
6
+ import type { IconName } from '../Icon/icons.generated';
7
+ import { Text } from '../Text/Text';
8
+
9
+ export type AlertStatus = 'info' | 'warning' | 'success' | 'destructive';
10
+
11
+ export interface AlertProps {
12
+ /** Color/status. Defaults to `info`. */
13
+ status?: AlertStatus;
14
+ /** Optional bold title line above the message. */
15
+ title?: string;
16
+ /** Message text. Alternatively pass `children`. */
17
+ message?: string;
18
+ /** Message content (overrides `message`). */
19
+ children?: ReactNode;
20
+ /** Leading icon. Defaults to `info` (as in the design). */
21
+ icon?: IconName;
22
+ /** Hide the leading icon. */
23
+ showIcon?: boolean;
24
+ /** Vertical alignment of the icon vs the text. Defaults to `center`. */
25
+ iconAlign?: 'top' | 'center';
26
+ /** Trailing content (e.g. a link/button). */
27
+ action?: ReactNode;
28
+ /** Show a close (×) button and call this on press. */
29
+ onClose?: () => void;
30
+ /** Background override (for a custom status). */
31
+ backgroundColor?: string;
32
+ /** Foreground (text/icon) override. */
33
+ color?: string;
34
+ /** Fixed width. Omit to fill the parent. */
35
+ width?: number;
36
+ /** Override the container style. */
37
+ style?: StyleProp<ViewStyle>;
38
+ }
39
+
40
+ function statusColors(theme: Theme, status: AlertStatus): { bg: string; fg: string } {
41
+ switch (status) {
42
+ case 'warning':
43
+ return { bg: theme.colors.feedback.warningSubtle, fg: palette.warning[600] };
44
+ case 'success':
45
+ return { bg: theme.colors.feedback.successSubtle, fg: theme.colors.feedback.success };
46
+ case 'destructive':
47
+ return { bg: theme.colors.feedback.errorSubtle, fg: theme.colors.feedback.error };
48
+ case 'info':
49
+ default:
50
+ return { bg: theme.colors.background.subtle, fg: palette.neutral[500] };
51
+ }
52
+ }
53
+
54
+ /**
55
+ * Alert — an inline banner in four statuses (info / warning / success /
56
+ * destructive), each a subtle tinted surface with a matching icon and text
57
+ * (Figma "Alert"). Fills its parent by default (text wraps to any width) or takes
58
+ * a fixed `width`. Supports an optional title, a trailing action and a close
59
+ * button; colors are overridable for custom statuses.
60
+ */
61
+ export function Alert({
62
+ status = 'info',
63
+ title,
64
+ message,
65
+ children,
66
+ icon = 'info',
67
+ showIcon = true,
68
+ iconAlign = 'center',
69
+ action,
70
+ onClose,
71
+ backgroundColor,
72
+ color,
73
+ width,
74
+ style,
75
+ }: AlertProps) {
76
+ const theme = useTheme();
77
+ const { bg, fg } = statusColors(theme, status);
78
+ const foreground = color ?? fg;
79
+ const background = backgroundColor ?? bg;
80
+
81
+ return (
82
+ <View
83
+ accessibilityRole="alert"
84
+ style={[
85
+ {
86
+ flexDirection: 'row',
87
+ alignItems: 'flex-start',
88
+ gap: 16,
89
+ paddingVertical: 20,
90
+ paddingHorizontal: 16,
91
+ borderRadius: theme.radii.lg,
92
+ backgroundColor: background,
93
+ ...(width != null ? { width } : { alignSelf: 'stretch' }),
94
+ },
95
+ style,
96
+ ]}
97
+ >
98
+ {showIcon ? (
99
+ <View style={{ width: 24, height: 24, flexShrink: 0, alignSelf: iconAlign === 'center' ? 'center' : 'flex-start' }}>
100
+ <Icon name={icon} size={24} color={foreground} />
101
+ </View>
102
+ ) : null}
103
+
104
+ <View style={{ flex: 1, minWidth: 0, gap: 2 }}>
105
+ {title ? (
106
+ <Text variant="bodyLarge" weight="semibold" color={foreground}>
107
+ {title}
108
+ </Text>
109
+ ) : null}
110
+ {children ?? (message ? (
111
+ <Text variant="bodyLarge" color={foreground}>
112
+ {message}
113
+ </Text>
114
+ ) : null)}
115
+ </View>
116
+
117
+ {action ? <View style={{ flexShrink: 0 }}>{action}</View> : null}
118
+
119
+ {onClose ? (
120
+ <Pressable
121
+ onPress={onClose}
122
+ hitSlop={8}
123
+ accessibilityRole="button"
124
+ accessibilityLabel="Dismiss"
125
+ style={{ width: 24, height: 24, flexShrink: 0, alignItems: 'center', justifyContent: 'center' }}
126
+ >
127
+ <Icon name="close" size={20} color={foreground} />
128
+ </Pressable>
129
+ ) : null}
130
+ </View>
131
+ );
132
+ }
@@ -0,0 +1,2 @@
1
+ export { Alert } from './Alert';
2
+ export type { AlertProps, AlertStatus } from './Alert';
@@ -0,0 +1,98 @@
1
+ import { type ReactNode } from 'react';
2
+ import { Pressable, View, type StyleProp, type ViewStyle } from 'react-native';
3
+ import { useTheme } from '../../theme';
4
+ import { Icon } from '../Icon/Icon';
5
+ import type { IconName } from '../Icon/icons.generated';
6
+ import { Text } from '../Text/Text';
7
+
8
+ export interface StatTileProps {
9
+ /** Small label above the value. */
10
+ label: string;
11
+ /** The value — a string/number, or a node for custom formatting/color. */
12
+ value: ReactNode;
13
+ /** Optional leading icon. */
14
+ icon?: IconName;
15
+ /** Fixed width. Omit to fill the parent (works in a flex/grid row of tiles). */
16
+ width?: number;
17
+ /** Make the tile pressable. */
18
+ onPress?: () => void;
19
+ /** Tile background. Defaults to `background.subtle`. */
20
+ backgroundColor?: string;
21
+ /** Label color. Defaults to `secondary`. */
22
+ labelColor?: string;
23
+ /** Value color (when `value` is text). Defaults to `primary`. */
24
+ valueColor?: string;
25
+ /** Override the container style. */
26
+ style?: StyleProp<ViewStyle>;
27
+ accessibilityLabel?: string;
28
+ }
29
+
30
+ /**
31
+ * StatTile — a compact KPI card: a small label over a prominent value (Figma
32
+ * "info card"). Fills its parent by default (so a row/grid of tiles sizes evenly)
33
+ * or takes a fixed `width`. `value` accepts a node for custom color/formatting.
34
+ */
35
+ export function StatTile({
36
+ label,
37
+ value,
38
+ icon,
39
+ width,
40
+ onPress,
41
+ backgroundColor,
42
+ labelColor,
43
+ valueColor,
44
+ style,
45
+ accessibilityLabel,
46
+ }: StatTileProps) {
47
+ const theme = useTheme();
48
+
49
+ const content = (
50
+ <>
51
+ {icon ? (
52
+ <View style={{ width: 24, height: 24, flexShrink: 0 }}>
53
+ <Icon name={icon} size={24} color="secondary" />
54
+ </View>
55
+ ) : null}
56
+ <View style={{ flex: 1, minWidth: 0, gap: 4 }}>
57
+ <Text variant="bodySmall" color={labelColor ?? 'secondary'} numberOfLines={1}>
58
+ {label}
59
+ </Text>
60
+ {typeof value === 'string' || typeof value === 'number' ? (
61
+ <Text variant="bodyLarge" weight="semibold" color={valueColor ?? 'primary'} numberOfLines={1}>
62
+ {String(value)}
63
+ </Text>
64
+ ) : (
65
+ value
66
+ )}
67
+ </View>
68
+ </>
69
+ );
70
+
71
+ const containerStyle: ViewStyle = {
72
+ flexDirection: 'row',
73
+ alignItems: 'center',
74
+ gap: 12,
75
+ padding: 12,
76
+ borderRadius: theme.radii.lg,
77
+ backgroundColor: backgroundColor ?? theme.colors.background.subtle,
78
+ ...(width != null ? { width } : { alignSelf: 'stretch' }),
79
+ };
80
+
81
+ if (!onPress) {
82
+ return (
83
+ <View accessibilityLabel={accessibilityLabel} style={[containerStyle, style]}>
84
+ {content}
85
+ </View>
86
+ );
87
+ }
88
+ return (
89
+ <Pressable
90
+ onPress={onPress}
91
+ accessibilityRole="button"
92
+ accessibilityLabel={accessibilityLabel ?? label}
93
+ style={({ pressed }) => [containerStyle, { opacity: pressed ? 0.96 : 1 }, style]}
94
+ >
95
+ {content}
96
+ </Pressable>
97
+ );
98
+ }
@@ -0,0 +1,2 @@
1
+ export { StatTile } from './StatTile';
2
+ export type { StatTileProps } from './StatTile';
@@ -1,3 +1,4 @@
1
+ export * from './Alert';
1
2
  export * from './Avatar';
2
3
  export * from './Badge';
3
4
  export * from './brand';
@@ -23,6 +24,7 @@ export * from './Radio';
23
24
  export * from './Select';
24
25
  export * from './Sidebar';
25
26
  export * from './Spinner';
27
+ export * from './StatTile';
26
28
  export * from './Surface';
27
29
  export * from './Switch';
28
30
  export * from './Table';