@almighty-shogun/utils 1.0.1
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 +31 -0
- package/dist/containsRoutePrefix.d.ts +2 -0
- package/dist/containsRoutePrefix.d.ts.map +1 -0
- package/dist/containsRoutePrefix.js +4 -0
- package/dist/disableZoom.d.ts +2 -0
- package/dist/disableZoom.d.ts.map +1 -0
- package/dist/disableZoom.js +23 -0
- package/dist/formatCelsius.d.ts +2 -0
- package/dist/formatCelsius.d.ts.map +1 -0
- package/dist/formatCelsius.js +3 -0
- package/dist/formatCurrency.d.ts +2 -0
- package/dist/formatCurrency.d.ts.map +1 -0
- package/dist/formatCurrency.js +9 -0
- package/dist/formatDate.d.ts +3 -0
- package/dist/formatDate.d.ts.map +1 -0
- package/dist/formatDate.js +7 -0
- package/dist/formatDateTime.d.ts +3 -0
- package/dist/formatDateTime.d.ts.map +1 -0
- package/dist/formatDateTime.js +7 -0
- package/dist/formatFullDate.d.ts +3 -0
- package/dist/formatFullDate.d.ts.map +1 -0
- package/dist/formatFullDate.js +7 -0
- package/dist/formatMonth.d.ts +3 -0
- package/dist/formatMonth.d.ts.map +1 -0
- package/dist/formatMonth.js +5 -0
- package/dist/formatNumber.d.ts +2 -0
- package/dist/formatNumber.d.ts.map +1 -0
- package/dist/formatNumber.js +6 -0
- package/dist/formatPercentage.d.ts +2 -0
- package/dist/formatPercentage.d.ts.map +1 -0
- package/dist/formatPercentage.js +7 -0
- package/dist/formatTime.d.ts +3 -0
- package/dist/formatTime.d.ts.map +1 -0
- package/dist/formatTime.js +6 -0
- package/dist/formatWeekday.d.ts +3 -0
- package/dist/formatWeekday.d.ts.map +1 -0
- package/dist/formatWeekday.js +5 -0
- package/dist/getCurrentRouteName.d.ts +2 -0
- package/dist/getCurrentRouteName.d.ts.map +1 -0
- package/dist/getCurrentRouteName.js +5 -0
- package/dist/getWeather.d.ts +3 -0
- package/dist/getWeather.d.ts.map +1 -0
- package/dist/getWeather.js +39 -0
- package/dist/hasCurrentRoute.d.ts +2 -0
- package/dist/hasCurrentRoute.d.ts.map +1 -0
- package/dist/hasCurrentRoute.js +4 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/internal/localization.d.ts +16 -0
- package/dist/internal/localization.d.ts.map +1 -0
- package/dist/internal/localization.js +41 -0
- package/dist/internal/types.d.ts +25 -0
- package/dist/internal/types.d.ts.map +1 -0
- package/dist/internal/types.js +1 -0
- package/dist/internal/weather.d.ts +28 -0
- package/dist/internal/weather.d.ts.map +1 -0
- package/dist/internal/weather.js +71 -0
- package/dist/isCurrentRoute.d.ts +2 -0
- package/dist/isCurrentRoute.d.ts.map +1 -0
- package/dist/isCurrentRoute.js +4 -0
- package/dist/scrollToTop.d.ts +2 -0
- package/dist/scrollToTop.d.ts.map +1 -0
- package/dist/scrollToTop.js +3 -0
- package/package.json +43 -0
- package/src/containsRoutePrefix.ts +5 -0
- package/src/disableZoom.ts +34 -0
- package/src/formatCelsius.ts +3 -0
- package/src/formatCurrency.ts +9 -0
- package/src/formatDate.ts +9 -0
- package/src/formatDateTime.ts +9 -0
- package/src/formatFullDate.ts +9 -0
- package/src/formatMonth.ts +7 -0
- package/src/formatNumber.ts +6 -0
- package/src/formatPercentage.ts +7 -0
- package/src/formatTime.ts +8 -0
- package/src/formatWeekday.ts +7 -0
- package/src/getCurrentRouteName.ts +7 -0
- package/src/getWeather.ts +41 -0
- package/src/hasCurrentRoute.ts +5 -0
- package/src/index.ts +19 -0
- package/src/internal/localization.ts +53 -0
- package/src/internal/types.ts +24 -0
- package/src/internal/weather.ts +122 -0
- package/src/isCurrentRoute.ts +5 -0
- package/src/scrollToTop.ts +3 -0
package/README.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Utils
|
|
2
|
+
|
|
3
|
+
A small package that contains common utilities used in all my projects.
|
|
4
|
+
|
|
5
|
+
## 📃 Prerequisites
|
|
6
|
+
- **[Node.js](https://nodejs.org/en/)**: >= v23.11.1
|
|
7
|
+
|
|
8
|
+
## 💻 Installation
|
|
9
|
+
|
|
10
|
+
### Step 1
|
|
11
|
+
Install the package using your package manager of choice.
|
|
12
|
+
```shell
|
|
13
|
+
bun add @almighty-shogun/utils
|
|
14
|
+
yarn add @almighty-shogun/utils
|
|
15
|
+
npm install @almighty-shogun/utils
|
|
16
|
+
pnpm install @almighty-shogun/utils
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Step 2
|
|
20
|
+
Import a utility function from the package and use it.
|
|
21
|
+
```ts
|
|
22
|
+
import { getWeather } from '@almighty-shogun/utils'
|
|
23
|
+
|
|
24
|
+
const weatherData = await getWeather(52.374, 4.8897);
|
|
25
|
+
|
|
26
|
+
console.log(`Current weather in Amsterdam: ${weatherData.current.temperature.current} °C`);
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## 📦 Building
|
|
30
|
+
- Use the command `bun install` in the root directory to install the required dependencies.
|
|
31
|
+
- Run `bun --cwd packages/utils build` to build the package.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"containsRoutePrefix.d.ts","sourceRoot":"","sources":["../src/containsRoutePrefix.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,OAAO,WAAW,MAAM,EAAE,MAAM,GAAG,OAAO,CAEhD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"disableZoom.d.ts","sourceRoot":"","sources":["../src/disableZoom.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,OAAO,cAAc,IAAI,CA+B/B"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { DateTime } from 'luxon';
|
|
2
|
+
export default function () {
|
|
3
|
+
let lastTouchEnd = 0;
|
|
4
|
+
document.addEventListener("touchend", (event) => {
|
|
5
|
+
const now = DateTime.now().toMillis();
|
|
6
|
+
if (now - lastTouchEnd <= 300) {
|
|
7
|
+
event.preventDefault();
|
|
8
|
+
}
|
|
9
|
+
lastTouchEnd = now;
|
|
10
|
+
});
|
|
11
|
+
document.addEventListener("gesturestart", (event) => {
|
|
12
|
+
event.preventDefault();
|
|
13
|
+
}, { passive: false });
|
|
14
|
+
const meta = document.querySelector('meta[name="viewport"]');
|
|
15
|
+
if (meta) {
|
|
16
|
+
meta.setAttribute("content", "width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no");
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const newMeta = document.createElement("meta");
|
|
20
|
+
newMeta.setAttribute("name", "viewport");
|
|
21
|
+
newMeta.setAttribute("content", "width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no");
|
|
22
|
+
document.head.appendChild(newMeta);
|
|
23
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatCelsius.d.ts","sourceRoot":"","sources":["../src/formatCelsius.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,OAAO,WAAW,WAAW,EAAE,MAAM,GAAG,MAAM,CAEpD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatCurrency.d.ts","sourceRoot":"","sources":["../src/formatCurrency.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,OAAO,WAAW,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAQlF"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export default function (value, currency, locale) {
|
|
2
|
+
return new Intl.NumberFormat(locale ?? navigator.language ?? "en", {
|
|
3
|
+
style: "currency",
|
|
4
|
+
currency: currency ?? "EUR",
|
|
5
|
+
currencyDisplay: "symbol",
|
|
6
|
+
maximumFractionDigits: 2,
|
|
7
|
+
minimumFractionDigits: 2
|
|
8
|
+
}).format(value);
|
|
9
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatDate.d.ts","sourceRoot":"","sources":["../src/formatDate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAEhC,MAAM,CAAC,OAAO,WAAW,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAMhE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatDateTime.d.ts","sourceRoot":"","sources":["../src/formatDateTime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAEhC,MAAM,CAAC,OAAO,WAAW,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAMhE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatFullDate.d.ts","sourceRoot":"","sources":["../src/formatFullDate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAEhC,MAAM,CAAC,OAAO,WAAW,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAMhE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatMonth.d.ts","sourceRoot":"","sources":["../src/formatMonth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAEhC,MAAM,CAAC,OAAO,WAAW,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAE,OAAc,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAIxF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatNumber.d.ts","sourceRoot":"","sources":["../src/formatNumber.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,OAAO,WAAW,KAAK,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAU,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAKrF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatPercentage.d.ts","sourceRoot":"","sources":["../src/formatPercentage.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,OAAO,WAAW,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAM/D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatTime.d.ts","sourceRoot":"","sources":["../src/formatTime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAEhC,MAAM,CAAC,OAAO,WAAW,IAAI,EAAE,QAAQ,GAAG,MAAM,CAK/C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatWeekday.d.ts","sourceRoot":"","sources":["../src/formatWeekday.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAEhC,MAAM,CAAC,OAAO,WAAW,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAE,OAAc,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAIxF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getCurrentRouteName.d.ts","sourceRoot":"","sources":["../src/getCurrentRouteName.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,OAAO,cAAc,MAAM,CAIjC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getWeather.d.ts","sourceRoot":"","sources":["../src/getWeather.ts"],"names":[],"mappings":"AACA,OAAO,EAAiC,KAAK,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAEhF,yBAA+B,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAqCpF"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { DateTime } from 'luxon';
|
|
2
|
+
import { callOpenMeteo, getWeatherIcon } from './internal/weather';
|
|
3
|
+
export default async function (latitude, longitude) {
|
|
4
|
+
const { current, daily, hourly } = await callOpenMeteo(latitude, longitude);
|
|
5
|
+
return {
|
|
6
|
+
current: {
|
|
7
|
+
time: current.time,
|
|
8
|
+
temperature: {
|
|
9
|
+
current: current.temperature_2m,
|
|
10
|
+
min: current.temperature_2m_min,
|
|
11
|
+
max: current.temperature_2m_max
|
|
12
|
+
},
|
|
13
|
+
weatherCode: current.weather_code,
|
|
14
|
+
icon: getWeatherIcon(current.weather_code, [current.time, daily.sunrise[0], daily.sunset[0]])
|
|
15
|
+
},
|
|
16
|
+
today: {
|
|
17
|
+
time: daily.time[0],
|
|
18
|
+
temperature: {
|
|
19
|
+
current: current.temperature_2m,
|
|
20
|
+
min: daily.temperature_2m_min[0],
|
|
21
|
+
max: daily.temperature_2m_max[0]
|
|
22
|
+
},
|
|
23
|
+
weatherCode: daily.weather_code[0],
|
|
24
|
+
icon: getWeatherIcon(daily.weather_code[0], [daily.time[0], daily.sunrise[0], daily.sunset[0]]),
|
|
25
|
+
sunrise: daily.sunrise[0],
|
|
26
|
+
sunset: daily.sunset[0]
|
|
27
|
+
},
|
|
28
|
+
hours: hourly.time.map((time, index) => ({
|
|
29
|
+
time,
|
|
30
|
+
temperature: {
|
|
31
|
+
current: hourly.temperature_2m[index],
|
|
32
|
+
min: hourly.temperature_2m_min[index],
|
|
33
|
+
max: hourly.temperature_2m_max[index]
|
|
34
|
+
},
|
|
35
|
+
weatherCode: hourly.weather_code[index],
|
|
36
|
+
icon: getWeatherIcon(hourly.weather_code[index], [time, daily.sunrise[0], daily.sunset[0]])
|
|
37
|
+
})).filter(hour => DateTime.fromISO(hour.time) >= DateTime.fromISO(current.time).startOf("hour"))
|
|
38
|
+
};
|
|
39
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hasCurrentRoute.d.ts","sourceRoot":"","sources":["../src/hasCurrentRoute.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,OAAO,WAAW,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAElD"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export { getCountry, getCountries } from './internal/localization';
|
|
2
|
+
export { default as containsRoutePrefix } from './containsRoutePrefix';
|
|
3
|
+
export { default as disableZoom } from './disableZoom';
|
|
4
|
+
export { default as formatCelsius } from './formatCelsius';
|
|
5
|
+
export { default as formatCurrency } from './formatCurrency';
|
|
6
|
+
export { default as formatDate } from './formatDate';
|
|
7
|
+
export { default as formatDateTime } from './formatDateTime';
|
|
8
|
+
export { default as formatFullDate } from './formatFullDate';
|
|
9
|
+
export { default as formatMonth } from './formatMonth';
|
|
10
|
+
export { default as formatNumber } from './formatNumber';
|
|
11
|
+
export { default as formatPercentage } from './formatPercentage';
|
|
12
|
+
export { default as formatTime } from './formatTime';
|
|
13
|
+
export { default as formatWeekday } from './formatWeekday';
|
|
14
|
+
export { default as getCurrentRouteName } from './getCurrentRouteName';
|
|
15
|
+
export { default as getWeather } from './getWeather';
|
|
16
|
+
export { default as hasCurrentRoute } from './hasCurrentRoute';
|
|
17
|
+
export { default as scrollToTop } from './scrollToTop';
|
|
18
|
+
export { default as isCurrentRoute } from './isCurrentRoute';
|
|
19
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAElE,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AACtE,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,eAAe,CAAA;AACtD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAC1D,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAC5D,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,cAAc,CAAA;AACpD,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAC5D,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAC5D,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,eAAe,CAAA;AACtD,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,gBAAgB,CAAA;AACxD,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAChE,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,cAAc,CAAA;AACpD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAC1D,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AACtE,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,cAAc,CAAA;AACpD,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAC9D,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,eAAe,CAAA;AACtD,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,kBAAkB,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export { getCountry, getCountries } from './internal/localization';
|
|
2
|
+
export { default as containsRoutePrefix } from './containsRoutePrefix';
|
|
3
|
+
export { default as disableZoom } from './disableZoom';
|
|
4
|
+
export { default as formatCelsius } from './formatCelsius';
|
|
5
|
+
export { default as formatCurrency } from './formatCurrency';
|
|
6
|
+
export { default as formatDate } from './formatDate';
|
|
7
|
+
export { default as formatDateTime } from './formatDateTime';
|
|
8
|
+
export { default as formatFullDate } from './formatFullDate';
|
|
9
|
+
export { default as formatMonth } from './formatMonth';
|
|
10
|
+
export { default as formatNumber } from './formatNumber';
|
|
11
|
+
export { default as formatPercentage } from './formatPercentage';
|
|
12
|
+
export { default as formatTime } from './formatTime';
|
|
13
|
+
export { default as formatWeekday } from './formatWeekday';
|
|
14
|
+
export { default as getCurrentRouteName } from './getCurrentRouteName';
|
|
15
|
+
export { default as getWeather } from './getWeather';
|
|
16
|
+
export { default as hasCurrentRoute } from './hasCurrentRoute';
|
|
17
|
+
export { default as scrollToTop } from './scrollToTop';
|
|
18
|
+
export { default as isCurrentRoute } from './isCurrentRoute';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type Country = {
|
|
2
|
+
name: string;
|
|
3
|
+
code: string;
|
|
4
|
+
flag: {
|
|
5
|
+
plain: string;
|
|
6
|
+
rounded: string;
|
|
7
|
+
};
|
|
8
|
+
};
|
|
9
|
+
export type CountryCode = keyof typeof countriesMap;
|
|
10
|
+
export type LocalizationCountries = Record<CountryCode, Country>;
|
|
11
|
+
declare const countriesMap: Record<string, Country>;
|
|
12
|
+
export declare const countries: LocalizationCountries;
|
|
13
|
+
export declare function getCountry(code: CountryCode): Country | null;
|
|
14
|
+
export declare function getCountries(): Country[];
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=localization.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"localization.d.ts","sourceRoot":"","sources":["../../src/internal/localization.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,OAAO,GAAG;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;KAAE,CAAC;CAC7C,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG,MAAM,OAAO,YAAY,CAAC;AACpD,MAAM,MAAM,qBAAqB,GAAG,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;AAEjE,QAAA,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAiCzC,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,qBAA6D,CAAC;AAEtF,wBAAgB,UAAU,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,GAAG,IAAI,CAE5D;AAED,wBAAgB,YAAY,IAAI,OAAO,EAAE,CAExC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const countriesMap = {
|
|
2
|
+
nl: {
|
|
3
|
+
name: "Netherlands",
|
|
4
|
+
code: "nl",
|
|
5
|
+
flag: {
|
|
6
|
+
plain: "images/country-flags/flag-netherlands",
|
|
7
|
+
rounded: "images/country-flags/rounded/flag-netherlands"
|
|
8
|
+
}
|
|
9
|
+
},
|
|
10
|
+
fr: {
|
|
11
|
+
name: "France",
|
|
12
|
+
code: "fr",
|
|
13
|
+
flag: {
|
|
14
|
+
plain: "images/country-flags/flag-france",
|
|
15
|
+
rounded: "images/country-flags/rounded/flag-france"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
de: {
|
|
19
|
+
name: "Germany",
|
|
20
|
+
code: "de",
|
|
21
|
+
flag: {
|
|
22
|
+
plain: "images/country-flags/flag-germany",
|
|
23
|
+
rounded: "images/country-flags/rounded/flag-germany"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
pl: {
|
|
27
|
+
name: "Poland",
|
|
28
|
+
code: "pl",
|
|
29
|
+
flag: {
|
|
30
|
+
plain: "images/country-flags/flag-poland",
|
|
31
|
+
rounded: "images/country-flags/rounded/flag-poland"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
export const countries = countriesMap;
|
|
36
|
+
export function getCountry(code) {
|
|
37
|
+
return countries[code] ?? null;
|
|
38
|
+
}
|
|
39
|
+
export function getCountries() {
|
|
40
|
+
return Object.values(countries);
|
|
41
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export type OpenMeteoResponse = {
|
|
2
|
+
current: {
|
|
3
|
+
time: string;
|
|
4
|
+
weather_code: number;
|
|
5
|
+
temperature_2m: number;
|
|
6
|
+
temperature_2m_min: number;
|
|
7
|
+
temperature_2m_max: number;
|
|
8
|
+
};
|
|
9
|
+
hourly: {
|
|
10
|
+
time: string[];
|
|
11
|
+
weather_code: number[];
|
|
12
|
+
temperature_2m: number[];
|
|
13
|
+
temperature_2m_min: number[];
|
|
14
|
+
temperature_2m_max: number[];
|
|
15
|
+
};
|
|
16
|
+
daily: {
|
|
17
|
+
time: string[];
|
|
18
|
+
sunrise: string[];
|
|
19
|
+
sunset: string[];
|
|
20
|
+
weather_code: number[];
|
|
21
|
+
temperature_2m_min: number[];
|
|
22
|
+
temperature_2m_max: number[];
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/internal/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GAAG;IAC5B,OAAO,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,YAAY,EAAE,MAAM,CAAC;QACrB,cAAc,EAAE,MAAM,CAAC;QACvB,kBAAkB,EAAE,MAAM,CAAC;QAC3B,kBAAkB,EAAE,MAAM,CAAC;KAC9B,CAAC;IACF,MAAM,EAAE;QACJ,IAAI,EAAE,MAAM,EAAE,CAAC;QACf,YAAY,EAAE,MAAM,EAAE,CAAC;QACvB,cAAc,EAAE,MAAM,EAAE,CAAC;QACzB,kBAAkB,EAAE,MAAM,EAAE,CAAC;QAC7B,kBAAkB,EAAE,MAAM,EAAE,CAAC;KAChC,CAAC;IACF,KAAK,EAAE;QACH,IAAI,EAAE,MAAM,EAAE,CAAC;QACf,OAAO,EAAE,MAAM,EAAE,CAAC;QAClB,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,YAAY,EAAE,MAAM,EAAE,CAAC;QACvB,kBAAkB,EAAE,MAAM,EAAE,CAAC;QAC7B,kBAAkB,EAAE,MAAM,EAAE,CAAC;KAChC,CAAA;CACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { OpenMeteoResponse } from './types';
|
|
2
|
+
type WeatherTemperature = {
|
|
3
|
+
current: number;
|
|
4
|
+
min: number;
|
|
5
|
+
max: number;
|
|
6
|
+
};
|
|
7
|
+
export type WeatherItem = {
|
|
8
|
+
time: string;
|
|
9
|
+
temperature: WeatherTemperature;
|
|
10
|
+
weatherCode: number;
|
|
11
|
+
icon: string;
|
|
12
|
+
};
|
|
13
|
+
export type Weather = {
|
|
14
|
+
current: WeatherItem;
|
|
15
|
+
today: WeatherItem & {
|
|
16
|
+
sunrise: string;
|
|
17
|
+
sunset: string;
|
|
18
|
+
};
|
|
19
|
+
hours: WeatherItem[];
|
|
20
|
+
};
|
|
21
|
+
type WeatherIcon = [day: string, night: string];
|
|
22
|
+
export type WeatherCode = keyof typeof weatherCodeMap;
|
|
23
|
+
export type WeatherCodes = Record<WeatherCode, WeatherIcon>;
|
|
24
|
+
declare const weatherCodeMap: Record<string, WeatherIcon>;
|
|
25
|
+
export declare function callOpenMeteo(latitude: number, longitude: number): Promise<OpenMeteoResponse>;
|
|
26
|
+
export declare function getWeatherIcon(code: number, timeStrings: string[]): string;
|
|
27
|
+
export {};
|
|
28
|
+
//# sourceMappingURL=weather.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"weather.d.ts","sourceRoot":"","sources":["../../src/internal/weather.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAEhD,KAAK,kBAAkB,GAAG;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,kBAAkB,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IAClB,OAAO,EAAE,WAAW,CAAC;IACrB,KAAK,EAAE,WAAW,GAAG;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,KAAK,EAAE,WAAW,EAAE,CAAC;CACxB,CAAC;AAEF,KAAK,WAAW,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;AAChD,MAAM,MAAM,WAAW,GAAG,MAAM,OAAO,cAAc,CAAC;AACtD,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;AAE5D,QAAA,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAoD/C,CAAA;AAID,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAcnG;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,MAAM,CAoB1E"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { DateTime } from 'luxon';
|
|
2
|
+
const weatherCodeMap = {
|
|
3
|
+
// 0 = Clear sky
|
|
4
|
+
0: ["images/weather-icons/clear-day", "images/weather-icons/clear-night"],
|
|
5
|
+
// 1 = Mainly clear, 2 = Partly cloudy, 3 = Overcast
|
|
6
|
+
1: ["images/weather-icons/partly-cloudy-day", "images/weather-icons/partly-cloudy-night"],
|
|
7
|
+
2: ["images/weather-icons/partly-cloudy-day", "images/weather-icons/partly-cloudy-night"],
|
|
8
|
+
3: ["images/weather-icons/overcast-day", "images/weather-icons/overcast-night"],
|
|
9
|
+
// 45 = Fog, 48 = Depositing rime fog
|
|
10
|
+
45: ["images/weather-icons/fog-day", "images/weather-icons/fod-night"],
|
|
11
|
+
48: ["images/weather-icons/overcast-day-fog", "images/weather-icons/overcast-night-fog"],
|
|
12
|
+
// 51 = Light drizzle, 53 = Moderate drizzle, 55 = Heavy drizzle
|
|
13
|
+
51: ["images/weather-icons/partly-cloudy-day-drizzle", "images/weather-icons/partly-cloudy-night-drizzle"],
|
|
14
|
+
53: ["images/weather-icons/overcast-day-drizzle", "images/weather-icons/overcast-night-drizzle"],
|
|
15
|
+
55: ["images/weather-icons/extreme-day-drizzle", "images/weather-icons/extreme-night-drizzle"],
|
|
16
|
+
// 56 = Light freezing drizzle, 57 = Heavy freezing drizzle
|
|
17
|
+
56: ["images/weather-icons/partly-cloudy-day-sleet", "images/weather-icons/partly-cloudy-night-sleet"],
|
|
18
|
+
57: ["images/weather-icons/extreme-day-sleet", "images/weather-icons/extreme-night-sleet"],
|
|
19
|
+
// 61 = Light rain, 63 = Moderate rain, 65 = Heavy rain
|
|
20
|
+
61: ["images/weather-icons/partly-cloudy-day-rain", "images/weather-icons/partly-cloudy-night-rain"],
|
|
21
|
+
63: ["images/weather-icons/overcast-day-rain", "images/weather-icons/overcast-night-rain"],
|
|
22
|
+
65: ["images/weather-icons/extreme-day-rain", "images/weather-icons/extreme-night-rain"],
|
|
23
|
+
// 66 = Light freezing rain, 67 = Heavy freezing rain
|
|
24
|
+
66: ["images/weather-icons/partly-cloudy-day-sleet", "images/weather-icons/partly-cloudy-night-sleet"],
|
|
25
|
+
67: ["images/weather-icons/extreme-day-sleet", "images/weather-icons/extreme-night-sleet"],
|
|
26
|
+
// 71 = Light snow, 73 = Moderate snow, 75 = Heavy snow
|
|
27
|
+
71: ["images/weather-icons/partly-cloudy-day-snow", "images/weather-icons/partly-cloudy-night-snow"],
|
|
28
|
+
73: ["images/weather-icons/overcast-day-snow", "images/weather-icons/overcast-night-snow"],
|
|
29
|
+
75: ["images/weather-icons/extreme-day-snow", "images/weather-icons/extreme-night-snow"],
|
|
30
|
+
// 77 Snow grains
|
|
31
|
+
77: ["images/weather-icons/partly-cloudy-day-snow", "images/weather-icons/partly-cloudy-night-snow"],
|
|
32
|
+
// 80 = Light rain showers, 81 = Moderate rain showers, 82 = Heavy rain showers
|
|
33
|
+
80: ["images/weather-icons/partly-cloudy-day-rain", "images/weather-icons/partly-cloudy-night-rain"],
|
|
34
|
+
81: ["images/weather-icons/overcast-day-rain", "images/weather-icons/overcast-night-rain"],
|
|
35
|
+
82: ["images/weather-icons/extreme-day-rain", "images/weather-icons/extreme-night-rain"],
|
|
36
|
+
// 85 = Light snow showers, 86 = Heavy snow showers
|
|
37
|
+
85: ["images/weather-icons/partly-cloudy-day-snow", "images/weather-icons/partly-cloudy-night-snow"],
|
|
38
|
+
86: ["images/weather-icons/extreme-day-snow", "images/weather-icons/extreme-night-snow"],
|
|
39
|
+
// 95 = Light and moderate thunderstorms, 96 = Light thunderstorms with hail, 99 = Heavy thunderstorms with hail
|
|
40
|
+
95: ["images/weather-icons/thunderstorms-day", "images/weather-icons/thunderstorms-night"],
|
|
41
|
+
96: ["images/weather-icons/thunderstorms-day", "images/weather-icons/thunderstorms-night"],
|
|
42
|
+
99: ["images/weather-icons/thunderstorms-day-extreme", "images/weather-icons/thunderstorms-night-extreme"]
|
|
43
|
+
};
|
|
44
|
+
const weatherCodes = weatherCodeMap;
|
|
45
|
+
export async function callOpenMeteo(latitude, longitude) {
|
|
46
|
+
const params = new URLSearchParams({
|
|
47
|
+
latitude: latitude.toString(),
|
|
48
|
+
longitude: longitude.toString(),
|
|
49
|
+
forecast_days: "1",
|
|
50
|
+
timezone: "Europe/Amsterdam",
|
|
51
|
+
current: "weather_code,temperature_2m,temperature_2m_max,temperature_2m_min",
|
|
52
|
+
daily: "temperature_2m_max,temperature_2m_min,weather_code,sunrise,sunset",
|
|
53
|
+
hourly: "weather_code,temperature_2m,temperature_2m_max,temperature_2m_min"
|
|
54
|
+
});
|
|
55
|
+
const response = await fetch(`https://api.open-meteo.com/v1/forecast?${params}`);
|
|
56
|
+
return await response.json();
|
|
57
|
+
}
|
|
58
|
+
export function getWeatherIcon(code, timeStrings) {
|
|
59
|
+
const weatherCode = code.toString();
|
|
60
|
+
const currentTime = DateTime.fromISO(timeStrings[0]);
|
|
61
|
+
const sunriseTime = DateTime.fromISO(timeStrings[1]);
|
|
62
|
+
const sunsetTime = DateTime.fromISO(timeStrings[2]);
|
|
63
|
+
const isDayTime = currentTime >= sunriseTime && currentTime < sunsetTime;
|
|
64
|
+
const weatherIcon = weatherCodes[weatherCode];
|
|
65
|
+
if (!weatherIcon) {
|
|
66
|
+
console.log(`[Weather] Unknown weather code ${weatherCode}`);
|
|
67
|
+
return "images/weather-icons/not-available";
|
|
68
|
+
}
|
|
69
|
+
const [day, night] = weatherIcon;
|
|
70
|
+
return isDayTime ? day : night;
|
|
71
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"isCurrentRoute.d.ts","sourceRoot":"","sources":["../src/isCurrentRoute.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,OAAO,WAAW,KAAK,EAAE,MAAM,GAAG,OAAO,CAE/C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scrollToTop.d.ts","sourceRoot":"","sources":["../src/scrollToTop.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,OAAO,cAAc,IAAI,CAE/B"}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@almighty-shogun/utils",
|
|
3
|
+
"description": "A small package that contains common utilities used in all my projects.",
|
|
4
|
+
"version": "1.0.1",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc"
|
|
9
|
+
},
|
|
10
|
+
"publishConfig": {
|
|
11
|
+
"access": "public",
|
|
12
|
+
"provenance": true
|
|
13
|
+
},
|
|
14
|
+
"author": {
|
|
15
|
+
"name": "Almighty-Shogun",
|
|
16
|
+
"email": "alm1ghtyshogun1998@gmail.com",
|
|
17
|
+
"url": "https://shogun.ms"
|
|
18
|
+
},
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "git+https://github.com/Almighty-Shogun/packages.git",
|
|
22
|
+
"directory": "packages/utils"
|
|
23
|
+
},
|
|
24
|
+
"main": "./dist/index.js",
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"typings": "./dist/index.d.ts",
|
|
27
|
+
"sideEffects": false,
|
|
28
|
+
"exports": {
|
|
29
|
+
".": {
|
|
30
|
+
"types": "./dist/index.d.ts",
|
|
31
|
+
"default": "./dist/index.js"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"files": [
|
|
35
|
+
"src",
|
|
36
|
+
"dist"
|
|
37
|
+
],
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@types/luxon": "^3.7.1",
|
|
40
|
+
"luxon": "^3.7.2",
|
|
41
|
+
"vue-router": "^4.6.3"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { DateTime } from 'luxon'
|
|
2
|
+
|
|
3
|
+
export default function (): void {
|
|
4
|
+
let lastTouchEnd = 0;
|
|
5
|
+
|
|
6
|
+
document.addEventListener("touchend", (event: TouchEvent) => {
|
|
7
|
+
const now = DateTime.now().toMillis();
|
|
8
|
+
|
|
9
|
+
if (now - lastTouchEnd <= 300) {
|
|
10
|
+
event.preventDefault();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
lastTouchEnd = now;
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
document.addEventListener("gesturestart", (event: Event) => {
|
|
17
|
+
event.preventDefault();
|
|
18
|
+
}, { passive: false });
|
|
19
|
+
|
|
20
|
+
const meta = document.querySelector('meta[name="viewport"]');
|
|
21
|
+
|
|
22
|
+
if (meta) {
|
|
23
|
+
meta.setAttribute("content", "width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no");
|
|
24
|
+
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const newMeta = document.createElement("meta");
|
|
29
|
+
|
|
30
|
+
newMeta.setAttribute("name", "viewport");
|
|
31
|
+
newMeta.setAttribute("content", "width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no");
|
|
32
|
+
|
|
33
|
+
document.head.appendChild(newMeta);
|
|
34
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export default function (value: number, currency?: string, locale?: string): string {
|
|
2
|
+
return new Intl.NumberFormat(locale ?? navigator.language ?? "en", {
|
|
3
|
+
style: "currency",
|
|
4
|
+
currency: currency ?? "EUR",
|
|
5
|
+
currencyDisplay: "symbol",
|
|
6
|
+
maximumFractionDigits: 2,
|
|
7
|
+
minimumFractionDigits: 2
|
|
8
|
+
}).format(value);
|
|
9
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { DateTime } from 'luxon'
|
|
2
|
+
import { callOpenMeteo, getWeatherIcon, type Weather } from './internal/weather'
|
|
3
|
+
|
|
4
|
+
export default async function (latitude: number, longitude: number): Promise<Weather> {
|
|
5
|
+
const { current, daily, hourly } = await callOpenMeteo(latitude, longitude);
|
|
6
|
+
|
|
7
|
+
return {
|
|
8
|
+
current: {
|
|
9
|
+
time: current.time,
|
|
10
|
+
temperature: {
|
|
11
|
+
current: current.temperature_2m,
|
|
12
|
+
min: current.temperature_2m_min,
|
|
13
|
+
max: current.temperature_2m_max
|
|
14
|
+
},
|
|
15
|
+
weatherCode: current.weather_code,
|
|
16
|
+
icon: getWeatherIcon(current.weather_code, [current.time, daily.sunrise[0], daily.sunset[0]])
|
|
17
|
+
},
|
|
18
|
+
today: {
|
|
19
|
+
time: daily.time[0],
|
|
20
|
+
temperature: {
|
|
21
|
+
current: current.temperature_2m,
|
|
22
|
+
min: daily.temperature_2m_min[0],
|
|
23
|
+
max: daily.temperature_2m_max[0]
|
|
24
|
+
},
|
|
25
|
+
weatherCode: daily.weather_code[0],
|
|
26
|
+
icon: getWeatherIcon(daily.weather_code[0], [daily.time[0], daily.sunrise[0], daily.sunset[0]]),
|
|
27
|
+
sunrise: daily.sunrise[0],
|
|
28
|
+
sunset: daily.sunset[0]
|
|
29
|
+
},
|
|
30
|
+
hours: hourly.time.map((time: string, index: number) => ({
|
|
31
|
+
time,
|
|
32
|
+
temperature: {
|
|
33
|
+
current: hourly.temperature_2m[index],
|
|
34
|
+
min: hourly.temperature_2m_min[index],
|
|
35
|
+
max: hourly.temperature_2m_max[index]
|
|
36
|
+
},
|
|
37
|
+
weatherCode: hourly.weather_code[index],
|
|
38
|
+
icon: getWeatherIcon(hourly.weather_code[index], [time, daily.sunrise[0], daily.sunset[0]])
|
|
39
|
+
})).filter(hour => DateTime.fromISO(hour.time) >= DateTime.fromISO(current.time).startOf("hour"))
|
|
40
|
+
};
|
|
41
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export { getCountry, getCountries } from './internal/localization'
|
|
2
|
+
|
|
3
|
+
export { default as containsRoutePrefix } from './containsRoutePrefix'
|
|
4
|
+
export { default as disableZoom } from './disableZoom'
|
|
5
|
+
export { default as formatCelsius } from './formatCelsius'
|
|
6
|
+
export { default as formatCurrency } from './formatCurrency'
|
|
7
|
+
export { default as formatDate } from './formatDate'
|
|
8
|
+
export { default as formatDateTime } from './formatDateTime'
|
|
9
|
+
export { default as formatFullDate } from './formatFullDate'
|
|
10
|
+
export { default as formatMonth } from './formatMonth'
|
|
11
|
+
export { default as formatNumber } from './formatNumber'
|
|
12
|
+
export { default as formatPercentage } from './formatPercentage'
|
|
13
|
+
export { default as formatTime } from './formatTime'
|
|
14
|
+
export { default as formatWeekday } from './formatWeekday'
|
|
15
|
+
export { default as getCurrentRouteName } from './getCurrentRouteName'
|
|
16
|
+
export { default as getWeather } from './getWeather'
|
|
17
|
+
export { default as hasCurrentRoute } from './hasCurrentRoute'
|
|
18
|
+
export { default as scrollToTop } from './scrollToTop'
|
|
19
|
+
export { default as isCurrentRoute } from './isCurrentRoute'
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export type Country = {
|
|
2
|
+
name: string;
|
|
3
|
+
code: string;
|
|
4
|
+
flag: { plain: string; rounded: string; };
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export type CountryCode = keyof typeof countriesMap;
|
|
8
|
+
export type LocalizationCountries = Record<CountryCode, Country>;
|
|
9
|
+
|
|
10
|
+
const countriesMap: Record<string, Country> = {
|
|
11
|
+
nl: {
|
|
12
|
+
name: "Netherlands",
|
|
13
|
+
code: "nl",
|
|
14
|
+
flag: {
|
|
15
|
+
plain: "images/country-flags/flag-netherlands",
|
|
16
|
+
rounded: "images/country-flags/rounded/flag-netherlands"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
fr: {
|
|
20
|
+
name: "France",
|
|
21
|
+
code: "fr",
|
|
22
|
+
flag: {
|
|
23
|
+
plain: "images/country-flags/flag-france",
|
|
24
|
+
rounded: "images/country-flags/rounded/flag-france"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
de: {
|
|
28
|
+
name: "Germany",
|
|
29
|
+
code: "de",
|
|
30
|
+
flag: {
|
|
31
|
+
plain: "images/country-flags/flag-germany",
|
|
32
|
+
rounded: "images/country-flags/rounded/flag-germany"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
pl: {
|
|
36
|
+
name: "Poland",
|
|
37
|
+
code: "pl",
|
|
38
|
+
flag: {
|
|
39
|
+
plain: "images/country-flags/flag-poland",
|
|
40
|
+
rounded: "images/country-flags/rounded/flag-poland"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const countries: LocalizationCountries = countriesMap as LocalizationCountries;
|
|
46
|
+
|
|
47
|
+
export function getCountry(code: CountryCode): Country | null {
|
|
48
|
+
return countries[code] ?? null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function getCountries(): Country[] {
|
|
52
|
+
return Object.values(countries);
|
|
53
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export type OpenMeteoResponse = {
|
|
2
|
+
current: {
|
|
3
|
+
time: string;
|
|
4
|
+
weather_code: number;
|
|
5
|
+
temperature_2m: number;
|
|
6
|
+
temperature_2m_min: number;
|
|
7
|
+
temperature_2m_max: number;
|
|
8
|
+
};
|
|
9
|
+
hourly: {
|
|
10
|
+
time: string[];
|
|
11
|
+
weather_code: number[];
|
|
12
|
+
temperature_2m: number[];
|
|
13
|
+
temperature_2m_min: number[];
|
|
14
|
+
temperature_2m_max: number[];
|
|
15
|
+
};
|
|
16
|
+
daily: {
|
|
17
|
+
time: string[];
|
|
18
|
+
sunrise: string[];
|
|
19
|
+
sunset: string[];
|
|
20
|
+
weather_code: number[];
|
|
21
|
+
temperature_2m_min: number[];
|
|
22
|
+
temperature_2m_max: number[];
|
|
23
|
+
}
|
|
24
|
+
};
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { DateTime } from 'luxon'
|
|
2
|
+
import type { OpenMeteoResponse } from './types'
|
|
3
|
+
|
|
4
|
+
type WeatherTemperature = {
|
|
5
|
+
current: number;
|
|
6
|
+
min: number;
|
|
7
|
+
max: number;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export type WeatherItem = {
|
|
11
|
+
time: string;
|
|
12
|
+
temperature: WeatherTemperature;
|
|
13
|
+
weatherCode: number;
|
|
14
|
+
icon: string;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type Weather = {
|
|
18
|
+
current: WeatherItem;
|
|
19
|
+
today: WeatherItem & {
|
|
20
|
+
sunrise: string;
|
|
21
|
+
sunset: string;
|
|
22
|
+
};
|
|
23
|
+
hours: WeatherItem[];
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
type WeatherIcon = [day: string, night: string];
|
|
27
|
+
export type WeatherCode = keyof typeof weatherCodeMap;
|
|
28
|
+
export type WeatherCodes = Record<WeatherCode, WeatherIcon>;
|
|
29
|
+
|
|
30
|
+
const weatherCodeMap: Record<string, WeatherIcon> = {
|
|
31
|
+
// 0 = Clear sky
|
|
32
|
+
0: ["images/weather-icons/clear-day", "images/weather-icons/clear-night"],
|
|
33
|
+
|
|
34
|
+
// 1 = Mainly clear, 2 = Partly cloudy, 3 = Overcast
|
|
35
|
+
1: ["images/weather-icons/partly-cloudy-day", "images/weather-icons/partly-cloudy-night"],
|
|
36
|
+
2: ["images/weather-icons/partly-cloudy-day", "images/weather-icons/partly-cloudy-night"],
|
|
37
|
+
3: ["images/weather-icons/overcast-day", "images/weather-icons/overcast-night"],
|
|
38
|
+
|
|
39
|
+
// 45 = Fog, 48 = Depositing rime fog
|
|
40
|
+
45: ["images/weather-icons/fog-day", "images/weather-icons/fod-night"],
|
|
41
|
+
48: ["images/weather-icons/overcast-day-fog", "images/weather-icons/overcast-night-fog"],
|
|
42
|
+
|
|
43
|
+
// 51 = Light drizzle, 53 = Moderate drizzle, 55 = Heavy drizzle
|
|
44
|
+
51: ["images/weather-icons/partly-cloudy-day-drizzle", "images/weather-icons/partly-cloudy-night-drizzle"],
|
|
45
|
+
53: ["images/weather-icons/overcast-day-drizzle", "images/weather-icons/overcast-night-drizzle"],
|
|
46
|
+
55: ["images/weather-icons/extreme-day-drizzle", "images/weather-icons/extreme-night-drizzle"],
|
|
47
|
+
|
|
48
|
+
// 56 = Light freezing drizzle, 57 = Heavy freezing drizzle
|
|
49
|
+
56: ["images/weather-icons/partly-cloudy-day-sleet", "images/weather-icons/partly-cloudy-night-sleet"],
|
|
50
|
+
57: ["images/weather-icons/extreme-day-sleet", "images/weather-icons/extreme-night-sleet"],
|
|
51
|
+
|
|
52
|
+
// 61 = Light rain, 63 = Moderate rain, 65 = Heavy rain
|
|
53
|
+
61: ["images/weather-icons/partly-cloudy-day-rain", "images/weather-icons/partly-cloudy-night-rain"],
|
|
54
|
+
63: ["images/weather-icons/overcast-day-rain", "images/weather-icons/overcast-night-rain"],
|
|
55
|
+
65: ["images/weather-icons/extreme-day-rain", "images/weather-icons/extreme-night-rain"],
|
|
56
|
+
|
|
57
|
+
// 66 = Light freezing rain, 67 = Heavy freezing rain
|
|
58
|
+
66: ["images/weather-icons/partly-cloudy-day-sleet", "images/weather-icons/partly-cloudy-night-sleet"],
|
|
59
|
+
67: ["images/weather-icons/extreme-day-sleet", "images/weather-icons/extreme-night-sleet"],
|
|
60
|
+
|
|
61
|
+
// 71 = Light snow, 73 = Moderate snow, 75 = Heavy snow
|
|
62
|
+
71: ["images/weather-icons/partly-cloudy-day-snow", "images/weather-icons/partly-cloudy-night-snow"],
|
|
63
|
+
73: ["images/weather-icons/overcast-day-snow", "images/weather-icons/overcast-night-snow"],
|
|
64
|
+
75: ["images/weather-icons/extreme-day-snow", "images/weather-icons/extreme-night-snow"],
|
|
65
|
+
|
|
66
|
+
// 77 Snow grains
|
|
67
|
+
77: ["images/weather-icons/partly-cloudy-day-snow", "images/weather-icons/partly-cloudy-night-snow"],
|
|
68
|
+
|
|
69
|
+
// 80 = Light rain showers, 81 = Moderate rain showers, 82 = Heavy rain showers
|
|
70
|
+
80: ["images/weather-icons/partly-cloudy-day-rain", "images/weather-icons/partly-cloudy-night-rain"],
|
|
71
|
+
81: ["images/weather-icons/overcast-day-rain", "images/weather-icons/overcast-night-rain"],
|
|
72
|
+
82: ["images/weather-icons/extreme-day-rain", "images/weather-icons/extreme-night-rain"],
|
|
73
|
+
|
|
74
|
+
// 85 = Light snow showers, 86 = Heavy snow showers
|
|
75
|
+
85: ["images/weather-icons/partly-cloudy-day-snow", "images/weather-icons/partly-cloudy-night-snow"],
|
|
76
|
+
86: ["images/weather-icons/extreme-day-snow", "images/weather-icons/extreme-night-snow"],
|
|
77
|
+
|
|
78
|
+
// 95 = Light and moderate thunderstorms, 96 = Light thunderstorms with hail, 99 = Heavy thunderstorms with hail
|
|
79
|
+
95: ["images/weather-icons/thunderstorms-day", "images/weather-icons/thunderstorms-night"],
|
|
80
|
+
96: ["images/weather-icons/thunderstorms-day", "images/weather-icons/thunderstorms-night"],
|
|
81
|
+
99: ["images/weather-icons/thunderstorms-day-extreme", "images/weather-icons/thunderstorms-night-extreme"]
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const weatherCodes: WeatherCodes = weatherCodeMap as WeatherCodes;
|
|
85
|
+
|
|
86
|
+
export async function callOpenMeteo(latitude: number, longitude: number): Promise<OpenMeteoResponse> {
|
|
87
|
+
const params = new URLSearchParams({
|
|
88
|
+
latitude: latitude.toString(),
|
|
89
|
+
longitude: longitude.toString(),
|
|
90
|
+
forecast_days: "1",
|
|
91
|
+
timezone: "Europe/Amsterdam",
|
|
92
|
+
current: "weather_code,temperature_2m,temperature_2m_max,temperature_2m_min",
|
|
93
|
+
daily: "temperature_2m_max,temperature_2m_min,weather_code,sunrise,sunset",
|
|
94
|
+
hourly: "weather_code,temperature_2m,temperature_2m_max,temperature_2m_min"
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
const response = await fetch(`https://api.open-meteo.com/v1/forecast?${params}`);
|
|
98
|
+
|
|
99
|
+
return await response.json();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function getWeatherIcon(code: number, timeStrings: string[]): string {
|
|
103
|
+
const weatherCode = code.toString() as WeatherCode;
|
|
104
|
+
|
|
105
|
+
const currentTime = DateTime.fromISO(timeStrings[0]);
|
|
106
|
+
const sunriseTime = DateTime.fromISO(timeStrings[1]);
|
|
107
|
+
const sunsetTime = DateTime.fromISO(timeStrings[2]);
|
|
108
|
+
|
|
109
|
+
const isDayTime = currentTime >= sunriseTime && currentTime < sunsetTime;
|
|
110
|
+
|
|
111
|
+
const weatherIcon = weatherCodes[weatherCode];
|
|
112
|
+
|
|
113
|
+
if (!weatherIcon) {
|
|
114
|
+
console.log(`[Weather] Unknown weather code ${weatherCode}`);
|
|
115
|
+
|
|
116
|
+
return "images/weather-icons/not-available";
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const [day, night] = weatherIcon;
|
|
120
|
+
|
|
121
|
+
return isDayTime ? day : night;
|
|
122
|
+
}
|