@sybilion/uilib 1.2.23 → 1.2.26

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.
Files changed (80) hide show
  1. package/dist/esm/components/ui/AppHeader/AppHeader.styl.js +1 -1
  2. package/dist/esm/components/ui/Card/Card.styl.js +1 -1
  3. package/dist/esm/components/ui/Chat/ChatSheet/ChatSelector.js +1 -1
  4. package/dist/esm/components/ui/Chat/ChatSheet/ChatSelector.styl.js +1 -1
  5. package/dist/esm/components/ui/DropdownMenu/DropdownMenu.js +4 -4
  6. package/dist/esm/components/ui/NavUserHeader/NavUserHeader.js +5 -2
  7. package/dist/esm/components/ui/WorkspaceAppSwitcher/WorkspaceAppSwitcher.js +1 -1
  8. package/dist/esm/components/ui/WorkspaceAppSwitcher/WorkspaceAppSwitcher.styl.js +2 -2
  9. package/dist/esm/components/widgets/DriverMap/DriverIcon/DriverIcon.constants.json.js +6 -0
  10. package/dist/esm/components/widgets/DriverMap/DriverIcon/DriverIcon.js +21 -0
  11. package/dist/esm/components/widgets/DriverMap/DriverIcon/DriverIcon.styl.js +7 -0
  12. package/dist/esm/components/widgets/DriverMap/DriverMap.helpers.js +107 -0
  13. package/dist/esm/components/widgets/DriverMap/DriverMap.js +129 -0
  14. package/dist/esm/components/widgets/DriverMap/DriverMap.styl.js +7 -0
  15. package/dist/esm/components/widgets/DriverMap/LoadingSpinner/LoadingSpinner.js +8 -0
  16. package/dist/esm/components/widgets/DriverMap/LoadingSpinner/LoadingSpinner.styl.js +7 -0
  17. package/dist/esm/components/widgets/DriverMap/MapBackground/MapBackground.js +10 -0
  18. package/dist/esm/components/widgets/DriverMap/MapBackground/MapBackground.styl.js +7 -0
  19. package/dist/esm/components/widgets/DriverMap/MapBackground/map.svg.js +3 -0
  20. package/dist/esm/components/widgets/DriverMap/driverCategoryIcon.js +194 -0
  21. package/dist/esm/components/widgets/DriverMap/driverMapGeography.js +345 -0
  22. package/dist/esm/components/widgets/DriverMap/driverMapSelection.js +17 -0
  23. package/dist/esm/hooks/index.js +1 -0
  24. package/dist/esm/hooks/useEvent.js +0 -2
  25. package/dist/esm/index.js +6 -0
  26. package/dist/esm/types/src/components/ui/DropdownMenu/DropdownMenu.d.ts +2 -2
  27. package/dist/esm/types/src/components/widgets/DriverMap/DriverIcon/DriverIcon.d.ts +17 -0
  28. package/dist/esm/types/src/components/widgets/DriverMap/DriverMap.d.ts +8 -0
  29. package/dist/esm/types/src/components/widgets/DriverMap/DriverMap.helpers.d.ts +21 -0
  30. package/dist/esm/types/src/components/widgets/DriverMap/LoadingSpinner/LoadingSpinner.d.ts +1 -0
  31. package/dist/esm/types/src/components/widgets/DriverMap/MapBackground/MapBackground.d.ts +1 -0
  32. package/dist/esm/types/src/components/widgets/DriverMap/driverCategoryIcon.d.ts +1 -0
  33. package/dist/esm/types/src/components/widgets/DriverMap/driverMapGeography.d.ts +80 -0
  34. package/dist/esm/types/src/components/widgets/DriverMap/driverMapSelection.d.ts +3 -0
  35. package/dist/esm/types/src/components/widgets/DriverMap/index.d.ts +8 -0
  36. package/dist/esm/types/src/docs/pages/DriverMapPage.d.ts +1 -0
  37. package/dist/esm/types/src/docs/registry.d.ts +1 -1
  38. package/dist/esm/types/src/hooks/index.d.ts +1 -0
  39. package/dist/esm/types/src/index.d.ts +1 -0
  40. package/dist/esm/types/src/sybilion-auth/SybilionAuthProvider.d.ts +1 -1
  41. package/package.json +4 -4
  42. package/src/components/ui/AppHeader/AppHeader.styl +4 -0
  43. package/src/components/ui/Card/Card.styl +1 -0
  44. package/src/components/ui/Chat/ChatSheet/ChatSelector.styl +3 -1
  45. package/src/components/ui/Chat/ChatSheet/ChatSelector.tsx +1 -1
  46. package/src/components/ui/DropdownMenu/DropdownMenu.tsx +4 -0
  47. package/src/components/ui/NavUserHeader/NavUserHeader.tsx +9 -3
  48. package/src/components/ui/WorkspaceAppSwitcher/WorkspaceAppSwitcher.styl +12 -0
  49. package/src/components/ui/WorkspaceAppSwitcher/WorkspaceAppSwitcher.styl.d.ts +1 -0
  50. package/src/components/ui/WorkspaceAppSwitcher/WorkspaceAppSwitcher.tsx +1 -1
  51. package/src/components/widgets/DriverMap/DriverIcon/DriverIcon.constants.json +3 -0
  52. package/src/components/widgets/DriverMap/DriverIcon/DriverIcon.styl +125 -0
  53. package/src/components/widgets/DriverMap/DriverIcon/DriverIcon.styl.d.ts +22 -0
  54. package/src/components/widgets/DriverMap/DriverIcon/DriverIcon.tsx +81 -0
  55. package/src/components/widgets/DriverMap/DriverMap.helpers.ts +164 -0
  56. package/src/components/widgets/DriverMap/DriverMap.styl +45 -0
  57. package/src/components/widgets/DriverMap/DriverMap.styl.d.ts +11 -0
  58. package/src/components/widgets/DriverMap/DriverMap.tsx +214 -0
  59. package/src/components/widgets/DriverMap/LoadingSpinner/LoadingSpinner.styl +24 -0
  60. package/src/components/widgets/DriverMap/LoadingSpinner/LoadingSpinner.styl.d.ts +9 -0
  61. package/src/components/widgets/DriverMap/LoadingSpinner/LoadingSpinner.tsx +11 -0
  62. package/src/components/widgets/DriverMap/MapBackground/MapBackground.styl +13 -0
  63. package/src/components/widgets/DriverMap/MapBackground/MapBackground.styl.d.ts +7 -0
  64. package/src/components/widgets/DriverMap/MapBackground/MapBackground.tsx +18 -0
  65. package/src/components/widgets/DriverMap/MapBackground/map.svg +4337 -0
  66. package/src/components/widgets/DriverMap/MapBackground/mapAspect.mixin.styl +3 -0
  67. package/src/components/widgets/DriverMap/MapBackground/mapAspect.mixin.styl.d.ts +2 -0
  68. package/src/components/widgets/DriverMap/driverCategoryIcon.tsx +279 -0
  69. package/src/components/widgets/DriverMap/driverMapGeography.ts +478 -0
  70. package/src/components/widgets/DriverMap/driverMapSelection.ts +23 -0
  71. package/src/components/widgets/DriverMap/index.ts +18 -0
  72. package/src/docs/config/webpack.config.js +25 -9
  73. package/src/docs/pages/DriverMapPage.tsx +114 -0
  74. package/src/docs/pages/StandaloneAppLayoutPage/StandaloneAppLayoutPage.tsx +5 -7
  75. package/src/docs/pages/TooltipPage.tsx +14 -10
  76. package/src/docs/registry.ts +6 -5
  77. package/src/hooks/index.ts +1 -0
  78. package/src/hooks/useEvent.ts +0 -2
  79. package/src/index.ts +1 -0
  80. package/src/sybilion-auth/SybilionAuthProvider.tsx +1 -1
