add Google Maps route import and plugin corridor search

This commit is contained in:
Maurice
2026-09-12 12:24:33 +02:00
parent af45b0ca74
commit ff5fa55fad
59 changed files with 849 additions and 36 deletions
+10 -5
View File
@@ -1,4 +1,4 @@
import React, { useState, useEffect, useRef } from 'react'
import React, { useState, useEffect, useLayoutEffect, useRef } from 'react'
import { createPortal } from 'react-dom'
import { LucideIcon } from 'lucide-react'
@@ -14,15 +14,17 @@ interface MenuState {
x: number
y: number
items: MenuItem[]
alignEnd?: boolean
}
export function useContextMenu() {
const [menu, setMenu] = useState<MenuState | null>(null)
const open = (e: React.MouseEvent, items: MenuItem[]) => {
const open = (e: React.MouseEvent, items: MenuItem[], alignEnd = false) => {
e.preventDefault()
e.stopPropagation()
setMenu({ x: e.clientX, y: e.clientY, items })
const anchor = e.currentTarget.getBoundingClientRect()
setMenu({ x: alignEnd ? anchor.right : e.clientX, y: alignEnd ? anchor.bottom + 6 : e.clientY, items, alignEnd })
}
const close = () => setMenu(null)
@@ -49,11 +51,12 @@ export function ContextMenu({ menu, onClose }: ContextMenuProps) {
}
}, [menu, onClose])
useEffect(() => {
useLayoutEffect(() => {
if (!menu || !ref.current) return
const el = ref.current
const rect = el.getBoundingClientRect()
let { x, y } = menu
if (menu.alignEnd) x = Math.max(8, x - rect.width)
if (x + rect.width > window.innerWidth - 8) x = window.innerWidth - rect.width - 8
if (y + rect.height > window.innerHeight - 8) y = window.innerHeight - rect.height - 8
if (x !== menu.x || y !== menu.y) {
@@ -72,8 +75,10 @@ export function ContextMenu({ menu, onClose }: ContextMenuProps) {
boxShadow: '0 8px 30px rgba(0,0,0,0.15)',
backdropFilter: 'blur(20px)', WebkitBackdropFilter: 'blur(20px)',
minWidth: 160,
width: menu.alignEnd ? 'max-content' : undefined,
whiteSpace: menu.alignEnd ? 'nowrap' : undefined,
fontFamily: "var(--font-system)",
transformOrigin: 'top left',
transformOrigin: menu.alignEnd ? 'top right' : 'top left',
}}>
{menu.items.filter(Boolean).map((item, i) => {
if (item.divider) return <div key={i} style={{ height: 1, background: 'var(--border-faint)', margin: '3px 6px' }} />