@ecohouse/ui 0.1.31 → 0.1.33
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/README.md +5 -0
- package/dist/index.cjs +1594 -523
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +218 -10
- package/dist/index.d.ts +218 -10
- package/dist/index.js +1516 -471
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/AccountHeader/AccountHeader.stories.tsx +70 -0
- package/src/components/AccountHeader/AccountHeader.tsx +224 -0
- package/src/components/AccountHeader/index.ts +2 -0
- package/src/components/AvatarSimple/AvatarSimple.tsx +2 -2
- package/src/components/Button/Button.tsx +4 -1
- package/src/components/DatePicker/DatePicker.tsx +129 -54
- package/src/components/FloatingActionButton/FloatingActionButton.stories.tsx +42 -0
- package/src/components/FloatingActionButton/FloatingActionButton.tsx +77 -0
- package/src/components/FloatingActionButton/index.ts +2 -0
- package/src/components/InfoTile/InfoTile.stories.tsx +80 -0
- package/src/components/InfoTile/InfoTile.tsx +118 -0
- package/src/components/InfoTile/index.ts +2 -0
- package/src/components/PaginationDots/PaginationDots.stories.tsx +48 -0
- package/src/components/PaginationDots/PaginationDots.tsx +111 -0
- package/src/components/PaginationDots/index.ts +2 -0
- package/src/components/Select/Select.tsx +5 -2
- package/src/components/Sidebar/Sidebar.tsx +25 -11
- package/src/components/StatusBadge/StatusBadge.stories.tsx +54 -0
- package/src/components/StatusBadge/StatusBadge.tsx +108 -0
- package/src/components/StatusBadge/index.ts +2 -0
- package/src/components/StepList/StepList.stories.tsx +37 -0
- package/src/components/StepList/StepList.tsx +152 -0
- package/src/components/StepList/index.ts +2 -0
- package/src/components/StepPager/StepPager.tsx +150 -0
- package/src/components/StepPager/index.ts +2 -0
- package/src/components/index.ts +21 -0
- package/src/icons/AlertTriangle/AlertTriangleIcon.tsx +19 -0
- package/src/icons/AlertTriangle/AlertTriangleIcon.web.tsx +18 -0
- package/src/icons/AlertTriangle/alertTrianglePath.ts +3 -0
- package/src/icons/AlertTriangle/index.ts +1 -0
- package/src/icons/Ban/BanIcon.tsx +15 -0
- package/src/icons/Ban/banPath.ts +2 -0
- package/src/icons/Ban/index.ts +1 -0
- package/src/icons/Bell/BellIcon.tsx +2 -2
- package/src/icons/Bell/BellIcon.web.tsx +2 -2
- package/src/icons/Bell/bellPath.ts +1 -1
- package/src/icons/CottageDetail/CottageDetailIcons.tsx +15 -0
- package/src/icons/CottageDetail/CottageDetailIcons.web.tsx +15 -0
- package/src/icons/CottageDetail/cottageDetailPaths.ts +3 -0
- package/src/icons/CottageDetail/index.ts +1 -0
- package/src/icons/Edit/EditIcon.tsx +20 -0
- package/src/icons/Edit/EditIcon.web.tsx +19 -0
- package/src/icons/Edit/editPath.ts +3 -0
- package/src/icons/Edit/index.ts +1 -0
- package/src/icons/Fullscreen/FullscreenIcon.tsx +21 -0
- package/src/icons/Fullscreen/fullscreenPath.ts +2 -0
- package/src/icons/Fullscreen/index.ts +1 -0
- package/src/icons/Home/homePath.ts +1 -1
- package/src/icons/HouseRules/HouseRulesIcons.tsx +62 -0
- package/src/icons/HouseRules/HouseRulesIcons.web.tsx +61 -0
- package/src/icons/HouseRules/houseRulesPaths.ts +24 -0
- package/src/icons/HouseRules/index.ts +2 -0
- package/src/icons/LocationUser/LocationUserIcon.tsx +15 -0
- package/src/icons/LocationUser/LocationUserIcon.web.tsx +14 -0
- package/src/icons/LocationUser/index.ts +1 -0
- package/src/icons/LocationUser/locationUserPath.ts +2 -0
- package/src/icons/Lock/LockIcon.tsx +21 -0
- package/src/icons/Lock/LockIcon.web.tsx +26 -0
- package/src/icons/Lock/index.ts +1 -0
- package/src/icons/Lock/lockPath.ts +3 -0
- package/src/icons/Refresh/RefreshIcon.tsx +20 -0
- package/src/icons/Refresh/RefreshIcon.web.tsx +19 -0
- package/src/icons/Refresh/index.ts +1 -0
- package/src/icons/Refresh/refreshPath.ts +3 -0
- package/src/icons/RefundStatus/RefundStatusIcon.tsx +24 -0
- package/src/icons/RefundStatus/RefundStatusIcon.web.tsx +23 -0
- package/src/icons/RefundStatus/index.ts +1 -0
- package/src/icons/RefundStatus/refundStatusPath.ts +3 -0
- package/src/icons/Sort/SortIcon.tsx +3 -3
- package/src/icons/Sort/SortIcon.web.tsx +2 -2
- package/src/icons/Sort/sortPath.ts +3 -2
- package/src/icons/VideoOff/VideoOffIcon.tsx +21 -0
- package/src/icons/VideoOff/VideoOffIcon.web.tsx +27 -0
- package/src/icons/VideoOff/index.ts +1 -0
- package/src/icons/VideoOff/videoOffPath.ts +2 -0
- package/src/icons/ZoomOut/ZoomOutIcon.tsx +21 -0
- package/src/icons/ZoomOut/index.ts +1 -0
- package/src/icons/ZoomOut/zoomOutPath.ts +2 -0
- package/src/icons/index.ts +12 -0
- package/src/icons/registry.ts +42 -0
- package/src/index.ts +34 -0
- package/src/theme/colors.test.ts +1 -1
- package/src/theme/colors.ts +4 -0
- package/src/theme/typography.ts +5 -5
- package/src/utils/dateUtils.ts +25 -0
- package/src/utils/popoverAlign.ts +85 -0
|
@@ -0,0 +1,108 @@
|
|
|
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 StatusBadgeTone = "active" | "completed" | "cancelled";
|
|
16
|
+
|
|
17
|
+
export interface StatusBadgeProps extends Omit<ViewProps, "style" | "children"> {
|
|
18
|
+
label: string;
|
|
19
|
+
tone?: StatusBadgeTone;
|
|
20
|
+
style?: StyleProp<ViewStyle>;
|
|
21
|
+
className?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const toneConfig = {
|
|
25
|
+
active: {
|
|
26
|
+
backgroundColor: colors.greenMuted,
|
|
27
|
+
color: colors.green,
|
|
28
|
+
},
|
|
29
|
+
completed: {
|
|
30
|
+
backgroundColor: colors.greyMuted,
|
|
31
|
+
color: colors.grey0,
|
|
32
|
+
},
|
|
33
|
+
cancelled: {
|
|
34
|
+
backgroundColor: colors.cancelledMuted,
|
|
35
|
+
color: colors.red,
|
|
36
|
+
},
|
|
37
|
+
} as const satisfies Record<StatusBadgeTone, { backgroundColor: string; color: string }>;
|
|
38
|
+
|
|
39
|
+
const webBlurStyle: ViewStyle =
|
|
40
|
+
Platform.OS === "web"
|
|
41
|
+
? ({
|
|
42
|
+
backdropFilter: "blur(39.5px)",
|
|
43
|
+
WebkitBackdropFilter: "blur(39.5px)",
|
|
44
|
+
} as ViewStyle)
|
|
45
|
+
: {};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Compact status chip (e.g. booking active / completed / cancelled).
|
|
49
|
+
* Height 28, pill radius, Semibold 12 — distinct from amenity `Badge`.
|
|
50
|
+
*/
|
|
51
|
+
export const StatusBadge = forwardRef<ComponentRef<typeof View>, StatusBadgeProps>(
|
|
52
|
+
function StatusBadge(
|
|
53
|
+
{ label, tone = "active", style, className, accessibilityLabel, ...rest },
|
|
54
|
+
forwardedRef,
|
|
55
|
+
) {
|
|
56
|
+
const containerRef = useRef<ComponentRef<typeof View>>(null);
|
|
57
|
+
const setContainerRef = useMemo(() => mergeRefs(containerRef, forwardedRef), [forwardedRef]);
|
|
58
|
+
const preset = toneConfig[tone];
|
|
59
|
+
|
|
60
|
+
useApplyWebClassName(containerRef, className);
|
|
61
|
+
|
|
62
|
+
return (
|
|
63
|
+
<View
|
|
64
|
+
{...rest}
|
|
65
|
+
ref={setContainerRef}
|
|
66
|
+
accessibilityRole="text"
|
|
67
|
+
accessibilityLabel={accessibilityLabel ?? label}
|
|
68
|
+
style={[styles.base, { backgroundColor: preset.backgroundColor }, webBlurStyle, style]}
|
|
69
|
+
>
|
|
70
|
+
<Text
|
|
71
|
+
style={[
|
|
72
|
+
styles.label,
|
|
73
|
+
{ color: preset.color },
|
|
74
|
+
Platform.OS === "android" ? styles.labelAndroid : null,
|
|
75
|
+
]}
|
|
76
|
+
>
|
|
77
|
+
{label}
|
|
78
|
+
</Text>
|
|
79
|
+
</View>
|
|
80
|
+
);
|
|
81
|
+
},
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
const styles = StyleSheet.create({
|
|
85
|
+
base: {
|
|
86
|
+
height: 28,
|
|
87
|
+
minHeight: 28,
|
|
88
|
+
flexDirection: "row",
|
|
89
|
+
alignItems: "center",
|
|
90
|
+
alignSelf: "flex-start",
|
|
91
|
+
justifyContent: "center",
|
|
92
|
+
gap: 6,
|
|
93
|
+
paddingVertical: 6,
|
|
94
|
+
paddingHorizontal: 12,
|
|
95
|
+
borderRadius: 50,
|
|
96
|
+
overflow: "hidden",
|
|
97
|
+
},
|
|
98
|
+
label: {
|
|
99
|
+
fontFamily: fonts.sans,
|
|
100
|
+
fontSize: 12,
|
|
101
|
+
fontWeight: "600",
|
|
102
|
+
lineHeight: 12,
|
|
103
|
+
letterSpacing: 0,
|
|
104
|
+
},
|
|
105
|
+
labelAndroid: {
|
|
106
|
+
includeFontPadding: false,
|
|
107
|
+
},
|
|
108
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
|
+
import { StyleSheet, View } from "react-native";
|
|
3
|
+
import { StepList } from "./StepList";
|
|
4
|
+
|
|
5
|
+
const meta = {
|
|
6
|
+
title: "Components/StepList",
|
|
7
|
+
component: StepList,
|
|
8
|
+
args: {
|
|
9
|
+
steps: [
|
|
10
|
+
"Ստացեք ակտիվ QR կոդը մուտքի օրը՝ ժամը 10:00-ին, այս էջի «Թվային բանալի» բաժնում։",
|
|
11
|
+
"Մոտեցեք քոթեջի մուտքի դռան սարքին (սկաներին) և պահեք հեռախոսի էկրանը։",
|
|
12
|
+
"Հաջող սկանավորումից հետո դուռը ավտոմատ կապակողպվի։",
|
|
13
|
+
],
|
|
14
|
+
},
|
|
15
|
+
parameters: {
|
|
16
|
+
backgrounds: { default: "black" },
|
|
17
|
+
},
|
|
18
|
+
} satisfies Meta<typeof StepList>;
|
|
19
|
+
|
|
20
|
+
export default meta;
|
|
21
|
+
type Story = StoryObj<typeof meta>;
|
|
22
|
+
|
|
23
|
+
export const Default: Story = {
|
|
24
|
+
render: (args) => (
|
|
25
|
+
<View style={styles.frame}>
|
|
26
|
+
<StepList {...args} />
|
|
27
|
+
</View>
|
|
28
|
+
),
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const styles = StyleSheet.create({
|
|
32
|
+
frame: {
|
|
33
|
+
padding: 24,
|
|
34
|
+
maxWidth: 560,
|
|
35
|
+
backgroundColor: "#090909",
|
|
36
|
+
},
|
|
37
|
+
});
|
|
@@ -0,0 +1,152 @@
|
|
|
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 interface StepListProps extends Omit<ViewProps, "style" | "children"> {
|
|
16
|
+
/** Step descriptions, numbered automatically from 1. */
|
|
17
|
+
steps: string[];
|
|
18
|
+
style?: StyleProp<ViewStyle>;
|
|
19
|
+
className?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const BADGE_SIZE = 42;
|
|
23
|
+
const ROW_GAP = 12;
|
|
24
|
+
const CONNECTOR_WIDTH = 2;
|
|
25
|
+
const CONNECTOR_HEIGHT = 19;
|
|
26
|
+
const CONNECTOR_GAP = 8;
|
|
27
|
+
|
|
28
|
+
const webBlurStyle: ViewStyle =
|
|
29
|
+
Platform.OS === "web"
|
|
30
|
+
? ({
|
|
31
|
+
backdropFilter: "blur(20px)",
|
|
32
|
+
WebkitBackdropFilter: "blur(20px)",
|
|
33
|
+
} as ViewStyle)
|
|
34
|
+
: {};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Vertical numbered process list — 42px badges, 2×19 connectors with 8px gaps.
|
|
38
|
+
*/
|
|
39
|
+
export const StepList = forwardRef<ComponentRef<typeof View>, StepListProps>(function StepList(
|
|
40
|
+
{ steps, style, className, accessibilityLabel, ...rest },
|
|
41
|
+
forwardedRef,
|
|
42
|
+
) {
|
|
43
|
+
const containerRef = useRef<ComponentRef<typeof View>>(null);
|
|
44
|
+
const setContainerRef = useMemo(() => mergeRefs(containerRef, forwardedRef), [forwardedRef]);
|
|
45
|
+
|
|
46
|
+
useApplyWebClassName(containerRef, className);
|
|
47
|
+
|
|
48
|
+
if (steps.length === 0) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<View
|
|
54
|
+
{...rest}
|
|
55
|
+
ref={setContainerRef}
|
|
56
|
+
accessibilityRole="summary"
|
|
57
|
+
accessibilityLabel={accessibilityLabel}
|
|
58
|
+
style={[styles.root, style]}
|
|
59
|
+
>
|
|
60
|
+
{steps.map((description, index) => {
|
|
61
|
+
const isLast = index === steps.length - 1;
|
|
62
|
+
const number = index + 1;
|
|
63
|
+
|
|
64
|
+
return (
|
|
65
|
+
<View key={`${number}-${description}`} style={styles.stepBlock}>
|
|
66
|
+
<View style={styles.row}>
|
|
67
|
+
<View style={[styles.badge, webBlurStyle]}>
|
|
68
|
+
<Text
|
|
69
|
+
style={[
|
|
70
|
+
styles.badgeLabel,
|
|
71
|
+
Platform.OS === "android" ? styles.labelAndroid : null,
|
|
72
|
+
]}
|
|
73
|
+
>
|
|
74
|
+
{String(number)}
|
|
75
|
+
</Text>
|
|
76
|
+
</View>
|
|
77
|
+
<Text
|
|
78
|
+
style={[styles.description, Platform.OS === "android" ? styles.labelAndroid : null]}
|
|
79
|
+
>
|
|
80
|
+
{description}
|
|
81
|
+
</Text>
|
|
82
|
+
</View>
|
|
83
|
+
|
|
84
|
+
{!isLast ? (
|
|
85
|
+
<View style={styles.connectorSlot}>
|
|
86
|
+
<View style={styles.connector} />
|
|
87
|
+
</View>
|
|
88
|
+
) : null}
|
|
89
|
+
</View>
|
|
90
|
+
);
|
|
91
|
+
})}
|
|
92
|
+
</View>
|
|
93
|
+
);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
const styles = StyleSheet.create({
|
|
97
|
+
root: {
|
|
98
|
+
width: "100%",
|
|
99
|
+
},
|
|
100
|
+
stepBlock: {
|
|
101
|
+
width: "100%",
|
|
102
|
+
},
|
|
103
|
+
row: {
|
|
104
|
+
flexDirection: "row",
|
|
105
|
+
alignItems: "center",
|
|
106
|
+
gap: ROW_GAP,
|
|
107
|
+
width: "100%",
|
|
108
|
+
},
|
|
109
|
+
badge: {
|
|
110
|
+
width: BADGE_SIZE,
|
|
111
|
+
height: BADGE_SIZE,
|
|
112
|
+
borderRadius: 79,
|
|
113
|
+
backgroundColor: colors.grey600,
|
|
114
|
+
alignItems: "center",
|
|
115
|
+
justifyContent: "center",
|
|
116
|
+
flexShrink: 0,
|
|
117
|
+
overflow: "hidden",
|
|
118
|
+
},
|
|
119
|
+
badgeLabel: {
|
|
120
|
+
fontFamily: fonts.sans,
|
|
121
|
+
fontSize: 14,
|
|
122
|
+
fontWeight: "500",
|
|
123
|
+
lineHeight: 14,
|
|
124
|
+
letterSpacing: 0,
|
|
125
|
+
color: colors.white,
|
|
126
|
+
textAlign: "center",
|
|
127
|
+
},
|
|
128
|
+
description: {
|
|
129
|
+
flex: 1,
|
|
130
|
+
minWidth: 0,
|
|
131
|
+
fontFamily: fonts.sans,
|
|
132
|
+
fontSize: 14,
|
|
133
|
+
fontWeight: "400",
|
|
134
|
+
lineHeight: 14,
|
|
135
|
+
letterSpacing: 0,
|
|
136
|
+
color: colors.white,
|
|
137
|
+
},
|
|
138
|
+
connectorSlot: {
|
|
139
|
+
width: BADGE_SIZE,
|
|
140
|
+
alignItems: "center",
|
|
141
|
+
paddingVertical: CONNECTOR_GAP,
|
|
142
|
+
},
|
|
143
|
+
connector: {
|
|
144
|
+
width: CONNECTOR_WIDTH,
|
|
145
|
+
height: CONNECTOR_HEIGHT,
|
|
146
|
+
borderRadius: 98,
|
|
147
|
+
backgroundColor: colors.grey600,
|
|
148
|
+
},
|
|
149
|
+
labelAndroid: {
|
|
150
|
+
includeFontPadding: false,
|
|
151
|
+
},
|
|
152
|
+
});
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { forwardRef, useMemo, useRef, type ComponentRef } from "react";
|
|
2
|
+
import {
|
|
3
|
+
Platform,
|
|
4
|
+
Pressable,
|
|
5
|
+
StyleSheet,
|
|
6
|
+
Text,
|
|
7
|
+
View,
|
|
8
|
+
type StyleProp,
|
|
9
|
+
type ViewProps,
|
|
10
|
+
type ViewStyle,
|
|
11
|
+
} from "react-native";
|
|
12
|
+
import { ChevronLeftIcon } from "../../icons";
|
|
13
|
+
import { colors, fonts } from "../../theme";
|
|
14
|
+
import { mergeRefs } from "../../utils/mergeRefs";
|
|
15
|
+
import { useApplyWebClassName } from "../../utils/useApplyWebClassName";
|
|
16
|
+
|
|
17
|
+
export interface StepPagerProps extends Omit<ViewProps, "style" | "children"> {
|
|
18
|
+
/** Zero-based active step index. */
|
|
19
|
+
index: number;
|
|
20
|
+
/** Total number of steps. */
|
|
21
|
+
count: number;
|
|
22
|
+
onPrevious?: () => void;
|
|
23
|
+
onNext?: () => void;
|
|
24
|
+
previousAccessibilityLabel?: string;
|
|
25
|
+
nextAccessibilityLabel?: string;
|
|
26
|
+
style?: StyleProp<ViewStyle>;
|
|
27
|
+
className?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const WIDTH = 121;
|
|
31
|
+
const HEIGHT = 48;
|
|
32
|
+
const ICON_SIZE = 24;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Compact prev / current-of-total / next control (e.g. camera fullscreen pager).
|
|
36
|
+
* Fixed 121×48 pill, 12 gap/padding, 77 radius.
|
|
37
|
+
*/
|
|
38
|
+
export const StepPager = forwardRef<ComponentRef<typeof View>, StepPagerProps>(function StepPager(
|
|
39
|
+
{
|
|
40
|
+
index,
|
|
41
|
+
count,
|
|
42
|
+
onPrevious,
|
|
43
|
+
onNext,
|
|
44
|
+
previousAccessibilityLabel = "Previous",
|
|
45
|
+
nextAccessibilityLabel = "Next",
|
|
46
|
+
style,
|
|
47
|
+
className,
|
|
48
|
+
accessibilityLabel,
|
|
49
|
+
...rest
|
|
50
|
+
},
|
|
51
|
+
forwardedRef,
|
|
52
|
+
) {
|
|
53
|
+
const containerRef = useRef<ComponentRef<typeof View>>(null);
|
|
54
|
+
const setContainerRef = useMemo(() => mergeRefs(containerRef, forwardedRef), [forwardedRef]);
|
|
55
|
+
const safeCount = Math.max(0, count);
|
|
56
|
+
const safeIndex = safeCount === 0 ? 0 : Math.min(Math.max(index, 0), safeCount - 1);
|
|
57
|
+
const label = safeCount === 0 ? "0/0" : `${safeIndex + 1}/${safeCount}`;
|
|
58
|
+
const atStart = safeIndex <= 0;
|
|
59
|
+
const atEnd = safeIndex >= safeCount - 1;
|
|
60
|
+
|
|
61
|
+
useApplyWebClassName(containerRef, className);
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<View
|
|
65
|
+
{...rest}
|
|
66
|
+
ref={setContainerRef}
|
|
67
|
+
accessibilityRole="adjustable"
|
|
68
|
+
accessibilityLabel={accessibilityLabel ?? label}
|
|
69
|
+
accessibilityValue={{
|
|
70
|
+
min: safeCount === 0 ? 0 : 1,
|
|
71
|
+
max: safeCount,
|
|
72
|
+
now: safeCount === 0 ? 0 : safeIndex + 1,
|
|
73
|
+
text: label,
|
|
74
|
+
}}
|
|
75
|
+
style={[styles.root, webBlurStyle, style]}
|
|
76
|
+
>
|
|
77
|
+
<Pressable
|
|
78
|
+
onPress={onPrevious}
|
|
79
|
+
disabled={atStart || !onPrevious}
|
|
80
|
+
hitSlop={4}
|
|
81
|
+
accessibilityRole="button"
|
|
82
|
+
accessibilityLabel={previousAccessibilityLabel}
|
|
83
|
+
accessibilityState={{ disabled: atStart || !onPrevious }}
|
|
84
|
+
style={[styles.navButton, (atStart || !onPrevious) && styles.navDisabled]}
|
|
85
|
+
>
|
|
86
|
+
<ChevronLeftIcon size={ICON_SIZE} color={colors.white} strokeWidth={2} />
|
|
87
|
+
</Pressable>
|
|
88
|
+
|
|
89
|
+
<Text style={styles.label}>{label}</Text>
|
|
90
|
+
|
|
91
|
+
<Pressable
|
|
92
|
+
onPress={onNext}
|
|
93
|
+
disabled={atEnd || !onNext}
|
|
94
|
+
hitSlop={4}
|
|
95
|
+
accessibilityRole="button"
|
|
96
|
+
accessibilityLabel={nextAccessibilityLabel}
|
|
97
|
+
accessibilityState={{ disabled: atEnd || !onNext }}
|
|
98
|
+
style={[styles.navButton, (atEnd || !onNext) && styles.navDisabled]}
|
|
99
|
+
>
|
|
100
|
+
<View style={styles.chevronRight}>
|
|
101
|
+
<ChevronLeftIcon size={ICON_SIZE} color={colors.white} strokeWidth={2} />
|
|
102
|
+
</View>
|
|
103
|
+
</Pressable>
|
|
104
|
+
</View>
|
|
105
|
+
);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
const webBlurStyle: ViewStyle =
|
|
109
|
+
Platform.OS === "web"
|
|
110
|
+
? ({
|
|
111
|
+
backdropFilter: "blur(50px)",
|
|
112
|
+
WebkitBackdropFilter: "blur(50px)",
|
|
113
|
+
} as ViewStyle)
|
|
114
|
+
: {};
|
|
115
|
+
|
|
116
|
+
const styles = StyleSheet.create({
|
|
117
|
+
root: {
|
|
118
|
+
width: WIDTH,
|
|
119
|
+
height: HEIGHT,
|
|
120
|
+
flexDirection: "row",
|
|
121
|
+
alignItems: "center",
|
|
122
|
+
justifyContent: "center",
|
|
123
|
+
gap: 12,
|
|
124
|
+
padding: 12,
|
|
125
|
+
borderRadius: 77,
|
|
126
|
+
backgroundColor: colors.whiteAlpha6,
|
|
127
|
+
overflow: "hidden",
|
|
128
|
+
},
|
|
129
|
+
navButton: {
|
|
130
|
+
width: ICON_SIZE,
|
|
131
|
+
height: ICON_SIZE,
|
|
132
|
+
alignItems: "center",
|
|
133
|
+
justifyContent: "center",
|
|
134
|
+
},
|
|
135
|
+
navDisabled: {
|
|
136
|
+
opacity: 0.35,
|
|
137
|
+
},
|
|
138
|
+
chevronRight: {
|
|
139
|
+
transform: [{ scaleX: -1 }],
|
|
140
|
+
},
|
|
141
|
+
label: {
|
|
142
|
+
fontFamily: fonts.sans,
|
|
143
|
+
fontSize: 16,
|
|
144
|
+
fontWeight: "700",
|
|
145
|
+
lineHeight: 16,
|
|
146
|
+
letterSpacing: 0,
|
|
147
|
+
color: colors.white,
|
|
148
|
+
textAlign: "center",
|
|
149
|
+
},
|
|
150
|
+
});
|
package/src/components/index.ts
CHANGED
|
@@ -4,9 +4,27 @@ export type { AvatarProps, AvatarMenuItem } from "./Avatar";
|
|
|
4
4
|
export { AvatarSimple } from "./AvatarSimple";
|
|
5
5
|
export type { AvatarSimpleProps } from "./AvatarSimple";
|
|
6
6
|
|
|
7
|
+
export { AccountHeader } from "./AccountHeader";
|
|
8
|
+
export type { AccountHeaderProps } from "./AccountHeader";
|
|
9
|
+
|
|
7
10
|
export { Badge } from "./Badge";
|
|
8
11
|
export type { BadgeProps, BadgeVariant } from "./Badge";
|
|
9
12
|
|
|
13
|
+
export { StatusBadge } from "./StatusBadge";
|
|
14
|
+
export type { StatusBadgeProps, StatusBadgeTone } from "./StatusBadge";
|
|
15
|
+
|
|
16
|
+
export { PaginationDots } from "./PaginationDots";
|
|
17
|
+
export type { PaginationDotsProps } from "./PaginationDots";
|
|
18
|
+
|
|
19
|
+
export { StepPager } from "./StepPager";
|
|
20
|
+
export type { StepPagerProps } from "./StepPager";
|
|
21
|
+
|
|
22
|
+
export { InfoTile } from "./InfoTile";
|
|
23
|
+
export type { InfoTileProps } from "./InfoTile";
|
|
24
|
+
|
|
25
|
+
export { StepList } from "./StepList";
|
|
26
|
+
export type { StepListProps } from "./StepList";
|
|
27
|
+
|
|
10
28
|
export { Counter } from "./Counter";
|
|
11
29
|
export type { CounterProps } from "./Counter";
|
|
12
30
|
|
|
@@ -37,6 +55,9 @@ export type {
|
|
|
37
55
|
DateRange,
|
|
38
56
|
} from "./DatePicker";
|
|
39
57
|
|
|
58
|
+
export { FloatingActionButton } from "./FloatingActionButton";
|
|
59
|
+
export type { FloatingActionButtonProps } from "./FloatingActionButton";
|
|
60
|
+
|
|
40
61
|
export { Input } from "./Input";
|
|
41
62
|
export type { InputIcon, InputProps, InputSize } from "./Input";
|
|
42
63
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import Svg, { Path } from "react-native-svg";
|
|
2
|
+
import type { IconProps } from "../types";
|
|
3
|
+
import { ALERT_TRIANGLE_PATH } from "./alertTrianglePath";
|
|
4
|
+
|
|
5
|
+
export function AlertTriangleIcon({ size = 16, color = "#E38E5E", strokeWidth = 1.5 }: IconProps) {
|
|
6
|
+
return (
|
|
7
|
+
<Svg width={size} height={size} viewBox="0 0 16 16" fill="none">
|
|
8
|
+
<Path
|
|
9
|
+
d={ALERT_TRIANGLE_PATH}
|
|
10
|
+
stroke={color}
|
|
11
|
+
strokeWidth={strokeWidth}
|
|
12
|
+
strokeLinecap="round"
|
|
13
|
+
strokeLinejoin="round"
|
|
14
|
+
/>
|
|
15
|
+
</Svg>
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export { ALERT_TRIANGLE_PATH } from "./alertTrianglePath";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { IconProps } from "../types";
|
|
2
|
+
import { ALERT_TRIANGLE_PATH } from "./alertTrianglePath";
|
|
3
|
+
|
|
4
|
+
export function AlertTriangleIcon({ size = 16, color = "#E38E5E", strokeWidth = 1.5 }: IconProps) {
|
|
5
|
+
return (
|
|
6
|
+
<svg width={size} height={size} viewBox="0 0 16 16" fill="none" aria-hidden>
|
|
7
|
+
<path
|
|
8
|
+
d={ALERT_TRIANGLE_PATH}
|
|
9
|
+
stroke={color}
|
|
10
|
+
strokeWidth={strokeWidth}
|
|
11
|
+
strokeLinecap="round"
|
|
12
|
+
strokeLinejoin="round"
|
|
13
|
+
/>
|
|
14
|
+
</svg>
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export { ALERT_TRIANGLE_PATH } from "./alertTrianglePath";
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
/** Alert triangle — viewBox 0 0 16 16. */
|
|
2
|
+
export const ALERT_TRIANGLE_PATH =
|
|
3
|
+
"M8.00049 6.00015V8.66682M8.00049 11.3335H8.00715M7.07737 2.59464L1.59411 12.0657C1.28997 12.591 1.1379 12.8537 1.16038 13.0693C1.17998 13.2573 1.2785 13.4282 1.4314 13.5394C1.60671 13.6668 1.91022 13.6668 2.51723 13.6668H13.4837C14.0908 13.6668 14.3943 13.6668 14.5696 13.5394C14.7225 13.4282 14.821 13.2573 14.8406 13.0693C14.8631 12.8537 14.711 12.591 14.4069 12.0657L8.92361 2.59463C8.62056 2.07119 8.46904 1.80947 8.27135 1.72157C8.09892 1.64489 7.90206 1.64489 7.72962 1.72157C7.53194 1.80947 7.38041 2.07119 7.07737 2.59464Z";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { AlertTriangleIcon, ALERT_TRIANGLE_PATH } from "./AlertTriangleIcon";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import Svg, { Path } from "react-native-svg";
|
|
2
|
+
import { colors } from "../../theme";
|
|
3
|
+
import type { IconProps } from "../types";
|
|
4
|
+
import { BAN_PATH } from "./banPath";
|
|
5
|
+
|
|
6
|
+
export { BAN_PATH } from "./banPath";
|
|
7
|
+
|
|
8
|
+
/** Filled prohibition / deactivated mark (28×28 viewBox). */
|
|
9
|
+
export function BanIcon({ size = 28, color = colors.primary }: IconProps) {
|
|
10
|
+
return (
|
|
11
|
+
<Svg width={size} height={size} viewBox="0 0 28 28" fill="none">
|
|
12
|
+
<Path d={BAN_PATH} fill={color} />
|
|
13
|
+
</Svg>
|
|
14
|
+
);
|
|
15
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export const BAN_PATH =
|
|
2
|
+
"M14.0007 2.33301C11.6932 2.33301 9.43758 3.01725 7.519 4.2992C5.60043 5.58115 4.10508 7.40323 3.22206 9.53503C2.33904 11.6668 2.108 14.0126 2.55816 16.2757C3.00832 18.5388 4.11946 20.6176 5.75108 22.2493C7.38269 23.8809 9.46149 24.992 11.7246 25.4422C13.9877 25.8923 16.3335 25.6613 18.4653 24.7783C20.5971 23.8952 22.4192 22.3999 23.7011 20.4813C24.9831 18.5628 25.6673 16.3071 25.6673 13.9997C25.6673 12.4676 25.3656 10.9505 24.7793 9.53503C24.1929 8.11957 23.3336 6.83345 22.2502 5.7501C21.1669 4.66675 19.8808 3.80738 18.4653 3.22108C17.0498 2.63478 15.5327 2.33301 14.0007 2.33301ZM14.0007 23.333C11.5253 23.333 9.15133 22.3497 7.40099 20.5993C5.65065 18.849 4.66732 16.475 4.66732 13.9997C4.66475 11.9269 5.35917 9.91348 6.63899 8.28301L19.7173 21.3613C18.0869 22.6412 16.0734 23.3356 14.0007 23.333ZM21.3623 19.7163L8.28399 6.63801C9.91446 5.35819 11.9279 4.66376 14.0007 4.66634C16.476 4.66634 18.85 5.64967 20.6003 7.40001C22.3507 9.15035 23.334 11.5243 23.334 13.9997C23.3366 16.0724 22.6421 18.0859 21.3623 19.7163Z";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { BanIcon, BAN_PATH } from "./BanIcon";
|
|
@@ -5,9 +5,9 @@ import type { IconProps } from "../types";
|
|
|
5
5
|
|
|
6
6
|
export { BELL_PATH } from "./bellPath";
|
|
7
7
|
|
|
8
|
-
export function BellIcon({ size =
|
|
8
|
+
export function BellIcon({ size = 16, color = colors.white, strokeWidth = 1.5 }: IconProps) {
|
|
9
9
|
return (
|
|
10
|
-
<Svg width={size} height={size} viewBox="0 0
|
|
10
|
+
<Svg width={size} height={size} viewBox="0 0 16 16" fill="none">
|
|
11
11
|
<Path
|
|
12
12
|
d={BELL_PATH}
|
|
13
13
|
stroke={color}
|
|
@@ -2,12 +2,12 @@ import { BELL_PATH } from "./bellPath";
|
|
|
2
2
|
import { colors } from "../../theme";
|
|
3
3
|
import type { IconProps } from "../types";
|
|
4
4
|
|
|
5
|
-
export function BellIcon({ size =
|
|
5
|
+
export function BellIcon({ size = 16, color = colors.white, strokeWidth = 1.5 }: IconProps) {
|
|
6
6
|
return (
|
|
7
7
|
<svg
|
|
8
8
|
width={size}
|
|
9
9
|
height={size}
|
|
10
|
-
viewBox="0 0
|
|
10
|
+
viewBox="0 0 16 16"
|
|
11
11
|
fill="none"
|
|
12
12
|
xmlns="http://www.w3.org/2000/svg"
|
|
13
13
|
aria-hidden
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export const BELL_PATH =
|
|
2
|
-
"
|
|
2
|
+
"M6.23597 14C6.70606 14.4149 7.32355 14.6667 7.99985 14.6667C8.67615 14.6667 9.29364 14.4149 9.76373 14M11.9998 5.33337C11.9998 4.27251 11.5784 3.25509 10.8283 2.50495C10.0781 1.7548 9.06072 1.33337 7.99985 1.33337C6.93898 1.33337 5.92157 1.7548 5.17142 2.50495C4.42128 3.25509 3.99985 4.27251 3.99985 5.33337C3.99985 7.3935 3.48016 8.80401 2.89963 9.73698C2.40993 10.524 2.16509 10.9174 2.17407 11.0272C2.18401 11.1488 2.20976 11.1951 2.3077 11.2678C2.39616 11.3334 2.79491 11.3334 3.59242 11.3334H12.4073C13.2048 11.3334 13.6035 11.3334 13.692 11.2678C13.7899 11.1951 13.8157 11.1488 13.8256 11.0272C13.8346 10.9174 13.5898 10.524 13.1001 9.73698C12.5195 8.80401 11.9998 7.3935 11.9998 5.33337Z";
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
CHECK_SUCCESS_PATH,
|
|
7
7
|
CLOCK_FILLED_PATH,
|
|
8
8
|
COPY_PATH,
|
|
9
|
+
DOWNLOAD_PATH,
|
|
9
10
|
QR_CODE_PATH,
|
|
10
11
|
SHARE_PATH,
|
|
11
12
|
TOOLTIP_ARROW_PATH,
|
|
@@ -26,6 +27,20 @@ export function ShareIcon({ size = 20, color = colors.white, strokeWidth = 2 }:
|
|
|
26
27
|
);
|
|
27
28
|
}
|
|
28
29
|
|
|
30
|
+
export function DownloadIcon({ size = 24, color = colors.white, strokeWidth = 2 }: IconProps) {
|
|
31
|
+
return (
|
|
32
|
+
<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
33
|
+
<Path
|
|
34
|
+
d={DOWNLOAD_PATH}
|
|
35
|
+
stroke={color}
|
|
36
|
+
strokeWidth={strokeWidth}
|
|
37
|
+
strokeLinecap="round"
|
|
38
|
+
strokeLinejoin="round"
|
|
39
|
+
/>
|
|
40
|
+
</Svg>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
29
44
|
export function AreaExpandIcon({ size = 24, color = colors.white, strokeWidth = 2 }: IconProps) {
|
|
30
45
|
return (
|
|
31
46
|
<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
CHECK_SUCCESS_PATH,
|
|
6
6
|
CLOCK_FILLED_PATH,
|
|
7
7
|
COPY_PATH,
|
|
8
|
+
DOWNLOAD_PATH,
|
|
8
9
|
QR_CODE_PATH,
|
|
9
10
|
SHARE_PATH,
|
|
10
11
|
TOOLTIP_ARROW_PATH,
|
|
@@ -25,6 +26,20 @@ export function ShareIcon({ size = 20, color = colors.white, strokeWidth = 2 }:
|
|
|
25
26
|
);
|
|
26
27
|
}
|
|
27
28
|
|
|
29
|
+
export function DownloadIcon({ size = 24, color = colors.white, strokeWidth = 2 }: IconProps) {
|
|
30
|
+
return (
|
|
31
|
+
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" aria-hidden>
|
|
32
|
+
<path
|
|
33
|
+
d={DOWNLOAD_PATH}
|
|
34
|
+
stroke={color}
|
|
35
|
+
strokeWidth={strokeWidth}
|
|
36
|
+
strokeLinecap="round"
|
|
37
|
+
strokeLinejoin="round"
|
|
38
|
+
/>
|
|
39
|
+
</svg>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
28
43
|
export function AreaExpandIcon({ size = 24, color = colors.white, strokeWidth = 2 }: IconProps) {
|
|
29
44
|
return (
|
|
30
45
|
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" aria-hidden>
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
export const SHARE_PATH =
|
|
2
2
|
"M7.5 11.25L12.5 13.75M12.5 6.25L7.5 8.75M15 17.5C13.6193 17.5 12.5 16.3807 12.5 15C12.5 13.6193 13.6193 12.5 15 12.5C16.3807 12.5 17.5 13.6193 17.5 15C17.5 16.3807 16.3807 17.5 15 17.5ZM5 12.5C3.61929 12.5 2.5 11.3807 2.5 10C2.5 8.61929 3.61929 7.5 5 7.5C6.38071 7.5 7.5 8.61929 7.5 10C7.5 11.3807 6.38071 12.5 5 12.5ZM15 7.5C13.6193 7.5 12.5 6.38071 12.5 5C12.5 3.61929 13.6193 2.5 15 2.5C16.3807 2.5 17.5 3.61929 17.5 5C17.5 6.38071 16.3807 7.5 15 7.5Z";
|
|
3
3
|
|
|
4
|
+
/** Download — viewBox 0 0 24 24. */
|
|
5
|
+
export const DOWNLOAD_PATH = "M21 21H3M6 11L12 17L18 11M12 17V3";
|
|
6
|
+
|
|
4
7
|
export const AREA_EXPAND_PATHS = [
|
|
5
8
|
"M15 3H21V9",
|
|
6
9
|
"M9 21H3V15",
|