@@ -0,0 +1,164 @@
1
+ import { BADGE_SIZES, type BadgeSize } from './DriverIcon/DriverIcon';
2
+ import {
3
+ type DriverData,
4
+ geographicToSVG,
5
+ getResponsiveCoordinates,
6
+ svgToPercentage,
7
+ } from './driverMapGeography';
8
+ import { getDriverImportance } from './driverMapSelection';
9
+
10
+ // Calculate badge sizes for all drivers based on their importance
11
+ export const calculateBadgeSizes = (
12
+ drivers: DriverData[],
13
+ ): Record<string, BadgeSize> => {
14
+ if (drivers.length === 0) return {};
15
+
16
+ const importanceValues = drivers
17
+ .map(getDriverImportance)
18
+ .filter(
19
+ (val): val is number =>
20
+ typeof val === 'number' && !isNaN(val) && val >= 0,
21
+ );
22
+
23
+ if (importanceValues.length === 0) {
24
+ return drivers.reduce(
25
+ (acc, driver) => {
26
+ acc[driver.id] = BADGE_SIZES.s;
27
+ return acc;
28
+ },
29
+ {} as Record<string, BadgeSize>,
30
+ );
31
+ }
32
+
33
+ const min = Math.min(...importanceValues);
34
+ const max = Math.max(...importanceValues);
35
+ const range = max - min;
36
+
37
+ if (range === 0) {
38
+ return drivers.reduce(
39
+ (acc, driver) => {
40
+ acc[driver.id] = BADGE_SIZES.s;
41
+ return acc;
42
+ },
43
+ {} as Record<string, BadgeSize>,
44
+ );
45
+ }
46
+
47
+ return drivers.reduce(
48
+ (acc, driver) => {
49
+ const importance = getDriverImportance(driver);
50
+
51
+ if (
52
+ typeof importance !== 'number' ||
53
+ isNaN(importance) ||
54
+ importance < 0
55
+ ) {
56
+ acc[driver.id] = BADGE_SIZES.s;
57
+ return acc;
58
+ }
59
+
60
+ const normalized = (importance - min) / range;
61
+ acc[driver.id] =
62
+ normalized >= 0.66
63
+ ? BADGE_SIZES.l
64
+ : normalized >= 0.33
65
+ ? BADGE_SIZES.m
66
+ : BADGE_SIZES.s;
67
+ return acc;
68
+ },
69
+ {} as Record<string, BadgeSize>,
70
+ );
71
+ };
72
+
73
+ export const hasValidCoords = (
74
+ coords: { x: number; y: number } | null | undefined,
75
+ ): boolean => {
76
+ return (
77
+ coords?.x != null &&
78
+ coords?.y != null &&
79
+ typeof coords.x === 'number' &&
80
+ typeof coords.y === 'number' &&
81
+ !isNaN(coords.x) &&
82
+ !isNaN(coords.y) &&
83
+ Math.abs(coords.x) > 0 &&
84
+ Math.abs(coords.y) > 0
85
+ );
86
+ };
87
+
88
+ export const findMostSpecificRegion = (
89
+ driver: DriverData,
90
+ ): {
91
+ name: string | null;
92
+ coordinates: { x: number; y: number } | null;
93
+ } => {
94
+ if (driver.region?.length > 0) {
95
+ return {
96
+ name: driver.region[driver.region.length - 1],
97
+ coordinates: null,
98
+ };
99
+ }
100
+
101
+ const srcName = driver.src_region?.name;
102
+ const tgtName = driver.tgt_region?.name;
103
+ const srcCoords = driver.src_region?.coordinates;
104
+ const tgtCoords = driver.tgt_region?.coordinates;
105
+ const srcIsNonWorld =
106
+ srcName && srcName !== 'World' && hasValidCoords(srcCoords);
107
+ const tgtIsNonWorld =
108
+ tgtName && tgtName !== 'World' && hasValidCoords(tgtCoords);
109
+
110
+ if (tgtIsNonWorld) {
111
+ return {
112
+ name: tgtName,
113
+ coordinates: tgtCoords!,
114
+ };
115
+ }
116
+ if (srcIsNonWorld) {
117
+ return {
118
+ name: srcName,
119
+ coordinates: srcCoords!,
120
+ };
121
+ }
122
+
123
+ return { name: null, coordinates: null };
124
+ };
125
+
126
+ export const getDriverCoordinates = (
127
+ driver: DriverData,
128
+ specificRegion: {
129
+ name: string | null;
130
+ coordinates: { x: number; y: number } | null;
131
+ },
132
+ existingDrivers: DriverData[] = [],
133
+ ): DriverData['coordinates'] => {
134
+ if (!specificRegion.name || specificRegion.name === 'World') {
135
+ return driver.coordinates;
136
+ }
137
+
138
+ if (specificRegion.coordinates) {
139
+ const isLatLng =
140
+ Math.abs(specificRegion.coordinates.x) <= 180 &&
141
+ Math.abs(specificRegion.coordinates.y) <= 90;
142
+
143
+ if (isLatLng) {
144
+ const svgCoords = geographicToSVG(
145
+ specificRegion.coordinates.y,
146
+ specificRegion.coordinates.x,
147
+ );
148
+ const percentageCoords = svgToPercentage(svgCoords.x, svgCoords.y);
149
+ return {
150
+ x: Math.min(95, Math.max(5, percentageCoords.x)),
151
+ y: Math.min(95, Math.max(5, percentageCoords.y)),
152
+ continent: driver.coordinates?.continent || 'Global',
153
+ };
154
+ }
155
+
156
+ return {
157
+ x: specificRegion.coordinates.x,
158
+ y: specificRegion.coordinates.y,
159
+ continent: driver.coordinates?.continent || 'Global',
160
+ };
161
+ }
162
+
163
+ return getResponsiveCoordinates(specificRegion.name, existingDrivers);
164
+ };
@@ -0,0 +1,45 @@
1
+ @import '../../../lib/theme.styl'
2
+ @import './MapBackground/mapAspect.mixin.styl'
3
+
4
+
5
+ .root
6
+ position relative
7
+ width 100%
8
+ mapAspect()
9
+ padding 0
10
+ overflow hidden
11
+
12
+ @media (min-width: 768px)
13
+ height 35rem
14
+ width fit-content
15
+ flex 1
16
+
17
+ .mapInner
18
+ position relative
19
+ max-height 100%
20
+ mapAspect()
21
+ margin 0 auto
22
+ border-radius var(--p-4)
23
+ overflow hidden
24
+
25
+ .shimmerOverlay
26
+ z-index 20
27
+
28
+ .inTransition
29
+ pointer-events none
30
+
31
+ .worldDrivers
32
+ position absolute
33
+ bottom 0
34
+ display flex
35
+ align-items center
36
+ gap 0.5rem
37
+ padding 0.5rem
38
+
39
+ button
40
+ position static !important
41
+ transform none !important
42
+
43
+ & > span
44
+ transform none !important
45
+ opacity 1 !important
@@ -0,0 +1,11 @@
1
+ // This file is automatically generated.
2
+ // Please do not change this file!
3
+ interface CssExports {
4
+ 'inTransition': string;
5
+ 'mapInner': string;
6
+ 'root': string;
7
+ 'shimmerOverlay': string;
8
+ 'worldDrivers': string;
9
+ }
10
+ export const cssExports: CssExports;
11
+ export default cssExports;
@@ -0,0 +1,214 @@
1
+ 'use client';
2
+
3
+ import cn from 'classnames';
4
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
5
+
6
+ import useEvent from '#uilib/hooks/useEvent';
7
+ import { Shimmer } from '@homecode/ui';
8
+
9
+ import { BadgeSize, DriverIcon } from './DriverIcon/DriverIcon';
10
+ import constants from './DriverIcon/DriverIcon.constants.json';
11
+ import {
12
+ calculateBadgeSizes,
13
+ findMostSpecificRegion,
14
+ getDriverCoordinates,
15
+ hasValidCoords,
16
+ } from './DriverMap.helpers';
17
+ import S from './DriverMap.styl';
18
+ import { MapBackground } from './MapBackground/MapBackground';
19
+ import type { DriverData } from './driverMapGeography';
20
+ import { getHighestImportanceDriver } from './driverMapSelection';
21
+
22
+ export interface DriverMapProps {
23
+ drivers: DriverData[];
24
+ isLoading: boolean;
25
+ setSelectedDriver: (driver: DriverData) => void;
26
+ selectedDriver: DriverData | null;
27
+ }
28
+
29
+ const delay = (ms: number) => new Promise<void>(r => setTimeout(r, ms));
30
+
31
+ const transitionDelay = () => delay(constants.FADE_DURATION);
32
+
33
+ export function DriverMap({
34
+ drivers,
35
+ isLoading,
36
+ setSelectedDriver,
37
+ selectedDriver,
38
+ }: DriverMapProps) {
39
+ const visibleDriversRef = useRef<DriverData[]>([]);
40
+
41
+ const [showingDrivers, setShowingDrivers] = useState<DriverData[]>(drivers);
42
+ const [badgeSizes, setBadgeSizes] = useState<Record<string, BadgeSize>>({});
43
+ const [isVisible, setIsVisible] = useState(false);
44
+ const [isTransitioning, setIsTransitioning] = useState(false);
45
+
46
+ const makeTransition = async (nextDrivers: DriverData[]) => {
47
+ const hadDrivers = showingDrivers.length > 0;
48
+
49
+ setIsTransitioning(true);
50
+
51
+ if (hadDrivers) {
52
+ setIsVisible(false);
53
+ await transitionDelay();
54
+ }
55
+
56
+ if (nextDrivers.length > 0) {
57
+ setShowingDrivers(nextDrivers);
58
+ setIsVisible(false);
59
+
60
+ const sizes = calculateBadgeSizes(nextDrivers);
61
+ setBadgeSizes(sizes);
62
+
63
+ await delay(30);
64
+ setIsVisible(true);
65
+ await transitionDelay();
66
+ } else {
67
+ setShowingDrivers([]);
68
+ setBadgeSizes({});
69
+ setIsVisible(false);
70
+ }
71
+
72
+ setIsTransitioning(false);
73
+ };
74
+
75
+ const [worldDrivers, otherDrivers] = useMemo(() => {
76
+ const visibleDrivers: DriverData[] = [];
77
+ const worldDriversList: DriverData[] = [];
78
+
79
+ drivers.forEach(driver => {
80
+ let importance = driver.importance || 0;
81
+ if (importance === 0) {
82
+ const mean = driver?.rawImportance?.overall?.mean;
83
+ if (typeof mean === 'number') {
84
+ importance = Math.abs(mean) * 100;
85
+ }
86
+ }
87
+
88
+ const specificRegion = findMostSpecificRegion(driver);
89
+ const isEmptyRegion = driver.region?.length === 0;
90
+ const isWorldRegion =
91
+ specificRegion.name === 'World' ||
92
+ driver.region?.slice(-1)[0] === 'World';
93
+
94
+ const coordinates = getDriverCoordinates(
95
+ driver,
96
+ specificRegion,
97
+ visibleDrivers,
98
+ );
99
+ const driverToAdd = {
100
+ ...driver,
101
+ coordinates,
102
+ };
103
+
104
+ const shouldGoToWorldDrivers =
105
+ isWorldRegion ||
106
+ !hasValidCoords(driverToAdd.coordinates) ||
107
+ (isEmptyRegion && !specificRegion.name);
108
+
109
+ if (shouldGoToWorldDrivers && importance >= 0) {
110
+ worldDriversList.push(driver);
111
+ } else if (hasValidCoords(driverToAdd.coordinates) && importance >= 0) {
112
+ visibleDrivers.push(driverToAdd);
113
+ }
114
+ });
115
+
116
+ return [
117
+ worldDriversList.sort((a, b) => b.importance - a.importance),
118
+ visibleDrivers,
119
+ ];
120
+ }, [drivers]);
121
+
122
+ useEffect(() => {
123
+ void makeTransition(drivers);
124
+
125
+ if (drivers.length > 0) {
126
+ const idx = getHighestImportanceDriver(drivers);
127
+ if (idx !== null && idx >= 0) {
128
+ setSelectedDriver(drivers[idx]);
129
+ }
130
+ }
131
+ }, [drivers]);
132
+
133
+ useEffect(() => {
134
+ visibleDriversRef.current = otherDrivers;
135
+ }, [otherDrivers]);
136
+
137
+ const handleKeyDown = useCallback(
138
+ (e: KeyboardEvent) => {
139
+ const items = visibleDriversRef.current;
140
+
141
+ if (!selectedDriver || items.length === 0 || e.metaKey || e.ctrlKey)
142
+ return;
143
+
144
+ const stop = () => {
145
+ e.preventDefault();
146
+ e.stopPropagation();
147
+ };
148
+
149
+ const currIndex = items.findIndex(d => d.id === selectedDriver.id);
150
+
151
+ if (e.key === 'ArrowLeft') {
152
+ const prevIndex = currIndex > 0 ? currIndex - 1 : items.length - 1;
153
+
154
+ setSelectedDriver(items[prevIndex]);
155
+ stop();
156
+ } else if (e.key === 'ArrowRight') {
157
+ const nextIndex = currIndex < items.length - 1 ? currIndex + 1 : 0;
158
+
159
+ setSelectedDriver(items[nextIndex]);
160
+ stop();
161
+ }
162
+ },
163
+ [selectedDriver, setSelectedDriver],
164
+ );
165
+
166
+ useEvent({
167
+ event: 'keydown',
168
+ callback: handleKeyDown,
169
+ isCapture: true,
170
+ });
171
+
172
+ return (
173
+ <div className={cn(S.root, isTransitioning && S.inTransition)}>
174
+ <div className={S.mapInner}>
175
+ <MapBackground />
176
+ {isLoading && <Shimmer className={S.shimmerOverlay} size="l" />}
177
+ {otherDrivers.map(driver => (
178
+ <DriverIcon
179
+ key={driver.id}
180
+ isLoading={isLoading}
181
+ isVisible={isVisible}
182
+ driver={driver}
183
+ size={badgeSizes[driver.id] || 's'}
184
+ isSelected={selectedDriver?.id === driver.id}
185
+ onClick={() => setSelectedDriver(driver)}
186
+ />
187
+ ))}
188
+ </div>
189
+ <div className={S.worldDrivers}>
190
+ {worldDrivers.map(driver => {
191
+ const driverWithCoords = {
192
+ ...driver,
193
+ coordinates: driver.coordinates || {
194
+ x: 0,
195
+ y: 0,
196
+ continent: 'Global',
197
+ },
198
+ };
199
+ return (
200
+ <DriverIcon
201
+ key={driver.id}
202
+ isLoading={isLoading}
203
+ isVisible={isVisible}
204
+ driver={driverWithCoords}
205
+ size={badgeSizes[driver.id] || 's'}
206
+ isSelected={selectedDriver?.id === driver.id}
207
+ onClick={() => setSelectedDriver(driver)}
208
+ />
209
+ );
210
+ })}
211
+ </div>
212
+ </div>
213
+ );
214
+ }
@@ -0,0 +1,24 @@
1
+ // Loading spinner component styles
2
+ .loadingSpinnerContainer
3
+ position absolute
4
+ inset 0
5
+ display flex
6
+ align-items center
7
+ justify-content center
8
+ z-index 20
9
+
10
+ .loadingSpinner
11
+ width 1.5rem
12
+ height 1.5rem
13
+ border 2px solid var(--muted-foreground)
14
+ border-opacity 0.2
15
+ border-top-color var(--muted-foreground)
16
+ border-top-opacity 0.6
17
+ border-radius 50%
18
+ animation spin 1s linear infinite
19
+
20
+ @keyframes spin
21
+ from
22
+ transform rotate(0deg)
23
+ to
24
+ transform rotate(360deg)
@@ -0,0 +1,9 @@
1
+ // This file is automatically generated.
2
+ // Please do not change this file!
3
+ interface CssExports {
4
+ 'loadingSpinner': string;
5
+ 'loadingSpinnerContainer': string;
6
+ 'spin': string;
7
+ }
8
+ export const cssExports: CssExports;
9
+ export default cssExports;
@@ -0,0 +1,11 @@
1
+ 'use client';
2
+
3
+ import S from './LoadingSpinner.styl';
4
+
5
+ export function LoadingSpinner() {
6
+ return (
7
+ <div className={S.loadingSpinnerContainer}>
8
+ <div className={S.loadingSpinner}></div>
9
+ </div>
10
+ );
11
+ }
@@ -0,0 +1,13 @@
1
+ @import './mapAspect.mixin.styl'
2
+
3
+ // Map is <img src> from bundled URL (data URL or file). Avoids CSS url() resolving to broken relative paths in consumers.
4
+ .mapBackground
5
+ position absolute
6
+ display block
7
+ width 100%
8
+ height 100%
9
+ mapAspect()
10
+ object-fit contain
11
+ object-position center
12
+ pointer-events none
13
+ user-select none
@@ -0,0 +1,7 @@
1
+ // This file is automatically generated.
2
+ // Please do not change this file!
3
+ interface CssExports {
4
+ 'mapBackground': string;
5
+ }
6
+ export const cssExports: CssExports;
7
+ export default cssExports;
@@ -0,0 +1,18 @@
1
+ 'use client';
2
+
3
+ import S from './MapBackground.styl';
4
+ import mapBgUrl from './map.svg';
5
+
6
+ export function MapBackground() {
7
+ const src = mapBgUrl as unknown as string;
8
+
9
+ return (
10
+ <img
11
+ alt=""
12
+ className={S.mapBackground}
13
+ decoding="async"
14
+ draggable={false}
15
+ src={src}
16
+ />
17
+ );
18
+ }