@homefile/components-v2 2.15.2 → 2.16.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.
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
import { WeatherWidgetI } from '../../../interfaces';
|
|
2
|
-
export declare const WeatherWidget: ({ current, details, forecast, header, }: WeatherWidgetI
|
|
2
|
+
export declare const WeatherWidget: ({ current, details, forecast, header, loading, }: WeatherWidgetI & {
|
|
3
|
+
loading?: boolean;
|
|
4
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Stack, Flex, Text, HStack, VStack, Divider,
|
|
2
|
+
import { Stack, Flex, Box, Text, HStack, VStack, Divider, } from '@chakra-ui/react';
|
|
3
3
|
import { extractCodeFromUrl } from '../../../utils';
|
|
4
4
|
import { LuSnowflake, LuSun, LuCloudSun, LuCloudy, LuCloud, LuCloudRain, LuCloudLightning, } from 'react-icons/lu';
|
|
5
5
|
import { colors } from '../../../theme/colors';
|
|
6
|
+
import { SkeletonBox } from '../../loaders';
|
|
6
7
|
const weatherIconMap = {
|
|
7
8
|
skc: LuSun,
|
|
8
9
|
few: LuCloudSun,
|
|
@@ -13,12 +14,15 @@ const weatherIconMap = {
|
|
|
13
14
|
tsra: LuCloudLightning,
|
|
14
15
|
snow: LuSnowflake,
|
|
15
16
|
};
|
|
16
|
-
export const WeatherWidget = ({ current, details, forecast, header, }) => {
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
export const WeatherWidget = ({ current, details, forecast, header, loading = false, }) => {
|
|
18
|
+
if (loading) {
|
|
19
|
+
return (_jsxs(Stack, { spacing: "base", p: "4", zIndex: "2", children: [_jsxs(Flex, { justify: "space-between", align: "center", children: [_jsx(SkeletonBox, { height: "12px", borderRadius: "md", width: "30%" }), _jsx(SkeletonBox, { height: "12px", borderRadius: "md", width: "30%" })] }), _jsxs(Stack, { align: "end", children: [_jsxs(Flex, { justify: "end", align: "start", gap: "base", mt: "4", children: [_jsx(SkeletonBox, { height: "50px", borderRadius: "md", width: "50px" }), _jsx(SkeletonBox, { height: "30px", width: "30px", borderRadius: "full" })] }), _jsx(SkeletonBox, { height: "12px", borderRadius: "md", width: "20%" })] }), _jsx(Divider, { borderColor: "gray.2", borderStyle: "dashed" }), _jsxs(Flex, { justify: "space-between", mt: "4", children: [_jsxs(Stack, { children: [_jsx(SkeletonBox, { height: "8px", borderRadius: "md", width: "70px" }), _jsx(SkeletonBox, { height: "8px", borderRadius: "md", width: "70px" })] }), _jsxs(Stack, { align: "end", children: [_jsx(SkeletonBox, { height: "8px", borderRadius: "md", width: "70px" }), _jsx(SkeletonBox, { height: "8px", borderRadius: "md", width: "70px" })] })] }), _jsx(Flex, { justify: "space-between", mt: "4", gap: "1", children: Array(5)
|
|
20
|
+
.fill(0)
|
|
21
|
+
.map((_, idx) => (_jsxs(VStack, { gap: "1", width: "46px", border: "1px solid", borderColor: "gray.2", py: "2", px: "1", children: [_jsx(SkeletonBox, { height: "6px", borderRadius: "md", width: "60%" }), _jsx(Divider, { borderColor: "gray.2", borderStyle: "solid", my: "0.5" }), _jsx(SkeletonBox, { height: "18px", width: "18px", borderRadius: "full" }), _jsx(SkeletonBox, { height: "8px", borderRadius: "md", width: "70%" }), _jsx(SkeletonBox, { height: "6px", borderRadius: "md", width: "70%" })] }, idx))) })] }));
|
|
22
|
+
}
|
|
23
|
+
return (_jsxs(Stack, { spacing: "base", p: "4", zIndex: "2", children: [header && (_jsxs(Flex, { justify: "space-between", align: "center", children: [header.date && (_jsx(Text, { fontSize: "sm", fontFamily: "secondary", textTransform: "uppercase", children: header.date })), header.location && (_jsx(Text, { fontSize: "sm", fontFamily: "secondary", textTransform: "uppercase", children: header.location }))] })), current && (_jsxs(Stack, { spacing: "0", align: "end", children: [_jsxs(HStack, { align: "start", spacing: "2", children: [current.temp != null && (_jsxs(Text, { fontSize: "6xl", fontWeight: "medium", lineHeight: 1, color: "gray.4", children: [current.temp, "\u00B0"] })), getWeatherIcon(current.icon, 50)] }), _jsxs(Text, { fontSize: "md", children: [_jsxs(Box, { as: "span", color: "gray.2", children: ["H", ' '] }), current.high, "\u00B0", ' ', _jsxs(Box, { as: "span", color: "gray.2", children: ["L", ' '] }), current.low, "\u00B0"] })] })), _jsx(Divider, { borderColor: "gray.2", borderStyle: "dashed" }), details && (_jsxs(Flex, { justify: "space-between", children: [_jsxs(VStack, { spacing: "0", align: "start", children: [_jsx(WeatherDetailText, { children: "Precipitation" }), details.humidity != null && (_jsx(WeatherDetailText, { children: "Humidity" })), _jsx(WeatherDetailText, { children: "Wind" })] }), _jsxs(VStack, { spacing: "0", align: "start", children: [details.precipitation != null && (_jsxs(WeatherDetailText, { children: [details.precipitation, "%"] })), details.humidity != null && (_jsxs(WeatherDetailText, { children: [details.humidity, "%"] })), details.wind && (_jsx(WeatherDetailText, { children: details.wind }))] })] })), forecast && (_jsx(Flex, { justify: "space-between", gap: "1", children: forecast.map((f) => (_jsxs(VStack, { spacing: "0", border: "1px solid", borderColor: "gray.2", borderRadius: "sm", children: [_jsx(Text, { fontFamily: "secondary", textTransform: "uppercase", fontSize: "xxs", color: "gray.2", children: f.day }), _jsx(Divider, { borderColor: "gray.2" }), _jsxs(Stack, { spacing: "0", py: "1", px: "2", align: "center", children: [getWeatherIcon(f.icon, 16, colors.gray[3]), _jsxs(Text, { fontSize: "sm", fontWeight: "medium", mb: "-1", children: [f.high, "\u00B0"] }), _jsxs(WeatherDetailText, { children: ["L ", f.low, "\u00B0"] })] })] }, f.day))) }))] }));
|
|
21
24
|
};
|
|
25
|
+
const WeatherDetailText = ({ children }) => (_jsx(Text, { fontFamily: "secondary", textTransform: "uppercase", fontSize: "xs", lineHeight: "1.2", children: children }));
|
|
22
26
|
const getWeatherIcon = (iconUrl, size = 48, color = colors.gray[4]) => {
|
|
23
27
|
if (!iconUrl)
|
|
24
28
|
return null;
|
package/package.json
CHANGED
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
HStack,
|
|
9
9
|
VStack,
|
|
10
10
|
Divider,
|
|
11
|
-
chakra,
|
|
12
11
|
} from '@chakra-ui/react'
|
|
13
12
|
import { extractCodeFromUrl } from '@/utils'
|
|
14
13
|
import {
|
|
@@ -21,6 +20,7 @@ import {
|
|
|
21
20
|
LuCloudLightning,
|
|
22
21
|
} from 'react-icons/lu'
|
|
23
22
|
import { colors } from '@/theme/colors'
|
|
23
|
+
import { SkeletonBox } from '@/components/loaders'
|
|
24
24
|
|
|
25
25
|
const weatherIconMap: Record<
|
|
26
26
|
string,
|
|
@@ -41,12 +41,69 @@ export const WeatherWidget = ({
|
|
|
41
41
|
details,
|
|
42
42
|
forecast,
|
|
43
43
|
header,
|
|
44
|
-
|
|
44
|
+
loading = false,
|
|
45
|
+
}: WeatherWidgetI & { loading?: boolean }) => {
|
|
46
|
+
if (loading) {
|
|
47
|
+
return (
|
|
48
|
+
<Stack spacing="base" p="4" zIndex="2">
|
|
49
|
+
{/* Header skeleton */}
|
|
50
|
+
<Flex justify="space-between" align="center">
|
|
51
|
+
<SkeletonBox height="12px" borderRadius="md" width="30%" />
|
|
52
|
+
<SkeletonBox height="12px" borderRadius="md" width="30%" />
|
|
53
|
+
</Flex>
|
|
54
|
+
{/* Current temp skeleton */}
|
|
55
|
+
<Stack align="end">
|
|
56
|
+
<Flex justify="end" align="start" gap="base" mt="4">
|
|
57
|
+
<SkeletonBox height="50px" borderRadius="md" width="50px" />
|
|
58
|
+
<SkeletonBox height="30px" width="30px" borderRadius="full" />
|
|
59
|
+
</Flex>
|
|
60
|
+
<SkeletonBox height="12px" borderRadius="md" width="20%" />
|
|
61
|
+
</Stack>
|
|
62
|
+
|
|
63
|
+
<Divider borderColor="gray.2" borderStyle="dashed" />
|
|
64
|
+
{/* Details skeleton */}
|
|
65
|
+
<Flex justify="space-between" mt="4">
|
|
66
|
+
<Stack>
|
|
67
|
+
<SkeletonBox height="8px" borderRadius="md" width="70px" />
|
|
68
|
+
<SkeletonBox height="8px" borderRadius="md" width="70px" />
|
|
69
|
+
</Stack>
|
|
70
|
+
<Stack align="end">
|
|
71
|
+
<SkeletonBox height="8px" borderRadius="md" width="70px" />
|
|
72
|
+
<SkeletonBox height="8px" borderRadius="md" width="70px" />
|
|
73
|
+
</Stack>
|
|
74
|
+
</Flex>
|
|
75
|
+
{/* Forecast skeleton */}
|
|
76
|
+
<Flex justify="space-between" mt="4" gap="1">
|
|
77
|
+
{Array(5)
|
|
78
|
+
.fill(0)
|
|
79
|
+
.map((_, idx) => (
|
|
80
|
+
<VStack
|
|
81
|
+
key={idx}
|
|
82
|
+
gap="1"
|
|
83
|
+
width="46px"
|
|
84
|
+
border="1px solid"
|
|
85
|
+
borderColor="gray.2"
|
|
86
|
+
py="2"
|
|
87
|
+
px="1"
|
|
88
|
+
>
|
|
89
|
+
<SkeletonBox height="6px" borderRadius="md" width="60%" />
|
|
90
|
+
<Divider borderColor="gray.2" borderStyle="solid" my="0.5" />
|
|
91
|
+
<SkeletonBox height="18px" width="18px" borderRadius="full" />
|
|
92
|
+
<SkeletonBox height="8px" borderRadius="md" width="70%" />
|
|
93
|
+
<SkeletonBox height="6px" borderRadius="md" width="70%" />
|
|
94
|
+
</VStack>
|
|
95
|
+
))}
|
|
96
|
+
</Flex>
|
|
97
|
+
</Stack>
|
|
98
|
+
)
|
|
99
|
+
}
|
|
100
|
+
|
|
45
101
|
return (
|
|
46
102
|
<Stack spacing="base" p="4" zIndex="2">
|
|
103
|
+
{/* Header */}
|
|
47
104
|
{header && (
|
|
48
105
|
<Flex justify="space-between" align="center">
|
|
49
|
-
{header
|
|
106
|
+
{header.date && (
|
|
50
107
|
<Text
|
|
51
108
|
fontSize="sm"
|
|
52
109
|
fontFamily="secondary"
|
|
@@ -55,7 +112,7 @@ export const WeatherWidget = ({
|
|
|
55
112
|
{header.date}
|
|
56
113
|
</Text>
|
|
57
114
|
)}
|
|
58
|
-
{header
|
|
115
|
+
{header.location && (
|
|
59
116
|
<Text
|
|
60
117
|
fontSize="sm"
|
|
61
118
|
fontFamily="secondary"
|
|
@@ -67,10 +124,11 @@ export const WeatherWidget = ({
|
|
|
67
124
|
</Flex>
|
|
68
125
|
)}
|
|
69
126
|
|
|
127
|
+
{/* Current Temperature */}
|
|
70
128
|
{current && (
|
|
71
129
|
<Stack spacing="0" align="end">
|
|
72
130
|
<HStack align="start" spacing="2">
|
|
73
|
-
{current
|
|
131
|
+
{current.temp != null && (
|
|
74
132
|
<Text
|
|
75
133
|
fontSize="6xl"
|
|
76
134
|
fontWeight="medium"
|
|
@@ -83,41 +141,48 @@ export const WeatherWidget = ({
|
|
|
83
141
|
{getWeatherIcon(current.icon, 50)}
|
|
84
142
|
</HStack>
|
|
85
143
|
<Text fontSize="md">
|
|
86
|
-
<
|
|
87
|
-
|
|
88
|
-
|
|
144
|
+
<Box as="span" color="gray.2">
|
|
145
|
+
H{' '}
|
|
146
|
+
</Box>
|
|
147
|
+
{current.high}°{' '}
|
|
148
|
+
<Box as="span" color="gray.2">
|
|
149
|
+
L{' '}
|
|
150
|
+
</Box>
|
|
151
|
+
{current.low}°
|
|
89
152
|
</Text>
|
|
90
153
|
</Stack>
|
|
91
154
|
)}
|
|
92
155
|
|
|
93
156
|
<Divider borderColor="gray.2" borderStyle="dashed" />
|
|
94
157
|
|
|
158
|
+
{/* Details */}
|
|
95
159
|
{details && (
|
|
96
160
|
<Flex justify="space-between">
|
|
97
161
|
<VStack spacing="0" align="start">
|
|
98
162
|
<WeatherDetailText>Precipitation</WeatherDetailText>
|
|
99
|
-
{details
|
|
163
|
+
{details.humidity != null && (
|
|
100
164
|
<WeatherDetailText>Humidity</WeatherDetailText>
|
|
101
165
|
)}
|
|
102
166
|
<WeatherDetailText>Wind</WeatherDetailText>
|
|
103
167
|
</VStack>
|
|
104
168
|
<VStack spacing="0" align="start">
|
|
105
|
-
{details
|
|
169
|
+
{details.precipitation != null && (
|
|
106
170
|
<WeatherDetailText>{details.precipitation}%</WeatherDetailText>
|
|
107
171
|
)}
|
|
108
|
-
{details
|
|
172
|
+
{details.humidity != null && (
|
|
109
173
|
<WeatherDetailText>{details.humidity}%</WeatherDetailText>
|
|
110
174
|
)}
|
|
111
|
-
{details
|
|
175
|
+
{details.wind && (
|
|
112
176
|
<WeatherDetailText>{details.wind}</WeatherDetailText>
|
|
113
177
|
)}
|
|
114
178
|
</VStack>
|
|
115
179
|
</Flex>
|
|
116
180
|
)}
|
|
117
181
|
|
|
182
|
+
{/* 5-Day Forecast */}
|
|
118
183
|
{forecast && (
|
|
119
184
|
<Flex justify="space-between" gap="1">
|
|
120
|
-
{forecast
|
|
185
|
+
{forecast.map((f) => (
|
|
121
186
|
<VStack
|
|
122
187
|
key={f.day}
|
|
123
188
|
spacing="0"
|
|
@@ -149,18 +214,16 @@ export const WeatherWidget = ({
|
|
|
149
214
|
)
|
|
150
215
|
}
|
|
151
216
|
|
|
152
|
-
const WeatherDetailText = ({ children }: PropsWithChildren) =>
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
)
|
|
163
|
-
}
|
|
217
|
+
const WeatherDetailText = ({ children }: PropsWithChildren) => (
|
|
218
|
+
<Text
|
|
219
|
+
fontFamily="secondary"
|
|
220
|
+
textTransform="uppercase"
|
|
221
|
+
fontSize="xs"
|
|
222
|
+
lineHeight="1.2"
|
|
223
|
+
>
|
|
224
|
+
{children}
|
|
225
|
+
</Text>
|
|
226
|
+
)
|
|
164
227
|
|
|
165
228
|
const getWeatherIcon = (iconUrl: string, size = 48, color = colors.gray[4]) => {
|
|
166
229
|
if (!iconUrl) return null
|