@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) => import("react/jsx-runtime").JSX.Element;
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, chakra, } from '@chakra-ui/react';
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
- return (_jsxs(Stack, { spacing: "base", p: "4", zIndex: "2", children: [header && (_jsxs(Flex, { justify: "space-between", align: "center", children: [(header === null || header === void 0 ? void 0 : header.date) && (_jsx(Text, { fontSize: "sm", fontFamily: "secondary", textTransform: "uppercase", children: header.date })), (header === null || header === void 0 ? void 0 : 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 === null || current === void 0 ? void 0 : current.temp) && (_jsxs(Text, { fontSize: "6xl", fontWeight: "medium", lineHeight: 1, color: "gray.4", children: [current.temp, "\u00B0"] })), getWeatherIcon(current.icon, 50)] }), _jsxs(Text, { fontSize: "md", children: [_jsx(chakra.span, { color: "gray.2", children: "H " }), " ", current === null || current === void 0 ? void 0 : current.high, "\u00B0 \u00A0", _jsx(chakra.span, { color: "gray.2", children: "L " }), current === null || current === void 0 ? void 0 : 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 === null || details === void 0 ? void 0 : details.humidity) && (_jsx(WeatherDetailText, { children: "Humidity" })), _jsx(WeatherDetailText, { children: "Wind" })] }), _jsxs(VStack, { spacing: "0", align: "start", children: [(details === null || details === void 0 ? void 0 : details.precipitation) && (_jsxs(WeatherDetailText, { children: [details.precipitation, "%"] })), (details === null || details === void 0 ? void 0 : details.humidity) && (_jsxs(WeatherDetailText, { children: [details.humidity, "%"] })), (details === null || details === void 0 ? void 0 : details.wind) && (_jsx(WeatherDetailText, { children: details.wind }))] })] })), forecast && (_jsx(Flex, { justify: "space-between", gap: "1", children: forecast === null || forecast === void 0 ? void 0 : 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))) }))] }));
18
- };
19
- const WeatherDetailText = ({ children }) => {
20
- return (_jsx(Text, { fontFamily: "secondary", textTransform: "uppercase", fontSize: "xs", lineHeight: "1.2", children: children }));
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@homefile/components-v2",
3
- "version": "2.15.2",
3
+ "version": "2.16.0",
4
4
  "author": "Homefile",
5
5
  "license": "UNLICENSED",
6
6
  "typings": "dist/index.d.ts",
@@ -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
- }: WeatherWidgetI) => {
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?.date && (
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?.location && (
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?.temp && (
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
- <chakra.span color="gray.2">H </chakra.span> {current?.high}° &nbsp;
87
- <chakra.span color="gray.2">L </chakra.span>
88
- {current?.low}°
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?.humidity && (
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?.precipitation && (
169
+ {details.precipitation != null && (
106
170
  <WeatherDetailText>{details.precipitation}%</WeatherDetailText>
107
171
  )}
108
- {details?.humidity && (
172
+ {details.humidity != null && (
109
173
  <WeatherDetailText>{details.humidity}%</WeatherDetailText>
110
174
  )}
111
- {details?.wind && (
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?.map((f) => (
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
- return (
154
- <Text
155
- fontFamily="secondary"
156
- textTransform="uppercase"
157
- fontSize="xs"
158
- lineHeight="1.2"
159
- >
160
- {children}
161
- </Text>
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