xertica-ui 1.3.7 → 1.3.8
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/components/Sidebar.tsx +16 -8
- package/components/examples/ApiKeyMapExample.tsx +71 -0
- package/components/examples/SidebarLogoExample.tsx +65 -0
- package/components/ui/google-maps-loader.tsx +56 -12
- package/components/ui/map.tsx +9 -1
- package/components/ui/route-map.tsx +9 -1
- package/dist/components/Sidebar.d.ts +3 -1
- package/dist/components/ui/google-maps-loader.d.ts +6 -3
- package/dist/index.es.js +62 -18
- package/dist/index.umd.js +62 -18
- package/package.json +1 -1
package/components/Sidebar.tsx
CHANGED
|
@@ -74,6 +74,8 @@ interface SidebarProps {
|
|
|
74
74
|
location: { pathname: string };
|
|
75
75
|
navigate: (path: string) => void;
|
|
76
76
|
routes: RouteConfig[];
|
|
77
|
+
logo?: React.ReactNode;
|
|
78
|
+
logoCollapsed?: React.ReactNode;
|
|
77
79
|
}
|
|
78
80
|
|
|
79
81
|
export function Sidebar({
|
|
@@ -84,6 +86,8 @@ export function Sidebar({
|
|
|
84
86
|
location,
|
|
85
87
|
navigate,
|
|
86
88
|
routes,
|
|
89
|
+
logo,
|
|
90
|
+
logoCollapsed,
|
|
87
91
|
}: SidebarProps) {
|
|
88
92
|
const navRef = useRef<HTMLDivElement>(null);
|
|
89
93
|
const [hasOverflow, setHasOverflow] = useState(false);
|
|
@@ -318,15 +322,19 @@ export function Sidebar({
|
|
|
318
322
|
>
|
|
319
323
|
<div className="flex items-center justify-center flex-shrink-0">
|
|
320
324
|
{expanded ? (
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
+
logo || (
|
|
326
|
+
<XerticaLogo
|
|
327
|
+
className="h-5 w-auto"
|
|
328
|
+
variant="white"
|
|
329
|
+
/>
|
|
330
|
+
)
|
|
325
331
|
) : (
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
332
|
+
logoCollapsed || (
|
|
333
|
+
<XerticaXLogo
|
|
334
|
+
className="h-5 w-auto"
|
|
335
|
+
variant="white"
|
|
336
|
+
/>
|
|
337
|
+
)
|
|
330
338
|
)}
|
|
331
339
|
</div>
|
|
332
340
|
</div>
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Map } from '../ui/map';
|
|
3
|
+
import { RouteMap } from '../ui/route-map';
|
|
4
|
+
|
|
5
|
+
export function ApiKeyMapExample() {
|
|
6
|
+
const [key, setKey] = React.useState('');
|
|
7
|
+
const [appliedKey, setAppliedKey] = React.useState('');
|
|
8
|
+
|
|
9
|
+
const handleApply = () => {
|
|
10
|
+
if (key) setAppliedKey(key);
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<div className="space-y-8 p-6">
|
|
15
|
+
<div className="space-y-4">
|
|
16
|
+
<h2 className="text-2xl font-bold">Map with Explicit API Key</h2>
|
|
17
|
+
<p className="text-muted-foreground">
|
|
18
|
+
Enter a Google Maps API Key to load the maps below. This simulates a scenario where the key is provided dynamically or via props, overriding/fallback for the global context.
|
|
19
|
+
</p>
|
|
20
|
+
|
|
21
|
+
<div className="flex gap-4 max-w-xl">
|
|
22
|
+
<input
|
|
23
|
+
type="text"
|
|
24
|
+
value={key}
|
|
25
|
+
onChange={(e) => setKey(e.target.value)}
|
|
26
|
+
placeholder="Enter Google Maps API Key"
|
|
27
|
+
className="flex-1 px-4 py-2 border rounded-md bg-background"
|
|
28
|
+
/>
|
|
29
|
+
<button
|
|
30
|
+
onClick={handleApply}
|
|
31
|
+
className="px-4 py-2 bg-primary text-primary-foreground rounded-md hover:bg-primary/90"
|
|
32
|
+
>
|
|
33
|
+
Load Maps
|
|
34
|
+
</button>
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
{appliedKey ? (
|
|
39
|
+
<div className="grid md:grid-cols-2 gap-8">
|
|
40
|
+
<div className="space-y-4">
|
|
41
|
+
<h3 className="font-semibold">Standard Map</h3>
|
|
42
|
+
<Map
|
|
43
|
+
apiKey={appliedKey}
|
|
44
|
+
height="400px"
|
|
45
|
+
center={{ lat: -23.5505, lng: -46.6333 }}
|
|
46
|
+
zoom={12}
|
|
47
|
+
markers={[
|
|
48
|
+
{ position: { lat: -23.5505, lng: -46.6333 }, title: 'São Paulo' }
|
|
49
|
+
]}
|
|
50
|
+
/>
|
|
51
|
+
</div>
|
|
52
|
+
|
|
53
|
+
<div className="space-y-4">
|
|
54
|
+
<h3 className="font-semibold">Route Map</h3>
|
|
55
|
+
<RouteMap
|
|
56
|
+
apiKey={appliedKey}
|
|
57
|
+
height="400px"
|
|
58
|
+
origin={{ lat: -23.5505, lng: -46.6333 }}
|
|
59
|
+
destination={{ lat: -23.6005, lng: -46.6833 }}
|
|
60
|
+
travelMode="DRIVING"
|
|
61
|
+
/>
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
) : (
|
|
65
|
+
<div className="p-12 border-2 border-dashed rounded-lg text-center text-muted-foreground">
|
|
66
|
+
Enter an API Key above to render the maps.
|
|
67
|
+
</div>
|
|
68
|
+
)}
|
|
69
|
+
</div>
|
|
70
|
+
);
|
|
71
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { Sidebar, RouteConfig } from '../Sidebar';
|
|
3
|
+
import { Home, Settings, User } from 'lucide-react';
|
|
4
|
+
import { BrowserRouter, useNavigate, useLocation } from 'react-router';
|
|
5
|
+
|
|
6
|
+
// Wrapper wrapper to provide router context
|
|
7
|
+
export function SidebarLogoExample() {
|
|
8
|
+
return (
|
|
9
|
+
<BrowserRouter>
|
|
10
|
+
<SidebarLogoContent />
|
|
11
|
+
</BrowserRouter>
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function SidebarLogoContent() {
|
|
16
|
+
const [expanded, setExpanded] = useState(true);
|
|
17
|
+
const navigate = useNavigate();
|
|
18
|
+
const location = useLocation();
|
|
19
|
+
|
|
20
|
+
const routes: RouteConfig[] = [
|
|
21
|
+
{ path: '/home', label: 'Home', icon: Home },
|
|
22
|
+
{ path: '/profile', label: 'Profile', icon: User },
|
|
23
|
+
{ path: '/settings', label: 'Settings', icon: Settings },
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
const CustomLogo = (
|
|
27
|
+
<div className="flex items-center gap-2 font-bold text-xl text-primary">
|
|
28
|
+
<div className="w-8 h-8 bg-primary rounded-full flex items-center justify-center text-primary-foreground">
|
|
29
|
+
C
|
|
30
|
+
</div>
|
|
31
|
+
<span>CustomBrand</span>
|
|
32
|
+
</div>
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
const CustomLogoCollapsed = (
|
|
36
|
+
<div className="w-8 h-8 bg-primary rounded-full flex items-center justify-center text-primary-foreground font-bold">
|
|
37
|
+
C
|
|
38
|
+
</div>
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<div className="flex h-[500px] border rounded-lg overflow-hidden bg-background">
|
|
43
|
+
<Sidebar
|
|
44
|
+
expanded={expanded}
|
|
45
|
+
onToggle={() => setExpanded(!expanded)}
|
|
46
|
+
user={{ email: 'test@example.com' }}
|
|
47
|
+
onLogout={() => console.log('Logout')}
|
|
48
|
+
location={location}
|
|
49
|
+
navigate={navigate}
|
|
50
|
+
routes={routes}
|
|
51
|
+
logo={CustomLogo}
|
|
52
|
+
logoCollapsed={CustomLogoCollapsed}
|
|
53
|
+
/>
|
|
54
|
+
<div className={`flex-1 p-8 transition-all duration-300 ${expanded ? 'ml-64' : 'ml-20'}`}>
|
|
55
|
+
<h1 className="text-2xl font-bold mb-4">Sidebar with Custom Logo</h1>
|
|
56
|
+
<p>This example demonstrates passing a custom logo component to the Sidebar.</p>
|
|
57
|
+
<div className="mt-8 p-4 border rounded bg-muted/20">
|
|
58
|
+
<p className="text-sm text-muted-foreground">
|
|
59
|
+
Try toggling the sidebar to see the collapsed logo version.
|
|
60
|
+
</p>
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
);
|
|
65
|
+
}
|
|
@@ -6,11 +6,13 @@ import { GOOGLE_MAPS_LIBRARIES, GOOGLE_MAPS_ID } from './map-config';
|
|
|
6
6
|
interface GoogleMapsContextType {
|
|
7
7
|
isLoaded: boolean;
|
|
8
8
|
loadError: Error | undefined;
|
|
9
|
+
load: (apiKey: string) => Promise<void>;
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
const GoogleMapsContext = createContext<GoogleMapsContextType>({
|
|
12
13
|
isLoaded: false,
|
|
13
14
|
loadError: undefined,
|
|
15
|
+
load: () => Promise.resolve(),
|
|
14
16
|
});
|
|
15
17
|
|
|
16
18
|
// Singleton global para prevenir múltiplos carregamentos
|
|
@@ -57,7 +59,7 @@ function removeExistingScript(): void {
|
|
|
57
59
|
}
|
|
58
60
|
|
|
59
61
|
// Remover script existente
|
|
60
|
-
const existingScript = document.querySelector(`script[src
|
|
62
|
+
const existingScript = document.querySelector(`script[src*="maps.googleapis.com/maps/api/js"]`);
|
|
61
63
|
if (existingScript) {
|
|
62
64
|
existingScript.remove();
|
|
63
65
|
}
|
|
@@ -202,6 +204,7 @@ function getOrCreateSingleton() {
|
|
|
202
204
|
isLoaded: isPreloaded,
|
|
203
205
|
loadError: undefined,
|
|
204
206
|
listeners: new Set(),
|
|
207
|
+
scriptElement: undefined
|
|
205
208
|
};
|
|
206
209
|
}
|
|
207
210
|
|
|
@@ -218,7 +221,24 @@ function updateSingleton(state: Partial<GoogleMapsContextType>) {
|
|
|
218
221
|
if (state.isLoaded !== undefined) singleton.isLoaded = state.isLoaded;
|
|
219
222
|
if (state.loadError !== undefined) singleton.loadError = state.loadError;
|
|
220
223
|
|
|
221
|
-
|
|
224
|
+
// Prepare safe state to notify
|
|
225
|
+
const newState: GoogleMapsContextType = {
|
|
226
|
+
isLoaded: singleton.isLoaded,
|
|
227
|
+
loadError: singleton.loadError,
|
|
228
|
+
load: async (apiKey: string) => {
|
|
229
|
+
// Allow manual loading call via stored function in context if needed,
|
|
230
|
+
// though typically we use the direct export or loadGoogleMapsScript
|
|
231
|
+
if (singleton.isLoaded) return;
|
|
232
|
+
try {
|
|
233
|
+
await loadGoogleMapsScript(apiKey);
|
|
234
|
+
updateSingleton({ isLoaded: true, loadError: undefined });
|
|
235
|
+
} catch (error: any) {
|
|
236
|
+
updateSingleton({ isLoaded: false, loadError: error });
|
|
237
|
+
throw error;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
|
|
222
242
|
singleton.listeners.forEach(listener => listener(newState));
|
|
223
243
|
}
|
|
224
244
|
|
|
@@ -228,11 +248,25 @@ function updateSingleton(state: Partial<GoogleMapsContextType>) {
|
|
|
228
248
|
const SingletonLoaderWrapper = ({ children }: { children: ReactNode }) => {
|
|
229
249
|
const [state, setState] = useState<GoogleMapsContextType>(() => {
|
|
230
250
|
const singleton = getOrCreateSingleton();
|
|
231
|
-
|
|
251
|
+
|
|
252
|
+
// Default load function that triggers the script load
|
|
253
|
+
const loadFn = async (apiKey: string) => {
|
|
254
|
+
if (singleton?.isLoaded) return;
|
|
255
|
+
try {
|
|
256
|
+
await loadGoogleMapsScript(apiKey);
|
|
257
|
+
updateSingleton({ isLoaded: true, loadError: undefined });
|
|
258
|
+
} catch (error: any) {
|
|
259
|
+
updateSingleton({ isLoaded: false, loadError: error });
|
|
260
|
+
throw error;
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
if (!singleton) return { isLoaded: false, loadError: undefined, load: loadFn };
|
|
232
265
|
|
|
233
266
|
return {
|
|
234
267
|
isLoaded: singleton.isLoaded,
|
|
235
268
|
loadError: singleton.loadError,
|
|
269
|
+
load: loadFn
|
|
236
270
|
};
|
|
237
271
|
});
|
|
238
272
|
|
|
@@ -246,8 +280,12 @@ const SingletonLoaderWrapper = ({ children }: { children: ReactNode }) => {
|
|
|
246
280
|
|
|
247
281
|
singleton.listeners.add(listener);
|
|
248
282
|
|
|
249
|
-
// Sincronizar estado inicial
|
|
250
|
-
listener({
|
|
283
|
+
// Sincronizar estado inicial e função de load
|
|
284
|
+
listener({
|
|
285
|
+
isLoaded: singleton.isLoaded,
|
|
286
|
+
loadError: singleton.loadError,
|
|
287
|
+
load: state.load
|
|
288
|
+
});
|
|
251
289
|
|
|
252
290
|
return () => {
|
|
253
291
|
singleton.listeners.delete(listener);
|
|
@@ -264,7 +302,7 @@ const SingletonLoaderWrapper = ({ children }: { children: ReactNode }) => {
|
|
|
264
302
|
/**
|
|
265
303
|
* Componente que carrega o Google Maps manualmente
|
|
266
304
|
*/
|
|
267
|
-
const LoaderInitializer = () => {
|
|
305
|
+
const LoaderInitializer = ({ apiKey }: { apiKey?: string }) => {
|
|
268
306
|
const hasInitializedRef = useRef(false);
|
|
269
307
|
|
|
270
308
|
useEffect(() => {
|
|
@@ -285,10 +323,11 @@ const LoaderInitializer = () => {
|
|
|
285
323
|
|
|
286
324
|
hasInitializedRef.current = true;
|
|
287
325
|
|
|
288
|
-
|
|
326
|
+
// Use prop key OR get from storage
|
|
327
|
+
const keyToUse = apiKey || getInitialApiKey();
|
|
289
328
|
|
|
290
329
|
// Se não houver API key, apenas marcar como não carregado (sem erro)
|
|
291
|
-
if (!
|
|
330
|
+
if (!keyToUse) {
|
|
292
331
|
updateSingleton({
|
|
293
332
|
isLoaded: false,
|
|
294
333
|
loadError: undefined // Não definir erro quando não há API key
|
|
@@ -296,25 +335,30 @@ const LoaderInitializer = () => {
|
|
|
296
335
|
return;
|
|
297
336
|
}
|
|
298
337
|
|
|
299
|
-
loadGoogleMapsScript(
|
|
338
|
+
loadGoogleMapsScript(keyToUse)
|
|
300
339
|
.then(() => {
|
|
301
340
|
updateSingleton({ isLoaded: true, loadError: undefined });
|
|
302
341
|
})
|
|
303
342
|
.catch((error) => {
|
|
304
343
|
updateSingleton({ isLoaded: false, loadError: error });
|
|
305
344
|
});
|
|
306
|
-
}, []);
|
|
345
|
+
}, [apiKey]);
|
|
307
346
|
|
|
308
347
|
return null;
|
|
309
348
|
};
|
|
310
349
|
|
|
350
|
+
interface GoogleMapsLoaderProviderProps {
|
|
351
|
+
children: ReactNode;
|
|
352
|
+
apiKey?: string;
|
|
353
|
+
}
|
|
354
|
+
|
|
311
355
|
/**
|
|
312
356
|
* GoogleMapsLoaderProvider
|
|
313
357
|
*
|
|
314
358
|
* Provider global que gerencia o carregamento da API do Google Maps.
|
|
315
359
|
* Usa carregamento manual do script para evitar conflitos com custom elements.
|
|
316
360
|
*/
|
|
317
|
-
export const GoogleMapsLoaderProvider = ({ children }:
|
|
361
|
+
export const GoogleMapsLoaderProvider = ({ children, apiKey }: GoogleMapsLoaderProviderProps) => {
|
|
318
362
|
const [shouldInitialize] = useState(() => {
|
|
319
363
|
const singleton = getOrCreateSingleton();
|
|
320
364
|
if (!singleton) return false;
|
|
@@ -330,7 +374,7 @@ export const GoogleMapsLoaderProvider = ({ children }: { children: ReactNode })
|
|
|
330
374
|
|
|
331
375
|
return (
|
|
332
376
|
<>
|
|
333
|
-
{shouldInitialize && <LoaderInitializer />}
|
|
377
|
+
{shouldInitialize && <LoaderInitializer apiKey={apiKey} />}
|
|
334
378
|
<SingletonLoaderWrapper>{children}</SingletonLoaderWrapper>
|
|
335
379
|
</>
|
|
336
380
|
);
|
package/components/ui/map.tsx
CHANGED
|
@@ -96,6 +96,14 @@ const MapContent = React.forwardRef<HTMLDivElement, MapProps & { apiKey: string
|
|
|
96
96
|
|
|
97
97
|
// Initialize map once
|
|
98
98
|
useEffect(() => {
|
|
99
|
+
// If we have an apiKey and not loaded, try to load it
|
|
100
|
+
if (!isLoaded && apiKey && !loadError) {
|
|
101
|
+
const { load } = useGoogleMapsLoader();
|
|
102
|
+
if (load) {
|
|
103
|
+
load(apiKey).catch((console.error));
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
99
107
|
if (!isLoaded || !mapContainerRef.current || isInitializedRef.current) return;
|
|
100
108
|
|
|
101
109
|
isInitializedRef.current = true;
|
|
@@ -121,7 +129,7 @@ const MapContent = React.forwardRef<HTMLDivElement, MapProps & { apiKey: string
|
|
|
121
129
|
isInitializedRef.current = false;
|
|
122
130
|
mapRef.current = null;
|
|
123
131
|
};
|
|
124
|
-
}, [isLoaded]);
|
|
132
|
+
}, [isLoaded, apiKey]);
|
|
125
133
|
|
|
126
134
|
// Update markers
|
|
127
135
|
useEffect(() => {
|
|
@@ -47,6 +47,14 @@ const RouteMapContent = React.forwardRef<HTMLDivElement, RouteMapProps & { apiKe
|
|
|
47
47
|
|
|
48
48
|
// Initialize map once
|
|
49
49
|
useEffect(() => {
|
|
50
|
+
// If we have an apiKey and not loaded, try to load it
|
|
51
|
+
if (!isLoaded && apiKey && !loadError) {
|
|
52
|
+
const { load } = useGoogleMapsLoader();
|
|
53
|
+
if (load) {
|
|
54
|
+
load(apiKey).catch((console.error));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
50
58
|
if (!isLoaded || !mapContainerRef.current || isInitializedRef.current) return;
|
|
51
59
|
|
|
52
60
|
isInitializedRef.current = true;
|
|
@@ -85,7 +93,7 @@ const RouteMapContent = React.forwardRef<HTMLDivElement, RouteMapProps & { apiKe
|
|
|
85
93
|
isInitializedRef.current = false;
|
|
86
94
|
mapRef.current = null;
|
|
87
95
|
};
|
|
88
|
-
}, [isLoaded]);
|
|
96
|
+
}, [isLoaded, apiKey]);
|
|
89
97
|
|
|
90
98
|
// Calculate route
|
|
91
99
|
useEffect(() => {
|
|
@@ -17,6 +17,8 @@ interface SidebarProps {
|
|
|
17
17
|
};
|
|
18
18
|
navigate: (path: string) => void;
|
|
19
19
|
routes: RouteConfig[];
|
|
20
|
+
logo?: React.ReactNode;
|
|
21
|
+
logoCollapsed?: React.ReactNode;
|
|
20
22
|
}
|
|
21
|
-
export declare function Sidebar({ expanded, onToggle, user, onLogout, location, navigate, routes, }: SidebarProps): import("react/jsx-runtime").JSX.Element;
|
|
23
|
+
export declare function Sidebar({ expanded, onToggle, user, onLogout, location, navigate, routes, logo, logoCollapsed, }: SidebarProps): import("react/jsx-runtime").JSX.Element;
|
|
22
24
|
export {};
|
|
@@ -2,6 +2,7 @@ import { ReactNode } from 'react';
|
|
|
2
2
|
interface GoogleMapsContextType {
|
|
3
3
|
isLoaded: boolean;
|
|
4
4
|
loadError: Error | undefined;
|
|
5
|
+
load: (apiKey: string) => Promise<void>;
|
|
5
6
|
}
|
|
6
7
|
declare global {
|
|
7
8
|
interface Window {
|
|
@@ -13,15 +14,17 @@ declare global {
|
|
|
13
14
|
};
|
|
14
15
|
}
|
|
15
16
|
}
|
|
17
|
+
interface GoogleMapsLoaderProviderProps {
|
|
18
|
+
children: ReactNode;
|
|
19
|
+
apiKey?: string;
|
|
20
|
+
}
|
|
16
21
|
/**
|
|
17
22
|
* GoogleMapsLoaderProvider
|
|
18
23
|
*
|
|
19
24
|
* Provider global que gerencia o carregamento da API do Google Maps.
|
|
20
25
|
* Usa carregamento manual do script para evitar conflitos com custom elements.
|
|
21
26
|
*/
|
|
22
|
-
export declare const GoogleMapsLoaderProvider: ({ children }:
|
|
23
|
-
children: ReactNode;
|
|
24
|
-
}) => import("react/jsx-runtime").JSX.Element;
|
|
27
|
+
export declare const GoogleMapsLoaderProvider: ({ children, apiKey }: GoogleMapsLoaderProviderProps) => import("react/jsx-runtime").JSX.Element;
|
|
25
28
|
export declare const useGoogleMapsLoader: () => GoogleMapsContextType;
|
|
26
29
|
/**
|
|
27
30
|
* Recarrega o Google Maps com uma nova API key
|
package/dist/index.es.js
CHANGED
|
@@ -47735,7 +47735,8 @@ const GOOGLE_MAPS_LIBRARIES = ["marker", "places", "geometry", "drawing"];
|
|
|
47735
47735
|
const GOOGLE_MAPS_ID = "xertica-google-map-script";
|
|
47736
47736
|
const GoogleMapsContext = createContext({
|
|
47737
47737
|
isLoaded: false,
|
|
47738
|
-
loadError: void 0
|
|
47738
|
+
loadError: void 0,
|
|
47739
|
+
load: () => Promise.resolve()
|
|
47739
47740
|
});
|
|
47740
47741
|
function getInitialApiKey() {
|
|
47741
47742
|
if (typeof window === "undefined") return void 0;
|
|
@@ -47856,7 +47857,8 @@ function getOrCreateSingleton() {
|
|
|
47856
47857
|
window.__XERTICA_GOOGLE_MAPS_LOADER__ = {
|
|
47857
47858
|
isLoaded: isPreloaded,
|
|
47858
47859
|
loadError: void 0,
|
|
47859
|
-
listeners: /* @__PURE__ */ new Set()
|
|
47860
|
+
listeners: /* @__PURE__ */ new Set(),
|
|
47861
|
+
scriptElement: void 0
|
|
47860
47862
|
};
|
|
47861
47863
|
}
|
|
47862
47864
|
return window.__XERTICA_GOOGLE_MAPS_LOADER__;
|
|
@@ -47866,16 +47868,40 @@ function updateSingleton(state) {
|
|
|
47866
47868
|
if (!singleton) return;
|
|
47867
47869
|
if (state.isLoaded !== void 0) singleton.isLoaded = state.isLoaded;
|
|
47868
47870
|
if (state.loadError !== void 0) singleton.loadError = state.loadError;
|
|
47869
|
-
const newState = {
|
|
47871
|
+
const newState = {
|
|
47872
|
+
isLoaded: singleton.isLoaded,
|
|
47873
|
+
loadError: singleton.loadError,
|
|
47874
|
+
load: async (apiKey) => {
|
|
47875
|
+
if (singleton.isLoaded) return;
|
|
47876
|
+
try {
|
|
47877
|
+
await loadGoogleMapsScript(apiKey);
|
|
47878
|
+
updateSingleton({ isLoaded: true, loadError: void 0 });
|
|
47879
|
+
} catch (error) {
|
|
47880
|
+
updateSingleton({ isLoaded: false, loadError: error });
|
|
47881
|
+
throw error;
|
|
47882
|
+
}
|
|
47883
|
+
}
|
|
47884
|
+
};
|
|
47870
47885
|
singleton.listeners.forEach((listener) => listener(newState));
|
|
47871
47886
|
}
|
|
47872
47887
|
const SingletonLoaderWrapper = ({ children }) => {
|
|
47873
47888
|
const [state, setState] = useState(() => {
|
|
47874
47889
|
const singleton = getOrCreateSingleton();
|
|
47875
|
-
|
|
47890
|
+
const loadFn = async (apiKey) => {
|
|
47891
|
+
if (singleton == null ? void 0 : singleton.isLoaded) return;
|
|
47892
|
+
try {
|
|
47893
|
+
await loadGoogleMapsScript(apiKey);
|
|
47894
|
+
updateSingleton({ isLoaded: true, loadError: void 0 });
|
|
47895
|
+
} catch (error) {
|
|
47896
|
+
updateSingleton({ isLoaded: false, loadError: error });
|
|
47897
|
+
throw error;
|
|
47898
|
+
}
|
|
47899
|
+
};
|
|
47900
|
+
if (!singleton) return { isLoaded: false, loadError: void 0, load: loadFn };
|
|
47876
47901
|
return {
|
|
47877
47902
|
isLoaded: singleton.isLoaded,
|
|
47878
|
-
loadError: singleton.loadError
|
|
47903
|
+
loadError: singleton.loadError,
|
|
47904
|
+
load: loadFn
|
|
47879
47905
|
};
|
|
47880
47906
|
});
|
|
47881
47907
|
useEffect(() => {
|
|
@@ -47885,14 +47911,18 @@ const SingletonLoaderWrapper = ({ children }) => {
|
|
|
47885
47911
|
setState(newState);
|
|
47886
47912
|
};
|
|
47887
47913
|
singleton.listeners.add(listener);
|
|
47888
|
-
listener({
|
|
47914
|
+
listener({
|
|
47915
|
+
isLoaded: singleton.isLoaded,
|
|
47916
|
+
loadError: singleton.loadError,
|
|
47917
|
+
load: state.load
|
|
47918
|
+
});
|
|
47889
47919
|
return () => {
|
|
47890
47920
|
singleton.listeners.delete(listener);
|
|
47891
47921
|
};
|
|
47892
47922
|
}, []);
|
|
47893
47923
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(GoogleMapsContext.Provider, { value: state, children });
|
|
47894
47924
|
};
|
|
47895
|
-
const LoaderInitializer = () => {
|
|
47925
|
+
const LoaderInitializer = ({ apiKey }) => {
|
|
47896
47926
|
const hasInitializedRef = useRef(false);
|
|
47897
47927
|
useEffect(() => {
|
|
47898
47928
|
if (hasInitializedRef.current) {
|
|
@@ -47906,8 +47936,8 @@ const LoaderInitializer = () => {
|
|
|
47906
47936
|
return;
|
|
47907
47937
|
}
|
|
47908
47938
|
hasInitializedRef.current = true;
|
|
47909
|
-
const
|
|
47910
|
-
if (!
|
|
47939
|
+
const keyToUse = apiKey || getInitialApiKey();
|
|
47940
|
+
if (!keyToUse) {
|
|
47911
47941
|
updateSingleton({
|
|
47912
47942
|
isLoaded: false,
|
|
47913
47943
|
loadError: void 0
|
|
@@ -47915,15 +47945,15 @@ const LoaderInitializer = () => {
|
|
|
47915
47945
|
});
|
|
47916
47946
|
return;
|
|
47917
47947
|
}
|
|
47918
|
-
loadGoogleMapsScript(
|
|
47948
|
+
loadGoogleMapsScript(keyToUse).then(() => {
|
|
47919
47949
|
updateSingleton({ isLoaded: true, loadError: void 0 });
|
|
47920
47950
|
}).catch((error) => {
|
|
47921
47951
|
updateSingleton({ isLoaded: false, loadError: error });
|
|
47922
47952
|
});
|
|
47923
|
-
}, []);
|
|
47953
|
+
}, [apiKey]);
|
|
47924
47954
|
return null;
|
|
47925
47955
|
};
|
|
47926
|
-
const GoogleMapsLoaderProvider = ({ children }) => {
|
|
47956
|
+
const GoogleMapsLoaderProvider = ({ children, apiKey }) => {
|
|
47927
47957
|
const [shouldInitialize] = useState(() => {
|
|
47928
47958
|
const singleton = getOrCreateSingleton();
|
|
47929
47959
|
if (!singleton) return false;
|
|
@@ -47934,7 +47964,7 @@ const GoogleMapsLoaderProvider = ({ children }) => {
|
|
|
47934
47964
|
return true;
|
|
47935
47965
|
});
|
|
47936
47966
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
47937
|
-
shouldInitialize && /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderInitializer, {}),
|
|
47967
|
+
shouldInitialize && /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderInitializer, { apiKey }),
|
|
47938
47968
|
/* @__PURE__ */ jsxRuntimeExports.jsx(SingletonLoaderWrapper, { children })
|
|
47939
47969
|
] });
|
|
47940
47970
|
};
|
|
@@ -50509,7 +50539,9 @@ function Sidebar({
|
|
|
50509
50539
|
onLogout,
|
|
50510
50540
|
location,
|
|
50511
50541
|
navigate,
|
|
50512
|
-
routes: routes2
|
|
50542
|
+
routes: routes2,
|
|
50543
|
+
logo,
|
|
50544
|
+
logoCollapsed
|
|
50513
50545
|
}) {
|
|
50514
50546
|
const navRef = useRef(null);
|
|
50515
50547
|
const [hasOverflow, setHasOverflow] = useState(false);
|
|
@@ -50666,13 +50698,13 @@ function Sidebar({
|
|
|
50666
50698
|
"div",
|
|
50667
50699
|
{
|
|
50668
50700
|
className: `flex items-center h-10 ${expanded ? "justify-center" : "justify-center"}`,
|
|
50669
|
-
children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center justify-center flex-shrink-0", children: expanded ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
50701
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center justify-center flex-shrink-0", children: expanded ? logo || /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
50670
50702
|
XerticaLogo,
|
|
50671
50703
|
{
|
|
50672
50704
|
className: "h-5 w-auto",
|
|
50673
50705
|
variant: "white"
|
|
50674
50706
|
}
|
|
50675
|
-
) : /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
50707
|
+
) : logoCollapsed || /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
50676
50708
|
XerticaXLogo,
|
|
50677
50709
|
{
|
|
50678
50710
|
className: "h-5 w-auto",
|
|
@@ -69229,6 +69261,12 @@ const MapContent = React__default.forwardRef(
|
|
|
69229
69261
|
}
|
|
69230
69262
|
}, []);
|
|
69231
69263
|
useEffect(() => {
|
|
69264
|
+
if (!isLoaded && apiKey && !loadError) {
|
|
69265
|
+
const { load } = useGoogleMapsLoader();
|
|
69266
|
+
if (load) {
|
|
69267
|
+
load(apiKey).catch(console.error);
|
|
69268
|
+
}
|
|
69269
|
+
}
|
|
69232
69270
|
if (!isLoaded || !mapContainerRef.current || isInitializedRef.current) return;
|
|
69233
69271
|
isInitializedRef.current = true;
|
|
69234
69272
|
const map2 = new google.maps.Map(mapContainerRef.current, {
|
|
@@ -69250,7 +69288,7 @@ const MapContent = React__default.forwardRef(
|
|
|
69250
69288
|
isInitializedRef.current = false;
|
|
69251
69289
|
mapRef.current = null;
|
|
69252
69290
|
};
|
|
69253
|
-
}, [isLoaded]);
|
|
69291
|
+
}, [isLoaded, apiKey]);
|
|
69254
69292
|
useEffect(() => {
|
|
69255
69293
|
var _a, _b;
|
|
69256
69294
|
const map2 = mapRef.current;
|
|
@@ -69525,6 +69563,12 @@ const RouteMapContent = React__default.forwardRef(
|
|
|
69525
69563
|
const isInitializedRef = useRef(false);
|
|
69526
69564
|
const isCalculatingRef = useRef(false);
|
|
69527
69565
|
useEffect(() => {
|
|
69566
|
+
if (!isLoaded && apiKey && !loadError) {
|
|
69567
|
+
const { load } = useGoogleMapsLoader();
|
|
69568
|
+
if (load) {
|
|
69569
|
+
load(apiKey).catch(console.error);
|
|
69570
|
+
}
|
|
69571
|
+
}
|
|
69528
69572
|
if (!isLoaded || !mapContainerRef.current || isInitializedRef.current) return;
|
|
69529
69573
|
isInitializedRef.current = true;
|
|
69530
69574
|
const map2 = new google.maps.Map(mapContainerRef.current, {
|
|
@@ -69557,7 +69601,7 @@ const RouteMapContent = React__default.forwardRef(
|
|
|
69557
69601
|
isInitializedRef.current = false;
|
|
69558
69602
|
mapRef.current = null;
|
|
69559
69603
|
};
|
|
69560
|
-
}, [isLoaded]);
|
|
69604
|
+
}, [isLoaded, apiKey]);
|
|
69561
69605
|
useEffect(() => {
|
|
69562
69606
|
const map2 = mapRef.current;
|
|
69563
69607
|
const renderer = directionsRendererRef.current;
|
package/dist/index.umd.js
CHANGED
|
@@ -47754,7 +47754,8 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
|
|
|
47754
47754
|
const GOOGLE_MAPS_ID = "xertica-google-map-script";
|
|
47755
47755
|
const GoogleMapsContext = React.createContext({
|
|
47756
47756
|
isLoaded: false,
|
|
47757
|
-
loadError: void 0
|
|
47757
|
+
loadError: void 0,
|
|
47758
|
+
load: () => Promise.resolve()
|
|
47758
47759
|
});
|
|
47759
47760
|
function getInitialApiKey() {
|
|
47760
47761
|
if (typeof window === "undefined") return void 0;
|
|
@@ -47875,7 +47876,8 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
|
|
|
47875
47876
|
window.__XERTICA_GOOGLE_MAPS_LOADER__ = {
|
|
47876
47877
|
isLoaded: isPreloaded,
|
|
47877
47878
|
loadError: void 0,
|
|
47878
|
-
listeners: /* @__PURE__ */ new Set()
|
|
47879
|
+
listeners: /* @__PURE__ */ new Set(),
|
|
47880
|
+
scriptElement: void 0
|
|
47879
47881
|
};
|
|
47880
47882
|
}
|
|
47881
47883
|
return window.__XERTICA_GOOGLE_MAPS_LOADER__;
|
|
@@ -47885,16 +47887,40 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
|
|
|
47885
47887
|
if (!singleton) return;
|
|
47886
47888
|
if (state.isLoaded !== void 0) singleton.isLoaded = state.isLoaded;
|
|
47887
47889
|
if (state.loadError !== void 0) singleton.loadError = state.loadError;
|
|
47888
|
-
const newState = {
|
|
47890
|
+
const newState = {
|
|
47891
|
+
isLoaded: singleton.isLoaded,
|
|
47892
|
+
loadError: singleton.loadError,
|
|
47893
|
+
load: async (apiKey) => {
|
|
47894
|
+
if (singleton.isLoaded) return;
|
|
47895
|
+
try {
|
|
47896
|
+
await loadGoogleMapsScript(apiKey);
|
|
47897
|
+
updateSingleton({ isLoaded: true, loadError: void 0 });
|
|
47898
|
+
} catch (error) {
|
|
47899
|
+
updateSingleton({ isLoaded: false, loadError: error });
|
|
47900
|
+
throw error;
|
|
47901
|
+
}
|
|
47902
|
+
}
|
|
47903
|
+
};
|
|
47889
47904
|
singleton.listeners.forEach((listener) => listener(newState));
|
|
47890
47905
|
}
|
|
47891
47906
|
const SingletonLoaderWrapper = ({ children }) => {
|
|
47892
47907
|
const [state, setState] = React.useState(() => {
|
|
47893
47908
|
const singleton = getOrCreateSingleton();
|
|
47894
|
-
|
|
47909
|
+
const loadFn = async (apiKey) => {
|
|
47910
|
+
if (singleton == null ? void 0 : singleton.isLoaded) return;
|
|
47911
|
+
try {
|
|
47912
|
+
await loadGoogleMapsScript(apiKey);
|
|
47913
|
+
updateSingleton({ isLoaded: true, loadError: void 0 });
|
|
47914
|
+
} catch (error) {
|
|
47915
|
+
updateSingleton({ isLoaded: false, loadError: error });
|
|
47916
|
+
throw error;
|
|
47917
|
+
}
|
|
47918
|
+
};
|
|
47919
|
+
if (!singleton) return { isLoaded: false, loadError: void 0, load: loadFn };
|
|
47895
47920
|
return {
|
|
47896
47921
|
isLoaded: singleton.isLoaded,
|
|
47897
|
-
loadError: singleton.loadError
|
|
47922
|
+
loadError: singleton.loadError,
|
|
47923
|
+
load: loadFn
|
|
47898
47924
|
};
|
|
47899
47925
|
});
|
|
47900
47926
|
React.useEffect(() => {
|
|
@@ -47904,14 +47930,18 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
|
|
|
47904
47930
|
setState(newState);
|
|
47905
47931
|
};
|
|
47906
47932
|
singleton.listeners.add(listener);
|
|
47907
|
-
listener({
|
|
47933
|
+
listener({
|
|
47934
|
+
isLoaded: singleton.isLoaded,
|
|
47935
|
+
loadError: singleton.loadError,
|
|
47936
|
+
load: state.load
|
|
47937
|
+
});
|
|
47908
47938
|
return () => {
|
|
47909
47939
|
singleton.listeners.delete(listener);
|
|
47910
47940
|
};
|
|
47911
47941
|
}, []);
|
|
47912
47942
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(GoogleMapsContext.Provider, { value: state, children });
|
|
47913
47943
|
};
|
|
47914
|
-
const LoaderInitializer = () => {
|
|
47944
|
+
const LoaderInitializer = ({ apiKey }) => {
|
|
47915
47945
|
const hasInitializedRef = React.useRef(false);
|
|
47916
47946
|
React.useEffect(() => {
|
|
47917
47947
|
if (hasInitializedRef.current) {
|
|
@@ -47925,8 +47955,8 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
|
|
|
47925
47955
|
return;
|
|
47926
47956
|
}
|
|
47927
47957
|
hasInitializedRef.current = true;
|
|
47928
|
-
const
|
|
47929
|
-
if (!
|
|
47958
|
+
const keyToUse = apiKey || getInitialApiKey();
|
|
47959
|
+
if (!keyToUse) {
|
|
47930
47960
|
updateSingleton({
|
|
47931
47961
|
isLoaded: false,
|
|
47932
47962
|
loadError: void 0
|
|
@@ -47934,15 +47964,15 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
|
|
|
47934
47964
|
});
|
|
47935
47965
|
return;
|
|
47936
47966
|
}
|
|
47937
|
-
loadGoogleMapsScript(
|
|
47967
|
+
loadGoogleMapsScript(keyToUse).then(() => {
|
|
47938
47968
|
updateSingleton({ isLoaded: true, loadError: void 0 });
|
|
47939
47969
|
}).catch((error) => {
|
|
47940
47970
|
updateSingleton({ isLoaded: false, loadError: error });
|
|
47941
47971
|
});
|
|
47942
|
-
}, []);
|
|
47972
|
+
}, [apiKey]);
|
|
47943
47973
|
return null;
|
|
47944
47974
|
};
|
|
47945
|
-
const GoogleMapsLoaderProvider = ({ children }) => {
|
|
47975
|
+
const GoogleMapsLoaderProvider = ({ children, apiKey }) => {
|
|
47946
47976
|
const [shouldInitialize] = React.useState(() => {
|
|
47947
47977
|
const singleton = getOrCreateSingleton();
|
|
47948
47978
|
if (!singleton) return false;
|
|
@@ -47953,7 +47983,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
|
|
|
47953
47983
|
return true;
|
|
47954
47984
|
});
|
|
47955
47985
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
47956
|
-
shouldInitialize && /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderInitializer, {}),
|
|
47986
|
+
shouldInitialize && /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderInitializer, { apiKey }),
|
|
47957
47987
|
/* @__PURE__ */ jsxRuntimeExports.jsx(SingletonLoaderWrapper, { children })
|
|
47958
47988
|
] });
|
|
47959
47989
|
};
|
|
@@ -50528,7 +50558,9 @@ Please change the parent <Route path="${parentPath}"> to <Route path="${parentPa
|
|
|
50528
50558
|
onLogout,
|
|
50529
50559
|
location: location2,
|
|
50530
50560
|
navigate,
|
|
50531
|
-
routes: routes2
|
|
50561
|
+
routes: routes2,
|
|
50562
|
+
logo,
|
|
50563
|
+
logoCollapsed
|
|
50532
50564
|
}) {
|
|
50533
50565
|
const navRef = React.useRef(null);
|
|
50534
50566
|
const [hasOverflow, setHasOverflow] = React.useState(false);
|
|
@@ -50685,13 +50717,13 @@ Please change the parent <Route path="${parentPath}"> to <Route path="${parentPa
|
|
|
50685
50717
|
"div",
|
|
50686
50718
|
{
|
|
50687
50719
|
className: `flex items-center h-10 ${expanded ? "justify-center" : "justify-center"}`,
|
|
50688
|
-
children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center justify-center flex-shrink-0", children: expanded ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
50720
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center justify-center flex-shrink-0", children: expanded ? logo || /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
50689
50721
|
XerticaLogo,
|
|
50690
50722
|
{
|
|
50691
50723
|
className: "h-5 w-auto",
|
|
50692
50724
|
variant: "white"
|
|
50693
50725
|
}
|
|
50694
|
-
) : /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
50726
|
+
) : logoCollapsed || /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
50695
50727
|
XerticaXLogo,
|
|
50696
50728
|
{
|
|
50697
50729
|
className: "h-5 w-auto",
|
|
@@ -69248,6 +69280,12 @@ For more information, see https://radix-ui.com/primitives/docs/components/alert-
|
|
|
69248
69280
|
}
|
|
69249
69281
|
}, []);
|
|
69250
69282
|
React.useEffect(() => {
|
|
69283
|
+
if (!isLoaded && apiKey && !loadError) {
|
|
69284
|
+
const { load } = useGoogleMapsLoader();
|
|
69285
|
+
if (load) {
|
|
69286
|
+
load(apiKey).catch(console.error);
|
|
69287
|
+
}
|
|
69288
|
+
}
|
|
69251
69289
|
if (!isLoaded || !mapContainerRef.current || isInitializedRef.current) return;
|
|
69252
69290
|
isInitializedRef.current = true;
|
|
69253
69291
|
const map2 = new google.maps.Map(mapContainerRef.current, {
|
|
@@ -69269,7 +69307,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/alert-
|
|
|
69269
69307
|
isInitializedRef.current = false;
|
|
69270
69308
|
mapRef.current = null;
|
|
69271
69309
|
};
|
|
69272
|
-
}, [isLoaded]);
|
|
69310
|
+
}, [isLoaded, apiKey]);
|
|
69273
69311
|
React.useEffect(() => {
|
|
69274
69312
|
var _a, _b;
|
|
69275
69313
|
const map2 = mapRef.current;
|
|
@@ -69544,6 +69582,12 @@ For more information, see https://radix-ui.com/primitives/docs/components/alert-
|
|
|
69544
69582
|
const isInitializedRef = React.useRef(false);
|
|
69545
69583
|
const isCalculatingRef = React.useRef(false);
|
|
69546
69584
|
React.useEffect(() => {
|
|
69585
|
+
if (!isLoaded && apiKey && !loadError) {
|
|
69586
|
+
const { load } = useGoogleMapsLoader();
|
|
69587
|
+
if (load) {
|
|
69588
|
+
load(apiKey).catch(console.error);
|
|
69589
|
+
}
|
|
69590
|
+
}
|
|
69547
69591
|
if (!isLoaded || !mapContainerRef.current || isInitializedRef.current) return;
|
|
69548
69592
|
isInitializedRef.current = true;
|
|
69549
69593
|
const map2 = new google.maps.Map(mapContainerRef.current, {
|
|
@@ -69576,7 +69620,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/alert-
|
|
|
69576
69620
|
isInitializedRef.current = false;
|
|
69577
69621
|
mapRef.current = null;
|
|
69578
69622
|
};
|
|
69579
|
-
}, [isLoaded]);
|
|
69623
|
+
}, [isLoaded, apiKey]);
|
|
69580
69624
|
React.useEffect(() => {
|
|
69581
69625
|
const map2 = mapRef.current;
|
|
69582
69626
|
const renderer = directionsRendererRef.current;
|