@cloudparse/up-miniapps-sdk 0.2.0 → 0.2.2

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/index.js CHANGED
@@ -5,6 +5,58 @@ import {
5
5
  handleRouteRequest
6
6
  } from "./chunk-S4UHRBSM.js";
7
7
 
8
+ // src/lib/utils.ts
9
+ import { clsx } from "clsx";
10
+ import { twMerge } from "tailwind-merge";
11
+ function cn(...inputs) {
12
+ return twMerge(clsx(inputs));
13
+ }
14
+
15
+ // src/components/ui/button.tsx
16
+ import { Slot } from "@radix-ui/react-slot";
17
+ import { cva } from "class-variance-authority";
18
+ import * as React from "react";
19
+ import { jsx } from "react/jsx-runtime";
20
+ var buttonVariants = cva(
21
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
22
+ {
23
+ defaultVariants: {
24
+ size: "default",
25
+ variant: "default"
26
+ },
27
+ variants: {
28
+ size: {
29
+ default: "h-10 px-4 py-2",
30
+ icon: "h-10 w-10",
31
+ lg: "h-11 rounded-md px-8",
32
+ sm: "h-9 rounded-md px-3"
33
+ },
34
+ variant: {
35
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
36
+ destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
37
+ ghost: "hover:bg-accent hover:text-accent-foreground",
38
+ link: "text-primary underline-offset-4 hover:underline",
39
+ outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
40
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80"
41
+ }
42
+ }
43
+ }
44
+ );
45
+ var Button = React.forwardRef(
46
+ ({ className, variant, size, asChild = false, ...props }, ref) => {
47
+ const Comp = asChild ? Slot : "button";
48
+ return /* @__PURE__ */ jsx(
49
+ Comp,
50
+ {
51
+ className: cn(buttonVariants({ className, size, variant })),
52
+ ref,
53
+ ...props
54
+ }
55
+ );
56
+ }
57
+ );
58
+ Button.displayName = "Button";
59
+
8
60
  // src/bridge.ts
9
61
  var Bridge = class {
10
62
  callbacks = /* @__PURE__ */ new Map();
@@ -166,9 +218,127 @@ var Bridge = class {
166
218
  }
167
219
  };
168
220
 
221
+ // src/components/ui/sheet.tsx
222
+ import * as SheetPrimitive from "@radix-ui/react-dialog";
223
+ import { cva as cva2 } from "class-variance-authority";
224
+ import { X } from "lucide-react";
225
+ import * as React2 from "react";
226
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
227
+ var Sheet = SheetPrimitive.Root;
228
+ var SheetPortal = SheetPrimitive.Portal;
229
+ var SheetOverlay = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx2(
230
+ SheetPrimitive.Overlay,
231
+ {
232
+ className: cn(
233
+ "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
234
+ className
235
+ ),
236
+ ...props,
237
+ ref
238
+ }
239
+ ));
240
+ SheetOverlay.displayName = SheetPrimitive.Overlay.displayName;
241
+ var sheetVariants = cva2(
242
+ "z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500",
243
+ {
244
+ defaultVariants: {
245
+ side: "right"
246
+ },
247
+ variants: {
248
+ side: {
249
+ bottom: "inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
250
+ left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
251
+ right: "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
252
+ top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top"
253
+ }
254
+ }
255
+ }
256
+ );
257
+ var SheetContent = React2.forwardRef(({ side = "right", className, children, portal = true, ...props }, ref) => {
258
+ const Content2 = /* @__PURE__ */ jsxs(
259
+ SheetPrimitive.Content,
260
+ {
261
+ className: cn(
262
+ sheetVariants({ side }),
263
+ portal ? "fixed" : "absolute",
264
+ className
265
+ ),
266
+ ref,
267
+ ...props,
268
+ children: [
269
+ children,
270
+ /* @__PURE__ */ jsxs(SheetPrimitive.Close, { className: "absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-105 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary", children: [
271
+ /* @__PURE__ */ jsx2(X, { className: "h-4 w-4" }),
272
+ /* @__PURE__ */ jsx2("span", { className: "sr-only", children: "Close" })
273
+ ] })
274
+ ]
275
+ }
276
+ );
277
+ if (!portal) {
278
+ return Content2;
279
+ }
280
+ return /* @__PURE__ */ jsxs(SheetPortal, { children: [
281
+ /* @__PURE__ */ jsx2(SheetOverlay, {}),
282
+ Content2
283
+ ] });
284
+ });
285
+ SheetContent.displayName = SheetPrimitive.Content.displayName;
286
+ var SheetHeader = ({
287
+ className,
288
+ ...props
289
+ }) => /* @__PURE__ */ jsx2(
290
+ "div",
291
+ {
292
+ className: cn(
293
+ "flex flex-col space-y-2 text-center sm:text-left",
294
+ className
295
+ ),
296
+ ...props
297
+ }
298
+ );
299
+ SheetHeader.displayName = "SheetHeader";
300
+ var SheetFooter = ({
301
+ className,
302
+ ...props
303
+ }) => /* @__PURE__ */ jsx2(
304
+ "div",
305
+ {
306
+ className: cn(
307
+ "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
308
+ className
309
+ ),
310
+ ...props
311
+ }
312
+ );
313
+ SheetFooter.displayName = "SheetFooter";
314
+ var SheetTitle = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx2(
315
+ SheetPrimitive.Title,
316
+ {
317
+ className: cn("text-lg font-semibold text-foreground", className),
318
+ ref,
319
+ ...props
320
+ }
321
+ ));
322
+ SheetTitle.displayName = SheetPrimitive.Title.displayName;
323
+ var SheetDescription = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx2(
324
+ SheetPrimitive.Description,
325
+ {
326
+ className: cn("text-sm text-muted-foreground", className),
327
+ ref,
328
+ ...props
329
+ }
330
+ ));
331
+ SheetDescription.displayName = SheetPrimitive.Description.displayName;
332
+
169
333
  // src/components/Map/components/MapDrawer.tsx
