@sybilion/uilib 1.2.24 → 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.
- package/dist/esm/components/ui/Chat/ChatSheet/ChatSelector.js +1 -1
- package/dist/esm/components/ui/Chat/ChatSheet/ChatSelector.styl.js +1 -1
- package/dist/esm/components/ui/DropdownMenu/DropdownMenu.js +4 -4
- package/dist/esm/components/widgets/DriverMap/DriverIcon/DriverIcon.constants.json.js +6 -0
- package/dist/esm/components/widgets/DriverMap/DriverIcon/DriverIcon.js +21 -0
- package/dist/esm/components/widgets/DriverMap/DriverIcon/DriverIcon.styl.js +7 -0
- package/dist/esm/components/widgets/DriverMap/DriverMap.helpers.js +107 -0
- package/dist/esm/components/widgets/DriverMap/DriverMap.js +129 -0
- package/dist/esm/components/widgets/DriverMap/DriverMap.styl.js +7 -0
- package/dist/esm/components/widgets/DriverMap/LoadingSpinner/LoadingSpinner.js +8 -0
- package/dist/esm/components/widgets/DriverMap/LoadingSpinner/LoadingSpinner.styl.js +7 -0
- package/dist/esm/components/widgets/DriverMap/MapBackground/MapBackground.js +10 -0
- package/dist/esm/components/widgets/DriverMap/MapBackground/MapBackground.styl.js +7 -0
- package/dist/esm/components/widgets/DriverMap/MapBackground/map.svg.js +3 -0
- package/dist/esm/components/widgets/DriverMap/driverCategoryIcon.js +194 -0
- package/dist/esm/components/widgets/DriverMap/driverMapGeography.js +345 -0
- package/dist/esm/components/widgets/DriverMap/driverMapSelection.js +17 -0
- package/dist/esm/hooks/index.js +1 -0
- package/dist/esm/hooks/useEvent.js +0 -2
- package/dist/esm/index.js +6 -0
- package/dist/esm/types/src/components/ui/DropdownMenu/DropdownMenu.d.ts +2 -2
- package/dist/esm/types/src/components/widgets/DriverMap/DriverIcon/DriverIcon.d.ts +17 -0
- package/dist/esm/types/src/components/widgets/DriverMap/DriverMap.d.ts +8 -0
- package/dist/esm/types/src/components/widgets/DriverMap/DriverMap.helpers.d.ts +21 -0
- package/dist/esm/types/src/components/widgets/DriverMap/LoadingSpinner/LoadingSpinner.d.ts +1 -0
- package/dist/esm/types/src/components/widgets/DriverMap/MapBackground/MapBackground.d.ts +1 -0
- package/dist/esm/types/src/components/widgets/DriverMap/driverCategoryIcon.d.ts +1 -0
- package/dist/esm/types/src/components/widgets/DriverMap/driverMapGeography.d.ts +80 -0
- package/dist/esm/types/src/components/widgets/DriverMap/driverMapSelection.d.ts +3 -0
- package/dist/esm/types/src/components/widgets/DriverMap/index.d.ts +8 -0
- package/dist/esm/types/src/docs/pages/DriverMapPage.d.ts +1 -0
- package/dist/esm/types/src/docs/registry.d.ts +1 -1
- package/dist/esm/types/src/hooks/index.d.ts +1 -0
- package/dist/esm/types/src/index.d.ts +1 -0
- package/package.json +1 -1
- package/src/components/ui/Chat/ChatSheet/ChatSelector.styl +3 -1
- package/src/components/ui/Chat/ChatSheet/ChatSelector.tsx +1 -1
- package/src/components/ui/DropdownMenu/DropdownMenu.tsx +4 -0
- package/src/components/widgets/DriverMap/DriverIcon/DriverIcon.constants.json +3 -0
- package/src/components/widgets/DriverMap/DriverIcon/DriverIcon.styl +125 -0
- package/src/components/widgets/DriverMap/DriverIcon/DriverIcon.styl.d.ts +22 -0
- package/src/components/widgets/DriverMap/DriverIcon/DriverIcon.tsx +81 -0
- package/src/components/widgets/DriverMap/DriverMap.helpers.ts +164 -0
- package/src/components/widgets/DriverMap/DriverMap.styl +45 -0
- package/src/components/widgets/DriverMap/DriverMap.styl.d.ts +11 -0
- package/src/components/widgets/DriverMap/DriverMap.tsx +214 -0
- package/src/components/widgets/DriverMap/LoadingSpinner/LoadingSpinner.styl +24 -0
- package/src/components/widgets/DriverMap/LoadingSpinner/LoadingSpinner.styl.d.ts +9 -0
- package/src/components/widgets/DriverMap/LoadingSpinner/LoadingSpinner.tsx +11 -0
- package/src/components/widgets/DriverMap/MapBackground/MapBackground.styl +13 -0
- package/src/components/widgets/DriverMap/MapBackground/MapBackground.styl.d.ts +7 -0
- package/src/components/widgets/DriverMap/MapBackground/MapBackground.tsx +18 -0
- package/src/components/widgets/DriverMap/MapBackground/map.svg +4337 -0
- package/src/components/widgets/DriverMap/MapBackground/mapAspect.mixin.styl +3 -0
- package/src/components/widgets/DriverMap/MapBackground/mapAspect.mixin.styl.d.ts +2 -0
- package/src/components/widgets/DriverMap/driverCategoryIcon.tsx +279 -0
- package/src/components/widgets/DriverMap/driverMapGeography.ts +478 -0
- package/src/components/widgets/DriverMap/driverMapSelection.ts +23 -0
- package/src/components/widgets/DriverMap/index.ts +18 -0
- package/src/docs/config/webpack.config.js +25 -9
- package/src/docs/pages/DriverMapPage.tsx +114 -0
- package/src/docs/pages/TooltipPage.tsx +14 -10
- package/src/docs/registry.ts +6 -5
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useEvent.ts +0 -2
- package/src/index.ts +1 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function MapBackground(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const getCategoryIcon: (category: string | undefined | null) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
export interface DriverData {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
region: string[];
|
|
5
|
+
category: string;
|
|
6
|
+
isPublic: boolean;
|
|
7
|
+
importance: number;
|
|
8
|
+
direction: number;
|
|
9
|
+
lag: string;
|
|
10
|
+
coordinates: {
|
|
11
|
+
x: number;
|
|
12
|
+
y: number;
|
|
13
|
+
continent: string;
|
|
14
|
+
};
|
|
15
|
+
normalized_series?: {
|
|
16
|
+
[date: string]: number | null;
|
|
17
|
+
};
|
|
18
|
+
rawImportance?: any;
|
|
19
|
+
summary?: string;
|
|
20
|
+
src_region?: {
|
|
21
|
+
name: string;
|
|
22
|
+
coordinates: {
|
|
23
|
+
x: number;
|
|
24
|
+
y: number;
|
|
25
|
+
};
|
|
26
|
+
} | null;
|
|
27
|
+
tgt_region?: {
|
|
28
|
+
name: string;
|
|
29
|
+
coordinates: {
|
|
30
|
+
x: number;
|
|
31
|
+
y: number;
|
|
32
|
+
};
|
|
33
|
+
} | null;
|
|
34
|
+
}
|
|
35
|
+
export interface RegionMapping {
|
|
36
|
+
[key: string]: {
|
|
37
|
+
x: number;
|
|
38
|
+
y: number;
|
|
39
|
+
continent: string;
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
export interface AnalysisInfo {
|
|
43
|
+
id: string;
|
|
44
|
+
name: string;
|
|
45
|
+
driverCount: number;
|
|
46
|
+
path: string;
|
|
47
|
+
}
|
|
48
|
+
export interface DatasetInfo {
|
|
49
|
+
id: string;
|
|
50
|
+
name: string;
|
|
51
|
+
analyses: AnalysisInfo[];
|
|
52
|
+
}
|
|
53
|
+
interface GeographicCoordinates {
|
|
54
|
+
latitude: number;
|
|
55
|
+
longitude: number;
|
|
56
|
+
continent: string;
|
|
57
|
+
}
|
|
58
|
+
export declare const geographicCoordinates: {
|
|
59
|
+
[key: string]: GeographicCoordinates;
|
|
60
|
+
};
|
|
61
|
+
export declare function geographicToSVG(lat: number, lng: number): {
|
|
62
|
+
x: number;
|
|
63
|
+
y: number;
|
|
64
|
+
};
|
|
65
|
+
export declare function svgToPercentage(svgX: number, svgY: number): {
|
|
66
|
+
x: number;
|
|
67
|
+
y: number;
|
|
68
|
+
};
|
|
69
|
+
export declare function getContinentFromRegion(region: string): string | null;
|
|
70
|
+
export declare function getPreciseCoordinates(region: string): {
|
|
71
|
+
x: number;
|
|
72
|
+
y: number;
|
|
73
|
+
continent: string;
|
|
74
|
+
};
|
|
75
|
+
export declare function getResponsiveCoordinates(region: string, existingDrivers?: DriverData[], mapContainerWidth?: number, mapContainerHeight?: number): {
|
|
76
|
+
x: number;
|
|
77
|
+
y: number;
|
|
78
|
+
continent: string;
|
|
79
|
+
};
|
|
80
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { DriverMap, type DriverMapProps } from './DriverMap';
|
|
2
|
+
export type { DriverData } from './driverMapGeography';
|
|
3
|
+
export { getCategoryIcon } from './driverCategoryIcon';
|
|
4
|
+
export { getDriverImportance, getHighestImportanceDriver, } from './driverMapSelection';
|
|
5
|
+
export { geographicCoordinates, geographicToSVG, getContinentFromRegion, getPreciseCoordinates, getResponsiveCoordinates, svgToPercentage, } from './driverMapGeography';
|
|
6
|
+
export { MapBackground } from './MapBackground/MapBackground';
|
|
7
|
+
export { LoadingSpinner } from './LoadingSpinner/LoadingSpinner';
|
|
8
|
+
export type { BadgeSize } from './DriverIcon/DriverIcon';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function DriverMapPage(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -8,7 +8,7 @@ export type DocEntry = {
|
|
|
8
8
|
}>;
|
|
9
9
|
};
|
|
10
10
|
/** Sidebar group order */
|
|
11
|
-
export declare const DOC_SECTION_ORDER: readonly ["Forms", "Feedback", "Layout", "Navigation", "Overlays", "Data display", "Charts", "Chat", "Media", "Misc"];
|
|
11
|
+
export declare const DOC_SECTION_ORDER: readonly ["Forms", "Feedback", "Layout", "Navigation", "Widgets", "Overlays", "Data display", "Charts", "Chat", "Media", "Misc"];
|
|
12
12
|
export declare const DOC_DEFAULT_SLUG = "button";
|
|
13
13
|
export declare const DOC_REGISTRY: DocEntry[];
|
|
14
14
|
export declare const docPageComponents: Record<string, LazyExoticComponent<ComponentType<object>>>;
|
|
@@ -60,6 +60,7 @@ export * from './components/ui/Tooltip';
|
|
|
60
60
|
export * from './components/ui/VimeoEmbed';
|
|
61
61
|
export * from './components/ui/WorkspaceAppSwitcher';
|
|
62
62
|
export * from './components/widgets/SidebarDatasetsItemsGrouped';
|
|
63
|
+
export * from './components/widgets/DriverMap';
|
|
63
64
|
export * from './components/widgets/SybilionAppHeader';
|
|
64
65
|
export * from './components/widgets/SybilionAuthLayout';
|
|
65
66
|
export * from './components/widgets/SybilionSignInPanel';
|
package/package.json
CHANGED
|
@@ -44,6 +44,7 @@ function DropdownMenuTrigger({ ...props }: DropdownMenuTriggerProps) {
|
|
|
44
44
|
function DropdownMenuContent({
|
|
45
45
|
className,
|
|
46
46
|
sideOffset = 4,
|
|
47
|
+
collisionPadding = 8,
|
|
47
48
|
elevation = 'sm',
|
|
48
49
|
...props
|
|
49
50
|
}: DropdownMenuContentProps) {
|
|
@@ -52,6 +53,7 @@ function DropdownMenuContent({
|
|
|
52
53
|
<DropdownMenuPrimitive.Content
|
|
53
54
|
data-slot="dropdown-menu-content"
|
|
54
55
|
sideOffset={sideOffset}
|
|
56
|
+
collisionPadding={collisionPadding}
|
|
55
57
|
className={cn(S.content, S[`elevation-${elevation}`], className)}
|
|
56
58
|
{...props}
|
|
57
59
|
/>
|
|
@@ -201,11 +203,13 @@ function DropdownMenuSubTrigger({
|
|
|
201
203
|
|
|
202
204
|
function DropdownMenuSubContent({
|
|
203
205
|
className,
|
|
206
|
+
collisionPadding = 8,
|
|
204
207
|
...props
|
|
205
208
|
}: DropdownMenuSubContentProps) {
|
|
206
209
|
return (
|
|
207
210
|
<DropdownMenuPrimitive.SubContent
|
|
208
211
|
data-slot="dropdown-menu-sub-content"
|
|
212
|
+
collisionPadding={collisionPadding}
|
|
209
213
|
className={cn(S.subContent, className)}
|
|
210
214
|
{...props}
|
|
211
215
|
/>
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
@import '../../../../lib/theme.styl';
|
|
2
|
+
json('./DriverIcon.constants.json')
|
|
3
|
+
|
|
4
|
+
$dur = unit(FADE_DURATION, 'ms')
|
|
5
|
+
$msOffset = 30ms
|
|
6
|
+
|
|
7
|
+
.root
|
|
8
|
+
position absolute
|
|
9
|
+
transform translateX(-50%) translateY(-50%)
|
|
10
|
+
cursor pointer
|
|
11
|
+
outline none
|
|
12
|
+
|
|
13
|
+
&:hover
|
|
14
|
+
transition transform 300ms ease-out
|
|
15
|
+
|
|
16
|
+
&:focus
|
|
17
|
+
outline none
|
|
18
|
+
|
|
19
|
+
.loadingHidden
|
|
20
|
+
opacity 0
|
|
21
|
+
pointer-events none
|
|
22
|
+
|
|
23
|
+
.badge
|
|
24
|
+
padding 0.25rem
|
|
25
|
+
transition all $dur ease-out
|
|
26
|
+
pointer-events none
|
|
27
|
+
|
|
28
|
+
opacity 0
|
|
29
|
+
transform translateY(10px)
|
|
30
|
+
|
|
31
|
+
svg
|
|
32
|
+
height 20px
|
|
33
|
+
width 20px
|
|
34
|
+
|
|
35
|
+
.size-s
|
|
36
|
+
.size-s .badge
|
|
37
|
+
width 2rem
|
|
38
|
+
height 2rem
|
|
39
|
+
border-radius 10px
|
|
40
|
+
.size-m
|
|
41
|
+
.size-m .badge
|
|
42
|
+
width 2.5rem
|
|
43
|
+
height 2.5rem
|
|
44
|
+
border-radius 12px
|
|
45
|
+
.size-l
|
|
46
|
+
.size-l .badge
|
|
47
|
+
width 3rem
|
|
48
|
+
height 3rem
|
|
49
|
+
border-radius 14px
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
// show/hide animations
|
|
53
|
+
.visible .badge
|
|
54
|
+
transition $dur ease-out
|
|
55
|
+
transition-property opacity, transform
|
|
56
|
+
opacity 1
|
|
57
|
+
transform translateY(0)
|
|
58
|
+
|
|
59
|
+
span
|
|
60
|
+
transition box-shadow 0s .1s ease-out
|
|
61
|
+
|
|
62
|
+
for $i in (1..6)
|
|
63
|
+
.root:nth-child({$i}) .badge
|
|
64
|
+
transition-delay ($i * $msOffset)
|
|
65
|
+
.visible:nth-child({$i}) .badge
|
|
66
|
+
transition-delay ($i * ($msOffset * 2))
|
|
67
|
+
.hidden:nth-child({$i}) .badge
|
|
68
|
+
transition-duration 'calc(%s - %s)' % ($dur ($i * $msOffset))
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
// Hover
|
|
72
|
+
.root:hover
|
|
73
|
+
z-index 10
|
|
74
|
+
|
|
75
|
+
.badge
|
|
76
|
+
box-shadow 0 0 0 1px var(--background)
|
|
77
|
+
transform scale(1.1)
|
|
78
|
+
transition-delay 0ms
|
|
79
|
+
transition-duration .2s
|
|
80
|
+
|
|
81
|
+
.selected .badge
|
|
82
|
+
.selected:hover .badge
|
|
83
|
+
transform scale(1.1)
|
|
84
|
+
|
|
85
|
+
// span
|
|
86
|
+
box-shadow inset 0 0 0 3px var(--sb-cyan-400)
|
|
87
|
+
|
|
88
|
+
:global(.dark) &
|
|
89
|
+
box-shadow inset 0 0 0 2px var(--sb-cyan-500)
|
|
90
|
+
|
|
91
|
+
.root:not(.selected):hover .icon
|
|
92
|
+
transform scale(1.05)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
.tooltipContent
|
|
96
|
+
max-width 20rem
|
|
97
|
+
border 1px solid var(--border)
|
|
98
|
+
background-color var(--popover)
|
|
99
|
+
color var(--popover-foreground)
|
|
100
|
+
font-size 0.75rem
|
|
101
|
+
font-family var(--font-family-body)
|
|
102
|
+
box-shadow 0 10px 15px -3px rgba(0, 0, 0, 0.1)
|
|
103
|
+
|
|
104
|
+
.tooltipCategory
|
|
105
|
+
color var(--muted-foreground)
|
|
106
|
+
display flex
|
|
107
|
+
align-items center
|
|
108
|
+
gap 0.25rem
|
|
109
|
+
|
|
110
|
+
.tooltipCategoryIcon
|
|
111
|
+
height 0.75rem
|
|
112
|
+
width 0.75rem
|
|
113
|
+
color var(--muted-foreground)
|
|
114
|
+
|
|
115
|
+
.tooltipCategoryText
|
|
116
|
+
line-clamp(1)
|
|
117
|
+
overflow hidden
|
|
118
|
+
|
|
119
|
+
.tooltipName
|
|
120
|
+
font-weight normal
|
|
121
|
+
|
|
122
|
+
.tooltipSpacing
|
|
123
|
+
display flex
|
|
124
|
+
flex-direction column
|
|
125
|
+
gap 0.25rem
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// This file is automatically generated.
|
|
2
|
+
// Please do not change this file!
|
|
3
|
+
interface CssExports {
|
|
4
|
+
'badge': string;
|
|
5
|
+
'hidden': string;
|
|
6
|
+
'icon': string;
|
|
7
|
+
'loadingHidden': string;
|
|
8
|
+
'root': string;
|
|
9
|
+
'selected': string;
|
|
10
|
+
'size-l': string;
|
|
11
|
+
'size-m': string;
|
|
12
|
+
'size-s': string;
|
|
13
|
+
'tooltipCategory': string;
|
|
14
|
+
'tooltipCategoryIcon': string;
|
|
15
|
+
'tooltipCategoryText': string;
|
|
16
|
+
'tooltipContent': string;
|
|
17
|
+
'tooltipName': string;
|
|
18
|
+
'tooltipSpacing': string;
|
|
19
|
+
'visible': string;
|
|
20
|
+
}
|
|
21
|
+
export const cssExports: CssExports;
|
|
22
|
+
export default cssExports;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import cn from 'classnames';
|
|
4
|
+
|
|
5
|
+
import { Badge } from '#uilib/components/ui/Badge';
|
|
6
|
+
import {
|
|
7
|
+
Tooltip,
|
|
8
|
+
TooltipContent,
|
|
9
|
+
TooltipTrigger,
|
|
10
|
+
} from '#uilib/components/ui/Tooltip';
|
|
11
|
+
|
|
12
|
+
import { getCategoryIcon } from '../driverCategoryIcon';
|
|
13
|
+
import type { DriverData } from '../driverMapGeography';
|
|
14
|
+
import S from './DriverIcon.styl';
|
|
15
|
+
|
|
16
|
+
export const BADGE_SIZES = {
|
|
17
|
+
s: 's',
|
|
18
|
+
m: 'm',
|
|
19
|
+
l: 'l',
|
|
20
|
+
} as const;
|
|
21
|
+
|
|
22
|
+
export type BadgeSize = (typeof BADGE_SIZES)[keyof typeof BADGE_SIZES];
|
|
23
|
+
|
|
24
|
+
interface DriverIconProps {
|
|
25
|
+
driver: DriverData;
|
|
26
|
+
size: BadgeSize;
|
|
27
|
+
isSelected: boolean;
|
|
28
|
+
onClick: () => void;
|
|
29
|
+
isVisible: boolean;
|
|
30
|
+
isLoading?: boolean;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function DriverIcon({
|
|
34
|
+
driver,
|
|
35
|
+
size,
|
|
36
|
+
isSelected,
|
|
37
|
+
onClick,
|
|
38
|
+
isVisible,
|
|
39
|
+
isLoading = false,
|
|
40
|
+
}: DriverIconProps) {
|
|
41
|
+
return (
|
|
42
|
+
<Tooltip>
|
|
43
|
+
<TooltipTrigger
|
|
44
|
+
asChild
|
|
45
|
+
className={cn(
|
|
46
|
+
S.root,
|
|
47
|
+
S[`size-${size}`],
|
|
48
|
+
isSelected && S.selected,
|
|
49
|
+
isVisible ? S.visible : S.hidden,
|
|
50
|
+
isLoading && S.loadingHidden,
|
|
51
|
+
)}
|
|
52
|
+
>
|
|
53
|
+
<button
|
|
54
|
+
type="button"
|
|
55
|
+
onClick={onClick}
|
|
56
|
+
style={{
|
|
57
|
+
left: `${driver.coordinates.x}%`,
|
|
58
|
+
top: `${driver.coordinates.y}%`,
|
|
59
|
+
zIndex: isSelected ? 2 : '',
|
|
60
|
+
}}
|
|
61
|
+
>
|
|
62
|
+
<Badge className={S.badge}>
|
|
63
|
+
<div className={S.icon}>{getCategoryIcon(driver.category)}</div>
|
|
64
|
+
</Badge>
|
|
65
|
+
</button>
|
|
66
|
+
</TooltipTrigger>
|
|
67
|
+
|
|
68
|
+
<TooltipContent side="top" className={S.tooltipContent}>
|
|
69
|
+
<div className={S.tooltipSpacing}>
|
|
70
|
+
<div className={S.tooltipCategory}>
|
|
71
|
+
<span className={S.tooltipCategoryIcon}>
|
|
72
|
+
{getCategoryIcon(driver.category)}
|
|
73
|
+
</span>
|
|
74
|
+
<span className={S.tooltipCategoryText}>{driver.category}</span>
|
|
75
|
+
</div>
|
|
76
|
+
<div className={S.tooltipName}>{driver.name}</div>
|
|
77
|
+
</div>
|
|
78
|
+
</TooltipContent>
|
|
79
|
+
</Tooltip>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
@@ -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;
|