@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.
- package/lib/commonjs/components/Alert/Alert.js +137 -0
- package/lib/commonjs/components/Alert/Alert.js.map +1 -0
- package/lib/commonjs/components/Alert/Alert.stories.js +104 -0
- package/lib/commonjs/components/Alert/Alert.stories.js.map +1 -0
- package/lib/commonjs/components/Alert/Alert.test.js +62 -0
- package/lib/commonjs/components/Alert/Alert.test.js.map +1 -0
- package/lib/commonjs/components/Alert/index.js +13 -0
- package/lib/commonjs/components/Alert/index.js.map +1 -0
- package/lib/commonjs/components/StatTile/StatTile.js +94 -0
- package/lib/commonjs/components/StatTile/StatTile.js.map +1 -0
- package/lib/commonjs/components/StatTile/StatTile.stories.js +100 -0
- package/lib/commonjs/components/StatTile/StatTile.stories.js.map +1 -0
- package/lib/commonjs/components/StatTile/StatTile.test.js +49 -0
- package/lib/commonjs/components/StatTile/StatTile.test.js.map +1 -0
- package/lib/commonjs/components/StatTile/index.js +13 -0
- package/lib/commonjs/components/StatTile/index.js.map +1 -0
- package/lib/commonjs/components/index.js +53 -31
- package/lib/commonjs/components/index.js.map +1 -1
- package/lib/module/components/Alert/Alert.js +133 -0
- package/lib/module/components/Alert/Alert.js.map +1 -0
- package/lib/module/components/Alert/Alert.stories.js +100 -0
- package/lib/module/components/Alert/Alert.stories.js.map +1 -0
- package/lib/module/components/Alert/Alert.test.js +62 -0
- package/lib/module/components/Alert/Alert.test.js.map +1 -0
- package/lib/module/components/Alert/index.js +4 -0
- package/lib/module/components/Alert/index.js.map +1 -0
- package/lib/module/components/StatTile/StatTile.js +90 -0
- package/lib/module/components/StatTile/StatTile.js.map +1 -0
- package/lib/module/components/StatTile/StatTile.stories.js +96 -0
- package/lib/module/components/StatTile/StatTile.stories.js.map +1 -0
- package/lib/module/components/StatTile/StatTile.test.js +49 -0
- package/lib/module/components/StatTile/StatTile.test.js.map +1 -0
- package/lib/module/components/StatTile/index.js +4 -0
- package/lib/module/components/StatTile/index.js.map +1 -0
- package/lib/module/components/index.js +2 -0
- package/lib/module/components/index.js.map +1 -1
- package/lib/typescript/commonjs/components/Alert/Alert.d.ts +41 -0
- package/lib/typescript/commonjs/components/Alert/Alert.d.ts.map +1 -0
- package/lib/typescript/commonjs/components/Alert/index.d.ts +3 -0
- package/lib/typescript/commonjs/components/Alert/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/components/StatTile/StatTile.d.ts +31 -0
- package/lib/typescript/commonjs/components/StatTile/StatTile.d.ts.map +1 -0
- package/lib/typescript/commonjs/components/StatTile/index.d.ts +3 -0
- package/lib/typescript/commonjs/components/StatTile/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/components/index.d.ts +2 -0
- package/lib/typescript/commonjs/components/index.d.ts.map +1 -1
- package/lib/typescript/module/components/Alert/Alert.d.ts +41 -0
- package/lib/typescript/module/components/Alert/Alert.d.ts.map +1 -0
- package/lib/typescript/module/components/Alert/index.d.ts +3 -0
- package/lib/typescript/module/components/Alert/index.d.ts.map +1 -0
- package/lib/typescript/module/components/StatTile/StatTile.d.ts +31 -0
- package/lib/typescript/module/components/StatTile/StatTile.d.ts.map +1 -0
- package/lib/typescript/module/components/StatTile/index.d.ts +3 -0
- package/lib/typescript/module/components/StatTile/index.d.ts.map +1 -0
- package/lib/typescript/module/components/index.d.ts +2 -0
- package/lib/typescript/module/components/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/Alert/Alert.tsx +132 -0
- package/src/components/Alert/index.ts +2 -0
- package/src/components/StatTile/StatTile.tsx +98 -0
- package/src/components/StatTile/index.ts +2 -0
- 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,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
|
+
}
|
package/src/components/index.ts
CHANGED
|
@@ -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';
|