170
- import { forwardRef, useImperativeHandle, useRef } from "react";
171
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
334
+ import {
335
+ forwardRef as forwardRef3,
336
+ useEffect,
337
+ useImperativeHandle,
338
+ useRef,
339
+ useState
340
+ } from "react";
341
+ import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
172
342
  var resolveHeightToPixels = (height, containerHeight) => {
173
343
  if (typeof height === "number") {
174
344
  return height;
@@ -178,7 +348,7 @@ var resolveHeightToPixels = (height, containerHeight) => {
178
348
  }
179
349
  return parseFloat(height);
180
350
  };
181
- var MapDrawer = forwardRef(
351
+ var MapDrawer = forwardRef3(
182
352
  ({
183
353
  menuItems,
184
354
  state,
@@ -197,7 +367,9 @@ var MapDrawer = forwardRef(
197
367
  containerHeight,
198
368
  menuContent,
199
369
  enableTouchDrag = false,
200
- safeAreaInsets = { top: 0, bottom: 0, left: 0, right: 0 }
370
+ showScrollToTopButton = true,
371
+ scrollToTopThreshold = 300,
372
+ safeAreaInsets = { bottom: 0, left: 0, right: 0, top: 0 }
201
373
  }, ref) => {
202
374
  const scrollContainerRef = useRef(null);
203
375
  const containerRef = useRef(null);
@@ -218,84 +390,240 @@ var MapDrawer = forwardRef(
218
390
  }
219
391
  }
220
392
  };
221
- const handleTouchStart = (e) => {
222
- if (side !== "bottom") return;
223
- setTouchStartY(e.targetTouches[0].clientY);
224
- setCurrentTouchY(e.targetTouches[0].clientY);
393
+ const [showScrollTop, setShowScrollTop] = useState(false);
394
+ const handleScroll = (e) => {
395
+ const scrollTop = e.currentTarget.scrollTop;
396
+ setShowScrollTop(state !== "closed" && scrollTop > scrollToTopThreshold);
225
397
  };
226
- const handleTouchMove = (e) => {
227
- if (touchStartY === null || side !== "bottom") return;
228
- const isScrollAtTop = scrollContainerRef.current ? scrollContainerRef.current.scrollTop === 0 : true;
229
- const currentY = e.targetTouches[0].clientY;
230
- const deltaY = touchStartY - currentY;
231
- if (deltaY < 0 && !isScrollAtTop) {
232
- return;
398
+ useEffect(() => {
399
+ if (state === "closed") {
400
+ setShowScrollTop(false);
401
+ } else {
402
+ const scrollTop = scrollContainerRef.current?.scrollTop || 0;
403
+ setShowScrollTop(scrollTop > scrollToTopThreshold);
233
404
  }
234
- setCurrentTouchY(currentY);
235
- };
236
- const handleTouchEnd = (e) => {
237
- if (touchStartY === null || currentTouchY === null || side !== "bottom")
238
- return;
239
- const touchEndY = e.changedTouches[0].clientY;
240
- const dragDistance = Math.abs(touchEndY - touchStartY);
241
- if (dragDistance < 10) {
405
+ }, [state, scrollToTopThreshold]);
406
+ const isDraggingSheet = useRef(false);
407
+ const hasDeterminedDirection = useRef(false);
408
+ const isTouchOnContent = useRef(false);
409
+ const stateRef = useRef(state);
410
+ const touchStartYRef = useRef(touchStartY);
411
+ const currentTouchYRef = useRef(currentTouchY);
412
+ useEffect(() => {
413
+ stateRef.current = state;
414
+ }, [state]);
415
+ useEffect(() => {
416
+ touchStartYRef.current = touchStartY;
417
+ }, [touchStartY]);
418
+ useEffect(() => {
419
+ currentTouchYRef.current = currentTouchY;
420
+ }, [currentTouchY]);
421
+ useEffect(() => {
422
+ const container = containerRef.current;
423
+ if (!container || side !== "bottom" || !enableTouchDrag) return;
424
+ const handleNativeTouchStart = (e) => {
425
+ const clientY = e.targetTouches[0].clientY;
426
+ setTouchStartY(clientY);
427
+ setCurrentTouchY(clientY);
428
+ isDraggingSheet.current = false;
429
+ hasDeterminedDirection.current = false;
430
+ const target = e.target;
431
+ isTouchOnContent.current = scrollContainerRef.current ? scrollContainerRef.current.contains(target) : false;
432
+ };
433
+ const handleNativeTouchMove = (e) => {
434
+ const startY = touchStartYRef.current;
435
+ if (startY === null) return;
436
+ const currentY = e.targetTouches[0].clientY;
437
+ const deltaY = startY - currentY;
438
+ const scrollTop = scrollContainerRef.current ? scrollContainerRef.current.scrollTop : 0;
439
+ const clientHeight = scrollContainerRef.current ? scrollContainerRef.current.clientHeight : 0;
440
+ const scrollHeight = scrollContainerRef.current ? scrollContainerRef.current.scrollHeight : 0;
441
+ const isAtBottom = scrollTop + clientHeight >= scrollHeight - 1;
442
+ const currentState = stateRef.current;
443
+ if (!hasDeterminedDirection.current) {
444
+ if (!isTouchOnContent.current) {
445
+ isDraggingSheet.current = true;
446
+ hasDeterminedDirection.current = true;
447
+ } else if (currentState !== "full") {
448
+ if (deltaY > 0 && isAtBottom) {
449
+ isDraggingSheet.current = true;
450
+ hasDeterminedDirection.current = true;
451
+ } else if (deltaY < 0 && scrollTop <= 0) {
452
+ isDraggingSheet.current = true;
453
+ hasDeterminedDirection.current = true;
454
+ } else {
455
+ isDraggingSheet.current = false;
456
+ hasDeterminedDirection.current = true;
457
+ }
458
+ } else {
459
+ if (deltaY < 0 && scrollTop <= 0) {
460
+ isDraggingSheet.current = true;
461
+ hasDeterminedDirection.current = true;
462
+ } else {
463
+ isDraggingSheet.current = false;
464
+ hasDeterminedDirection.current = true;
465
+ }
466
+ }
467
+ } else if (!isDraggingSheet.current && isTouchOnContent.current) {
468
+ if (deltaY < 0 && scrollTop <= 0) {
469
+ isDraggingSheet.current = true;
470
+ setTouchStartY(currentY);
471
+ return;
472
+ }
473
+ if (deltaY > 0 && isAtBottom && currentState !== "full") {
474
+ isDraggingSheet.current = true;
475
+ setTouchStartY(currentY);
476
+ return;
477
+ }
478
+ }
479
+ if (isDraggingSheet.current) {
480
+ if (e.cancelable) {
481
+ e.preventDefault();
482
+ }
483
+ const parentContainer = container.parentElement;
484
+ if (parentContainer) {
485
+ const containerH2 = containerHeight || parentContainer.getBoundingClientRect().height;
486
+ const fullPx2 = resolveHeightToPixels(
487
+ drawerFullHeight || "85%",
488
+ containerH2
489
+ );
490
+ const peekPx2 = resolveHeightToPixels(
491
+ drawerPeekHeight || "15%",
492
+ containerH2
493
+ );
494
+ const closedPx = 32 + (currentState === "closed" ? safeAreaInsets.bottom : 0);
495
+ const dragOffset = currentY - startY;
496
+ let localClamped = dragOffset;
497
+ if (currentState === "full") {
498
+ localClamped = Math.max(
499
+ 0,
500
+ Math.min(fullPx2 - closedPx, dragOffset)
501
+ );
502
+ } else if (currentState === "peek") {
503
+ localClamped = Math.max(
504
+ -(fullPx2 - peekPx2),
505
+ Math.min(peekPx2 - closedPx, dragOffset)
506
+ );
507
+ } else if (currentState === "closed") {
508
+ localClamped = Math.min(
509
+ 0,
510
+ Math.max(-(fullPx2 - closedPx), dragOffset)
511
+ );
512
+ }
513
+ parentContainer.style.setProperty(
514
+ "--drag-offset",
515
+ `${localClamped}px`
516
+ );
517
+ }
518
+ }
519
+ };
520
+ const handleNativeTouchEnd = (e) => {
521
+ const startY = touchStartYRef.current;
522
+ const currentY = currentTouchYRef.current;
523
+ const parentContainer = container.parentElement;
524
+ if (startY === null || currentY === null) {
525
+ if (parentContainer) {
526
+ parentContainer.style.setProperty("--drag-offset", "0px");
527
+ }
528
+ return;
529
+ }
530
+ if (!isDraggingSheet.current) {
531
+ setTouchStartY(null);
532
+ setCurrentTouchY(null);
533
+ if (parentContainer) {
534
+ parentContainer.style.setProperty("--drag-offset", "0px");
535
+ }
536
+ return;
537
+ }
538
+ const touchEndY = e.changedTouches[0].clientY;
539
+ const dragDistance = Math.abs(touchEndY - startY);
540
+ if (dragDistance < 10) {
541
+ setTouchStartY(null);
542
+ setCurrentTouchY(null);
543
+ if (parentContainer) {
544
+ parentContainer.style.setProperty("--drag-offset", "0px");
545
+ }
546
+ return;
547
+ }
548
+ const containerH2 = containerHeight || (parentContainer ? parentContainer.getBoundingClientRect().height : window.innerHeight);
549
+ const containerTop = parentContainer ? parentContainer.getBoundingClientRect().top : 0;
550
+ const touchYInContainer = touchEndY - containerTop;
551
+ const drawerHeightFromBottom = containerH2 - touchYInContainer;
552
+ const fullPx2 = resolveHeightToPixels(
553
+ drawerFullHeight || "85%",
554
+ containerH2
555
+ );
556
+ const peekPx2 = resolveHeightToPixels(
557
+ drawerPeekHeight || "15%",
558
+ containerH2
559
+ );
560
+ const currentState = stateRef.current;
561
+ const closedPx = 32 + (currentState === "closed" ? safeAreaInsets.bottom : 0);
562
+ const distToFull = Math.abs(drawerHeightFromBottom - fullPx2);
563
+ const distToPeek = Math.abs(drawerHeightFromBottom - peekPx2);
564
+ const distToClosed = Math.abs(drawerHeightFromBottom - closedPx);
565
+ const minDist = Math.min(distToFull, distToPeek, distToClosed);
566
+ let targetState = "closed";
567
+ if (minDist === distToFull) {
568
+ targetState = "full";
569
+ } else if (minDist === distToPeek) {
570
+ targetState = "peek";
571
+ } else {
572
+ targetState = "closed";
573
+ }
242
574
  setTouchStartY(null);
243
575
  setCurrentTouchY(null);
244
- return;
245
- }
246
- const parentContainer = containerRef.current?.parentElement;
247
- const containerH = containerHeight || (parentContainer ? parentContainer.getBoundingClientRect().height : window.innerHeight);
248
- const containerTop = parentContainer ? parentContainer.getBoundingClientRect().top : 0;
249
- const touchYInContainer = touchEndY - containerTop;
250
- const drawerHeightFromBottom = containerH - touchYInContainer;
251
- const fullPx = resolveHeightToPixels(
252
- drawerFullHeight || "85%",
253
- containerH
254
- );
255
- const peekPx = resolveHeightToPixels(
256
- drawerPeekHeight || "15%",
257
- containerH
258
- );
259
- const closedPx = 32 + (state === "closed" ? safeAreaInsets.bottom : 0);
260
- const distToFull = Math.abs(drawerHeightFromBottom - fullPx);
261
- const distToPeek = Math.abs(drawerHeightFromBottom - peekPx);
262
- const distToClosed = Math.abs(drawerHeightFromBottom - closedPx);
263
- const minDist = Math.min(distToFull, distToPeek, distToClosed);
264
- if (minDist === distToFull) {
265
- onChangeState("full");
266
- } else if (minDist === distToPeek) {
267
- onChangeState("peek");
268
- } else {
269
- onChangeState("closed");
270
- }
271
- setTouchStartY(null);
272
- setCurrentTouchY(null);
273
- };
576
+ onChangeState(targetState);
577
+ requestAnimationFrame(() => {
578
+ if (parentContainer) {
579
+ parentContainer.style.setProperty("--drag-offset", "0px");
580
+ }
581
+ });
582
+ };
583
+ container.addEventListener("touchstart", handleNativeTouchStart, {
584
+ passive: true
585
+ });
586
+ container.addEventListener("touchmove", handleNativeTouchMove, {
587
+ passive: false
588
+ });
589
+ container.addEventListener("touchend", handleNativeTouchEnd, {
590
+ passive: true
591
+ });
592
+ return () => {
593
+ container.removeEventListener("touchstart", handleNativeTouchStart);
594
+ container.removeEventListener("touchmove", handleNativeTouchMove);
595
+ container.removeEventListener("touchend", handleNativeTouchEnd);
596
+ };
597
+ }, [
598
+ side,
599
+ enableTouchDrag,
600
+ containerHeight,
601
+ drawerFullHeight,
602
+ drawerPeekHeight,
603
+ safeAreaInsets,
604
+ onChangeState,
605
+ setTouchStartY,
606
+ setCurrentTouchY
607
+ ]);
274
608
  const isBackdropActive = state === "full";
275
609
  const backdropStyles = isBackdropActive ? "opacity-100 pointer-events-auto" : "opacity-0 pointer-events-none";
610
+ const containerH = containerHeight || window.innerHeight;
611
+ const fullPx = resolveHeightToPixels(drawerFullHeight || "85%", containerH);
612
+ const peekPx = resolveHeightToPixels(drawerPeekHeight || "15%", containerH);
613
+ const shiftPx = fullPx - peekPx;
276
614
  const getBottomDrawerTransform = () => {
277
- const containerH = containerHeight || window.innerHeight;
278
- const fullPx = resolveHeightToPixels(
279
- drawerFullHeight || "85%",
280
- containerH
281
- );
282
- const peekPx = resolveHeightToPixels(
283
- drawerPeekHeight || "15%",
284
- containerH
285
- );
286
615
  if (state === "full") {
287
- return `translateY(${clampedDragOffset}px)`;
616
+ return "translateY(var(--drag-offset, 0px))";
288
617
  }
289
618
  if (state === "peek") {
290
- const shiftPx2 = fullPx - peekPx;
291
- return `translateY(calc(${shiftPx2}px + ${clampedDragOffset}px))`;
619
+ return `translateY(calc(${shiftPx}px + var(--drag-offset, 0px)))`;
292
620
  }
293
621
  const closedVisibleHeight = 32;
294
- const shiftPx = fullPx - closedVisibleHeight;
295
- return `translateY(calc(${shiftPx}px + ${clampedDragOffset}px))`;
622
+ const closedShiftPx = fullPx - closedVisibleHeight;
623
+ return `translateY(calc(${closedShiftPx}px + var(--drag-offset, 0px)))`;
296
624
  };
297
- return /* @__PURE__ */ jsxs(Fragment, { children: [
298
- /* @__PURE__ */ jsx("style", { children: `
625
+ return /* @__PURE__ */ jsxs2(Fragment, { children: [
626
+ /* @__PURE__ */ jsx3("style", { children: `
299
627
  .no-scrollbar {
300
628
  -ms-overflow-style: none;
301
629
  scrollbar-width: none;
@@ -304,127 +632,213 @@ var MapDrawer = forwardRef(
304
632
  display: none;
305
633
  }
306
634
  ` }),
307
- /* @__PURE__ */ jsx(
635
+ /* @__PURE__ */ jsx3(
308
636
  "div",
309
637
  {
310
638
  className: `absolute inset-0 bg-black/45 backdrop-blur-[1px] transition-opacity duration-300 z-30 ${backdropStyles}`,
311
639
  onClick: () => onChangeState("closed")
312
640
  }
313
641
  ),
314
- side === "left" ? (
315
- /* Left Drawer Panel */
316
- /* @__PURE__ */ jsxs(
317
- "div",
642
+ side === "left" ? /* @__PURE__ */ jsxs2(Fragment, { children: [
643
+ state === "closed" && /* @__PURE__ */ jsx3(
644
+ Button,
318
645
  {
319
- className: `absolute top-4 left-0 w-80 bg-zinc-950/85 backdrop-blur-md border-r border-y border-white/10 rounded-r-2xl shadow-2xl flex z-40 transition-transform duration-300 ease-out select-none ${state !== "closed" ? "translate-x-0" : "translate-x-[calc(-100%+24px)]"}`,
320
- ref: containerRef,
321
- style: {
322
- bottom: `calc(1rem + ${etaBarHeight}px)`
323
- },
324
- children: [
325
- /* @__PURE__ */ jsxs("div", { className: "flex-1 flex flex-col h-full overflow-hidden pl-4 py-4 pr-1", children: [
326
- /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between pb-3 border-b border-white/10 mb-2", children: /* @__PURE__ */ jsx("span", { className: "text-sm font-bold tracking-wider text-zinc-400 uppercase", children: "Menu" }) }),
327
- /* @__PURE__ */ jsx(
328
- "div",
329
- {
330
- className: "flex-1 overflow-y-auto no-scrollbar pr-2",
331
- ref: scrollContainerRef,
332
- children: menuContent ? menuContent : /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-1.5", children: menuItems.map((item) => /* @__PURE__ */ jsxs(
333
- "button",
334
- {
335
- className: `flex items-center gap-3 w-full py-3 px-3.5 rounded-xl text-left cursor-pointer transition-all duration-150 ${item.disabled ? "opacity-45 cursor-not-allowed pointer-events-none" : "hover:bg-white/5 active:bg-white/10 text-white"}`,
336
- disabled: item.disabled,
337
- onClick: () => {
338
- if (!item.disabled) {
339
- item.onPress();
340
- onChangeState("closed");
341
- }
646
+ className: "absolute top-4 left-4 z-40 w-12 h-12 rounded-full bg-zinc-950/80 backdrop-blur-md border border-white/10 shadow-lg flex items-center justify-center text-white active:scale-95 transition-all cursor-pointer hover:bg-zinc-900 hover:text-white p-0!",
647
+ onClick: () => onChangeState("full"),
648
+ variant: "ghost",
649
+ children: /* @__PURE__ */ jsxs2(
650
+ "svg",
651
+ {
652
+ fill: "none",
653
+ height: "24",
654
+ stroke: "currentColor",
655
+ strokeLinecap: "round",
656
+ strokeLinejoin: "round",
657
+ strokeWidth: "2",
658
+ viewBox: "0 0 24 24",
659
+ width: "24",
660
+ xmlns: "http://www.w3.org/2000/svg",
661
+ children: [
662
+ /* @__PURE__ */ jsx3("line", { x1: "4", x2: "20", y1: "12", y2: "12" }),
663
+ /* @__PURE__ */ jsx3("line", { x1: "4", x2: "20", y1: "6", y2: "6" }),
664
+ /* @__PURE__ */ jsx3("line", { x1: "4", x2: "20", y1: "18", y2: "18" })
665
+ ]
666
+ }
667
+ )
668
+ }
669
+ ),
670
+ /* @__PURE__ */ jsx3(
671
+ Sheet,
672
+ {
673
+ onOpenChange: (open) => onChangeState(open ? "full" : "closed"),
674
+ open: state !== "closed",
675
+ children: /* @__PURE__ */ jsxs2(
676
+ SheetContent,
677
+ {
678
+ className: "w-80 bg-zinc-950/85 backdrop-blur-md border-r border-y border-white/10 rounded-r-2xl shadow-2xl p-4 text-white flex flex-col h-full overflow-hidden",
679
+ portal: false,
680
+ side: "left",
681
+ children: [
682
+ /* @__PURE__ */ jsx3(SheetHeader, { className: "pb-3 border-b border-white/10 mb-2 text-left", children: /* @__PURE__ */ jsx3(SheetTitle, { className: "text-sm font-bold tracking-wider text-zinc-400 uppercase", children: "Menu" }) }),
683
+ /* @__PURE__ */ jsx3(
684
+ "div",
685
+ {
686
+ className: "flex-1 overflow-y-auto no-scrollbar pr-2",
687
+ onScroll: handleScroll,
688
+ ref: scrollContainerRef,
689
+ children: menuContent ? menuContent : /* @__PURE__ */ jsx3("div", { className: "flex flex-col gap-1.5", children: menuItems.map((item) => /* @__PURE__ */ jsxs2(
690
+ Button,
691
+ {
692
+ className: `flex items-center gap-3 w-full py-3 px-3.5 rounded-xl text-left cursor-pointer transition-all duration-150 justify-start hover:bg-white/5 hover:text-white active:bg-white/10 text-white ${item.disabled ? "opacity-45 cursor-not-allowed pointer-events-none" : ""}`,
693
+ disabled: item.disabled,
694
+ onClick: () => {
695
+ if (!item.disabled) {
696
+ item.onPress();
697
+ onChangeState("closed");
698
+ }
699
+ },
700
+ variant: "ghost",
701
+ children: [
702
+ /* @__PURE__ */ jsxs2("div", { className: "relative flex items-center justify-center w-8 h-8 rounded-lg bg-white/5 text-zinc-300", children: [
703
+ item.icon,
704
+ item.badge !== void 0 && /* @__PURE__ */ jsx3("span", { className: "absolute -top-1 -right-1 bg-cyan-500 text-black text-[9px] font-extrabold min-w-[15px] h-3.5 rounded-full flex items-center justify-center px-1 border border-zinc-950 shadow", children: item.badge })
705
+ ] }),
706
+ /* @__PURE__ */ jsx3("span", { className: "text-sm font-medium tracking-wide flex-1", children: item.label })
707
+ ]
342
708
  },
343
- children: [
344
- /* @__PURE__ */ jsxs("div", { className: "relative flex items-center justify-center w-8 h-8 rounded-lg bg-white/5 text-zinc-300", children: [
345
- item.icon,
346
- item.badge !== void 0 && /* @__PURE__ */ jsx("span", { className: "absolute -top-1 -right-1 bg-cyan-500 text-black text-[9px] font-extrabold min-w-[15px] h-3.5 rounded-full flex items-center justify-center px-1 border border-zinc-950 shadow", children: item.badge })
347
- ] }),
348
- /* @__PURE__ */ jsx("span", { className: "text-sm font-medium tracking-wide flex-1", children: item.label })
349
- ]
709
+ item.id
710
+ )) })
711
+ }
712
+ ),
713
+ showScrollToTopButton && showScrollTop && /* @__PURE__ */ jsx3(
714
+ Button,
715
+ {
716
+ className: "absolute bottom-6 right-6 z-50 flex items-center justify-center w-10 h-10 rounded-full bg-cyan-500 hover:bg-cyan-400 active:scale-95 text-black hover:text-black shadow-lg shadow-cyan-500/25 transition-all duration-200 cursor-pointer p-0!",
717
+ onClick: () => {
718
+ scrollContainerRef.current?.scrollTo({
719
+ behavior: "smooth",
720
+ top: 0
721
+ });
350
722
  },
351
- item.id
352
- )) })
353
- }
354
- )
355
- ] }),
356
- /* @__PURE__ */ jsx(
357
- "div",
358
- {
359
- className: "w-6 flex items-center justify-center cursor-pointer hover:bg-white/5 active:bg-white/10 transition-colors border-l border-white/5 rounded-r-2xl",
360
- onClick: handleHandleClick,
361
- children: /* @__PURE__ */ jsx("div", { className: "w-1.5 h-12 bg-white/20 rounded-full transition-colors group-hover:bg-white/40" })
362
- }
363
- )
364
- ]
723
+ variant: "ghost",
724
+ children: /* @__PURE__ */ jsx3(
725
+ "svg",
726
+ {
727
+ fill: "none",
728
+ height: "20",
729
+ stroke: "currentColor",
730
+ strokeLinecap: "round",
731
+ strokeLinejoin: "round",
732
+ strokeWidth: "2.5",
733
+ viewBox: "0 0 24 24",
734
+ width: "20",
735
+ xmlns: "http://www.w3.org/2000/svg",
736
+ children: /* @__PURE__ */ jsx3("polyline", { points: "18 15 12 9 6 15" })
737
+ }
738
+ )
739
+ }
740
+ )
741
+ ]
742
+ }
743
+ )
365
744
  }
366
745
  )
367
- ) : (
746
+ ] }) : (
368
747
  /* Bottom Sheet Panel - Hardware accelerated translateY transitions */
369
- /* @__PURE__ */ jsxs(
748
+ /* @__PURE__ */ jsxs2(
370
749
  "div",
371
750
  {
372
751
  className: `absolute w-full bg-zinc-950/85 backdrop-blur-md border border-white/10 rounded-t-2xl shadow-2xl flex flex-col z-40 select-none ${isDragging ? "transition-none" : "transition-transform duration-300 ease-out"}`,
373
- onTouchEnd: enableTouchDrag ? handleTouchEnd : void 0,
374
- onTouchMove: enableTouchDrag ? handleTouchMove : void 0,
375
- onTouchStart: enableTouchDrag ? handleTouchStart : void 0,
376
752
  ref: containerRef,
377
753
  style: {
378
754
  bottom: "0px",
379
- marginBottom: state === "closed" ? `${safeAreaInsets.bottom}px` : "0px",
380
755
  height: typeof drawerFullHeight === "number" ? `${drawerFullHeight}px` : drawerFullHeight || "85%",
756
+ marginBottom: state === "closed" ? `${safeAreaInsets.bottom}px` : "0px",
381
757
  transform: getBottomDrawerTransform(),
382
758
  transition: isDragging ? "none" : "transform 300ms ease-out, margin-bottom 250ms ease-in-out"
383
759
  },
384
760
  children: [
385
- /* @__PURE__ */ jsx(
761
+ /* @__PURE__ */ jsx3(
386
762
  "div",
387
763
  {
388
764
  className: "w-full h-8 flex flex-col items-center justify-center cursor-pointer hover:bg-white/5 rounded-t-2xl transition-colors border-b border-white/5",
389
765
  onClick: handleHandleClick,
390
- children: /* @__PURE__ */ jsx("div", { className: "w-12 h-1 bg-white/25 rounded-full" })
766
+ children: /* @__PURE__ */ jsx3("div", { className: "w-12 h-1 bg-white/25 rounded-full" })
391
767
  }
392
768
  ),
393
- /* @__PURE__ */ jsx(
769
+ /* @__PURE__ */ jsxs2(
394
770
  "div",
395
771
  {
396
- className: "flex-1 flex flex-col overflow-hidden px-4 pb-4 pt-2 transition-[margin-top] duration-250 ease-in-out",
772
+ className: "flex-1 flex flex-col overflow-hidden px-4 pb-4 pt-2 transition-[margin-top] duration-250 ease-in-out relative",
397
773
  style: {
398
774
  marginTop: state === "closed" ? `${safeAreaInsets.bottom}px` : "0px"
399
775
  },
400
- children: /* @__PURE__ */ jsx(
401
- "div",
402
- {
403
- className: "flex-1 overflow-y-auto no-scrollbar",
404
- ref: scrollContainerRef,
405
- children: menuContent ? menuContent : /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-1", children: menuItems.map((item) => /* @__PURE__ */ jsxs(
406
- "button",
407
- {
408
- className: `flex items-center gap-3 w-full py-3 px-3.5 rounded-xl text-left cursor-pointer transition-all duration-150 ${item.disabled ? "opacity-45 cursor-not-allowed pointer-events-none" : "hover:bg-white/5 active:bg-white/10 text-white"}`,
409
- disabled: item.disabled,
410
- onClick: () => {
411
- if (!item.disabled) {
412
- item.onPress();
413
- onChangeState("closed");
414
- }
776
+ children: [
777
+ /* @__PURE__ */ jsx3(
778
+ "div",
779
+ {
780
+ className: "flex-1 overflow-y-auto no-scrollbar",
781
+ onScroll: handleScroll,
782
+ ref: scrollContainerRef,
783
+ style: {
784
+ paddingBottom: state === "peek" ? `${shiftPx}px` : "0px"
785
+ },
786
+ children: menuContent ? menuContent : /* @__PURE__ */ jsx3("div", { className: "flex flex-col gap-1", children: menuItems.map((item) => /* @__PURE__ */ jsxs2(
787
+ Button,
788
+ {
789
+ className: `flex items-center gap-3 w-full py-3 px-3.5 rounded-xl text-left cursor-pointer transition-all duration-150 justify-start hover:bg-white/5 hover:text-white active:bg-white/10 text-white ${item.disabled ? "opacity-45 cursor-not-allowed pointer-events-none" : ""}`,
790
+ disabled: item.disabled,
791
+ onClick: () => {
792
+ if (!item.disabled) {
793
+ item.onPress();
794
+ onChangeState("closed");
795
+ }
796
+ },
797
+ variant: "ghost",
798
+ children: [
799
+ /* @__PURE__ */ jsxs2("div", { className: "relative flex items-center justify-center w-8 h-8 rounded-lg bg-white/5 text-zinc-300", children: [
800
+ item.icon,
801
+ item.badge !== void 0 && /* @__PURE__ */ jsx3("span", { className: "absolute -top-1 -right-1 bg-cyan-500 text-black text-[9px] font-extrabold min-w-[15px] h-3.5 rounded-full flex items-center justify-center px-1 border border-zinc-950 shadow", children: item.badge })
802
+ ] }),
803
+ /* @__PURE__ */ jsx3("span", { className: "text-sm font-medium tracking-wide", children: item.label })
804
+ ]
415
805
  },
416
- children: [
417
- /* @__PURE__ */ jsxs("div", { className: "relative flex items-center justify-center w-8 h-8 rounded-lg bg-white/5 text-zinc-300", children: [
418
- item.icon,
419
- item.badge !== void 0 && /* @__PURE__ */ jsx("span", { className: "absolute -top-1 -right-1 bg-cyan-500 text-black text-[9px] font-extrabold min-w-[15px] h-3.5 rounded-full flex items-center justify-center px-1 border border-zinc-950 shadow", children: item.badge })
420
- ] }),
421
- /* @__PURE__ */ jsx("span", { className: "text-sm font-medium tracking-wide", children: item.label })
422
- ]
806
+ item.id
807
+ )) })
808
+ }
809
+ ),
810
+ showScrollToTopButton && showScrollTop && /* @__PURE__ */ jsx3(
811
+ Button,
812
+ {
813
+ className: "absolute right-6 z-50 flex items-center justify-center w-10 h-10 rounded-full bg-cyan-500 hover:bg-cyan-400 active:scale-95 text-black hover:text-black shadow-lg shadow-cyan-500/25 transition-all duration-200 cursor-pointer p-0!",
814
+ onClick: () => {
815
+ scrollContainerRef.current?.scrollTo({
816
+ behavior: "smooth",
817
+ top: 0
818
+ });
423
819
  },
424
- item.id
425
- )) })
426
- }
427
- )
820
+ style: {
821
+ bottom: state === "peek" ? `calc(${24 + shiftPx}px + var(--drag-offset, 0px))` : `calc(24px + var(--drag-offset, 0px))`
822
+ },
823
+ variant: "ghost",
824
+ children: /* @__PURE__ */ jsx3(
825
+ "svg",
826
+ {
827
+ fill: "none",
828
+ height: "20",
829
+ stroke: "currentColor",
830
+ strokeLinecap: "round",
831
+ strokeLinejoin: "round",
832
+ strokeWidth: "2.5",
833
+ viewBox: "0 0 24 24",
834
+ width: "20",
835
+ xmlns: "http://www.w3.org/2000/svg",
836
+ children: /* @__PURE__ */ jsx3("polyline", { points: "18 15 12 9 6 15" })
837
+ }
838
+ )
839
+ }
840
+ )
841
+ ]
428
842
  }
429
843
  )
430
844
  ]
@@ -435,8 +849,65 @@ var MapDrawer = forwardRef(
435
849
  }
436
850
  );
437
851
 
852
+ // src/components/ui/card.tsx
853
+ import * as React3 from "react";
854
+ import { jsx as jsx4 } from "react/jsx-runtime";
855
+ var Card = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx4(
856
+ "div",
857
+ {
858
+ className: cn(
859
+ "rounded-lg border bg-card text-card-foreground shadow-sm",
860
+ className
861
+ ),
862
+ ref,
863
+ ...props
864
+ }
865
+ ));
866
+ Card.displayName = "Card";
867
+ var CardHeader = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx4(
868
+ "div",
869
+ {
870
+ className: cn("flex flex-col space-y-1.5 p-6", className),
871
+ ref,
872
+ ...props
873
+ }
874
+ ));
875
+ CardHeader.displayName = "CardHeader";
876
+ var CardTitle = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx4(
877
+ "div",
878
+ {
879
+ className: cn(
880
+ "text-2xl font-semibold leading-none tracking-tight",
881
+ className
882
+ ),
883
+ ref,
884
+ ...props
885
+ }
886
+ ));
887
+ CardTitle.displayName = "CardTitle";
888
+ var CardDescription = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx4(
889
+ "div",
890
+ {
891
+ className: cn("text-sm text-muted-foreground", className),
892
+ ref,
893
+ ...props
894
+ }
895
+ ));
896
+ CardDescription.displayName = "CardDescription";
897
+ var CardContent = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx4("div", { className: cn("p-6 pt-0", className), ref, ...props }));
898
+ CardContent.displayName = "CardContent";
899
+ var CardFooter = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx4(
900
+ "div",
901
+ {
902
+ className: cn("flex items-center p-6 pt-0", className),
903
+ ref,
904
+ ...props
905
+ }
906
+ ));
907
+ CardFooter.displayName = "CardFooter";
908
+
438
909
  // src/components/Map/components/MapEtaPanel.tsx
439
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
910
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
440
911
  var MapEtaPanel = ({
441
912
  etaData,
442
913
  layoutMode,
@@ -445,15 +916,15 @@ var MapEtaPanel = ({
445
916
  isDragging = false
446
917
  }) => {
447
918
  if (layoutMode === "closed-banner") {
448
- return /* @__PURE__ */ jsxs2("div", { className: "w-full h-10 flex items-center justify-between px-4 pb-2 pt-1 border-b border-white/5 bg-zinc-950/15 relative overflow-hidden", children: [
449
- /* @__PURE__ */ jsxs2(
919
+ return /* @__PURE__ */ jsxs3("div", { className: "w-full h-10 flex items-center justify-between px-4 pb-2 pt-1 border-b border-white/5 bg-zinc-950/15 relative overflow-hidden", children: [
920
+ /* @__PURE__ */ jsxs3(
450
921
  "div",
451
922
  {
452
923
  className: "flex items-center gap-2 cursor-pointer flex-1",
453
924
  onClick: onHeaderClick,
454
925
  children: [
455
- /* @__PURE__ */ jsx2("span", { className: "w-2 h-2 rounded-full bg-emerald-500 animate-pulse" }),
456
- /* @__PURE__ */ jsxs2("span", { className: "text-xs font-bold text-emerald-400", children: [
926
+ /* @__PURE__ */ jsx5("span", { className: "w-2 h-2 rounded-full bg-emerald-500 animate-pulse" }),
927
+ /* @__PURE__ */ jsxs3("span", { className: "text-xs font-bold text-emerald-400", children: [
457
928
  etaData.etaMins,
458
929
  " min (",
459
930
  etaData.distanceRemainingKm.toFixed(1),
@@ -462,36 +933,37 @@ var MapEtaPanel = ({
462
933
  ]
463
934
  }
464
935
  ),
465
- etaData.onAbort && /* @__PURE__ */ jsx2(
466
- "button",
936
+ etaData.onAbort && /* @__PURE__ */ jsx5(
937
+ Button,
467
938
  {
468
- className: "px-1 py-1 text-[10px] font-black bg-red-500/20 text-red-400 hover:bg-red-500/30 border border-red-500/25 active:scale-95 rounded-md transition-all cursor-pointer pointer-events-auto",
939
+ className: "px-1 py-1 text-[10px] font-black bg-red-500/20 text-red-400 hover:bg-red-500/30 border border-red-500/25 active:scale-95 rounded-md transition-all cursor-pointer pointer-events-auto h-auto p-0!",
469
940
  onClick: (e) => {
470
941
  e.stopPropagation();
471
942
  etaData.onAbort?.();
472
943
  },
473
- children: /* @__PURE__ */ jsxs2(
944
+ variant: "ghost",
945
+ children: /* @__PURE__ */ jsxs3(
474
946
  "svg",
475
947
  {
476
948
  className: "lucide lucide-x",
477
949
  fill: "none",
478
950
  height: "18",
479
951
  stroke: "currentColor",
480
- "stroke-linecap": "round",
481
- "stroke-linejoin": "round",
482
- "stroke-width": "2.5",
952
+ strokeLinecap: "round",
953
+ strokeLinejoin: "round",
954
+ strokeWidth: "2.5",
483
955
  viewBox: "0 0 24 24",
484
956
  width: "18",
485
957
  xmlns: "http://www.w3.org/2000/svg",
486
958
  children: [
487
- /* @__PURE__ */ jsx2("path", { d: "M18 6 6 18" }),
488
- /* @__PURE__ */ jsx2("path", { d: "m6 6 12 12" })
959
+ /* @__PURE__ */ jsx5("path", { d: "M18 6 6 18" }),
960
+ /* @__PURE__ */ jsx5("path", { d: "m6 6 12 12" })
489
961
  ]
490
962
  }
491
963
  )
492
964
  }
493
965
  ),
494
- etaData.progress !== void 0 && /* @__PURE__ */ jsx2("div", { className: "absolute bottom-0 left-0 right-0 h-[2px] bg-white/5", children: /* @__PURE__ */ jsx2(
966
+ etaData.progress !== void 0 && /* @__PURE__ */ jsx5("div", { className: "absolute bottom-0 left-0 right-0 h-[2px] bg-white/5", children: /* @__PURE__ */ jsx5(
495
967
  "div",
496
968
  {
497
969
  className: "h-full bg-cyan-400",
@@ -501,166 +973,174 @@ var MapEtaPanel = ({
501
973
  ] });
502
974
  }
503
975
  if (layoutMode === "open-card") {
504
- return /* @__PURE__ */ jsxs2("div", { className: "mx-4 mt-2 p-4 bg-white/5 border border-white/10 rounded-xl flex flex-col", children: [
505
- /* @__PURE__ */ jsxs2("div", { className: "flex items-center justify-between mb-2", children: [
506
- /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2", children: [
507
- /* @__PURE__ */ jsx2("span", { className: "w-2 h-2 rounded-full bg-emerald-500 animate-pulse" }),
508
- /* @__PURE__ */ jsx2("span", { className: "text-[10px] font-bold text-emerald-400 uppercase tracking-wider", children: etaData.label || "Journey Active" })
976
+ return /* @__PURE__ */ jsxs3(Card, { className: "mx-4 mt-2 p-4 bg-white/5 border border-white/10 rounded-xl flex flex-col text-card-foreground", children: [
977
+ /* @__PURE__ */ jsxs3("div", { className: "flex items-center justify-between mb-2", children: [
978
+ /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2", children: [
979
+ /* @__PURE__ */ jsx5("span", { className: "w-2 h-2 rounded-full bg-emerald-500 animate-pulse" }),
980
+ /* @__PURE__ */ jsx5("span", { className: "text-[10px] font-bold text-emerald-400 uppercase tracking-wider", children: etaData.label || "Journey Active" })
509
981
  ] }),
510
- etaData.onAbort && /* @__PURE__ */ jsx2(
511
- "button",
982
+ etaData.onAbort && /* @__PURE__ */ jsx5(
983
+ Button,
512
984
  {
513
- className: "px-1 px-1 text-xs font-bold bg-red-500/20 text-red-400 hover:bg-red-500/30 border border-red-500/30 active:scale-95 rounded-lg transition-all cursor-pointer pointer-events-auto",
985
+ className: "px-1 py-1 text-xs font-bold bg-red-500/20 text-red-400 hover:bg-red-500/30 border border-red-500/30 active:scale-95 rounded-lg transition-all cursor-pointer pointer-events-auto h-auto p-0!",
514
986
  onClick: etaData.onAbort,
515
- children: /* @__PURE__ */ jsxs2(
987
+ variant: "ghost",
988
+ children: /* @__PURE__ */ jsxs3(
516
989
  "svg",
517
990
  {
518
991
  className: "lucide lucide-x",
519
992
  fill: "none",
520
993
  height: "18",
521
994
  stroke: "currentColor",
522
- "stroke-linecap": "round",
523
- "stroke-linejoin": "round",
524
- "stroke-width": "2.5",
995
+ strokeLinecap: "round",
996
+ strokeLinejoin: "round",
997
+ strokeWidth: "2.5",
525
998
  viewBox: "0 0 24 24",
526
999
  width: "18",
527
1000
  xmlns: "http://www.w3.org/2000/svg",
528
1001
  children: [
529
- /* @__PURE__ */ jsx2("path", { d: "M18 6 6 18" }),
530
- /* @__PURE__ */ jsx2("path", { d: "m6 6 12 12" })
1002
+ /* @__PURE__ */ jsx5("path", { d: "M18 6 6 18" }),
1003
+ /* @__PURE__ */ jsx5("path", { d: "m6 6 12 12" })
531
1004
  ]
532
1005
  }
533
1006
  )
534
1007
  }
535
1008
  )
536
1009
  ] }),
537
- /* @__PURE__ */ jsxs2("div", { className: "grid grid-cols-2 divide-x divide-white/10 py-1.5 mb-2.5", children: [
538
- /* @__PURE__ */ jsxs2("div", { className: "text-center", children: [
539
- /* @__PURE__ */ jsxs2("div", { className: "text-xl font-black text-white leading-none", children: [
540
- etaData.etaMins,
541
- /* @__PURE__ */ jsx2("span", { className: "text-xs text-zinc-400 font-normal", children: " min" })
1010
+ /* @__PURE__ */ jsxs3(CardContent, { className: "p-0 flex flex-col", children: [
1011
+ /* @__PURE__ */ jsxs3("div", { className: "grid grid-cols-2 divide-x divide-white/10 py-1.5 mb-2.5", children: [
1012
+ /* @__PURE__ */ jsxs3("div", { className: "text-center", children: [
1013
+ /* @__PURE__ */ jsxs3("div", { className: "text-xl font-black text-white leading-none", children: [
1014
+ etaData.etaMins,
1015
+ /* @__PURE__ */ jsx5("span", { className: "text-xs text-zinc-400 font-normal", children: " min" })
1016
+ ] }),
1017
+ /* @__PURE__ */ jsx5("div", { className: "text-[8px] text-zinc-500 font-bold uppercase tracking-wider mt-1", children: "Time Remaining" })
542
1018
  ] }),
543
- /* @__PURE__ */ jsx2("div", { className: "text-[8px] text-zinc-500 font-bold uppercase tracking-wider mt-1", children: "Time Remaining" })
1019
+ /* @__PURE__ */ jsxs3("div", { className: "text-center", children: [
1020
+ /* @__PURE__ */ jsxs3("div", { className: "text-xl font-black text-white leading-none", children: [
1021
+ etaData.distanceRemainingKm.toFixed(1),
1022
+ /* @__PURE__ */ jsx5("span", { className: "text-xs text-zinc-400 font-normal", children: " km" })
1023
+ ] }),
1024
+ /* @__PURE__ */ jsx5("div", { className: "text-[8px] text-zinc-500 font-bold uppercase tracking-wider mt-1", children: "Distance Remaining" })
1025
+ ] })
544
1026
  ] }),
545
- /* @__PURE__ */ jsxs2("div", { className: "text-center", children: [
546
- /* @__PURE__ */ jsxs2("div", { className: "text-xl font-black text-white leading-none", children: [
547
- etaData.distanceRemainingKm.toFixed(1),
548
- /* @__PURE__ */ jsx2("span", { className: "text-xs text-zinc-400 font-normal", children: " km" })
1027
+ etaData.progress !== void 0 && /* @__PURE__ */ jsxs3("div", { className: "mb-3", children: [
1028
+ /* @__PURE__ */ jsxs3("div", { className: "flex justify-between text-[9px] font-bold text-zinc-400 mb-1", children: [
1029
+ /* @__PURE__ */ jsx5("span", { children: "Progress" }),
1030
+ /* @__PURE__ */ jsxs3("span", { children: [
1031
+ Math.round(etaData.progress),
1032
+ "%"
1033
+ ] })
549
1034
  ] }),
550
- /* @__PURE__ */ jsx2("div", { className: "text-[8px] text-zinc-500 font-bold uppercase tracking-wider mt-1", children: "Distance Remaining" })
551
- ] })
552
- ] }),
553
- etaData.progress !== void 0 && /* @__PURE__ */ jsxs2("div", { className: "mb-3", children: [
554
- /* @__PURE__ */ jsxs2("div", { className: "flex justify-between text-[9px] font-bold text-zinc-450 mb-1", children: [
555
- /* @__PURE__ */ jsx2("span", { children: "Progress" }),
556
- /* @__PURE__ */ jsxs2("span", { children: [
557
- Math.round(etaData.progress),
558
- "%"
559
- ] })
1035
+ /* @__PURE__ */ jsx5("div", { className: "h-1 bg-white/10 rounded-full overflow-hidden", children: /* @__PURE__ */ jsx5(
1036
+ "div",
1037
+ {
1038
+ className: "h-full bg-cyan-400 rounded-full",
1039
+ style: { width: `${etaData.progress}%` }
1040
+ }
1041
+ ) })
560
1042
  ] }),
561
- /* @__PURE__ */ jsx2("div", { className: "h-1 bg-white/10 rounded-full overflow-hidden", children: /* @__PURE__ */ jsx2(
562
- "div",
1043
+ etaData.mode === "preview" && etaData.onStart && /* @__PURE__ */ jsx5(
1044
+ Button,
563
1045
  {
564
- className: "h-full bg-cyan-400 rounded-full",
565
- style: { width: `${etaData.progress}%` }
1046
+ className: "w-full py-2.5 text-xs font-bold bg-cyan-500 text-black hover:bg-cyan-400 hover:text-black active:scale-95 rounded-lg transition-all cursor-pointer h-auto",
1047
+ onClick: etaData.onStart,
1048
+ variant: "ghost",
1049
+ children: "Start Guidance"
566
1050
  }
567
- ) })
568
- ] }),
569
- etaData.mode === "preview" && etaData.onStart && /* @__PURE__ */ jsx2(
570
- "button",
571
- {
572
- className: "w-full py-2.5 text-xs font-bold bg-cyan-500 text-black hover:bg-cyan-400 active:scale-95 rounded-lg transition-all cursor-pointer",
573
- onClick: etaData.onStart,
574
- children: "Start Guidance"
575
- }
576
- )
1051
+ )
1052
+ ] })
577
1053
  ] });
578
1054
  }
579
- return /* @__PURE__ */ jsxs2(
580
- "div",
1055
+ return /* @__PURE__ */ jsxs3(
1056
+ Card,
581
1057
  {
582
- className: `absolute left-1/2 -translate-x-1/2 z-40 w-[calc(100%-2rem)] max-w-[320px] sm:max-w-[380px] bg-zinc-950/85 backdrop-blur-md border border-white/10 rounded-2xl shadow-2xl p-3 sm:p-4 flex flex-col pointer-events-auto select-none ${isDragging ? "transition-none" : "transition-all duration-300 ease-out"}`,
1058
+ className: `absolute left-1/2 -translate-x-1/2 z-40 w-[calc(100%-2rem)] max-w-[320px] sm:max-w-[380px] bg-zinc-950/85 backdrop-blur-md border border-white/10 rounded-2xl shadow-2xl p-3 sm:p-4 flex flex-col pointer-events-auto select-none text-card-foreground ${isDragging ? "transition-none" : "transition-all duration-300 ease-out"}`,
583
1059
  style,
584
1060
  children: [
585
- /* @__PURE__ */ jsxs2("div", { className: "flex items-center justify-between mb-2 sm:mb-3", children: [
586
- /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2", children: [
587
- /* @__PURE__ */ jsx2("span", { className: "w-1.5 h-1.5 sm:w-2 sm:h-2 rounded-full bg-emerald-500 animate-pulse" }),
588
- /* @__PURE__ */ jsx2("span", { className: "text-[9px] sm:text-[10px] font-bold text-emerald-400 uppercase tracking-wider", children: etaData.label || "Guidance Active" })
1061
+ /* @__PURE__ */ jsxs3("div", { className: "flex items-center justify-between mb-2 sm:mb-3", children: [
1062
+ /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2", children: [
1063
+ /* @__PURE__ */ jsx5("span", { className: "w-1.5 h-1.5 sm:w-2 sm:h-2 rounded-full bg-emerald-500 animate-pulse" }),
1064
+ /* @__PURE__ */ jsx5("span", { className: "text-[9px] sm:text-[10px] font-bold text-emerald-400 uppercase tracking-wider", children: etaData.label || "Guidance Active" })
589
1065
  ] }),
590
- etaData.onAbort && /* @__PURE__ */ jsx2(
591
- "button",
1066
+ etaData.onAbort && /* @__PURE__ */ jsx5(
1067
+ Button,
592
1068
  {
593
- className: "px-1 py-1 text-[10px] sm:text-xs font-bold bg-red-500/20 text-red-400 hover:bg-red-500/30 border border-red-500/30 active:scale-95 rounded-lg transition-all cursor-pointer",
1069
+ className: "px-1 py-1 text-[10px] sm:text-xs font-bold bg-red-500/20 text-red-400 hover:bg-red-500/30 border border-red-500/30 active:scale-95 rounded-lg transition-all cursor-pointer h-auto p-0!",
594
1070
  onClick: etaData.onAbort,
595
- children: /* @__PURE__ */ jsxs2(
1071
+ variant: "ghost",
1072
+ children: /* @__PURE__ */ jsxs3(
596
1073
  "svg",
597
1074
  {
598
1075
  className: "lucide lucide-x",
599
1076
  fill: "none",
600
1077
  height: "18",
601
1078
  stroke: "currentColor",
602
- "stroke-linecap": "round",
603
- "stroke-linejoin": "round",
604
- "stroke-width": "2.5",
1079
+ strokeLinecap: "round",
1080
+ strokeLinejoin: "round",
1081
+ strokeWidth: "2.5",
605
1082
  viewBox: "0 0 24 24",
606
1083
  width: "18",
607
1084
  xmlns: "http://www.w3.org/2000/svg",
608
1085
  children: [
609
- /* @__PURE__ */ jsx2("path", { d: "M18 6 6 18" }),
610
- /* @__PURE__ */ jsx2("path", { d: "m6 6 12 12" })
1086
+ /* @__PURE__ */ jsx5("path", { d: "M18 6 6 18" }),
1087
+ /* @__PURE__ */ jsx5("path", { d: "m6 6 12 12" })
611
1088
  ]
612
1089
  }
613
1090
  )
614
1091
  }
615
1092
  )
616
1093
  ] }),
617
- /* @__PURE__ */ jsxs2("div", { className: "grid grid-cols-2 divide-x divide-white/10 py-0.5 sm:py-1 mb-2 sm:mb-3", children: [
618
- /* @__PURE__ */ jsx2("div", { className: "text-center", children: /* @__PURE__ */ jsxs2("div", { className: "text-base sm:text-lg font-black text-white leading-none", children: [
619
- etaData.etaMins,
620
- /* @__PURE__ */ jsxs2("span", { className: "text-[10px] sm:text-xs text-zinc-400 font-normal", children: [
621
- " ",
622
- "min"
623
- ] })
624
- ] }) }),
625
- /* @__PURE__ */ jsx2("div", { className: "text-center", children: /* @__PURE__ */ jsxs2("div", { className: "text-base sm:text-lg font-black text-white leading-none", children: [
626
- etaData.distanceRemainingKm.toFixed(1),
627
- /* @__PURE__ */ jsxs2("span", { className: "text-[10px] sm:text-xs text-zinc-400 font-normal", children: [
628
- " ",
629
- "km"
630
- ] })
631
- ] }) })
632
- ] }),
633
- etaData.progress !== void 0 && /* @__PURE__ */ jsxs2("div", { children: [
634
- /* @__PURE__ */ jsxs2("div", { className: "flex justify-between text-[8px] sm:text-[9px] font-bold text-zinc-400 mb-1", children: [
635
- /* @__PURE__ */ jsx2("span", { children: "Progress" }),
636
- /* @__PURE__ */ jsxs2("span", { children: [
637
- Math.round(etaData.progress),
638
- "%"
639
- ] })
1094
+ /* @__PURE__ */ jsxs3(CardContent, { className: "p-0 flex flex-col", children: [
1095
+ /* @__PURE__ */ jsxs3("div", { className: "grid grid-cols-2 divide-x divide-white/10 py-0.5 sm:py-1 mb-2 sm:mb-3", children: [
1096
+ /* @__PURE__ */ jsx5("div", { className: "text-center", children: /* @__PURE__ */ jsxs3("div", { className: "text-base sm:text-lg font-black text-white leading-none", children: [
1097
+ etaData.etaMins,
1098
+ /* @__PURE__ */ jsxs3("span", { className: "text-[10px] sm:text-xs text-zinc-400 font-normal", children: [
1099
+ " ",
1100
+ "min"
1101
+ ] })
1102
+ ] }) }),
1103
+ /* @__PURE__ */ jsx5("div", { className: "text-center", children: /* @__PURE__ */ jsxs3("div", { className: "text-base sm:text-lg font-black text-white leading-none", children: [
1104
+ etaData.distanceRemainingKm.toFixed(1),
1105
+ /* @__PURE__ */ jsxs3("span", { className: "text-[10px] sm:text-xs text-zinc-400 font-normal", children: [
1106
+ " ",
1107
+ "km"
1108
+ ] })
1109
+ ] }) })
640
1110
  ] }),
641
- /* @__PURE__ */ jsx2("div", { className: "h-1 sm:h-1.5 bg-white/10 rounded-full overflow-hidden", children: /* @__PURE__ */ jsx2(
642
- "div",
1111
+ etaData.progress !== void 0 && /* @__PURE__ */ jsxs3("div", { children: [
1112
+ /* @__PURE__ */ jsxs3("div", { className: "flex justify-between text-[8px] sm:text-[9px] font-bold text-zinc-400 mb-1", children: [
1113
+ /* @__PURE__ */ jsx5("span", { children: "Progress" }),
1114
+ /* @__PURE__ */ jsxs3("span", { children: [
1115
+ Math.round(etaData.progress),
1116
+ "%"
1117
+ ] })
1118
+ ] }),
1119
+ /* @__PURE__ */ jsx5("div", { className: "h-1 sm:h-1.5 bg-white/10 rounded-full overflow-hidden", children: /* @__PURE__ */ jsx5(
1120
+ "div",
1121
+ {
1122
+ className: "h-full bg-cyan-400 rounded-full",
1123
+ style: { width: `${etaData.progress}%` }
1124
+ }
1125
+ ) })
1126
+ ] }),
1127
+ etaData.mode === "preview" && etaData.onStart && /* @__PURE__ */ jsx5(
1128
+ Button,
643
1129
  {
644
- className: "h-full bg-cyan-400 rounded-full",
645
- style: { width: `${etaData.progress}%` }
1130
+ className: "mt-2.5 sm:mt-3 py-1.5 sm:py-2 text-[11px] sm:text-xs font-bold bg-cyan-500 text-black hover:bg-cyan-400 hover:text-black active:scale-95 rounded-lg transition-all cursor-pointer h-auto",
1131
+ onClick: etaData.onStart,
1132
+ variant: "ghost",
1133
+ children: "Start Guidance"
646
1134
  }
647
- ) })
648
- ] }),
649
- etaData.mode === "preview" && etaData.onStart && /* @__PURE__ */ jsx2(
650
- "button",
651
- {
652
- className: "mt-2.5 sm:mt-3 py-1.5 sm:py-2 text-[11px] sm:text-xs font-bold bg-cyan-500 text-black hover:bg-cyan-400 active:scale-95 rounded-lg transition-all cursor-pointer",
653
- onClick: etaData.onStart,
654
- children: "Start Guidance"
655
- }
656
- )
1135
+ )
1136
+ ] })
657
1137
  ]
658
1138
  }
659
1139
  );
660
1140
  };
661
1141
 
662
1142
  // src/components/Map/components/MapRightControls.tsx
663
- import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
1143
+ import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
664
1144
  var MapRightControls = ({
665
1145
  customControls = [],
666
1146
  etaBarHeight,
@@ -678,7 +1158,7 @@ var MapRightControls = ({
678
1158
  customRecenterButton,
679
1159
  customCompassButton,
680
1160
  drawerPeekHeight,
681
- insets = { top: 0, bottom: 0, left: 0, right: 0 }
1161
+ insets = { bottom: 0, left: 0, right: 0, top: 0 }
682
1162
  }) => {
683
1163
  const aboveControls = customControls.filter(
684
1164
  (c) => c.position === "above-recenter"
@@ -690,9 +1170,9 @@ var MapRightControls = ({
690
1170
  const closedHeightOffset = "32px";
691
1171
  const activeEtaHeight = etaData ? etaBarHeight : drawerState === "closed" ? insets.bottom : 0;
692
1172
  const peekStyle = typeof drawerPeekHeight === "number" ? `${drawerPeekHeight}px` : drawerPeekHeight || "15%";
693
- const controlsBottom = side === "bottom" ? drawerState === "closed" ? `calc(${closedHeightOffset} + 1rem + ${activeEtaHeight}px - ${clampedDragOffset}px)` : `calc(${peekStyle} + 1rem + ${etaData ? etaBarHeight : 0}px - ${clampedDragOffset}px)` : `calc(1rem + ${insets.bottom}px)`;
1173
+ const controlsBottom = side === "bottom" ? drawerState === "closed" ? `calc(${closedHeightOffset} + 1rem + ${activeEtaHeight}px - var(--drag-offset, 0px))` : `calc(${peekStyle} + 1rem + ${etaData ? etaBarHeight : 0}px - var(--drag-offset, 0px))` : `calc(1rem + ${insets.bottom}px)`;
694
1174
  const isControlsVisible = side !== "bottom" || drawerState !== "full";
695
- return /* @__PURE__ */ jsxs3(
1175
+ return /* @__PURE__ */ jsxs4(
696
1176
  "div",
697
1177
  {
698
1178
  className: `absolute right-4 z-30 flex flex-col items-center gap-3 select-none pointer-events-none ${isDragging ? "transition-none" : "transition-all duration-300 ease-out"} ${isControlsVisible ? "opacity-100 scale-100 pointer-events-auto" : "opacity-0 scale-75 pointer-events-none"}`,
@@ -700,27 +1180,29 @@ var MapRightControls = ({
700
1180
  bottom: controlsBottom
701
1181
  },
702
1182
  children: [
703
- aboveControls.length > 0 && /* @__PURE__ */ jsx3("div", { className: "flex flex-col gap-2 pointer-events-auto", children: aboveControls.map((control) => /* @__PURE__ */ jsxs3("div", { className: "relative group flex items-center", children: [
704
- control.tooltip && /* @__PURE__ */ jsx3("div", { className: "absolute right-14 pointer-events-none opacity-0 scale-95 origin-right group-hover:opacity-100 group-hover:scale-100 transition-all duration-150 bg-zinc-900/95 border border-white/10 text-white text-xs px-2.5 py-1.5 rounded-lg shadow-xl whitespace-nowrap", children: control.tooltip }),
705
- /* @__PURE__ */ jsx3(
706
- "button",
1183
+ aboveControls.length > 0 && /* @__PURE__ */ jsx6("div", { className: "flex flex-col gap-2 pointer-events-auto", children: aboveControls.map((control) => /* @__PURE__ */ jsxs4("div", { className: "relative group flex items-center", children: [
1184
+ control.tooltip && /* @__PURE__ */ jsx6("div", { className: "absolute right-14 pointer-events-none opacity-0 scale-95 origin-right group-hover:opacity-100 group-hover:scale-100 transition-all duration-150 bg-zinc-900/95 border border-white/10 text-white text-xs px-2.5 py-1.5 rounded-lg shadow-xl whitespace-nowrap", children: control.tooltip }),
1185
+ /* @__PURE__ */ jsx6(
1186
+ Button,
707
1187
  {
708
- className: `w-12 h-12 rounded-full bg-zinc-950/80 backdrop-blur-md border border-white/10 shadow-lg flex items-center justify-center text-white active:scale-95 transition-all cursor-pointer ${control.activeState ? "ring-2 ring-cyan-400 ring-offset-2 ring-offset-zinc-950" : "hover:bg-zinc-900"}`,
1188
+ className: `w-12 h-12 rounded-full bg-zinc-950/80 backdrop-blur-md border border-white/10 shadow-lg flex items-center justify-center text-white active:scale-95 transition-all cursor-pointer p-0! hover:bg-zinc-900 hover:text-white ${control.activeState ? "ring-2 ring-cyan-400 ring-offset-2 ring-offset-zinc-950" : ""}`,
709
1189
  onClick: control.onPress,
1190
+ variant: "ghost",
710
1191
  children: control.icon
711
1192
  }
712
1193
  )
713
1194
  ] }, control.id)) }),
714
- isCompassVisible && (customCompassButton ? /* @__PURE__ */ jsx3("div", { className: "pointer-events-auto", children: customCompassButton }) : /* @__PURE__ */ jsx3("div", { className: "pointer-events-auto", children: /* @__PURE__ */ jsx3(
715
- "button",
1195
+ isCompassVisible && (customCompassButton ? /* @__PURE__ */ jsx6("div", { className: "pointer-events-auto", children: customCompassButton }) : /* @__PURE__ */ jsx6("div", { className: "pointer-events-auto", children: /* @__PURE__ */ jsx6(
1196
+ Button,
716
1197
  {
717
- className: `w-12 h-12 rounded-full bg-zinc-950/80 backdrop-blur-md border border-white/10 shadow-lg flex items-center justify-center text-white active:scale-95 transition-all duration-300 ${isCompassVisible ? "opacity-100 pointer-events-auto" : "opacity-0 pointer-events-none h-0 w-0 border-none m-0 p-0 overflow-hidden"}`,
1198
+ className: `w-12 h-12 rounded-full bg-zinc-950/80 backdrop-blur-md border border-white/10 shadow-lg flex items-center justify-center text-white active:scale-95 transition-all duration-300 p-0! hover:bg-zinc-900 hover:text-white ${isCompassVisible ? "opacity-100 pointer-events-auto" : "opacity-0 pointer-events-none h-0 w-0 border-none m-0 p-0 overflow-hidden"}`,
718
1199
  onClick: () => onResetBearing({ pitch: initialViewState?.pitch ?? 0 }),
719
1200
  style: {
720
1201
  transform: isCompassVisible ? "scale(1) rotate(0deg)" : "scale(0.7) rotate(0deg)"
721
1202
  },
722
1203
  title: "Reset bearing to North",
723
- children: /* @__PURE__ */ jsxs3(
1204
+ variant: "ghost",
1205
+ children: /* @__PURE__ */ jsxs4(
724
1206
  "svg",
725
1207
  {
726
1208
  className: "w-7 h-7 transition-transform duration-75 ease-out",
@@ -730,7 +1212,7 @@ var MapRightControls = ({
730
1212
  },
731
1213
  viewBox: "0 0 24 24",
732
1214
  children: [
733
- /* @__PURE__ */ jsx3(
1215
+ /* @__PURE__ */ jsx6(
734
1216
  "circle",
735
1217
  {
736
1218
  cx: "12",
@@ -741,23 +1223,24 @@ var MapRightControls = ({
741
1223
  strokeWidth: "1"
742
1224
  }
743
1225
  ),
744
- /* @__PURE__ */ jsx3("path", { d: "M12 4.5L15 12H9L12 4.5Z", fill: "#ef4444" }),
745
- /* @__PURE__ */ jsx3("path", { d: "M12 19.5L9 12H15L12 19.5Z", fill: "#f4f4f5" }),
746
- /* @__PURE__ */ jsx3("circle", { cx: "12", cy: "12", fill: "#18181b", r: "1.5" })
1226
+ /* @__PURE__ */ jsx6("path", { d: "M12 4.5L15 12H9L12 4.5Z", fill: "#ef4444" }),
1227
+ /* @__PURE__ */ jsx6("path", { d: "M12 19.5L9 12H15L12 19.5Z", fill: "#f4f4f5" }),
1228
+ /* @__PURE__ */ jsx6("circle", { cx: "12", cy: "12", fill: "#18181b", r: "1.5" })
747
1229
  ]
748
1230
  }
749
1231
  )
750
1232
  }
751
1233
  ) })),
752
- customRecenterButton ? /* @__PURE__ */ jsx3("div", { className: "pointer-events-auto", children: customRecenterButton }) : /* @__PURE__ */ jsx3("div", { className: "pointer-events-auto", children: /* @__PURE__ */ jsx3(
753
- "button",
1234
+ customRecenterButton ? /* @__PURE__ */ jsx6("div", { className: "pointer-events-auto", children: customRecenterButton }) : /* @__PURE__ */ jsx6("div", { className: "pointer-events-auto", children: /* @__PURE__ */ jsx6(
1235
+ Button,
754
1236
  {
755
- className: `w-12 h-12 rounded-full bg-zinc-950/80 backdrop-blur-md border border-white/10 shadow-lg flex items-center justify-center text-white active:scale-95 transition-all cursor-pointer ${isMapCentered ? "ring-2 ring-cyan-400 ring-offset-2 ring-offset-zinc-950" : "hover:bg-zinc-900"}`,
1237
+ className: `w-12 h-12 rounded-full bg-zinc-950/80 backdrop-blur-md border border-white/10 shadow-lg flex items-center justify-center text-white active:scale-95 transition-all cursor-pointer p-0! hover:bg-zinc-900 hover:text-white ${isMapCentered ? "ring-2 ring-cyan-400 ring-offset-2 ring-offset-zinc-950" : ""}`,
756
1238
  onClick: () => onRecenter(),
757
1239
  title: "Recenter Map",
1240
+ variant: "ghost",
758
1241
  children: isMapCentered ? (
759
1242
  /* Filled active lock state */
760
- /* @__PURE__ */ jsxs3(
1243
+ /* @__PURE__ */ jsxs4(
761
1244
  "svg",
762
1245
  {
763
1246
  className: "w-6 h-6 text-cyan-400",
@@ -766,18 +1249,18 @@ var MapRightControls = ({
766
1249
  strokeWidth: "2.2",
767
1250
  viewBox: "0 0 24 24",
768
1251
  children: [
769
- /* @__PURE__ */ jsx3("circle", { cx: "12", cy: "12", r: "8" }),
770
- /* @__PURE__ */ jsx3("circle", { cx: "12", cy: "12", fill: "currentColor", r: "3" }),
771
- /* @__PURE__ */ jsx3("line", { x1: "12", x2: "12", y1: "2", y2: "4" }),
772
- /* @__PURE__ */ jsx3("line", { x1: "12", x2: "12", y1: "20", y2: "22" }),
773
- /* @__PURE__ */ jsx3("line", { x1: "2", x2: "4", y1: "12", y2: "12" }),
774
- /* @__PURE__ */ jsx3("line", { x1: "20", x2: "22", y1: "12", y2: "12" })
1252
+ /* @__PURE__ */ jsx6("circle", { cx: "12", cy: "12", r: "8" }),
1253
+ /* @__PURE__ */ jsx6("circle", { cx: "12", cy: "12", fill: "currentColor", r: "3" }),
1254
+ /* @__PURE__ */ jsx6("line", { x1: "12", x2: "12", y1: "2", y2: "4" }),
1255
+ /* @__PURE__ */ jsx6("line", { x1: "12", x2: "12", y1: "20", y2: "22" }),
1256
+ /* @__PURE__ */ jsx6("line", { x1: "2", x2: "4", y1: "12", y2: "12" }),
1257
+ /* @__PURE__ */ jsx6("line", { x1: "20", x2: "22", y1: "12", y2: "12" })
775
1258
  ]
776
1259
  }
777
1260
  )
778
1261
  ) : (
779
1262
  /* Outlined drifted state */
780
- /* @__PURE__ */ jsxs3(
1263
+ /* @__PURE__ */ jsxs4(
781
1264
  "svg",
782
1265
  {
783
1266
  className: "w-6 h-6 text-zinc-300",
@@ -786,24 +1269,25 @@ var MapRightControls = ({
786
1269
  strokeWidth: "2",
787
1270
  viewBox: "0 0 24 24",
788
1271
  children: [
789
- /* @__PURE__ */ jsx3("circle", { cx: "12", cy: "12", r: "8" }),
790
- /* @__PURE__ */ jsx3("line", { x1: "12", x2: "12", y1: "2", y2: "4" }),
791
- /* @__PURE__ */ jsx3("line", { x1: "12", x2: "12", y1: "20", y2: "22" }),
792
- /* @__PURE__ */ jsx3("line", { x1: "2", x2: "4", y1: "12", y2: "12" }),
793
- /* @__PURE__ */ jsx3("line", { x1: "20", x2: "22", y1: "12", y2: "12" })
1272
+ /* @__PURE__ */ jsx6("circle", { cx: "12", cy: "12", r: "8" }),
1273
+ /* @__PURE__ */ jsx6("line", { x1: "12", x2: "12", y1: "2", y2: "4" }),
1274
+ /* @__PURE__ */ jsx6("line", { x1: "12", x2: "12", y1: "20", y2: "22" }),
1275
+ /* @__PURE__ */ jsx6("line", { x1: "2", x2: "4", y1: "12", y2: "12" }),
1276
+ /* @__PURE__ */ jsx6("line", { x1: "20", x2: "22", y1: "12", y2: "12" })
794
1277
  ]
795
1278
  }
796
1279
  )
797
1280
  )
798
1281
  }
799
1282
  ) }),
800
- belowControls.length > 0 && /* @__PURE__ */ jsx3("div", { className: "flex flex-col gap-2 pointer-events-auto", children: belowControls.map((control) => /* @__PURE__ */ jsxs3("div", { className: "relative group flex items-center", children: [
801
- control.tooltip && /* @__PURE__ */ jsx3("div", { className: "absolute right-14 pointer-events-none opacity-0 scale-95 origin-right group-hover:opacity-100 group-hover:scale-100 transition-all duration-150 bg-zinc-900/95 border border-white/10 text-white text-xs px-2.5 py-1.5 rounded-lg shadow-xl whitespace-nowrap", children: control.tooltip }),
802
- /* @__PURE__ */ jsx3(
803
- "button",
1283
+ belowControls.length > 0 && /* @__PURE__ */ jsx6("div", { className: "flex flex-col gap-2 pointer-events-auto", children: belowControls.map((control) => /* @__PURE__ */ jsxs4("div", { className: "relative group flex items-center", children: [
1284
+ control.tooltip && /* @__PURE__ */ jsx6("div", { className: "absolute right-14 pointer-events-none opacity-0 scale-95 origin-right group-hover:opacity-100 group-hover:scale-100 transition-all duration-150 bg-zinc-900/95 border border-white/10 text-white text-xs px-2.5 py-1.5 rounded-lg shadow-xl whitespace-nowrap", children: control.tooltip }),
1285
+ /* @__PURE__ */ jsx6(
1286
+ Button,
804
1287
  {
805
- className: `w-12 h-12 rounded-full bg-zinc-950/80 backdrop-blur-md border border-white/10 shadow-lg flex items-center justify-center text-white active:scale-95 transition-all cursor-pointer ${control.activeState ? "ring-2 ring-cyan-400 ring-offset-2 ring-offset-zinc-950" : "hover:bg-zinc-900"}`,
1288
+ className: `w-12 h-12 rounded-full bg-zinc-950/80 backdrop-blur-md border border-white/10 shadow-lg flex items-center justify-center text-white active:scale-95 transition-all cursor-pointer p-0! hover:bg-zinc-900 hover:text-white ${control.activeState ? "ring-2 ring-cyan-400 ring-offset-2 ring-offset-zinc-950" : ""}`,
806
1289
  onClick: control.onPress,
1290
+ variant: "ghost",
807
1291
  children: control.icon
808
1292
  }
809
1293
  )
@@ -820,28 +1304,28 @@ import {
820
1304
  useContext,
821
1305
  useMemo,
822
1306
  useRef as useRef2,
823
- useState
1307
+ useState as useState2
824
1308
  } from "react";
825
- import { jsx as jsx4 } from "react/jsx-runtime";
1309
+ import { jsx as jsx7 } from "react/jsx-runtime";
826
1310
  var MapControlsContext = createContext(
827
1311
  null
828
1312
  );
829
1313
  var SDKMapProvider = ({
830
1314
  children
831
1315
  }) => {
832
- const [isFollowing, setIsFollowing] = useState(true);
833
- const [bearing, setBearingState] = useState(0);
834
- const [pitch, setPitchState] = useState(0);
835
- const [drawerState, setDrawerStateInternal] = useState("closed");
1316
+ const [isFollowing, setIsFollowing] = useState2(true);
1317
+ const [bearing, setBearingState] = useState2(0);
1318
+ const [pitch, setPitchState] = useState2(0);
1319
+ const [drawerState, setDrawerStateInternal] = useState2("closed");
836
1320
  const drawerContentRef = useRef2(null);
837
1321
  const setDrawerState = useCallback((val) => {
838
1322
  setDrawerStateInternal(val);
839
1323
  }, []);
840
- const [hasControls, setHasControlsState] = useState(false);
1324
+ const [hasControls, setHasControlsState] = useState2(false);
841
1325
  const setHasControls = useCallback((val) => {
842
1326
  setHasControlsState((prev) => prev === val ? prev : val);
843
1327
  }, []);
844
- const [etaData, setEtaDataState] = useState(void 0);
1328
+ const [etaData, setEtaDataState] = useState2(void 0);
845
1329
  const setEtaData = useCallback((newData) => {
846
1330
  setEtaDataState((prev) => {
847
1331
  if (!prev && !newData) return prev;
@@ -852,11 +1336,11 @@ var SDKMapProvider = ({
852
1336
  return newData;
853
1337
  });
854
1338
  }, []);
855
- const [insets, setInsetsState] = useState({
856
- top: 0,
1339
+ const [insets, setInsetsState] = useState2({
857
1340
  bottom: 0,
858
1341
  left: 0,
859
- right: 0
1342
+ right: 0,
1343
+ top: 0
860
1344
  });
861
1345
  const setInsets = useCallback((newInsets) => {
862
1346
  setInsetsState((prev) => ({ ...prev, ...newInsets }));
@@ -901,6 +1385,7 @@ var SDKMapProvider = ({
901
1385
  drawerState,
902
1386
  etaData,
903
1387
  hasControls,
1388
+ insets,
904
1389
  isFollowing,
905
1390
  pitch,
906
1391
  resetBearing,
@@ -908,10 +1393,9 @@ var SDKMapProvider = ({
908
1393
  setDrawerState,
909
1394
  setEtaData,
910
1395
  setHasControls,
1396
+ setInsets,
911
1397
  setIsFollowing,
912
- setPitch,
913
- insets,
914
- setInsets
1398
+ setPitch
915
1399
  }),
916
1400
  [
917
1401
  _registerCenterCallback,
@@ -933,7 +1417,7 @@ var SDKMapProvider = ({
933
1417
  setInsets
934
1418
  ]
935
1419
  );
936
- return /* @__PURE__ */ jsx4(MapControlsContext.Provider, { value: contextValue, children });
1420
+ return /* @__PURE__ */ jsx7(MapControlsContext.Provider, { value: contextValue, children });
937
1421
  };
938
1422
  var useMapControls = () => {
939
1423
  const context = useContext(MapControlsContext);
@@ -944,8 +1428,8 @@ var useMapControls = () => {
944
1428
  };
945
1429
 
946
1430
  // src/components/Map/components/MapControls.tsx
947
- import { useCallback as useCallback2, useContext as useContext2, useEffect, useRef as useRef3, useState as useState2 } from "react";
948
- import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
1431
+ import { useCallback as useCallback2, useContext as useContext2, useEffect as useEffect2, useRef as useRef3, useState as useState3 } from "react";
1432
+ import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
949
1433
  var resolveHeightToPixels2 = (height, containerHeight) => {
950
1434
  if (typeof height === "number") {
951
1435
  return height;
@@ -975,6 +1459,8 @@ var MapControls = ({
975
1459
  menuContent,
976
1460
  children,
977
1461
  enableTouchDrag = false,
1462
+ showScrollToTopButton = true,
1463
+ scrollToTopThreshold = 300,
978
1464
  isInternal = false
979
1465
  }) => {
980
1466
  const mapContext = useContext2(MapControlsContext);
@@ -994,7 +1480,7 @@ var MapControls = ({
994
1480
  },
995
1481
  [drawerContentRef, contextRef]
996
1482
  );
997
- const [localDrawerState, setLocalDrawerState] = useState2(
1483
+ const [localDrawerState, setLocalDrawerState] = useState3(
998
1484
  defaultState ?? "closed"
999
1485
  );
1000
1486
  const drawerState = mapContext ? mapContext.drawerState : localDrawerState;
@@ -1008,15 +1494,15 @@ var MapControls = ({
1008
1494
  },
1009
1495
  [mapContext]
1010
1496
  );
1011
- useEffect(() => {
1497
+ useEffect2(() => {
1012
1498
  if (defaultState && mapContext) {
1013
1499
  mapContext.setDrawerState(defaultState);
1014
1500
  }
1015
1501
  }, []);
1016
- const [side, setSide] = useState2("left");
1502
+ const [side, setSide] = useState3("left");
1017
1503
  const containerRef = useRef3(null);
1018
- const [mapHeight, setMapHeight] = useState2(600);
1019
- useEffect(() => {
1504
+ const [mapHeight, setMapHeight] = useState3(600);
1505
+ useEffect2(() => {
1020
1506
  const parent = containerRef.current?.parentElement;
1021
1507
  if (!parent) return;
1022
1508
  const updateHeight = () => {
@@ -1030,7 +1516,7 @@ var MapControls = ({
1030
1516
  };
1031
1517
  }, []);
1032
1518
  const setHasControls = mapContext?.setHasControls;
1033
- useEffect(() => {
1519
+ useEffect2(() => {
1034
1520
  if (setHasControls && !isInternal) {
1035
1521
  setHasControls(true);
1036
1522
  return () => setHasControls(false);
@@ -1054,9 +1540,9 @@ var MapControls = ({
1054
1540
  };
1055
1541
  const mapPitch = mapContext ? mapContext.pitch : 0;
1056
1542
  const resolvedEtaData = etaData !== void 0 ? etaData : mapContext?.etaData;
1057
- const [touchStartY, setTouchStartY] = useState2(null);
1058
- const [currentTouchY, setCurrentTouchY] = useState2(null);
1059
- useEffect(() => {
1543
+ const [touchStartY, setTouchStartY] = useState3(null);
1544
+ const [currentTouchY, setCurrentTouchY] = useState3(null);
1545
+ useEffect2(() => {
1060
1546
  if (typeof window === "undefined") return;
1061
1547
  const checkLayout = () => {
1062
1548
  if (drawerSide) {
@@ -1075,14 +1561,23 @@ var MapControls = ({
1075
1561
  }, [drawerSide]);
1076
1562
  const isDragging = touchStartY !== null && currentTouchY !== null;
1077
1563
  const dragOffset = isDragging ? currentTouchY - touchStartY : 0;
1564
+ const fullPx = resolveHeightToPixels2(drawerFullHeight || "85%", mapHeight);
1565
+ const peekPx = resolveHeightToPixels2(drawerPeekHeight || "15%", mapHeight);
1566
+ const bottomInset = mapContext?.insets.bottom || 0;
1567
+ const closedPx = 32 + (drawerState === "closed" ? bottomInset : 0);
1078
1568
  let clampedDragOffset = dragOffset;
1079
1569
  if (drawerState === "full") {
1080
- clampedDragOffset = Math.max(0, dragOffset);
1570
+ clampedDragOffset = Math.max(0, Math.min(fullPx - closedPx, dragOffset));
1571
+ } else if (drawerState === "peek") {
1572
+ clampedDragOffset = Math.max(
1573
+ -(fullPx - peekPx),
1574
+ // up to full
1575
+ Math.min(peekPx - closedPx, dragOffset)
1576
+ // down to closed
1577
+ );
1081
1578
  } else if (drawerState === "closed") {
1082
- clampedDragOffset = Math.min(0, dragOffset);
1579
+ clampedDragOffset = Math.min(0, Math.max(-(fullPx - closedPx), dragOffset));
1083
1580
  }
1084
- const fullPx = resolveHeightToPixels2(drawerFullHeight || "85%", mapHeight);
1085
- const peekPx = resolveHeightToPixels2(drawerPeekHeight || "15%", mapHeight);
1086
1581
  let baseHeight = 32;
1087
1582
  if (drawerState === "peek") {
1088
1583
  baseHeight = peekPx;
@@ -1092,7 +1587,6 @@ var MapControls = ({
1092
1587
  const currentDrawerHeight = baseHeight - clampedDragOffset;
1093
1588
  const startFadeHeight = peekPx + 20;
1094
1589
  const endFadeHeight = peekPx + (fullPx - peekPx) * 0.35;
1095
- const bottomInset = mapContext?.insets.bottom || 0;
1096
1590
  let etaOpacity = 1;
1097
1591
  let etaBottomStyle = "1rem";
1098
1592
  if (side === "bottom") {
@@ -1105,14 +1599,14 @@ var MapControls = ({
1105
1599
  etaOpacity = 1 - fraction;
1106
1600
  }
1107
1601
  const effectiveInset = drawerState === "closed" ? bottomInset : 0;
1108
- etaBottomStyle = `${currentDrawerHeight + effectiveInset + 16}px`;
1602
+ etaBottomStyle = `calc(${baseHeight + effectiveInset + 16}px - var(--drag-offset, 0px))`;
1109
1603
  } else {
1110
1604
  etaOpacity = drawerState === "full" ? 0 : 1;
1111
1605
  etaBottomStyle = `calc(1rem + ${bottomInset}px)`;
1112
1606
  }
1113
- return /* @__PURE__ */ jsxs4(Fragment2, { children: [
1114
- /* @__PURE__ */ jsx5("div", { ref: containerRef, style: { display: "none" } }),
1115
- /* @__PURE__ */ jsx5(
1607
+ return /* @__PURE__ */ jsxs5(Fragment2, { children: [
1608
+ /* @__PURE__ */ jsx8("div", { ref: containerRef, style: { display: "none" } }),
1609
+ /* @__PURE__ */ jsx8(
1116
1610
  MapDrawer,
1117
1611
  {
1118
1612
  clampedDragOffset,
@@ -1129,14 +1623,16 @@ var MapControls = ({
1129
1623
  onChangeState: setDrawerState,
1130
1624
  ref: mergedRef,
1131
1625
  safeAreaInsets: mapContext?.insets,
1626
+ scrollToTopThreshold,
1132
1627
  setCurrentTouchY,
1133
1628
  setTouchStartY,
1629
+ showScrollToTopButton,
1134
1630
  side,
1135
1631
  state: drawerState,
1136
1632
  touchStartY
1137
1633
  }
1138
1634
  ),
1139
- /* @__PURE__ */ jsx5(
1635
+ /* @__PURE__ */ jsx8(
1140
1636
  MapRightControls,
1141
1637
  {
1142
1638
  clampedDragOffset,
@@ -1158,7 +1654,7 @@ var MapControls = ({
1158
1654
  side
1159
1655
  }
1160
1656
  ),
1161
- resolvedEtaData && /* @__PURE__ */ jsx5(
1657
+ resolvedEtaData && /* @__PURE__ */ jsx8(
1162
1658
  MapEtaPanel,
1163
1659
  {
1164
1660
  etaData: resolvedEtaData,
@@ -1177,9 +1673,9 @@ var MapControls = ({
1177
1673
 
1178
1674
  // src/components/Map/components/MapMenu.tsx
1179
1675
  import { useContext as useContext3 } from "react";
1180
- import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
1676
+ import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
1181
1677
  var MapMenu = ({ children }) => {
1182
- return /* @__PURE__ */ jsx6("div", { className: "flex flex-col gap-1.5", children });
1678
+ return /* @__PURE__ */ jsx9("div", { className: "flex flex-col gap-1.5", children });
1183
1679
  };
1184
1680
  var MapMenuItem = ({
1185
1681
  id,
@@ -1198,7 +1694,7 @@ var MapMenuItem = ({
1198
1694
  context.setDrawerState("closed");
1199
1695
  }
1200
1696
  };
1201
- return /* @__PURE__ */ jsxs5(
1697
+ return /* @__PURE__ */ jsxs6(
1202
1698
  "button",
1203
1699
  {
1204
1700
  className: `flex items-center gap-3 w-full py-3 px-3.5 rounded-xl text-left cursor-pointer transition-all duration-150 ${disabled ? "opacity-45 cursor-not-allowed pointer-events-none" : "hover:bg-white/5 active:bg-white/10 text-white"}`,
@@ -1206,12 +1702,12 @@ var MapMenuItem = ({
1206
1702
  onClick: handleClick,
1207
1703
  type: "button",
1208
1704
  children: [
1209
- icon && /* @__PURE__ */ jsxs5("div", { className: "relative flex items-center justify-center w-8 h-8 rounded-lg bg-white/5 text-zinc-300", children: [
1705
+ icon && /* @__PURE__ */ jsxs6("div", { className: "relative flex items-center justify-center w-8 h-8 rounded-lg bg-white/5 text-zinc-300", children: [
1210
1706
  icon,
1211
- badge !== void 0 && /* @__PURE__ */ jsx6("span", { className: "absolute -top-1 -right-1 bg-cyan-500 text-black text-[9px] font-extrabold min-w-[15px] h-3.5 rounded-full flex items-center justify-center px-1 border border-zinc-950 shadow", children: badge })
1707
+ badge !== void 0 && /* @__PURE__ */ jsx9("span", { className: "absolute -top-1 -right-1 bg-cyan-500 text-black text-[9px] font-extrabold min-w-[15px] h-3.5 rounded-full flex items-center justify-center px-1 border border-zinc-950 shadow", children: badge })
1212
1708
  ] }),
1213
- /* @__PURE__ */ jsxs5("div", { className: "flex-1 flex flex-col justify-center", children: [
1214
- /* @__PURE__ */ jsx6("span", { className: "text-sm font-medium tracking-wide flex-1", children: label }),
1709
+ /* @__PURE__ */ jsxs6("div", { className: "flex-1 flex flex-col justify-center", children: [
1710
+ /* @__PURE__ */ jsx9("span", { className: "text-sm font-medium tracking-wide flex-1", children: label }),
1215
1711
  children
1216
1712
  ] })
1217
1713
  ]
@@ -1225,7 +1721,7 @@ var MapMenuTitle = ({
1225
1721
  showDivider = true,
1226
1722
  className = ""
1227
1723
  }) => {
1228
- return /* @__PURE__ */ jsx6(
1724
+ return /* @__PURE__ */ jsx9(
1229
1725
  "div",
1230
1726
  {
1231
1727
  className: `flex items-center justify-between pb-3 first:mt-0 px-3.5 ${className} ${showDivider ? "border-b border-white/10 mb-2 mt-4" : ""}`,
@@ -1237,14 +1733,14 @@ MapMenuTitle.displayName = "MapMenuTitle";
1237
1733
  var MapMenuDivider = ({
1238
1734
  className = ""
1239
1735
  }) => {
1240
- return /* @__PURE__ */ jsx6("div", { className: `h-[1px] bg-white/10 my-3 mx-3.5 ${className}` });
1736
+ return /* @__PURE__ */ jsx9("div", { className: `h-[1px] bg-white/10 my-3 mx-3.5 ${className}` });
1241
1737
  };
1242
1738
  MapMenuDivider.displayName = "MapMenuDivider";
1243
1739
  var MapMenuFooter = ({
1244
1740
  children,
1245
1741
  className = ""
1246
1742
  }) => {
1247
- return /* @__PURE__ */ jsx6(
1743
+ return /* @__PURE__ */ jsx9(
1248
1744
  "div",
1249
1745
  {
1250
1746
  className: `mt-auto pt-4 border-t border-white/10 px-3.5 text-xs text-zinc-500 font-medium ${className}`,
@@ -1272,10 +1768,10 @@ var GlobalEvent = /* @__PURE__ */ ((GlobalEvent2) => {
1272
1768
  })(GlobalEvent || {});
1273
1769
 
1274
1770
  // src/components/Map/hooks/useUserLocation.ts
1275
- import { useCallback as useCallback3, useEffect as useEffect2, useRef as useRef4, useState as useState3 } from "react";
1771
+ import { useCallback as useCallback3, useEffect as useEffect3, useRef as useRef4, useState as useState4 } from "react";
1276
1772
  var LERP_FACTOR = 0.12;
1277
1773
  var useUserLocation = () => {
1278
- const [locationState, setLocationState] = useState3({
1774
+ const [locationState, setLocationState] = useState4({
1279
1775
  accuracy: null,
1280
1776
  coords: null,
1281
1777
  heading: null
@@ -1308,7 +1804,7 @@ var useUserLocation = () => {
1308
1804
  heading
1309
1805
  };
1310
1806
  }, []);
1311
- useEffect2(() => {
1807
+ useEffect3(() => {
1312
1808
  let rafId;
1313
1809
  const animate = () => {
1314
1810
  let changed = false;
@@ -1387,7 +1883,7 @@ var useUserLocation = () => {
1387
1883
  };
1388
1884
 
1389
1885
  // src/components/Map/hooks/useLiveRouting.ts
1390
- import { useCallback as useCallback4, useEffect as useEffect3, useMemo as useMemo2, useRef as useRef5, useState as useState4 } from "react";
1886
+ import { useCallback as useCallback4, useEffect as useEffect4, useMemo as useMemo2, useRef as useRef5, useState as useState5 } from "react";
1391
1887
  var useLiveRouting = ({
1392
1888
  origin: manualOrigin,
1393
1889
  destination,
@@ -1396,13 +1892,14 @@ var useLiveRouting = ({
1396
1892
  enabled = true,
1397
1893
  initialMode = "preview"
1398
1894
  }) => {
1399
- const [route, setRoute] = useState4(null);
1400
- const [totalDistance, setTotalDistance] = useState4(null);
1401
- const [isCalculating, setIsCalculating] = useState4(false);
1402
- const [error, setError] = useState4(null);
1403
- const [mode, setMode] = useState4(initialMode);
1895
+ const [route, setRoute] = useState5(null);
1896
+ const [totalDistance, setTotalDistance] = useState5(null);
1897
+ const [isCalculating, setIsCalculating] = useState5(false);
1898
+ const [error, setError] = useState5(null);
1899
+ const [mode, setMode] = useState5(initialMode);
1404
1900
  const userLocationState = useUserLocation();
1405
- const userLocation = manualOrigin || userLocationState.coords;
1901
+ const calculationOrigin = manualOrigin || userLocationState.coords;
1902
+ const trackingLocation = userLocationState.coords || manualOrigin;
1406
1903
  const lastCalcOrigin = useRef5(null);
1407
1904
  const lastCalcDest = useRef5(null);
1408
1905
  const isRequestInProgress = useRef5(false);
@@ -1420,9 +1917,32 @@ var useLiveRouting = ({
1420
1917
  []
1421
1918
  );
1422
1919
  const currentDistanceMeters = useMemo2(() => {
1423
- if (!userLocation || !destination) return null;
1424
- return getDistance(userLocation, destination);
1425
- }, [userLocation, destination, getDistance]);
1920
+ if (!trackingLocation || !route || route.geometry.coordinates.length < 2) {
1921
+ if (trackingLocation && destination) {
1922
+ return getDistance(trackingLocation, destination);
1923
+ }
1924
+ return null;
1925
+ }
1926
+ const coords = route.geometry.coordinates;
1927
+ let minDistSq = Infinity;
1928
+ let closestIndex = 0;
1929
+ const getDistSq = (p1, p2) => (p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2;
1930
+ for (let i = 0; i < coords.length; i++) {
1931
+ const d = getDistSq(trackingLocation, coords[i]);
1932
+ if (d < minDistSq) {
1933
+ minDistSq = d;
1934
+ closestIndex = i;
1935
+ }
1936
+ }
1937
+ const remainingCoords = coords.slice(closestIndex + 1);
1938
+ let dist = 0;
1939
+ let prev = trackingLocation;
1940
+ for (const coord of remainingCoords) {
1941
+ dist += getDistance(prev, coord);
1942
+ prev = coord;
1943
+ }
1944
+ return dist;
1945
+ }, [trackingLocation, route, destination, getDistance]);
1426
1946
  const calculate = useCallback4(
1427
1947
  async (origin, dest, isNewDest) => {
1428
1948
  if (isRequestInProgress.current) return;
@@ -1437,7 +1957,15 @@ var useLiveRouting = ({
1437
1957
  setRoute(data);
1438
1958
  setError(null);
1439
1959
  if (isNewDest) {
1440
- setTotalDistance(data.distanceMeters);
1960
+ const coords = data.geometry.coordinates;
1961
+ let sum = 0;
1962
+ for (let i = 0; i < coords.length - 1; i++) {
1963
+ sum += getDistance(
1964
+ coords[i],
1965
+ coords[i + 1]
1966
+ );
1967
+ }
1968
+ setTotalDistance(sum);
1441
1969
  }
1442
1970
  lastCalcOrigin.current = origin;
1443
1971
  lastCalcDest.current = dest;
@@ -1448,10 +1976,10 @@ var useLiveRouting = ({
1448
1976
  isRequestInProgress.current = false;
1449
1977
  }
1450
1978
  },
1451
- [profile]
1979
+ [profile, getDistance]
1452
1980
  );
1453
- useEffect3(() => {
1454
- if (!enabled || !destination || !userLocation) {
1981
+ useEffect4(() => {
1982
+ if (!enabled || !destination || !calculationOrigin) {
1455
1983
  if (!enabled || !destination) {
1456
1984
  setRoute(null);
1457
1985
  setTotalDistance(null);
@@ -1462,17 +1990,19 @@ var useLiveRouting = ({
1462
1990
  }
1463
1991
  const destChanged = !lastCalcDest.current || lastCalcDest.current[0] !== destination[0] || lastCalcDest.current[1] !== destination[1];
1464
1992
  if (destChanged) {
1465
- calculate(userLocation, destination, true);
1993
+ calculate(calculationOrigin, destination, true);
1466
1994
  } else if (lastCalcOrigin.current) {
1467
- const dist = getDistance(userLocation, lastCalcOrigin.current);
1995
+ const livePos = trackingLocation || calculationOrigin;
1996
+ const dist = getDistance(livePos, lastCalcOrigin.current);
1468
1997
  if (dist > recalculateThreshold) {
1469
- calculate(userLocation, destination, false);
1998
+ calculate(livePos, destination, false);
1470
1999
  }
1471
2000
  } else {
1472
- calculate(userLocation, destination, true);
2001
+ calculate(calculationOrigin, destination, true);
1473
2002
  }
1474
2003
  }, [
1475
- userLocation,
2004
+ calculationOrigin,
2005
+ trackingLocation,
1476
2006
  destination,
1477
2007
  enabled,
1478
2008
  recalculateThreshold,
@@ -1484,17 +2014,17 @@ var useLiveRouting = ({
1484
2014
  error,
1485
2015
  isCalculating,
1486
2016
  mode,
1487
- recalculate: () => userLocation && destination && calculate(userLocation, destination, false),
2017
+ recalculate: () => calculationOrigin && destination && calculate(calculationOrigin, destination, false),
1488
2018
  route,
1489
2019
  start: () => setMode("navigation"),
1490
2020
  totalDistance
1491
2021
  };
1492
2022
  };
1493
2023
  var useRoute = (origin, destination, profile = "driving") => {
1494
- const [route, setRoute] = useState4(null);
1495
- const [isCalculating, setIsCalculating] = useState4(false);
1496
- const [error, setError] = useState4(null);
1497
- useEffect3(() => {
2024
+ const [route, setRoute] = useState5(null);
2025
+ const [isCalculating, setIsCalculating] = useState5(false);
2026
+ const [error, setError] = useState5(null);
2027
+ useEffect4(() => {
1498
2028
  if (!origin || !destination) {
1499
2029
  setRoute(null);
1500
2030
  return;
@@ -1548,7 +2078,7 @@ var useTrimmedRoute = (route, userLocation) => {
1548
2078
 
1549
2079
  // src/components/Map/layers/RouteLayer.tsx
1550
2080
  import { Layer, Source } from "@vis.gl/react-maplibre";
1551
- import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
2081
+ import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
1552
2082
  var RouteLayer = ({
1553
2083
  geometry,
1554
2084
  color = "#3b82f6",
@@ -1561,8 +2091,8 @@ var RouteLayer = ({
1561
2091
  properties: {},
1562
2092
  type: "Feature"
1563
2093
  };
1564
- return /* @__PURE__ */ jsxs6(Source, { data, id: "sdk-route-source", type: "geojson", children: [
1565
- /* @__PURE__ */ jsx7(
2094
+ return /* @__PURE__ */ jsxs7(Source, { data, id: "sdk-route-source", type: "geojson", children: [
2095
+ /* @__PURE__ */ jsx10(
1566
2096
  Layer,
1567
2097
  {
1568
2098
  id: "sdk-route-layer-casing",
@@ -1575,7 +2105,7 @@ var RouteLayer = ({
1575
2105
  type: "line"
1576
2106
  }
1577
2107
  ),
1578
- /* @__PURE__ */ jsx7(
2108
+ /* @__PURE__ */ jsx10(
1579
2109
  Layer,
1580
2110
  {
1581
2111
  id: "sdk-route-layer",
@@ -1596,20 +2126,20 @@ var RouteLayer = ({
1596
2126
 
1597
2127
  // src/components/Map/Map.tsx
1598
2128
  import { Map as MapLibre, MapProvider } from "@vis.gl/react-maplibre";
1599
- import React, {
2129
+ import React4, {
1600
2130
  useCallback as useCallback5,
1601
2131
  useContext as useContext4,
1602
- useEffect as useEffect5,
2132
+ useEffect as useEffect6,
1603
2133
  useMemo as useMemo5,
1604
2134
  useRef as useRef6,
1605
- useState as useState6
2135
+ useState as useState7
1606
2136
  } from "react";
1607
2137
  import "maplibre-gl/dist/maplibre-gl.css";
1608
2138
 
1609
2139
  // src/components/Map/layers/POILayers.tsx
1610
2140
  import { Layer as Layer2, Source as Source2, useMap } from "@vis.gl/react-maplibre";
1611
- import { useEffect as useEffect4, useMemo as useMemo4, useState as useState5 } from "react";
1612
- import { jsx as jsx8 } from "react/jsx-runtime";
2141
+ import { useEffect as useEffect5, useMemo as useMemo4, useState as useState6 } from "react";
2142
+ import { jsx as jsx11 } from "react/jsx-runtime";
1613
2143
  function createEmojiIcon(emoji, size = 64) {
1614
2144
  const canvas = document.createElement("canvas");
1615
2145
  canvas.width = size;
@@ -1622,13 +2152,13 @@ function createEmojiIcon(emoji, size = 64) {
1622
2152
  return ctx.getImageData(0, 0, size, size);
1623
2153
  }
1624
2154
  var POILayers = ({ pois }) => {
1625
- const [loadedImages, setLoadedImages] = useState5(0);
2155
+ const [loadedImages, setLoadedImages] = useState6(0);
1626
2156
  const { current: map } = useMap();
1627
2157
  const glPois = useMemo4(
1628
2158
  () => pois.filter((p) => !p.displayMode || p.displayMode === "gl"),
1629
2159
  [pois]
1630
2160
  );
1631
- useEffect4(() => {
2161
+ useEffect5(() => {
1632
2162
  if (!map) return;
1633
2163
  const glMap = map.getMap();
1634
2164
  const defaults = [
@@ -1686,7 +2216,7 @@ var POILayers = ({ pois }) => {
1686
2216
  }),
1687
2217
  [glPois]
1688
2218
  );
1689
- return /* @__PURE__ */ jsx8(Source2, { data: geojson, id: "sdk-pois", type: "geojson", children: /* @__PURE__ */ jsx8(
2219
+ return /* @__PURE__ */ jsx11(Source2, { data: geojson, id: "sdk-pois", type: "geojson", children: /* @__PURE__ */ jsx11(
1690
2220
  Layer2,
1691
2221
  {
1692
2222
  id: "sdk-poi-layer",
@@ -1723,11 +2253,11 @@ var POILayers = ({ pois }) => {
1723
2253
 
1724
2254
  // src/components/Map/layers/POIMarkers.tsx
1725
2255
  import { Marker } from "@vis.gl/react-maplibre";
1726
- import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
2256
+ import { Fragment as Fragment3, jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
1727
2257
  var POIMarkers = ({ pois, onClick }) => {
1728
2258
  const markerPois = pois.filter((p) => p.displayMode === "marker");
1729
2259
  if (markerPois.length === 0) return null;
1730
- return /* @__PURE__ */ jsx9(Fragment3, { children: markerPois.map((poi) => /* @__PURE__ */ jsx9(
2260
+ return /* @__PURE__ */ jsx12(Fragment3, { children: markerPois.map((poi) => /* @__PURE__ */ jsx12(
1731
2261
  Marker,
1732
2262
  {
1733
2263
  anchor: "bottom",
@@ -1737,7 +2267,7 @@ var POIMarkers = ({ pois, onClick }) => {
1737
2267
  e.originalEvent.stopPropagation();
1738
2268
  if (onClick) onClick(poi);
1739
2269
  },
1740
- children: poi.markerComponent ? poi.markerComponent : /* @__PURE__ */ jsxs7(
2270
+ children: poi.markerComponent ? poi.markerComponent : /* @__PURE__ */ jsxs8(
1741
2271
  "div",
1742
2272
  {
1743
2273
  style: {
@@ -1746,7 +2276,7 @@ var POIMarkers = ({ pois, onClick }) => {
1746
2276
  transform: "transition-transform duration-200 hover:scale-110"
1747
2277
  },
1748
2278
  children: [
1749
- /* @__PURE__ */ jsx9(
2279
+ /* @__PURE__ */ jsx12(
1750
2280
  "div",
1751
2281
  {
1752
2282
  style: {
@@ -1759,7 +2289,7 @@ var POIMarkers = ({ pois, onClick }) => {
1759
2289
  justifyContent: "center",
1760
2290
  width: "32px"
1761
2291
  },
1762
- children: poi.emoji ? /* @__PURE__ */ jsx9("span", { style: { fontSize: "16px" }, children: poi.emoji }) : /* @__PURE__ */ jsx9(
2292
+ children: poi.emoji ? /* @__PURE__ */ jsx12("span", { style: { fontSize: "16px" }, children: poi.emoji }) : /* @__PURE__ */ jsx12(
1763
2293
  "div",
1764
2294
  {
1765
2295
  style: {
@@ -1772,7 +2302,7 @@ var POIMarkers = ({ pois, onClick }) => {
1772
2302
  )
1773
2303
  }
1774
2304
  ),
1775
- /* @__PURE__ */ jsx9(
2305
+ /* @__PURE__ */ jsx12(
1776
2306
  "div",
1777
2307
  {
1778
2308
  style: {
@@ -1795,19 +2325,19 @@ var POIMarkers = ({ pois, onClick }) => {
1795
2325
 
1796
2326
  // src/components/Map/layers/UserLocationLayer.tsx
1797
2327
  import { Marker as Marker2 } from "@vis.gl/react-maplibre";
1798
- import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
2328
+ import { jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
1799
2329
  var UserLocationLayer = ({
1800
2330
  forcedLocation,
1801
2331
  heading
1802
2332
  }) => {
1803
2333
  if (!forcedLocation) return null;
1804
- return /* @__PURE__ */ jsx10(
2334
+ return /* @__PURE__ */ jsx13(
1805
2335
  Marker2,
1806
2336
  {
1807
2337
  anchor: "center",
1808
2338
  latitude: forcedLocation[1],
1809
2339
  longitude: forcedLocation[0],
1810
- children: /* @__PURE__ */ jsxs8(
2340
+ children: /* @__PURE__ */ jsxs9(
1811
2341
  "div",
1812
2342
  {
1813
2343
  style: {
@@ -1817,7 +2347,7 @@ var UserLocationLayer = ({
1817
2347
  position: "relative"
1818
2348
  },
1819
2349
  children: [
1820
- /* @__PURE__ */ jsx10(
2350
+ /* @__PURE__ */ jsx13(
1821
2351
  "div",
1822
2352
  {
1823
2353
  style: {
@@ -1830,7 +2360,7 @@ var UserLocationLayer = ({
1830
2360
  }
1831
2361
  }
1832
2362
  ),
1833
- heading !== void 0 && heading !== null && /* @__PURE__ */ jsx10(
2363
+ heading !== void 0 && heading !== null && /* @__PURE__ */ jsx13(
1834
2364
  "div",
1835
2365
  {
1836
2366
  style: {
@@ -1840,13 +2370,13 @@ var UserLocationLayer = ({
1840
2370
  width: "60px",
1841
2371
  zIndex: 0
1842
2372
  },
1843
- children: /* @__PURE__ */ jsxs8(
2373
+ children: /* @__PURE__ */ jsxs9(
1844
2374
  "svg",
1845
2375
  {
1846
2376
  style: { height: "100%", width: "100%" },
1847
2377
  viewBox: "0 0 100 100",
1848
2378
  children: [
1849
- /* @__PURE__ */ jsx10("defs", { children: /* @__PURE__ */ jsxs8(
2379
+ /* @__PURE__ */ jsx13("defs", { children: /* @__PURE__ */ jsxs9(
1850
2380
  "radialGradient",
1851
2381
  {
1852
2382
  cx: "50%",
@@ -1856,7 +2386,7 @@ var UserLocationLayer = ({
1856
2386
  id: "grad1",
1857
2387
  r: "50%",
1858
2388
  children: [
1859
- /* @__PURE__ */ jsx10(
2389
+ /* @__PURE__ */ jsx13(
1860
2390
  "stop",
1861
2391
  {
1862
2392
  offset: "0%",
@@ -1866,7 +2396,7 @@ var UserLocationLayer = ({
1866
2396
  }
1867
2397
  }
1868
2398
  ),
1869
- /* @__PURE__ */ jsx10(
2399
+ /* @__PURE__ */ jsx13(
1870
2400
  "stop",
1871
2401
  {
1872
2402
  offset: "100%",
@@ -1879,7 +2409,7 @@ var UserLocationLayer = ({
1879
2409
  ]
1880
2410
  }
1881
2411
  ) }),
1882
- /* @__PURE__ */ jsx10(
2412
+ /* @__PURE__ */ jsx13(
1883
2413
  "path",
1884
2414
  {
1885
2415
  d: "M 50 50 L 35 0 A 50 50 0 0 1 65 0 Z",
@@ -1891,7 +2421,7 @@ var UserLocationLayer = ({
1891
2421
  )
1892
2422
  }
1893
2423
  ),
1894
- /* @__PURE__ */ jsx10(
2424
+ /* @__PURE__ */ jsx13(
1895
2425
  "div",
1896
2426
  {
1897
2427
  style: {
@@ -1905,7 +2435,7 @@ var UserLocationLayer = ({
1905
2435
  width: "20px",
1906
2436
  zIndex: 1
1907
2437
  },
1908
- children: /* @__PURE__ */ jsx10(
2438
+ children: /* @__PURE__ */ jsx13(
1909
2439
  "div",
1910
2440
  {
1911
2441
  style: {
@@ -1919,7 +2449,7 @@ var UserLocationLayer = ({
1919
2449
  )
1920
2450
  }
1921
2451
  ),
1922
- /* @__PURE__ */ jsx10("style", { children: `@keyframes pulse { 0% { transform: scale(0.95); opacity: 0.7; } 70% { transform: scale(1.5); opacity: 0; } 100% { transform: scale(0.95); opacity: 0; } }` })
2452
+ /* @__PURE__ */ jsx13("style", { children: `@keyframes pulse { 0% { transform: scale(0.95); opacity: 0.7; } 70% { transform: scale(1.5); opacity: 0; } 100% { transform: scale(0.95); opacity: 0; } }` })
1923
2453
  ]
1924
2454
  }
1925
2455
  )
@@ -1928,7 +2458,7 @@ var UserLocationLayer = ({
1928
2458
  };
1929
2459
 
1930
2460
  // src/components/Map/Map.tsx
1931
- import { Fragment as Fragment4, jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
2461
+ import { Fragment as Fragment4, jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
1932
2462
  var MapInternal = ({
1933
2463
  initialViewState = {
1934
2464
  latitude: 45.90583599233422,
@@ -1968,15 +2498,19 @@ var MapInternal = ({
1968
2498
  const mapControls = useContext4(MapControlsContext);
1969
2499
  const mapRef = useRef6(null);
1970
2500
  const userLocationState = useUserLocation();
1971
- const [progNav, setProgNav] = useState6(null);
1972
- useEffect5(() => {
2501
+ const [progNav, setProgNav] = useState7(null);
2502
+ const [isAborted, setIsAborted] = useState7(false);
2503
+ useEffect6(() => {
1973
2504
  const unsubCreate = sdk.on("SDK_NAVIGATION_CREATE", (payload) => {
2505
+ setIsAborted(false);
1974
2506
  setProgNav(payload);
1975
2507
  });
1976
2508
  const unsubStart = sdk.on("SDK_NAVIGATION_START", () => {
2509
+ setIsAborted(false);
1977
2510
  setProgNav((prev) => prev ? { ...prev, mode: "navigation" } : null);
1978
2511
  });
1979
2512
  const unsubAbort = sdk.on("SDK_NAVIGATION_ABORT", () => {
2513
+ setIsAborted(true);
1980
2514
  setProgNav(null);
1981
2515
  });
1982
2516
  return () => {
@@ -1994,19 +2528,29 @@ var MapInternal = ({
1994
2528
  profile: effectiveNavOptions?.profile || "driving",
1995
2529
  recalculateThreshold: effectiveNavOptions?.recalculateThreshold || 50
1996
2530
  });
1997
- useEffect5(() => {
2531
+ useEffect6(() => {
1998
2532
  if (onNavigationModeChange && navigation) {
1999
2533
  onNavigationModeChange(internalNav.mode);
2000
2534
  }
2001
2535
  }, [internalNav.mode, onNavigationModeChange, navigation]);
2002
- const navigationData = effectiveNavOptions ? internalNav : externalNavigationData;
2003
- const route = effectiveNavOptions ? internalNav.route?.geometry : externalRoute;
2004
- const showNavigationUI = effectiveNavOptions?.showUI !== false && (effectiveNavOptions ? !!effectiveNavOptions.destination : externalShowNavigationUI);
2536
+ const prevDest = useRef6(null);
2537
+ const currentDest = effectiveNavOptions?.destination;
2538
+ useEffect6(() => {
2539
+ if (currentDest) {
2540
+ if (!prevDest.current || prevDest.current[0] !== currentDest[0] || prevDest.current[1] !== currentDest[1]) {
2541
+ setIsAborted(false);
2542
+ }
2543
+ }
2544
+ prevDest.current = currentDest;
2545
+ }, [currentDest]);
2546
+ const navigationData = !isAborted ? effectiveNavOptions ? internalNav : externalNavigationData : void 0;
2547
+ const route = !isAborted ? effectiveNavOptions ? internalNav.route?.geometry : externalRoute : void 0;
2548
+ const showNavigationUI = !isAborted && effectiveNavOptions?.showUI !== false && (effectiveNavOptions ? !!effectiveNavOptions.destination : externalShowNavigationUI);
2005
2549
  const mode = navigationData?.mode || "preview";
2006
2550
  const resolvedInitialFollow = mapControls ? mapControls.isFollowing : initialFollowUser;
2007
2551
  const isFollowingRef = useRef6(resolvedInitialFollow);
2008
2552
  const isFlyingRef = useRef6(false);
2009
- const [localIsFollowingUI, setLocalIsFollowingUI] = useState6(
2553
+ const [localIsFollowingUI, setLocalIsFollowingUI] = useState7(
2010
2554
  resolvedInitialFollow
2011
2555
  );
2012
2556
  const isFollowingUI = mapControls ? mapControls.isFollowing : localIsFollowingUI;
@@ -2021,7 +2565,7 @@ var MapInternal = ({
2021
2565
  },
2022
2566
  [setIsFollowingCtx]
2023
2567
  );
2024
- useEffect5(() => {
2568
+ useEffect6(() => {
2025
2569
  if (mapControls && mapControls.isFollowing !== isFollowingRef.current) {
2026
2570
  isFollowingRef.current = mapControls.isFollowing;
2027
2571
  }
@@ -2031,7 +2575,7 @@ var MapInternal = ({
2031
2575
  mergedInteractiveLayerIds.push("sdk-poi-layer");
2032
2576
  }
2033
2577
  const prevInitialFollow = useRef6(initialFollowUser);
2034
- useEffect5(() => {
2578
+ useEffect6(() => {
2035
2579
  if (initialFollowUser !== prevInitialFollow.current) {
2036
2580
  setFollowMode(initialFollowUser);
2037
2581
  prevInitialFollow.current = initialFollowUser;
@@ -2050,15 +2594,29 @@ var MapInternal = ({
2050
2594
  }
2051
2595
  }, [initialFollowUser, setFollowMode, userLocationState.coords]);
2052
2596
  const lastAutoLockedRouteRef = useRef6(null);
2053
- useEffect5(() => {
2597
+ const lastModeRef = useRef6(null);
2598
+ useEffect6(() => {
2054
2599
  if (!route || !mapRef.current) {
2055
2600
  if (!route) lastAutoLockedRouteRef.current = null;
2056
2601
  return;
2057
2602
  }
2058
2603
  const isNewRoute = route !== lastAutoLockedRouteRef.current;
2059
- if (!isNewRoute && mode === "navigation") return;
2604
+ const modeChanged = lastModeRef.current !== mode;
2060
2605
  if (mode === "navigation") {
2061
2606
  setFollowMode(true);
2607
+ if ((modeChanged || isNewRoute) && userLocationState.coords && mapRef.current) {
2608
+ isFlyingRef.current = true;
2609
+ mapRef.current.flyTo({
2610
+ center: userLocationState.coords,
2611
+ duration: 1e3,
2612
+ essential: true,
2613
+ zoom: 17
2614
+ // Zoomed in on user for active guidance
2615
+ });
2616
+ setTimeout(() => {
2617
+ isFlyingRef.current = false;
2618
+ }, 1050);
2619
+ }
2062
2620
  } else if (mode === "preview" && isNewRoute) {
2063
2621
  setFollowMode(false);
2064
2622
  const coords = route.coordinates;
@@ -2082,8 +2640,9 @@ var MapInternal = ({
2082
2640
  }
2083
2641
  }
2084
2642
  lastAutoLockedRouteRef.current = route;
2085
- }, [route, mode, setFollowMode]);
2086
- useEffect5(() => {
2643
+ lastModeRef.current = mode;
2644
+ }, [route, mode, setFollowMode, userLocationState.coords]);
2645
+ useEffect6(() => {
2087
2646
  if (isFollowingRef.current && !isFlyingRef.current && userLocationState.coords && mapRef.current) {
2088
2647
  mapRef.current.easeTo({
2089
2648
  center: userLocationState.coords,
@@ -2098,41 +2657,41 @@ var MapInternal = ({
2098
2657
  route,
2099
2658
  showUserLocation ? userLocationState.coords : null
2100
2659
  );
2101
- const remainingMeters = navigationData?.currentDistanceMeters ?? navigationData?.route?.distanceMeters ?? 0;
2102
- const etaMins = navigationData?.route?.durationSeconds ? Math.ceil(navigationData.route.durationSeconds / 60) : 0;
2660
+ const currentDistMeters = navigationData?.currentDistanceMeters ?? null;
2661
+ const totalDist = navigationData?.totalDistance ?? null;
2662
+ const routeDurationSeconds = navigationData?.route?.durationSeconds ?? null;
2663
+ const remainingMeters = currentDistMeters ?? 0;
2664
+ const etaMins = (() => {
2665
+ if (!routeDurationSeconds || !totalDist || !currentDistMeters) return 0;
2666
+ const ratio = currentDistMeters / totalDist;
2667
+ return Math.ceil(routeDurationSeconds * ratio / 60);
2668
+ })();
2103
2669
  const kmRemaining = remainingMeters / 1e3;
2104
- const totalDist = navigationData?.totalDistance ?? 0;
2105
- const progressValue = totalDist > 0 ? (totalDist - remainingMeters) / totalDist * 100 : 0;
2106
- const showEtaData = useMemo5(() => {
2107
- if (!navigationData || !route) return void 0;
2108
- return {
2109
- distanceRemainingKm: kmRemaining,
2110
- etaMins,
2111
- label: mode === "navigation" ? "Walking Guidance Active" : "Route Preview",
2112
- mode,
2113
- onAbort: onNavigationAbort || (() => {
2114
- setProgNav(null);
2115
- }),
2116
- onStart: navigationData.start,
2117
- progress: progressValue
2118
- };
2119
- }, [
2120
- navigationData,
2121
- route,
2670
+ const progressValue = totalDist && totalDist > 0 ? Math.min(100, Math.max(0, (totalDist - remainingMeters) / totalDist * 100)) : 0;
2671
+ const showEtaData = navigationData && route ? {
2672
+ distanceRemainingKm: kmRemaining,
2122
2673
  etaMins,
2123
- kmRemaining,
2674
+ label: mode === "navigation" ? "Walking Guidance Active" : "Route Preview",
2124
2675
  mode,
2125
- progressValue,
2126
- onNavigationAbort
2127
- ]);
2676
+ onAbort: () => {
2677
+ setIsAborted(true);
2678
+ setProgNav(null);
2679
+ sdk.navigation.abort();
2680
+ if (onNavigationAbort) {
2681
+ onNavigationAbort();
2682
+ }
2683
+ },
2684
+ onStart: navigationData.start,
2685
+ progress: progressValue
2686
+ } : void 0;
2128
2687
  const setEtaDataCtx = mapControls?.setEtaData;
2129
- useEffect5(() => {
2688
+ useEffect6(() => {
2130
2689
  if (setEtaDataCtx) {
2131
2690
  setEtaDataCtx(showEtaData);
2132
2691
  }
2133
2692
  }, [showEtaData, setEtaDataCtx]);
2134
2693
  const setDrawerStateCtx = mapControls?.setDrawerState;
2135
- useEffect5(() => {
2694
+ useEffect6(() => {
2136
2695
  if (setDrawerStateCtx && propDrawerState !== void 0) {
2137
2696
  setDrawerStateCtx(propDrawerState);
2138
2697
  }
@@ -2140,7 +2699,7 @@ var MapInternal = ({
2140
2699
  const defaultMenuItems = useMemo5(
2141
2700
  () => [
2142
2701
  {
2143
- icon: /* @__PURE__ */ jsx11(
2702
+ icon: /* @__PURE__ */ jsx14(
2144
2703
  "svg",
2145
2704
  {
2146
2705
  className: "w-5 h-5",
@@ -2148,7 +2707,7 @@ var MapInternal = ({
2148
2707
  stroke: "currentColor",
2149
2708
  strokeWidth: "2",
2150
2709
  viewBox: "0 0 24 24",
2151
- children: /* @__PURE__ */ jsx11(
2710
+ children: /* @__PURE__ */ jsx14(
2152
2711
  "path",
2153
2712
  {
2154
2713
  d: "M12 11c0 3.517-1.009 6.799-2.753 9.571m-3.44-2.04l.054-.09A13.916 13.916 0 008 11a4 4 0 118 0c0 1.017-.07 2.019-.203 3m-2.118 6.844A21.88 21.88 0 0015.171 17m3.839 1.132c.645-2.266.99-4.659.99-7.132A8 8 0 008 4.07M3 15.364c.64-1.319 1-2.8 1-4.364 0-1.457.39-2.823 1.07-4",
@@ -2170,8 +2729,8 @@ var MapInternal = ({
2170
2729
  const { mapLibreChildren, menuContentFromChildren } = useMemo5(() => {
2171
2730
  const mapLibreChildren2 = [];
2172
2731
  const extractedMenuItems = [];
2173
- React.Children.forEach(children, (child) => {
2174
- if (React.isValidElement(child)) {
2732
+ React4.Children.forEach(children, (child) => {
2733
+ if (React4.isValidElement(child)) {
2175
2734
  const type = child.type;
2176
2735
  const displayName = type?.displayName || type?.name;
2177
2736
  const isMenu = type === MapMenu || displayName === "MapMenu";
@@ -2182,7 +2741,7 @@ var MapInternal = ({
2182
2741
  "MapMenuFooter"
2183
2742
  ].includes(displayName);
2184
2743
  if (isMenu) {
2185
- React.Children.forEach(
2744
+ React4.Children.forEach(
2186
2745
  child.props.children,
2187
2746
  (nestedChild) => {
2188
2747
  if (nestedChild) {
@@ -2199,7 +2758,7 @@ var MapInternal = ({
2199
2758
  mapLibreChildren2.push(child);
2200
2759
  }
2201
2760
  });
2202
- const menuContentFromChildren2 = extractedMenuItems.length > 0 ? /* @__PURE__ */ jsx11(MapMenu, { children: extractedMenuItems }) : null;
2761
+ const menuContentFromChildren2 = extractedMenuItems.length > 0 ? /* @__PURE__ */ jsx14(MapMenu, { children: extractedMenuItems }) : null;
2203
2762
  return { mapLibreChildren: mapLibreChildren2, menuContentFromChildren: menuContentFromChildren2 };
2204
2763
  }, [children]);
2205
2764
  const handleMapClick = (e) => {
@@ -2252,7 +2811,7 @@ var MapInternal = ({
2252
2811
  });
2253
2812
  }
2254
2813
  }, []);
2255
- useEffect5(() => {
2814
+ useEffect6(() => {
2256
2815
  if (mapControls) {
2257
2816
  mapControls._registerCenterCallback(handleCenterOnUser);
2258
2817
  mapControls._registerResetBearingCallback(handleResetBearing);
@@ -2273,13 +2832,13 @@ var MapInternal = ({
2273
2832
  }
2274
2833
  }
2275
2834
  };
2276
- return /* @__PURE__ */ jsxs9(
2835
+ return /* @__PURE__ */ jsxs10(
2277
2836
  "div",
2278
2837
  {
2279
2838
  className: `w-full h-full overflow-hidden relative ${className}`,
2280
2839
  style,
2281
2840
  children: [
2282
- /* @__PURE__ */ jsxs9(
2841
+ /* @__PURE__ */ jsxs10(
2283
2842
  MapLibre,
2284
2843
  {
2285
2844
  attributionControl: false,
@@ -2308,23 +2867,23 @@ var MapInternal = ({
2308
2867
  showUserLocation && userLocationState.coords && (renderUserLocation ? renderUserLocation({
2309
2868
  coords: userLocationState.coords,
2310
2869
  heading: userLocationState.heading
2311
- }) : /* @__PURE__ */ jsx11(
2870
+ }) : /* @__PURE__ */ jsx14(
2312
2871
  UserLocationLayer,
2313
2872
  {
2314
2873
  forcedLocation: userLocationState.coords,
2315
2874
  heading: userLocationState.heading
2316
2875
  }
2317
2876
  )),
2318
- displayRoute && /* @__PURE__ */ jsx11(RouteLayer, { geometry: displayRoute }),
2319
- pois.length > 0 && /* @__PURE__ */ jsxs9(Fragment4, { children: [
2320
- /* @__PURE__ */ jsx11(POILayers, { pois }),
2321
- /* @__PURE__ */ jsx11(POIMarkers, { onClick: onPoiClick, pois })
2877
+ displayRoute && /* @__PURE__ */ jsx14(RouteLayer, { geometry: displayRoute }),
2878
+ pois.length > 0 && /* @__PURE__ */ jsxs10(Fragment4, { children: [
2879
+ /* @__PURE__ */ jsx14(POILayers, { pois }),
2880
+ /* @__PURE__ */ jsx14(POIMarkers, { onClick: onPoiClick, pois })
2322
2881
  ] }),
2323
2882
  mapLibreChildren
2324
2883
  ]
2325
2884
  }
2326
2885
  ),
2327
- showControls && mapControls && !mapControls.hasControls && /* @__PURE__ */ jsx11(
2886
+ showControls && mapControls && !mapControls.hasControls && /* @__PURE__ */ jsx14(
2328
2887
  MapControls,
2329
2888
  {
2330
2889
  drawerContentRef,
@@ -2346,16 +2905,16 @@ var SDKMapProviderWrapper = ({
2346
2905
  }) => {
2347
2906
  const context = useContext4(MapControlsContext);
2348
2907
  if (context) {
2349
- return /* @__PURE__ */ jsx11(Fragment4, { children });
2908
+ return /* @__PURE__ */ jsx14(Fragment4, { children });
2350
2909
  }
2351
- return /* @__PURE__ */ jsx11(SDKMapProvider, { children });
2910
+ return /* @__PURE__ */ jsx14(SDKMapProvider, { children });
2352
2911
  };
2353
2912
  var Map2 = (props) => {
2354
- return /* @__PURE__ */ jsx11(SDKMapProviderWrapper, { children: /* @__PURE__ */ jsx11(MapProvider, { children: /* @__PURE__ */ jsx11(MapInternal, { ...props }) }) });
2913
+ return /* @__PURE__ */ jsx14(SDKMapProviderWrapper, { children: /* @__PURE__ */ jsx14(MapProvider, { children: /* @__PURE__ */ jsx14(MapInternal, { ...props }) }) });
2355
2914
  };
2356
2915
 
2357
2916
  // src/components/MapWrapper.tsx
2358
- import React2 from "react";
2917
+ import React5 from "react";
2359
2918
  import { createRoot } from "react-dom/client";
2360
2919
  function renderMap(containerId, props = {}) {
2361
2920
  const container = document.getElementById(containerId);
@@ -2363,12 +2922,12 @@ function renderMap(containerId, props = {}) {
2363
2922
  throw new Error(`Container with id "${containerId}" not found.`);
2364
2923
  }
2365
2924
  const root = createRoot(container);
2366
- root.render(React2.createElement(Map2, props));
2925
+ root.render(React5.createElement(Map2, props));
2367
2926
  return root;
2368
2927
  }
2369
2928
 
2370
2929
  // package.json
2371
- var version = "0.2.0";
2930
+ var version = "0.2.2";
2372
2931
 
2373
2932
  // src/sdk.ts
2374
2933
  function deepFreeze(obj) {
@@ -2700,8 +3259,8 @@ var MiniAppSDK = class {
2700
3259
  var sdk = deepFreeze(new MiniAppSDK());
2701
3260
 
2702
3261
  // src/components/BridgeMocker.tsx
2703
- import { useCallback as useCallback6, useEffect as useEffect6, useRef as useRef7, useState as useState7 } from "react";
2704
- import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
3262
+ import { useCallback as useCallback6, useEffect as useEffect7, useRef as useRef7, useState as useState8 } from "react";
3263
+ import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
2705
3264
  var getBearing = (p1, p2) => {
2706
3265
  const lat1 = p1[1] * Math.PI / 180;
2707
3266
  const lat2 = p2[1] * Math.PI / 180;
@@ -2720,12 +3279,12 @@ var BridgeMocker = ({
2720
3279
  mockJWTToken,
2721
3280
  children
2722
3281
  }) => {
2723
- const [autoMove, setAutoMove] = useState7(isMoving);
2724
- const [location, setLocation] = useState7(initialLocation);
2725
- const [heading, setHeading] = useState7(0);
2726
- const [speedMultiplier, setSpeedMultiplier] = useState7(simulationSpeed);
2727
- const [isReady, setIsReady] = useState7(false);
2728
- const [isMinimized, setIsMinimized] = useState7(true);
3282
+ const [autoMove, setAutoMove] = useState8(isMoving);
3283
+ const [location, setLocation] = useState8(initialLocation);
3284
+ const [heading, setHeading] = useState8(0);
3285
+ const [speedMultiplier, setSpeedMultiplier] = useState8(simulationSpeed);
3286
+ const [isReady, setIsReady] = useState8(false);
3287
+ const [isMinimized, setIsMinimized] = useState8(true);
2729
3288
  const streamIntervalRef = useRef7(null);
2730
3289
  const pathIndexRef = useRef7(0);
2731
3290
  const activeConfigRef = useRef7(null);
@@ -2770,7 +3329,7 @@ var BridgeMocker = ({
2770
3329
  type: "EVENT"
2771
3330
  });
2772
3331
  }, []);
2773
- useEffect6(() => {
3332
+ useEffect7(() => {
2774
3333
  stateRef.current = {
2775
3334
  autoMove,
2776
3335
  heading,
@@ -2791,19 +3350,19 @@ var BridgeMocker = ({
2791
3350
  speedMultiplier,
2792
3351
  mockJWTToken
2793
3352
  ]);
2794
- useEffect6(() => {
3353
+ useEffect7(() => {
2795
3354
  setAutoMove(isMoving);
2796
3355
  }, [isMoving]);
2797
- useEffect6(() => {
3356
+ useEffect7(() => {
2798
3357
  setSpeedMultiplier(simulationSpeed);
2799
3358
  }, [simulationSpeed]);
2800
- useEffect6(() => {
3359
+ useEffect7(() => {
2801
3360
  if (simulationPath && simulationPath.length > 0) {
2802
3361
  pathIndexRef.current = 0;
2803
3362
  setLocation(simulationPath[0]);
2804
3363
  }
2805
3364
  }, [simulationPath]);
2806
- useEffect6(() => {
3365
+ useEffect7(() => {
2807
3366
  if (streamIntervalRef.current && activeConfigRef.current) {
2808
3367
  sdk.bridge.send(
2809
3368
  "START_LOCATION_STREAM",
@@ -2811,7 +3370,7 @@ var BridgeMocker = ({
2811
3370
  );
2812
3371
  }
2813
3372
  }, [speedMultiplier]);
2814
- useEffect6(() => {
3373
+ useEffect7(() => {
2815
3374
  const bridge = sdk.bridge;
2816
3375
  const originalSend = bridge.send.bind(bridge);
2817
3376
  const stopStream = () => {
@@ -2993,16 +3552,17 @@ var BridgeMocker = ({
2993
3552
  };
2994
3553
  }, [appId]);
2995
3554
  if (!isReady) return null;
2996
- return /* @__PURE__ */ jsxs10("div", { className: "relative w-full h-full", children: [
2997
- /* @__PURE__ */ jsx12("div", { className: "w-full h-full", children }),
2998
- isMinimized ? /* @__PURE__ */ jsx12(
2999
- "button",
3555
+ return /* @__PURE__ */ jsxs11("div", { className: "relative w-full h-full", children: [
3556
+ /* @__PURE__ */ jsx15("div", { className: "w-full h-full", children }),
3557
+ isMinimized ? /* @__PURE__ */ jsx15(
3558
+ Button,
3000
3559
  {
3001
- className: "fixed bottom-4 right-4 w-8 h-8 rounded-full bg-slate-900/60 backdrop-blur-sm border border-slate-700/50 flex items-center justify-center text-slate-400 hover:text-blue-400 z-[9999] transition-all shadow-lg group",
3560
+ className: "fixed bottom-4 right-4 w-8 h-8 rounded-full bg-slate-900/60 backdrop-blur-sm border border-slate-700/50 flex items-center justify-center text-slate-400 hover:text-blue-400 hover:bg-slate-900/80 z-[9999] transition-all shadow-lg group p-0!",
3002
3561
  onClick: () => setIsMinimized(false),
3003
3562
  title: "Open Simulation Controls",
3004
3563
  type: "button",
3005
- children: /* @__PURE__ */ jsxs10(
3564
+ variant: "ghost",
3565
+ children: /* @__PURE__ */ jsxs11(
3006
3566
  "svg",
3007
3567
  {
3008
3568
  className: "group-hover:scale-110 transition-transform",
@@ -3016,41 +3576,49 @@ var BridgeMocker = ({
3016
3576
  width: "14",
3017
3577
  xmlns: "http://www.w3.org/2000/svg",
3018
3578
  children: [
3019
- /* @__PURE__ */ jsx12("path", { d: "M21 4H3" }),
3020
- /* @__PURE__ */ jsx12("path", { d: "M10 8H3" }),
3021
- /* @__PURE__ */ jsx12("path", { d: "M21 12H3" }),
3022
- /* @__PURE__ */ jsx12("path", { d: "M10 16H3" }),
3023
- /* @__PURE__ */ jsx12("path", { d: "M21 20H3" }),
3024
- /* @__PURE__ */ jsx12("circle", { cx: "14", cy: "8", r: "2" }),
3025
- /* @__PURE__ */ jsx12("circle", { cx: "14", cy: "16", r: "2" })
3579
+ /* @__PURE__ */ jsx15("path", { d: "M21 4H3" }),
3580
+ /* @__PURE__ */ jsx15("path", { d: "M10 8H3" }),
3581
+ /* @__PURE__ */ jsx15("path", { d: "M21 12H3" }),
3582
+ /* @__PURE__ */ jsx15("path", { d: "M10 16H3" }),
3583
+ /* @__PURE__ */ jsx15("path", { d: "M21 20H3" }),
3584
+ /* @__PURE__ */ jsx15("circle", { cx: "14", cy: "8", r: "2" }),
3585
+ /* @__PURE__ */ jsx15("circle", { cx: "14", cy: "16", r: "2" })
3026
3586
  ]
3027
3587
  }
3028
3588
  )
3029
3589
  }
3030
- ) : /* @__PURE__ */ jsxs10(
3590
+ ) : /* @__PURE__ */ jsxs11(
3031
3591
  "div",
3032
3592
  {
3033
3593
  className: "fixed bottom-4 right-4 bg-slate-900 text-slate-300 font-mono text-xs rounded-xl shadow-2xl border border-slate-700 pointer-events-auto flex flex-col w-80 overflow-hidden animate-in slide-in-from-right duration-300",
3034
3594
  style: { zIndex: 9998 },
3035
3595
  children: [
3036
- /* @__PURE__ */ jsxs10(
3596
+ /* @__PURE__ */ jsxs11(
3037
3597
  "div",
3038
3598
  {
3039
3599
  className: "flex justify-between items-center p-3 border-b border-slate-800 cursor-pointer bg-slate-800/50 hover:bg-slate-800 transition-colors",
3040
3600
  onClick: () => setIsMinimized(true),
3041
3601
  children: [
3042
- /* @__PURE__ */ jsxs10("span", { className: "font-bold text-slate-100 flex items-center gap-2", children: [
3043
- /* @__PURE__ */ jsx12("span", { className: "text-lg", children: "\u{1F6E0}\uFE0F" }),
3602
+ /* @__PURE__ */ jsxs11("span", { className: "font-bold text-slate-100 flex items-center gap-2", children: [
3603
+ /* @__PURE__ */ jsx15("span", { className: "text-lg", children: "\u{1F6E0}\uFE0F" }),
3044
3604
  " Simulation Controls"
3045
3605
  ] }),
3046
- /* @__PURE__ */ jsx12("button", { className: "text-slate-500 hover:text-white", type: "button", children: "\u25BC" })
3606
+ /* @__PURE__ */ jsx15(
3607
+ Button,
3608
+ {
3609
+ className: "text-slate-500 hover:text-white p-0 h-auto hover:bg-transparent cursor-pointer",
3610
+ type: "button",
3611
+ variant: "ghost",
3612
+ children: "\u25BC"
3613
+ }
3614
+ )
3047
3615
  ]
3048
3616
  }
3049
3617
  ),
3050
- /* @__PURE__ */ jsxs10("div", { className: "p-4 flex flex-col gap-3", children: [
3051
- /* @__PURE__ */ jsxs10("div", { className: "flex justify-between items-center", children: [
3052
- /* @__PURE__ */ jsxs10("label", { className: "flex items-center gap-2 cursor-pointer", children: [
3053
- /* @__PURE__ */ jsx12(
3618
+ /* @__PURE__ */ jsxs11("div", { className: "p-4 flex flex-col gap-3", children: [
3619
+ /* @__PURE__ */ jsxs11("div", { className: "flex justify-between items-center", children: [
3620
+ /* @__PURE__ */ jsxs11("label", { className: "flex items-center gap-2 cursor-pointer", children: [
3621
+ /* @__PURE__ */ jsx15(
3054
3622
  "input",
3055
3623
  {
3056
3624
  checked: autoMove,
@@ -3059,20 +3627,20 @@ var BridgeMocker = ({
3059
3627
  type: "checkbox"
3060
3628
  }
3061
3629
  ),
3062
- /* @__PURE__ */ jsxs10("span", { className: "text-slate-200 font-bold", children: [
3630
+ /* @__PURE__ */ jsxs11("span", { className: "text-slate-200 font-bold", children: [
3063
3631
  "Auto-Move ",
3064
3632
  simulationPath ? "(Path)" : "(Random)"
3065
3633
  ] })
3066
3634
  ] }),
3067
- /* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-2", children: [
3068
- /* @__PURE__ */ jsx12("span", { className: "text-[10px] text-slate-500", children: "Speed:" }),
3069
- /* @__PURE__ */ jsx12(
3635
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2", children: [
3636
+ /* @__PURE__ */ jsx15("span", { className: "text-[10px] text-slate-500", children: "Speed:" }),
3637
+ /* @__PURE__ */ jsx15(
3070
3638
  "select",
3071
3639
  {
3072
3640
  className: "bg-slate-800 border border-slate-700 rounded px-1 py-0.5 text-white focus:outline-none focus:border-blue-500 text-[10px]",
3073
3641
  onChange: (e) => setSpeedMultiplier(Number(e.target.value)),
3074
3642
  value: speedMultiplier,
3075
- children: [1, 2, 5, 10, 50, 100, 250].map((s) => /* @__PURE__ */ jsxs10("option", { value: s, children: [
3643
+ children: [1, 2, 5, 10, 50, 100, 250].map((s) => /* @__PURE__ */ jsxs11("option", { value: s, children: [
3076
3644
  s,
3077
3645
  "x"
3078
3646
  ] }, s))
@@ -3080,10 +3648,10 @@ var BridgeMocker = ({
3080
3648
  )
3081
3649
  ] })
3082
3650
  ] }),
3083
- /* @__PURE__ */ jsxs10("div", { className: "grid grid-cols-2 gap-2", children: [
3084
- /* @__PURE__ */ jsxs10("div", { className: "flex flex-col gap-1", children: [
3085
- /* @__PURE__ */ jsx12("span", { className: "text-[10px] text-slate-500 text-left", children: "Lng" }),
3086
- /* @__PURE__ */ jsx12(
3651
+ /* @__PURE__ */ jsxs11("div", { className: "grid grid-cols-2 gap-2", children: [
3652
+ /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-1", children: [
3653
+ /* @__PURE__ */ jsx15("span", { className: "text-[10px] text-slate-500 text-left", children: "Lng" }),
3654
+ /* @__PURE__ */ jsx15(
3087
3655
  "input",
3088
3656
  {
3089
3657
  className: "bg-slate-800 border border-slate-700 rounded px-2 py-1 text-white focus:outline-none focus:border-blue-500",
@@ -3098,9 +3666,9 @@ var BridgeMocker = ({
3098
3666
  }
3099
3667
  )
3100
3668
  ] }),
3101
- /* @__PURE__ */ jsxs10("div", { className: "flex flex-col gap-1", children: [
3102
- /* @__PURE__ */ jsx12("span", { className: "text-[10px] text-slate-500 text-left", children: "Lat" }),
3103
- /* @__PURE__ */ jsx12(
3669
+ /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-1", children: [
3670
+ /* @__PURE__ */ jsx15("span", { className: "text-[10px] text-slate-500 text-left", children: "Lat" }),
3671
+ /* @__PURE__ */ jsx15(
3104
3672
  "input",
3105
3673
  {
3106
3674
  className: "bg-slate-800 border border-slate-700 rounded px-2 py-1 text-white focus:outline-none focus:border-blue-500",
@@ -3115,9 +3683,9 @@ var BridgeMocker = ({
3115
3683
  }
3116
3684
  )
3117
3685
  ] }),
3118
- /* @__PURE__ */ jsxs10("div", { className: "flex flex-col gap-1 col-span-2", children: [
3119
- /* @__PURE__ */ jsx12("span", { className: "text-[10px] text-slate-500", children: "Heading (Degrees)" }),
3120
- /* @__PURE__ */ jsx12(
3686
+ /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-1 col-span-2", children: [
3687
+ /* @__PURE__ */ jsx15("span", { className: "text-[10px] text-slate-500", children: "Heading (Degrees)" }),
3688
+ /* @__PURE__ */ jsx15(
3121
3689
  "input",
3122
3690
  {
3123
3691
  className: "w-full accent-blue-500",
@@ -3131,7 +3699,7 @@ var BridgeMocker = ({
3131
3699
  value: heading
3132
3700
  }
3133
3701
  ),
3134
- /* @__PURE__ */ jsxs10("div", { className: "text-right text-slate-400", children: [
3702
+ /* @__PURE__ */ jsxs11("div", { className: "text-right text-slate-400", children: [
3135
3703
  heading,
3136
3704
  "\xB0"
3137
3705
  ] })
@@ -3145,16 +3713,16 @@ var BridgeMocker = ({
3145
3713
  };
3146
3714
 
3147
3715
  // src/components/DebugConsole.tsx
3148
- import { useCallback as useCallback7, useEffect as useEffect7, useRef as useRef8, useState as useState8 } from "react";
3149
- import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
3716
+ import { useCallback as useCallback7, useEffect as useEffect8, useRef as useRef8, useState as useState9 } from "react";
3717
+ import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
3150
3718
  var DebugConsole = ({
3151
3719
  isOpen: initialOpen = false,
3152
3720
  onClose
3153
3721
  }) => {
3154
- const [showConsole, setShowConsole] = useState8(initialOpen);
3155
- const [logs, setLogs] = useState8([]);
3722
+ const [showConsole, setShowConsole] = useState9(initialOpen);
3723
+ const [logs, setLogs] = useState9([]);
3156
3724
  const scrollRef = useRef8(null);
3157
- useEffect7(() => {
3725
+ useEffect8(() => {
3158
3726
  setShowConsole(initialOpen);
3159
3727
  }, [initialOpen]);
3160
3728
  const clearLogs = () => setLogs([]);
@@ -3168,7 +3736,7 @@ var DebugConsole = ({
3168
3736
  };
3169
3737
  setLogs((prev) => [entry, ...prev].slice(0, 100));
3170
3738
  }, []);
3171
- useEffect7(() => {
3739
+ useEffect8(() => {
3172
3740
  if (typeof window === "undefined") return;
3173
3741
  const bridge = sdk.bridge;
3174
3742
  const originalSend = bridge.send.bind(bridge);
@@ -3190,14 +3758,15 @@ var DebugConsole = ({
3190
3758
  };
3191
3759
  }, [addLog]);
3192
3760
  if (!showConsole) {
3193
- return /* @__PURE__ */ jsx13(
3194
- "button",
3761
+ return /* @__PURE__ */ jsx16(
3762
+ Button,
3195
3763
  {
3196
- className: "fixed bottom-4 left-4 w-8 h-8 rounded-full bg-slate-900/60 backdrop-blur-sm border border-slate-700/50 flex items-center justify-center text-slate-400 hover:text-emerald-400 transition-all z-[9998] shadow-lg group",
3764
+ className: "fixed bottom-4 left-4 w-8 h-8 rounded-full bg-slate-900/60 backdrop-blur-sm border border-slate-700/50 flex items-center justify-center text-slate-400 hover:text-emerald-400 hover:bg-slate-900/80 transition-all z-[9998] shadow-lg group p-0!",
3197
3765
  onClick: () => setShowConsole(true),
3198
3766
  title: "Open Debug Console",
3199
3767
  type: "button",
3200
- children: /* @__PURE__ */ jsxs11(
3768
+ variant: "ghost",
3769
+ children: /* @__PURE__ */ jsxs12(
3201
3770
  "svg",
3202
3771
  {
3203
3772
  className: "group-hover:scale-110 transition-transform",
@@ -3211,68 +3780,70 @@ var DebugConsole = ({
3211
3780
  width: "14",
3212
3781
  xmlns: "http://www.w3.org/2000/svg",
3213
3782
  children: [
3214
- /* @__PURE__ */ jsx13("path", { d: "m8 2 1.88 1.88" }),
3215
- /* @__PURE__ */ jsx13("path", { d: "M14.12 3.88 16 2" }),
3216
- /* @__PURE__ */ jsx13("path", { d: "M9 7.13v-1a3.003 3.003 0 1 1 6 0v1" }),
3217
- /* @__PURE__ */ jsx13("path", { d: "M12 20c-3.3 0-6-2.7-6-6v-3a4 4 0 0 1 4-4h4a4 4 0 0 1 4 4v3c0 3.3-2.7 6-6 6" }),
3218
- /* @__PURE__ */ jsx13("path", { d: "M12 20v-9" }),
3219
- /* @__PURE__ */ jsx13("path", { d: "M6.53 9C4.6 8.8 3 7.1 3 5" }),
3220
- /* @__PURE__ */ jsx13("path", { d: "M6 13H2" }),
3221
- /* @__PURE__ */ jsx13("path", { d: "M3 21c0-2.1 1.7-3.9 3.8-4" }),
3222
- /* @__PURE__ */ jsx13("path", { d: "M20.97 5c0 2.1-1.6 3.8-3.5 4" }),
3223
- /* @__PURE__ */ jsx13("path", { d: "M22 13h-4" }),
3224
- /* @__PURE__ */ jsx13("path", { d: "M17.2 17c2.1.1 3.8 1.9 3.8 4" })
3783
+ /* @__PURE__ */ jsx16("path", { d: "m8 2 1.88 1.88" }),
3784
+ /* @__PURE__ */ jsx16("path", { d: "M14.12 3.88 16 2" }),
3785
+ /* @__PURE__ */ jsx16("path", { d: "M9 7.13v-1a3.003 3.003 0 1 1 6 0v1" }),
3786
+ /* @__PURE__ */ jsx16("path", { d: "M12 20c-3.3 0-6-2.7-6-6v-3a4 4 0 0 1 4-4h4a4 4 0 0 1 4 4v3c0 3.3-2.7 6-6 6" }),
3787
+ /* @__PURE__ */ jsx16("path", { d: "M12 20v-9" }),
3788
+ /* @__PURE__ */ jsx16("path", { d: "M6.53 9C4.6 8.8 3 7.1 3 5" }),
3789
+ /* @__PURE__ */ jsx16("path", { d: "M6 13H2" }),
3790
+ /* @__PURE__ */ jsx16("path", { d: "M3 21c0-2.1 1.7-3.9 3.8-4" }),
3791
+ /* @__PURE__ */ jsx16("path", { d: "M20.97 5c0 2.1-1.6 3.8-3.5 4" }),
3792
+ /* @__PURE__ */ jsx16("path", { d: "M22 13h-4" }),
3793
+ /* @__PURE__ */ jsx16("path", { d: "M17.2 17c2.1.1 3.8 1.9 3.8 4" })
3225
3794
  ]
3226
3795
  }
3227
3796
  )
3228
3797
  }
3229
3798
  );
3230
3799
  }
3231
- return /* @__PURE__ */ jsxs11("div", { className: "fixed inset-x-0 bottom-0 w-full bg-[#0a080f] border-t border-slate-800 z-[9998] p-4 shadow-2xl flex flex-col animate-in slide-in-from-bottom duration-300", children: [
3232
- /* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between mb-2", children: [
3233
- /* @__PURE__ */ jsxs11("span", { className: "text-[10px] font-bold uppercase tracking-widest text-slate-400 flex items-center gap-2", children: [
3234
- /* @__PURE__ */ jsx13("span", { className: "w-2 h-2 rounded-full bg-emerald-500 animate-pulse" }),
3800
+ return /* @__PURE__ */ jsxs12("div", { className: "fixed inset-x-0 bottom-0 w-full bg-[#0a080f] border-t border-slate-800 z-[9998] p-4 shadow-2xl flex flex-col animate-in slide-in-from-bottom duration-300", children: [
3801
+ /* @__PURE__ */ jsxs12("div", { className: "flex items-center justify-between mb-2", children: [
3802
+ /* @__PURE__ */ jsxs12("span", { className: "text-[10px] font-bold uppercase tracking-widest text-slate-400 flex items-center gap-2", children: [
3803
+ /* @__PURE__ */ jsx16("span", { className: "w-2 h-2 rounded-full bg-emerald-500 animate-pulse" }),
3235
3804
  "UP SDK Debug Console"
3236
3805
  ] }),
3237
- /* @__PURE__ */ jsxs11("div", { className: "flex gap-4", children: [
3238
- /* @__PURE__ */ jsx13(
3239
- "button",
3806
+ /* @__PURE__ */ jsxs12("div", { className: "flex gap-4", children: [
3807
+ /* @__PURE__ */ jsx16(
3808
+ Button,
3240
3809
  {
3241
- className: "text-[10px] text-slate-500 font-bold uppercase hover:text-slate-300 transition-colors",
3810
+ className: "text-[10px] text-slate-500 font-bold uppercase hover:text-slate-300 hover:bg-transparent transition-colors p-0 h-auto cursor-pointer",
3242
3811
  onClick: clearLogs,
3243
3812
  type: "button",
3813
+ variant: "ghost",
3244
3814
  children: "Clear"
3245
3815
  }
3246
3816
  ),
3247
- /* @__PURE__ */ jsx13(
3248
- "button",
3817
+ /* @__PURE__ */ jsx16(
3818
+ Button,
3249
3819
  {
3250
- className: "text-[10px] text-pink-500 font-bold uppercase hover:underline transition-colors",
3820
+ className: "text-[10px] text-pink-500 font-bold uppercase hover:text-pink-400 hover:bg-transparent transition-colors p-0 h-auto cursor-pointer",
3251
3821
  onClick: () => {
3252
3822
  setShowConsole(false);
3253
3823
  if (onClose) onClose();
3254
3824
  },
3255
3825
  type: "button",
3826
+ variant: "ghost",
3256
3827
  children: "Close"
3257
3828
  }
3258
3829
  )
3259
3830
  ] })
3260
3831
  ] }),
3261
- /* @__PURE__ */ jsx13(
3832
+ /* @__PURE__ */ jsx16(
3262
3833
  "div",
3263
3834
  {
3264
3835
  className: "bg-black/80 rounded-xl p-3 font-mono text-[10px] text-emerald-400 min-h-[120px] max-h-[240px] overflow-y-auto border border-slate-900 custom-scrollbar",
3265
3836
  ref: scrollRef,
3266
- children: logs.length === 0 ? /* @__PURE__ */ jsx13("div", { className: "text-slate-600 italic text-center py-8", children: "No logs yet. Interacting with the SDK will show events here." }) : logs.map((log) => /* @__PURE__ */ jsxs11(
3837
+ children: logs.length === 0 ? /* @__PURE__ */ jsx16("div", { className: "text-slate-600 italic text-center py-8", children: "No logs yet. Interacting with the SDK will show events here." }) : logs.map((log) => /* @__PURE__ */ jsxs12(
3267
3838
  "div",
3268
3839
  {
3269
3840
  className: "mb-3 pb-3 border-b border-slate-900/50 last:border-0 last:mb-0 last:pb-0",
3270
3841
  children: [
3271
- /* @__PURE__ */ jsxs11("div", { className: "flex gap-2 text-slate-500 mb-1 items-center", children: [
3272
- /* @__PURE__ */ jsx13("span", { className: "text-[8px]", children: log.time }),
3273
- /* @__PURE__ */ jsx13("span", { className: "font-bold text-white uppercase text-[8px] bg-slate-800 px-1.5 py-0.5 rounded leading-none", children: log.label })
3842
+ /* @__PURE__ */ jsxs12("div", { className: "flex gap-2 text-slate-500 mb-1 items-center", children: [
3843
+ /* @__PURE__ */ jsx16("span", { className: "text-[8px]", children: log.time }),
3844
+ /* @__PURE__ */ jsx16("span", { className: "font-bold text-white uppercase text-[8px] bg-slate-800 px-1.5 py-0.5 rounded leading-none", children: log.label })
3274
3845
  ] }),
3275
- /* @__PURE__ */ jsx13("pre", { className: "whitespace-pre-wrap break-all opacity-90", children: log.content })
3846
+ /* @__PURE__ */ jsx16("pre", { className: "whitespace-pre-wrap break-all opacity-90", children: log.content })
3276
3847
  ]
3277
3848
  },
3278
3849
  log.id
@@ -3284,7 +3855,7 @@ var DebugConsole = ({
3284
3855
 
3285
3856
  // src/components/SDKProvider.tsx
3286
3857
  import { createContext as createContext2, useContext as useContext5, useMemo as useMemo6 } from "react";
3287
- import { Fragment as Fragment5, jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
3858
+ import { Fragment as Fragment5, jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
3288
3859
  var SDKContext = createContext2({ isMocked: false });
3289
3860
  var useIsMocked = () => useContext5(SDKContext).isMocked;
3290
3861
  var SDKProvider = ({
@@ -3294,14 +3865,14 @@ var SDKProvider = ({
3294
3865
  }) => {
3295
3866
  const isMocked = typeof window !== "undefined" && !(window.__UP_REACT_NATIVE_APP__ === true || !!window.ReactNativeWebView);
3296
3867
  const value = useMemo6(() => ({ isMocked }), [isMocked]);
3297
- const content = /* @__PURE__ */ jsxs12(Fragment5, { children: [
3868
+ const content = /* @__PURE__ */ jsxs13(Fragment5, { children: [
3298
3869
  children,
3299
- debug && /* @__PURE__ */ jsx14(DebugConsole, {})
3870
+ debug && /* @__PURE__ */ jsx17(DebugConsole, {})
3300
3871
  ] });
3301
3872
  if (isMocked) {
3302
- return /* @__PURE__ */ jsx14(SDKContext.Provider, { value, children: /* @__PURE__ */ jsx14(BridgeMocker, { ...mockerProps, children: content }) });
3873
+ return /* @__PURE__ */ jsx17(SDKContext.Provider, { value, children: /* @__PURE__ */ jsx17(BridgeMocker, { ...mockerProps, children: content }) });
3303
3874
  }
3304
- return /* @__PURE__ */ jsx14(SDKContext.Provider, { value, children: content });
3875
+ return /* @__PURE__ */ jsx17(SDKContext.Provider, { value, children: content });
3305
3876
  };
3306
3877
 
3307
3878
  // src/index.ts