@ecohouse/ui 0.1.56 → 0.1.58
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/dist/index.cjs +961 -504
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +53 -3
- package/dist/index.d.ts +53 -3
- package/dist/index.js +857 -414
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/NotificationStatus/NotificationStatus.stories.tsx +86 -0
- package/src/components/NotificationStatus/NotificationStatus.tsx +255 -0
- package/src/components/NotificationStatus/index.ts +9 -0
- package/src/components/StatusIndicator/StatusIndicator.stories.tsx +36 -0
- package/src/components/StatusIndicator/StatusIndicator.tsx +105 -0
- package/src/components/StatusIndicator/index.ts +2 -0
- package/src/components/index.ts +13 -0
- package/src/icons/ChevronRight/ChevronRightIcon.tsx +25 -0
- package/src/icons/ChevronRight/ChevronRightIcon.web.tsx +31 -0
- package/src/icons/ChevronRight/chevronRightPath.ts +2 -0
- package/src/icons/ChevronRight/index.ts +1 -0
- package/src/icons/DoubleCheck/DoubleCheckIcon.tsx +25 -0
- package/src/icons/DoubleCheck/DoubleCheckIcon.web.tsx +31 -0
- package/src/icons/DoubleCheck/doubleCheckPath.ts +3 -0
- package/src/icons/DoubleCheck/index.ts +1 -0
- package/src/icons/NotificationCancelled/NotificationCancelledIcon.tsx +22 -0
- package/src/icons/NotificationCancelled/NotificationCancelledIcon.web.tsx +21 -0
- package/src/icons/NotificationCancelled/index.ts +1 -0
- package/src/icons/NotificationCheckout/NotificationCheckoutIcon.tsx +22 -0
- package/src/icons/NotificationCheckout/NotificationCheckoutIcon.web.tsx +21 -0
- package/src/icons/NotificationCheckout/index.ts +1 -0
- package/src/icons/NotificationIcons.stories.tsx +99 -0
- package/src/icons/NotificationQrCode/NotificationQrCodeIcon.tsx +25 -0
- package/src/icons/NotificationQrCode/NotificationQrCodeIcon.web.tsx +24 -0
- package/src/icons/NotificationQrCode/index.ts +1 -0
- package/src/icons/NotificationSuccess/NotificationSuccessIcon.tsx +26 -0
- package/src/icons/NotificationSuccess/NotificationSuccessIcon.web.tsx +25 -0
- package/src/icons/NotificationSuccess/index.ts +1 -0
- package/src/icons/NotificationWarning/NotificationWarningIcon.tsx +22 -0
- package/src/icons/NotificationWarning/NotificationWarningIcon.web.tsx +21 -0
- package/src/icons/NotificationWarning/index.ts +1 -0
- package/src/icons/index.ts +7 -0
- package/src/icons/registry.ts +23 -0
- package/src/index.ts +17 -0
package/package.json
CHANGED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
|
+
import { StyleSheet, View } from "react-native";
|
|
3
|
+
import { colors } from "../../theme";
|
|
4
|
+
import {
|
|
5
|
+
BookingWarningNotification,
|
|
6
|
+
CancelledBookingNotification,
|
|
7
|
+
GuestCheckInNotification,
|
|
8
|
+
NewBookingNotification,
|
|
9
|
+
NotificationStatusSkeleton,
|
|
10
|
+
QrKeyNotification,
|
|
11
|
+
} from "./NotificationStatus";
|
|
12
|
+
|
|
13
|
+
const meta = {
|
|
14
|
+
title: "Components/Notification Statuses",
|
|
15
|
+
component: NewBookingNotification,
|
|
16
|
+
args: {
|
|
17
|
+
title: "Նոր ամրագրում",
|
|
18
|
+
description: "Արմեն Գրիգորյանը ամրագրեց «Լեռնային Ռեզիդենցիա» (Օգս 28 - Օգս 30):",
|
|
19
|
+
timestamp: "2 ժ առաջ",
|
|
20
|
+
unread: true,
|
|
21
|
+
onPress: () => undefined,
|
|
22
|
+
},
|
|
23
|
+
decorators: [
|
|
24
|
+
(Story) => (
|
|
25
|
+
<View style={styles.frame}>
|
|
26
|
+
<Story />
|
|
27
|
+
</View>
|
|
28
|
+
),
|
|
29
|
+
],
|
|
30
|
+
parameters: {
|
|
31
|
+
backgrounds: { default: "dark" },
|
|
32
|
+
},
|
|
33
|
+
} satisfies Meta<typeof NewBookingNotification>;
|
|
34
|
+
|
|
35
|
+
export default meta;
|
|
36
|
+
type Story = StoryObj<typeof meta>;
|
|
37
|
+
|
|
38
|
+
export const NewBooking: Story = {};
|
|
39
|
+
|
|
40
|
+
export const CancelledBooking: Story = {
|
|
41
|
+
render: (args) => <CancelledBookingNotification {...args} title="Ամրագրումը չեղարկվել է" />,
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export const GuestCheckIn: Story = {
|
|
45
|
+
render: (args) => <GuestCheckInNotification {...args} title="Հյուրը մուտք գործեց" />,
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export const QrKey: Story = {
|
|
49
|
+
name: "QR Key",
|
|
50
|
+
render: (args) => <QrKeyNotification {...args} title="QR բանալին ակտիվացված է" />,
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export const BookingWarning: Story = {
|
|
54
|
+
render: (args) => (
|
|
55
|
+
<BookingWarningNotification {...args} title="Քոթեջն ուշադրություն է պահանջում" />
|
|
56
|
+
),
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const Loading: Story = {
|
|
60
|
+
render: () => <NotificationStatusSkeleton />,
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export const AllStatuses: Story = {
|
|
64
|
+
render: (args) => (
|
|
65
|
+
<View>
|
|
66
|
+
<NewBookingNotification {...args} />
|
|
67
|
+
<CancelledBookingNotification {...args} title="Ամրագրումը չեղարկվել է" />
|
|
68
|
+
<GuestCheckInNotification {...args} title="Հյուրը մուտք գործեց" />
|
|
69
|
+
<QrKeyNotification {...args} title="QR բանալին ակտիվացված է" unread={false} />
|
|
70
|
+
<BookingWarningNotification
|
|
71
|
+
{...args}
|
|
72
|
+
title="Քոթեջն ուշադրություն է պահանջում"
|
|
73
|
+
unread={false}
|
|
74
|
+
/>
|
|
75
|
+
</View>
|
|
76
|
+
),
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const styles = StyleSheet.create({
|
|
80
|
+
frame: {
|
|
81
|
+
width: 460,
|
|
82
|
+
overflow: "hidden",
|
|
83
|
+
borderRadius: 16,
|
|
84
|
+
backgroundColor: colors.grey750,
|
|
85
|
+
},
|
|
86
|
+
});
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import { useState, type ReactNode } from "react";
|
|
2
|
+
import {
|
|
3
|
+
Pressable,
|
|
4
|
+
StyleSheet,
|
|
5
|
+
Text,
|
|
6
|
+
View,
|
|
7
|
+
type PressableProps,
|
|
8
|
+
type StyleProp,
|
|
9
|
+
type ViewStyle,
|
|
10
|
+
} from "react-native";
|
|
11
|
+
import {
|
|
12
|
+
ChevronRightIcon,
|
|
13
|
+
NotificationCancelledIcon,
|
|
14
|
+
NotificationCheckoutIcon,
|
|
15
|
+
NotificationQrCodeIcon,
|
|
16
|
+
NotificationSuccessIcon,
|
|
17
|
+
NotificationWarningIcon,
|
|
18
|
+
} from "../../icons";
|
|
19
|
+
import { colors, fonts } from "../../theme";
|
|
20
|
+
|
|
21
|
+
export interface NotificationStatusProps extends Omit<
|
|
22
|
+
PressableProps,
|
|
23
|
+
"children" | "disabled" | "onPress" | "style"
|
|
24
|
+
> {
|
|
25
|
+
title: string;
|
|
26
|
+
description: string;
|
|
27
|
+
timestamp: string;
|
|
28
|
+
unread?: boolean;
|
|
29
|
+
disabled?: boolean;
|
|
30
|
+
showChevron?: boolean;
|
|
31
|
+
onPress?: PressableProps["onPress"];
|
|
32
|
+
style?: StyleProp<ViewStyle>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function NewBookingNotification(props: NotificationStatusProps) {
|
|
36
|
+
return <NotificationStatus icon={<NotificationSuccessIcon />} {...props} />;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function CancelledBookingNotification(props: NotificationStatusProps) {
|
|
40
|
+
return <NotificationStatus icon={<NotificationCancelledIcon />} {...props} />;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function GuestCheckInNotification(props: NotificationStatusProps) {
|
|
44
|
+
return <NotificationStatus icon={<NotificationCheckoutIcon />} {...props} />;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function QrKeyNotification(props: NotificationStatusProps) {
|
|
48
|
+
return <NotificationStatus icon={<NotificationQrCodeIcon />} {...props} />;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function BookingWarningNotification(props: NotificationStatusProps) {
|
|
52
|
+
return <NotificationStatus icon={<NotificationWarningIcon />} {...props} />;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function NotificationStatusSkeleton() {
|
|
56
|
+
return (
|
|
57
|
+
<View
|
|
58
|
+
accessibilityElementsHidden
|
|
59
|
+
importantForAccessibility="no-hide-descendants"
|
|
60
|
+
style={styles.root}
|
|
61
|
+
>
|
|
62
|
+
<View style={[styles.icon, styles.skeletonIcon]} />
|
|
63
|
+
<View style={[styles.content, styles.skeletonContent]}>
|
|
64
|
+
<View style={[styles.skeletonLine, styles.skeletonTitle]} />
|
|
65
|
+
<View style={styles.skeletonDescription}>
|
|
66
|
+
<View style={[styles.skeletonLine, styles.skeletonDescriptionFirst]} />
|
|
67
|
+
<View style={[styles.skeletonLine, styles.skeletonDescriptionSecond]} />
|
|
68
|
+
</View>
|
|
69
|
+
<View style={[styles.skeletonLine, styles.skeletonTimestamp]} />
|
|
70
|
+
</View>
|
|
71
|
+
<View style={[styles.chevron, styles.skeletonChevron]} />
|
|
72
|
+
</View>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function NotificationStatus({
|
|
77
|
+
icon,
|
|
78
|
+
title,
|
|
79
|
+
description,
|
|
80
|
+
timestamp,
|
|
81
|
+
unread = false,
|
|
82
|
+
disabled = false,
|
|
83
|
+
showChevron,
|
|
84
|
+
onPress,
|
|
85
|
+
style,
|
|
86
|
+
accessibilityLabel,
|
|
87
|
+
onHoverIn,
|
|
88
|
+
onHoverOut,
|
|
89
|
+
onPressIn,
|
|
90
|
+
onPressOut,
|
|
91
|
+
...rest
|
|
92
|
+
}: NotificationStatusProps & { icon: ReactNode }) {
|
|
93
|
+
const [active, setActive] = useState(false);
|
|
94
|
+
const interactive = onPress !== undefined;
|
|
95
|
+
|
|
96
|
+
return (
|
|
97
|
+
<Pressable
|
|
98
|
+
{...rest}
|
|
99
|
+
accessibilityLabel={accessibilityLabel ?? `${title}. ${description}. ${timestamp}`}
|
|
100
|
+
accessibilityRole={interactive ? "button" : undefined}
|
|
101
|
+
accessibilityState={{ disabled }}
|
|
102
|
+
disabled={disabled}
|
|
103
|
+
onPress={onPress}
|
|
104
|
+
onHoverIn={(event) => {
|
|
105
|
+
setActive(true);
|
|
106
|
+
onHoverIn?.(event);
|
|
107
|
+
}}
|
|
108
|
+
onHoverOut={(event) => {
|
|
109
|
+
setActive(false);
|
|
110
|
+
onHoverOut?.(event);
|
|
111
|
+
}}
|
|
112
|
+
onPressIn={(event) => {
|
|
113
|
+
setActive(true);
|
|
114
|
+
onPressIn?.(event);
|
|
115
|
+
}}
|
|
116
|
+
onPressOut={(event) => {
|
|
117
|
+
setActive(false);
|
|
118
|
+
onPressOut?.(event);
|
|
119
|
+
}}
|
|
120
|
+
style={[styles.root, active && styles.rootActive, disabled && styles.disabled, style]}
|
|
121
|
+
>
|
|
122
|
+
<View style={styles.icon}>{icon}</View>
|
|
123
|
+
<View style={styles.content}>
|
|
124
|
+
<View style={styles.titleRow}>
|
|
125
|
+
{unread ? <View style={styles.unreadIndicator} /> : null}
|
|
126
|
+
<Text numberOfLines={1} style={styles.title}>
|
|
127
|
+
{title}
|
|
128
|
+
</Text>
|
|
129
|
+
</View>
|
|
130
|
+
<Text style={styles.description}>{description}</Text>
|
|
131
|
+
<Text numberOfLines={1} style={styles.timestamp}>
|
|
132
|
+
{timestamp}
|
|
133
|
+
</Text>
|
|
134
|
+
</View>
|
|
135
|
+
{(showChevron ?? interactive) ? (
|
|
136
|
+
<View
|
|
137
|
+
accessibilityElementsHidden
|
|
138
|
+
importantForAccessibility="no-hide-descendants"
|
|
139
|
+
style={styles.chevron}
|
|
140
|
+
>
|
|
141
|
+
<ChevronRightIcon color={colors.grey300} size={16} strokeWidth={1.5} />
|
|
142
|
+
</View>
|
|
143
|
+
) : null}
|
|
144
|
+
</Pressable>
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const styles = StyleSheet.create({
|
|
149
|
+
root: {
|
|
150
|
+
width: "100%",
|
|
151
|
+
minHeight: 111,
|
|
152
|
+
flexDirection: "row",
|
|
153
|
+
alignItems: "flex-start",
|
|
154
|
+
gap: 16,
|
|
155
|
+
padding: 16,
|
|
156
|
+
backgroundColor: "transparent",
|
|
157
|
+
},
|
|
158
|
+
rootActive: {
|
|
159
|
+
backgroundColor: colors.whiteAlpha1,
|
|
160
|
+
},
|
|
161
|
+
disabled: {
|
|
162
|
+
opacity: 0.4,
|
|
163
|
+
},
|
|
164
|
+
icon: {
|
|
165
|
+
width: 44,
|
|
166
|
+
height: 44,
|
|
167
|
+
flexShrink: 0,
|
|
168
|
+
},
|
|
169
|
+
content: {
|
|
170
|
+
minWidth: 0,
|
|
171
|
+
flex: 1,
|
|
172
|
+
alignSelf: "stretch",
|
|
173
|
+
justifyContent: "space-between",
|
|
174
|
+
},
|
|
175
|
+
titleRow: {
|
|
176
|
+
minWidth: 0,
|
|
177
|
+
flexDirection: "row",
|
|
178
|
+
alignItems: "center",
|
|
179
|
+
gap: 10,
|
|
180
|
+
},
|
|
181
|
+
unreadIndicator: {
|
|
182
|
+
width: 8,
|
|
183
|
+
height: 8,
|
|
184
|
+
flexShrink: 0,
|
|
185
|
+
borderRadius: 4,
|
|
186
|
+
backgroundColor: colors.primaryLight,
|
|
187
|
+
},
|
|
188
|
+
title: {
|
|
189
|
+
minWidth: 0,
|
|
190
|
+
flex: 1,
|
|
191
|
+
color: colors.white,
|
|
192
|
+
fontFamily: fonts.sans,
|
|
193
|
+
fontSize: 14,
|
|
194
|
+
fontWeight: "600",
|
|
195
|
+
lineHeight: 14,
|
|
196
|
+
letterSpacing: 0,
|
|
197
|
+
},
|
|
198
|
+
description: {
|
|
199
|
+
color: colors.lightGrey,
|
|
200
|
+
fontFamily: fonts.sans,
|
|
201
|
+
fontSize: 12,
|
|
202
|
+
fontWeight: "400",
|
|
203
|
+
lineHeight: 16,
|
|
204
|
+
letterSpacing: 0,
|
|
205
|
+
},
|
|
206
|
+
timestamp: {
|
|
207
|
+
color: colors.grey50,
|
|
208
|
+
fontFamily: fonts.sans,
|
|
209
|
+
fontSize: 12,
|
|
210
|
+
fontWeight: "400",
|
|
211
|
+
lineHeight: 16,
|
|
212
|
+
letterSpacing: 0,
|
|
213
|
+
},
|
|
214
|
+
chevron: {
|
|
215
|
+
alignSelf: "center",
|
|
216
|
+
flexShrink: 0,
|
|
217
|
+
},
|
|
218
|
+
skeletonIcon: {
|
|
219
|
+
borderRadius: 22,
|
|
220
|
+
backgroundColor: colors.grey600,
|
|
221
|
+
},
|
|
222
|
+
skeletonContent: {
|
|
223
|
+
paddingTop: 1,
|
|
224
|
+
paddingBottom: 2,
|
|
225
|
+
},
|
|
226
|
+
skeletonLine: {
|
|
227
|
+
borderRadius: 999,
|
|
228
|
+
backgroundColor: colors.grey500,
|
|
229
|
+
},
|
|
230
|
+
skeletonTitle: {
|
|
231
|
+
width: "42%",
|
|
232
|
+
height: 12,
|
|
233
|
+
},
|
|
234
|
+
skeletonDescription: {
|
|
235
|
+
gap: 5,
|
|
236
|
+
},
|
|
237
|
+
skeletonDescriptionFirst: {
|
|
238
|
+
width: "92%",
|
|
239
|
+
height: 10,
|
|
240
|
+
},
|
|
241
|
+
skeletonDescriptionSecond: {
|
|
242
|
+
width: "68%",
|
|
243
|
+
height: 10,
|
|
244
|
+
},
|
|
245
|
+
skeletonTimestamp: {
|
|
246
|
+
width: 58,
|
|
247
|
+
height: 10,
|
|
248
|
+
},
|
|
249
|
+
skeletonChevron: {
|
|
250
|
+
width: 7,
|
|
251
|
+
height: 12,
|
|
252
|
+
borderRadius: 4,
|
|
253
|
+
backgroundColor: colors.grey500,
|
|
254
|
+
},
|
|
255
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export {
|
|
2
|
+
BookingWarningNotification,
|
|
3
|
+
CancelledBookingNotification,
|
|
4
|
+
GuestCheckInNotification,
|
|
5
|
+
NewBookingNotification,
|
|
6
|
+
NotificationStatusSkeleton,
|
|
7
|
+
QrKeyNotification,
|
|
8
|
+
} from "./NotificationStatus";
|
|
9
|
+
export type { NotificationStatusProps } from "./NotificationStatus";
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
|
+
import { StyleSheet, View } from "react-native";
|
|
3
|
+
import { StatusIndicator } from "./StatusIndicator";
|
|
4
|
+
|
|
5
|
+
const meta = {
|
|
6
|
+
title: "Components/StatusIndicator",
|
|
7
|
+
component: StatusIndicator,
|
|
8
|
+
args: { label: "Ակտիվ է", status: "active" },
|
|
9
|
+
parameters: { backgrounds: { default: "black" } },
|
|
10
|
+
} satisfies Meta<typeof StatusIndicator>;
|
|
11
|
+
|
|
12
|
+
export default meta;
|
|
13
|
+
type Story = StoryObj<typeof meta>;
|
|
14
|
+
|
|
15
|
+
export const Active: Story = {};
|
|
16
|
+
|
|
17
|
+
export const AllStatuses: Story = {
|
|
18
|
+
render: () => (
|
|
19
|
+
<View style={styles.column}>
|
|
20
|
+
<StatusIndicator label="Ակտիվ է" status="active" />
|
|
21
|
+
<StatusIndicator label="Սպասվող" status="pending" />
|
|
22
|
+
<StatusIndicator label="Ավարտված" status="completed" />
|
|
23
|
+
<StatusIndicator label="Չեղարկված" status="cancelled" />
|
|
24
|
+
<StatusIndicator label="Ապաակտիվ է" status="inactive" />
|
|
25
|
+
<StatusIndicator label="Հասանելի չէ" status="unavailable" />
|
|
26
|
+
</View>
|
|
27
|
+
),
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const styles = StyleSheet.create({
|
|
31
|
+
column: {
|
|
32
|
+
gap: 16,
|
|
33
|
+
padding: 24,
|
|
34
|
+
backgroundColor: "#090909",
|
|
35
|
+
},
|
|
36
|
+
});
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { forwardRef, useMemo, useRef, type ComponentRef } from "react";
|
|
2
|
+
import {
|
|
3
|
+
Platform,
|
|
4
|
+
StyleSheet,
|
|
5
|
+
Text,
|
|
6
|
+
View,
|
|
7
|
+
type StyleProp,
|
|
8
|
+
type ViewProps,
|
|
9
|
+
type ViewStyle,
|
|
10
|
+
} from "react-native";
|
|
11
|
+
import { colors, fonts } from "../../theme";
|
|
12
|
+
import { mergeRefs } from "../../utils/mergeRefs";
|
|
13
|
+
import { useApplyWebClassName } from "../../utils/useApplyWebClassName";
|
|
14
|
+
|
|
15
|
+
export type StatusIndicatorStatus =
|
|
16
|
+
"active" | "pending" | "completed" | "cancelled" | "inactive" | "unavailable";
|
|
17
|
+
|
|
18
|
+
export interface StatusIndicatorProps extends Omit<ViewProps, "style" | "children"> {
|
|
19
|
+
status: StatusIndicatorStatus;
|
|
20
|
+
label: string;
|
|
21
|
+
style?: StyleProp<ViewStyle>;
|
|
22
|
+
className?: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const statusColors: Record<Exclude<StatusIndicatorStatus, "unavailable">, string> = {
|
|
26
|
+
active: colors.green,
|
|
27
|
+
pending: colors.primary,
|
|
28
|
+
completed: colors.grey0,
|
|
29
|
+
cancelled: colors.red,
|
|
30
|
+
inactive: colors.primary,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const StatusIndicator = forwardRef<ComponentRef<typeof View>, StatusIndicatorProps>(
|
|
34
|
+
function StatusIndicator(
|
|
35
|
+
{ status, label, style, className, accessibilityLabel, ...rest },
|
|
36
|
+
forwardedRef,
|
|
37
|
+
) {
|
|
38
|
+
const containerRef = useRef<ComponentRef<typeof View>>(null);
|
|
39
|
+
const setContainerRef = useMemo(() => mergeRefs(containerRef, forwardedRef), [forwardedRef]);
|
|
40
|
+
const indicatorColor = status === "unavailable" ? null : statusColors[status];
|
|
41
|
+
|
|
42
|
+
useApplyWebClassName(containerRef, className);
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<View
|
|
46
|
+
{...rest}
|
|
47
|
+
ref={setContainerRef}
|
|
48
|
+
accessibilityRole="text"
|
|
49
|
+
accessibilityLabel={accessibilityLabel ?? label}
|
|
50
|
+
style={[styles.container, style]}
|
|
51
|
+
>
|
|
52
|
+
{indicatorColor ? (
|
|
53
|
+
<View style={[styles.indicatorOuter, { backgroundColor: `${indicatorColor}1F` }]}>
|
|
54
|
+
<View style={[styles.indicatorMiddle, { backgroundColor: `${indicatorColor}52` }]}>
|
|
55
|
+
<View style={[styles.indicatorInner, { backgroundColor: indicatorColor }]} />
|
|
56
|
+
</View>
|
|
57
|
+
</View>
|
|
58
|
+
) : null}
|
|
59
|
+
<Text style={[styles.label, Platform.OS === "android" ? styles.labelAndroid : null]}>
|
|
60
|
+
{label}
|
|
61
|
+
</Text>
|
|
62
|
+
</View>
|
|
63
|
+
);
|
|
64
|
+
},
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
const styles = StyleSheet.create({
|
|
68
|
+
container: {
|
|
69
|
+
flexDirection: "row",
|
|
70
|
+
alignItems: "center",
|
|
71
|
+
alignSelf: "flex-start",
|
|
72
|
+
gap: 8,
|
|
73
|
+
},
|
|
74
|
+
indicatorOuter: {
|
|
75
|
+
width: 14,
|
|
76
|
+
height: 14,
|
|
77
|
+
flexShrink: 0,
|
|
78
|
+
alignItems: "center",
|
|
79
|
+
justifyContent: "center",
|
|
80
|
+
borderRadius: 7,
|
|
81
|
+
},
|
|
82
|
+
indicatorMiddle: {
|
|
83
|
+
width: 10,
|
|
84
|
+
height: 10,
|
|
85
|
+
alignItems: "center",
|
|
86
|
+
justifyContent: "center",
|
|
87
|
+
borderRadius: 5,
|
|
88
|
+
},
|
|
89
|
+
indicatorInner: {
|
|
90
|
+
width: 6,
|
|
91
|
+
height: 6,
|
|
92
|
+
borderRadius: 3,
|
|
93
|
+
},
|
|
94
|
+
label: {
|
|
95
|
+
color: colors.white,
|
|
96
|
+
fontFamily: fonts.sans,
|
|
97
|
+
fontSize: 12,
|
|
98
|
+
fontWeight: "500",
|
|
99
|
+
lineHeight: 12,
|
|
100
|
+
letterSpacing: 0,
|
|
101
|
+
},
|
|
102
|
+
labelAndroid: {
|
|
103
|
+
includeFontPadding: false,
|
|
104
|
+
},
|
|
105
|
+
});
|
package/src/components/index.ts
CHANGED
|
@@ -13,6 +13,9 @@ export type { BadgeProps, BadgeVariant } from "./Badge";
|
|
|
13
13
|
export { StatusBadge } from "./StatusBadge";
|
|
14
14
|
export type { StatusBadgeProps, StatusBadgeTone } from "./StatusBadge";
|
|
15
15
|
|
|
16
|
+
export { StatusIndicator } from "./StatusIndicator";
|
|
17
|
+
export type { StatusIndicatorProps, StatusIndicatorStatus } from "./StatusIndicator";
|
|
18
|
+
|
|
16
19
|
export { PaginationDots } from "./PaginationDots";
|
|
17
20
|
export type { PaginationDotsProps } from "./PaginationDots";
|
|
18
21
|
|
|
@@ -116,6 +119,16 @@ export type { RatingInputProps } from "./RatingInput";
|
|
|
116
119
|
export { CommentCard } from "./CommentCard";
|
|
117
120
|
export type { CommentCardProps } from "./CommentCard";
|
|
118
121
|
|
|
122
|
+
export {
|
|
123
|
+
BookingWarningNotification,
|
|
124
|
+
CancelledBookingNotification,
|
|
125
|
+
GuestCheckInNotification,
|
|
126
|
+
NewBookingNotification,
|
|
127
|
+
NotificationStatusSkeleton,
|
|
128
|
+
QrKeyNotification,
|
|
129
|
+
} from "./NotificationStatus";
|
|
130
|
+
export type { NotificationStatusProps } from "./NotificationStatus";
|
|
131
|
+
|
|
119
132
|
export { Range } from "./Range";
|
|
120
133
|
export type { RangeProps, RangeValue } from "./Range";
|
|
121
134
|
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import Svg, { Path } from "react-native-svg";
|
|
2
|
+
import { colors } from "../../theme";
|
|
3
|
+
import type { IconProps } from "../types";
|
|
4
|
+
import { CHEVRON_RIGHT_PATH } from "./chevronRightPath";
|
|
5
|
+
|
|
6
|
+
export { CHEVRON_RIGHT_PATH } from "./chevronRightPath";
|
|
7
|
+
|
|
8
|
+
/** Native — react-native-svg (peer dependency). */
|
|
9
|
+
export function ChevronRightIcon({
|
|
10
|
+
size = 16,
|
|
11
|
+
color = colors.grey100,
|
|
12
|
+
strokeWidth = 1.5,
|
|
13
|
+
}: IconProps) {
|
|
14
|
+
return (
|
|
15
|
+
<Svg width={size} height={size} viewBox="0 0 16 16" fill="none">
|
|
16
|
+
<Path
|
|
17
|
+
d={CHEVRON_RIGHT_PATH}
|
|
18
|
+
stroke={color}
|
|
19
|
+
strokeWidth={strokeWidth}
|
|
20
|
+
strokeLinecap="round"
|
|
21
|
+
strokeLinejoin="round"
|
|
22
|
+
/>
|
|
23
|
+
</Svg>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { colors } from "../../theme";
|
|
2
|
+
import type { IconProps } from "../types";
|
|
3
|
+
import { CHEVRON_RIGHT_PATH } from "./chevronRightPath";
|
|
4
|
+
|
|
5
|
+
/** Web / Storybook — plain SVG (no react-native-svg). */
|
|
6
|
+
export function ChevronRightIcon({
|
|
7
|
+
size = 16,
|
|
8
|
+
color = colors.grey100,
|
|
9
|
+
strokeWidth = 1.5,
|
|
10
|
+
}: IconProps) {
|
|
11
|
+
return (
|
|
12
|
+
<svg
|
|
13
|
+
width={size}
|
|
14
|
+
height={size}
|
|
15
|
+
viewBox="0 0 16 16"
|
|
16
|
+
fill="none"
|
|
17
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
18
|
+
aria-hidden
|
|
19
|
+
>
|
|
20
|
+
<path
|
|
21
|
+
d={CHEVRON_RIGHT_PATH}
|
|
22
|
+
stroke={color}
|
|
23
|
+
strokeWidth={strokeWidth}
|
|
24
|
+
strokeLinecap="round"
|
|
25
|
+
strokeLinejoin="round"
|
|
26
|
+
/>
|
|
27
|
+
</svg>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export { CHEVRON_RIGHT_PATH } from "./chevronRightPath";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { ChevronRightIcon, CHEVRON_RIGHT_PATH } from "./ChevronRightIcon";
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import Svg, { Path } from "react-native-svg";
|
|
2
|
+
import { colors } from "../../theme";
|
|
3
|
+
import type { IconProps } from "../types";
|
|
4
|
+
import { DOUBLE_CHECK_PATH } from "./doubleCheckPath";
|
|
5
|
+
|
|
6
|
+
export { DOUBLE_CHECK_PATH } from "./doubleCheckPath";
|
|
7
|
+
|
|
8
|
+
/** Native — react-native-svg (peer dependency). */
|
|
9
|
+
export function DoubleCheckIcon({
|
|
10
|
+
size = 16,
|
|
11
|
+
color = colors.primary,
|
|
12
|
+
strokeWidth = 1.5,
|
|
13
|
+
}: IconProps) {
|
|
14
|
+
return (
|
|
15
|
+
<Svg width={size} height={size} viewBox="0 0 16 16" fill="none">
|
|
16
|
+
<Path
|
|
17
|
+
d={DOUBLE_CHECK_PATH}
|
|
18
|
+
stroke={color}
|
|
19
|
+
strokeWidth={strokeWidth}
|
|
20
|
+
strokeLinecap="round"
|
|
21
|
+
strokeLinejoin="round"
|
|
22
|
+
/>
|
|
23
|
+
</Svg>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { colors } from "../../theme";
|
|
2
|
+
import type { IconProps } from "../types";
|
|
3
|
+
import { DOUBLE_CHECK_PATH } from "./doubleCheckPath";
|
|
4
|
+
|
|
5
|
+
/** Web / Storybook — plain SVG (no react-native-svg). */
|
|
6
|
+
export function DoubleCheckIcon({
|
|
7
|
+
size = 16,
|
|
8
|
+
color = colors.primary,
|
|
9
|
+
strokeWidth = 1.5,
|
|
10
|
+
}: IconProps) {
|
|
11
|
+
return (
|
|
12
|
+
<svg
|
|
13
|
+
width={size}
|
|
14
|
+
height={size}
|
|
15
|
+
viewBox="0 0 16 16"
|
|
16
|
+
fill="none"
|
|
17
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
18
|
+
aria-hidden
|
|
19
|
+
>
|
|
20
|
+
<path
|
|
21
|
+
d={DOUBLE_CHECK_PATH}
|
|
22
|
+
stroke={color}
|
|
23
|
+
strokeWidth={strokeWidth}
|
|
24
|
+
strokeLinecap="round"
|
|
25
|
+
strokeLinejoin="round"
|
|
26
|
+
/>
|
|
27
|
+
</svg>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export { DOUBLE_CHECK_PATH } from "./doubleCheckPath";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { DoubleCheckIcon, DOUBLE_CHECK_PATH } from "./DoubleCheckIcon";
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import Svg, { Path, Rect } from "react-native-svg";
|
|
2
|
+
import type { IconProps } from "../types";
|
|
3
|
+
|
|
4
|
+
export function NotificationCancelledIcon({
|
|
5
|
+
size = 44,
|
|
6
|
+
color = "#A63E3E",
|
|
7
|
+
strokeWidth = 2,
|
|
8
|
+
fillOpacity = 0.08,
|
|
9
|
+
}: IconProps) {
|
|
10
|
+
return (
|
|
11
|
+
<Svg width={size} height={size} viewBox="0 0 44 44" fill="none">
|
|
12
|
+
<Rect width="44" height="44" rx="22" fill={color} fillOpacity={fillOpacity} />
|
|
13
|
+
<Path
|
|
14
|
+
d="M27 17L17 27M17 17L27 27"
|
|
15
|
+
stroke={color}
|
|
16
|
+
strokeWidth={strokeWidth}
|
|
17
|
+
strokeLinecap="round"
|
|
18
|
+
strokeLinejoin="round"
|
|
19
|
+
/>
|
|
20
|
+
</Svg>
|
|
21
|
+
);
|
|
22
|
+
}
|