xertica-ui 1.4.1 → 1.4.3
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/TemplateContent.tsx +99 -0
- package/components/ui/dialog.tsx +3 -3
- package/components/ui/map.tsx +32 -24
- package/components/ui/route-map.tsx +38 -30
- package/dist/index.es.js +13593 -96826
- package/dist/index.umd.js +13600 -96851
- package/package.json +1 -1
- package/vite.config.ts +15 -1
|
@@ -21,6 +21,26 @@ import { ScrollArea } from './ui/scroll-area';
|
|
|
21
21
|
import { ThemeToggle } from './ThemeToggle';
|
|
22
22
|
import { LanguageSelector } from './LanguageSelector';
|
|
23
23
|
import { MapShowcase } from './examples/MapShowcase';
|
|
24
|
+
import {
|
|
25
|
+
Dialog,
|
|
26
|
+
DialogTrigger,
|
|
27
|
+
DialogContent,
|
|
28
|
+
DialogHeader,
|
|
29
|
+
DialogTitle,
|
|
30
|
+
DialogDescription,
|
|
31
|
+
DialogFooter,
|
|
32
|
+
} from './ui/dialog';
|
|
33
|
+
import {
|
|
34
|
+
AlertDialog,
|
|
35
|
+
AlertDialogTrigger,
|
|
36
|
+
AlertDialogContent,
|
|
37
|
+
AlertDialogHeader,
|
|
38
|
+
AlertDialogTitle,
|
|
39
|
+
AlertDialogDescription,
|
|
40
|
+
AlertDialogFooter,
|
|
41
|
+
AlertDialogAction,
|
|
42
|
+
AlertDialogCancel,
|
|
43
|
+
} from './ui/alert-dialog';
|
|
24
44
|
|
|
25
45
|
import { useLayout } from '../contexts/LayoutContext';
|
|
26
46
|
|
|
@@ -598,6 +618,85 @@ export function TemplateContent({ }: TemplateContentProps) {
|
|
|
598
618
|
</CardContent>
|
|
599
619
|
</Card>
|
|
600
620
|
</section>
|
|
621
|
+
|
|
622
|
+
<Separator className="my-8" />
|
|
623
|
+
|
|
624
|
+
{/* Dialogs */}
|
|
625
|
+
<section>
|
|
626
|
+
<h3 className="mb-4">Dialogs</h3>
|
|
627
|
+
<div className="grid gap-4 md:grid-cols-2">
|
|
628
|
+
<Card>
|
|
629
|
+
<CardHeader>
|
|
630
|
+
<CardTitle>Dialog</CardTitle>
|
|
631
|
+
<CardDescription>Um modal básico interativo</CardDescription>
|
|
632
|
+
</CardHeader>
|
|
633
|
+
<CardContent className="flex justify-center py-6">
|
|
634
|
+
<Dialog>
|
|
635
|
+
<DialogTrigger asChild>
|
|
636
|
+
<Button variant="outline">Editar Perfil</Button>
|
|
637
|
+
</DialogTrigger>
|
|
638
|
+
<DialogContent className="sm:max-w-[425px]">
|
|
639
|
+
<DialogHeader>
|
|
640
|
+
<DialogTitle>Editar Perfil</DialogTitle>
|
|
641
|
+
<DialogDescription>
|
|
642
|
+
Faça alterações no seu perfil aqui. Clique em salvar quando terminar.
|
|
643
|
+
</DialogDescription>
|
|
644
|
+
</DialogHeader>
|
|
645
|
+
<div className="grid gap-4 py-4">
|
|
646
|
+
<div className="grid grid-cols-4 items-center gap-4">
|
|
647
|
+
<Label htmlFor="name" className="text-right">
|
|
648
|
+
Nome
|
|
649
|
+
</Label>
|
|
650
|
+
<Input id="name" defaultValue="Pedro Duarte" className="col-span-3" />
|
|
651
|
+
</div>
|
|
652
|
+
<div className="grid grid-cols-4 items-center gap-4">
|
|
653
|
+
<Label htmlFor="username" className="text-right">
|
|
654
|
+
Username
|
|
655
|
+
</Label>
|
|
656
|
+
<Input id="username" defaultValue="@pedroduarte" className="col-span-3" />
|
|
657
|
+
</div>
|
|
658
|
+
</div>
|
|
659
|
+
<DialogFooter>
|
|
660
|
+
<Button type="submit">Atualizar</Button>
|
|
661
|
+
</DialogFooter>
|
|
662
|
+
</DialogContent>
|
|
663
|
+
</Dialog>
|
|
664
|
+
</CardContent>
|
|
665
|
+
</Card>
|
|
666
|
+
|
|
667
|
+
<Card>
|
|
668
|
+
<CardHeader>
|
|
669
|
+
<CardTitle>Alert Dialog</CardTitle>
|
|
670
|
+
<CardDescription>Um alerta para decisões importantes</CardDescription>
|
|
671
|
+
</CardHeader>
|
|
672
|
+
<CardContent className="flex justify-center py-6">
|
|
673
|
+
<AlertDialog>
|
|
674
|
+
<AlertDialogTrigger asChild>
|
|
675
|
+
<Button variant="destructive">Excluir Conta</Button>
|
|
676
|
+
</AlertDialogTrigger>
|
|
677
|
+
<AlertDialogContent className="sm:max-w-[425px]">
|
|
678
|
+
<AlertDialogHeader>
|
|
679
|
+
<AlertDialogTitle>Você tem certeza absoluta?</AlertDialogTitle>
|
|
680
|
+
<AlertDialogDescription>
|
|
681
|
+
Esta ação não pode ser desfeita. Isso excluirá permanentemente sua
|
|
682
|
+
conta e removerá seus dados de nossos servidores.
|
|
683
|
+
</AlertDialogDescription>
|
|
684
|
+
</AlertDialogHeader>
|
|
685
|
+
<AlertDialogFooter>
|
|
686
|
+
<AlertDialogCancel>Cancelar</AlertDialogCancel>
|
|
687
|
+
<AlertDialogAction className="bg-destructive text-destructive-foreground hover:bg-destructive/90">
|
|
688
|
+
Continuar
|
|
689
|
+
</AlertDialogAction>
|
|
690
|
+
</AlertDialogFooter>
|
|
691
|
+
</AlertDialogContent>
|
|
692
|
+
</AlertDialog>
|
|
693
|
+
</CardContent>
|
|
694
|
+
</Card>
|
|
695
|
+
</div>
|
|
696
|
+
</section>
|
|
697
|
+
|
|
698
|
+
<Separator className="my-8" />
|
|
699
|
+
|
|
601
700
|
{/* Maps */}
|
|
602
701
|
<section>
|
|
603
702
|
<MapShowcase />
|
package/components/ui/dialog.tsx
CHANGED
|
@@ -58,7 +58,7 @@ function DialogContent({
|
|
|
58
58
|
<DialogPrimitive.Content
|
|
59
59
|
data-slot="dialog-content"
|
|
60
60
|
className={cn(
|
|
61
|
-
"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-
|
|
61
|
+
"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border p-6 shadow-elevation-sm duration-200 rounded-[var(--radius-card)]",
|
|
62
62
|
className,
|
|
63
63
|
)}
|
|
64
64
|
{...props}
|
|
@@ -79,7 +79,7 @@ function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
|
79
79
|
return (
|
|
80
80
|
<div
|
|
81
81
|
data-slot="dialog-header"
|
|
82
|
-
className={cn("flex flex-col gap-2
|
|
82
|
+
className={cn("flex flex-col gap-2 text-center sm:text-left", className)}
|
|
83
83
|
{...props}
|
|
84
84
|
/>
|
|
85
85
|
);
|
|
@@ -90,7 +90,7 @@ function DialogFooter({ className, ...props }: React.ComponentProps<"div">) {
|
|
|
90
90
|
<div
|
|
91
91
|
data-slot="dialog-footer"
|
|
92
92
|
className={cn(
|
|
93
|
-
"flex flex-col-reverse gap-
|
|
93
|
+
"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
|
|
94
94
|
className,
|
|
95
95
|
)}
|
|
96
96
|
{...props}
|
package/components/ui/map.tsx
CHANGED
|
@@ -413,39 +413,47 @@ MapContent.displayName = "MapContent";
|
|
|
413
413
|
|
|
414
414
|
export const Map = React.forwardRef<HTMLDivElement, MapProps>(
|
|
415
415
|
(props, ref) => {
|
|
416
|
+
const { isLoaded, loadError } = useGoogleMapsLoader();
|
|
416
417
|
const effectiveApiKey = props.apiKey || (typeof import.meta !== 'undefined' && import.meta.env && import.meta.env.VITE_GOOGLE_MAPS_API_KEY) || "";
|
|
417
418
|
|
|
418
419
|
const isValidKey = effectiveApiKey &&
|
|
419
420
|
effectiveApiKey !== "YOUR_GOOGLE_MAPS_API_KEY_HERE" &&
|
|
420
421
|
effectiveApiKey.startsWith("AIza");
|
|
421
422
|
|
|
422
|
-
if (
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
423
|
+
if (isLoaded || isValidKey || loadError) {
|
|
424
|
+
return <MapContent ref={ref} {...props} apiKey={effectiveApiKey} />;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// Check if the script is injected in the DOM (loading via provider)
|
|
428
|
+
const isScriptInjected = typeof document !== 'undefined' && !!document.querySelector('script[src*="maps.googleapis.com/maps/api/js"]');
|
|
429
|
+
|
|
430
|
+
if (isScriptInjected) {
|
|
431
|
+
// Let MapContent show the loading skeleton
|
|
432
|
+
return <MapContent ref={ref} {...props} apiKey={effectiveApiKey} />;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
return (
|
|
436
|
+
<div
|
|
437
|
+
ref={ref}
|
|
438
|
+
className={cn(
|
|
439
|
+
"relative rounded-[var(--radius-card)] border border-border overflow-hidden bg-muted",
|
|
440
|
+
props.className
|
|
441
|
+
)}
|
|
442
|
+
style={{ height: props.height || "400px" }}
|
|
443
|
+
>
|
|
444
|
+
<div className="absolute inset-0 flex items-center justify-center bg-muted">
|
|
445
|
+
<div className="text-center space-y-3 p-6">
|
|
446
|
+
<div className="w-16 h-16 mx-auto bg-primary/10 rounded-full flex items-center justify-center">
|
|
447
|
+
<svg className="w-8 h-8 text-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
448
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z" />
|
|
449
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 11a3 3 0 11-6 0 3 3 0 016 0z" />
|
|
450
|
+
</svg>
|
|
442
451
|
</div>
|
|
452
|
+
<p className="text-sm text-muted-foreground">Configure Google Maps API Key in Settings</p>
|
|
443
453
|
</div>
|
|
444
454
|
</div>
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
return <MapContent ref={ref} {...props} apiKey={effectiveApiKey} />;
|
|
455
|
+
</div>
|
|
456
|
+
);
|
|
449
457
|
}
|
|
450
458
|
);
|
|
451
459
|
Map.displayName = "Map";
|
|
@@ -234,46 +234,54 @@ RouteMapContent.displayName = "RouteMapContent";
|
|
|
234
234
|
|
|
235
235
|
export const RouteMap = React.forwardRef<HTMLDivElement, RouteMapProps>(
|
|
236
236
|
(props, ref) => {
|
|
237
|
+
const { isLoaded, loadError } = useGoogleMapsLoader();
|
|
237
238
|
const effectiveApiKey = props.apiKey || (typeof import.meta !== 'undefined' && import.meta.env && import.meta.env.VITE_GOOGLE_MAPS_API_KEY) || "";
|
|
238
239
|
|
|
239
240
|
const isValidKey = effectiveApiKey &&
|
|
240
241
|
effectiveApiKey !== "YOUR_GOOGLE_MAPS_API_KEY_HERE" &&
|
|
241
242
|
effectiveApiKey.startsWith("AIza");
|
|
242
243
|
|
|
243
|
-
if (
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
mapContainerClassName, disableDefaultUI, zoomControl,
|
|
247
|
-
streetViewControl, mapTypeControl, fullscreenControl,
|
|
248
|
-
onRouteCalculated, ...divProps
|
|
249
|
-
} = props;
|
|
244
|
+
if (isLoaded || isValidKey || loadError) {
|
|
245
|
+
return <RouteMapContent ref={ref} {...props} apiKey={effectiveApiKey} />;
|
|
246
|
+
}
|
|
250
247
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
248
|
+
// Check if the script is injected in the DOM (loading via provider)
|
|
249
|
+
const isScriptInjected = typeof document !== 'undefined' && !!document.querySelector('script[src*="maps.googleapis.com/maps/api/js"]');
|
|
250
|
+
|
|
251
|
+
if (isScriptInjected) {
|
|
252
|
+
return <RouteMapContent ref={ref} {...props} apiKey={effectiveApiKey} />;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const {
|
|
256
|
+
origin, destination, waypoints, travelMode, height, apiKey,
|
|
257
|
+
mapContainerClassName, disableDefaultUI, zoomControl,
|
|
258
|
+
streetViewControl, mapTypeControl, fullscreenControl,
|
|
259
|
+
onRouteCalculated, ...divProps
|
|
260
|
+
} = props;
|
|
261
|
+
|
|
262
|
+
return (
|
|
263
|
+
<div
|
|
264
|
+
ref={ref}
|
|
265
|
+
className={cn(
|
|
266
|
+
"relative rounded-[var(--radius-card)] border border-border overflow-hidden bg-muted",
|
|
267
|
+
props.className
|
|
268
|
+
)}
|
|
269
|
+
style={{ height: props.height || "450px" }}
|
|
270
|
+
{...divProps}
|
|
271
|
+
>
|
|
272
|
+
<div className="absolute inset-0 flex items-center justify-center bg-gradient-to-br from-muted/50 to-muted">
|
|
273
|
+
<div className="text-center space-y-3 p-6">
|
|
274
|
+
<div className="w-16 h-16 mx-auto bg-primary/10 rounded-full flex items-center justify-center">
|
|
275
|
+
<svg className="w-8 h-8 text-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
276
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z" />
|
|
277
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 11a3 3 0 11-6 0 3 3 0 016 0z" />
|
|
278
|
+
</svg>
|
|
270
279
|
</div>
|
|
280
|
+
<p className="text-sm text-muted-foreground">Configure Google Maps API Key in Settings</p>
|
|
271
281
|
</div>
|
|
272
282
|
</div>
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
return <RouteMapContent ref={ref} {...props} apiKey={effectiveApiKey} />;
|
|
283
|
+
</div>
|
|
284
|
+
);
|
|
277
285
|
}
|
|
278
286
|
);
|
|
279
287
|
RouteMap.displayName = "RouteMap";
|