mirror of
https://github.com/gpxstudio/gpx.studio.git
synced 2025-08-31 15:43:25 +00:00
tab context menu and shortcuts
This commit is contained in:
8
website/package-lock.json
generated
8
website/package-lock.json
generated
@@ -9,7 +9,7 @@
|
||||
"version": "0.0.1",
|
||||
"dependencies": {
|
||||
"@mapbox/mapbox-gl-geocoder": "^5.0.2",
|
||||
"bits-ui": "^0.21.4",
|
||||
"bits-ui": "^0.21.5",
|
||||
"chart.js": "^4.4.2",
|
||||
"clsx": "^2.1.0",
|
||||
"gpx": "file:../gpx",
|
||||
@@ -1891,9 +1891,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/bits-ui": {
|
||||
"version": "0.21.4",
|
||||
"resolved": "https://registry.npmjs.org/bits-ui/-/bits-ui-0.21.4.tgz",
|
||||
"integrity": "sha512-IL+7s19GW561jwkeYk23dwkTfQ9606I062qqv2AtjCdhhIdoOEJNVBX0kjP5xefSaS6ojL0HGG54att0aRTcAQ==",
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/bits-ui/-/bits-ui-0.21.5.tgz",
|
||||
"integrity": "sha512-EDGHWkxnlcV2fbXn2tMps3SfpS7k6bfX3BrQ4s/h79jT6yprBS8DdDficlDK0SDHmPYHBZ0hSy4OgQUDodS/6w==",
|
||||
"dependencies": {
|
||||
"@internationalized/date": "^3.5.1",
|
||||
"@melt-ui/svelte": "0.76.2",
|
||||
|
@@ -42,7 +42,7 @@
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@mapbox/mapbox-gl-geocoder": "^5.0.2",
|
||||
"bits-ui": "^0.21.4",
|
||||
"bits-ui": "^0.21.5",
|
||||
"chart.js": "^4.4.2",
|
||||
"clsx": "^2.1.0",
|
||||
"gpx": "file:../gpx",
|
||||
|
@@ -1,7 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { fileOrder, files, getFileIndex, selectedFiles, selectFiles } from '$lib/stores';
|
||||
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
import { ScrollArea } from '$lib/components/ui/scroll-area/index';
|
||||
import Sortable from 'sortablejs/Sortable';
|
||||
|
||||
@@ -9,6 +8,7 @@
|
||||
|
||||
import { afterUpdate, onMount } from 'svelte';
|
||||
import { get } from 'svelte/store';
|
||||
import FileListItem from './FileListItem.svelte';
|
||||
|
||||
let container: HTMLDivElement;
|
||||
let buttons: HTMLDivElement[] = [];
|
||||
@@ -133,9 +133,7 @@
|
||||
data-id={index}
|
||||
class="pointer-events-auto first:ml-1 last:mr-1 mb-1 bg-transparent"
|
||||
>
|
||||
<Button variant="outline" class="h-9 px-1.5 py-1 border-none shadow-md">
|
||||
{get(file).metadata.name}
|
||||
</Button>
|
||||
<FileListItem {file} />
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
@@ -148,7 +146,7 @@
|
||||
@apply hover:bg-background;
|
||||
}
|
||||
|
||||
div :global(.sortable-selected > button) {
|
||||
div :global(.sortable-selected button) {
|
||||
@apply bg-background;
|
||||
}
|
||||
</style>
|
||||
|
50
website/src/lib/components/FileListItem.svelte
Normal file
50
website/src/lib/components/FileListItem.svelte
Normal file
@@ -0,0 +1,50 @@
|
||||
<script lang="ts">
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
import * as ContextMenu from '$lib/components/ui/context-menu';
|
||||
import Shortcut from './Shortcut.svelte';
|
||||
import { Copy, Trash2 } from 'lucide-svelte';
|
||||
|
||||
import type { GPXFile } from 'gpx';
|
||||
|
||||
import { get, type Writable } from 'svelte/store';
|
||||
import {
|
||||
duplicateSelectedFiles,
|
||||
removeSelectedFiles,
|
||||
selectedFiles,
|
||||
selectFiles
|
||||
} from '$lib/stores';
|
||||
|
||||
import { _ } from 'svelte-i18n';
|
||||
|
||||
export let file: Writable<GPXFile>;
|
||||
</script>
|
||||
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<div
|
||||
on:contextmenu={() => {
|
||||
if (!get(selectedFiles).has(get(file))) {
|
||||
get(selectFiles).select(get(file));
|
||||
}
|
||||
}}
|
||||
>
|
||||
<ContextMenu.Root>
|
||||
<ContextMenu.Trigger>
|
||||
<Button variant="outline" class="h-9 px-1.5 py-1 border-none shadow-md">
|
||||
{$file.metadata.name}
|
||||
</Button>
|
||||
</ContextMenu.Trigger>
|
||||
<ContextMenu.Content>
|
||||
<ContextMenu.Item on:click={duplicateSelectedFiles}>
|
||||
<Copy size="16" class="mr-1" />
|
||||
{$_('menu.duplicate')}
|
||||
<Shortcut key="D" ctrl={true} /></ContextMenu.Item
|
||||
>
|
||||
<ContextMenu.Separator />
|
||||
<ContextMenu.Item on:click={removeSelectedFiles}
|
||||
><Trash2 size="16" class="mr-1" />
|
||||
{$_('menu.delete')}
|
||||
<Shortcut key="⌫" ctrl={true} /></ContextMenu.Item
|
||||
>
|
||||
</ContextMenu.Content>
|
||||
</ContextMenu.Root>
|
||||
</div>
|
@@ -2,6 +2,7 @@
|
||||
import * as Menubar from '$lib/components/ui/menubar/index.js';
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
import Logo from './Logo.svelte';
|
||||
import Shortcut from './Shortcut.svelte';
|
||||
import { Plus, Copy, Download, Undo2, Redo2, Trash2, Upload, Cloud, Heart } from 'lucide-svelte';
|
||||
|
||||
import {
|
||||
@@ -55,13 +56,13 @@
|
||||
<Menubar.Item on:click={createFile}>
|
||||
<Plus size="16" class="mr-1" />
|
||||
{$_('menu.new')}
|
||||
<Menubar.Shortcut>⌘N</Menubar.Shortcut>
|
||||
<Shortcut key="N" ctrl={true} />
|
||||
</Menubar.Item>
|
||||
<Menubar.Separator />
|
||||
<Menubar.Item on:click={triggerFileInput}>
|
||||
<Upload size="16" class="mr-1" />
|
||||
{$_('menu.load_desktop')}
|
||||
<Menubar.Shortcut>⌘O</Menubar.Shortcut>
|
||||
<Shortcut key="O" ctrl={true} />
|
||||
</Menubar.Item>
|
||||
<Menubar.Item>
|
||||
<Cloud size="16" class="mr-1" />
|
||||
@@ -71,18 +72,18 @@
|
||||
<Menubar.Item on:click={duplicateSelectedFiles} disabled={$selectedFiles.size == 0}>
|
||||
<Copy size="16" class="mr-1" />
|
||||
{$_('menu.duplicate')}
|
||||
<Menubar.Shortcut>⌘D</Menubar.Shortcut>
|
||||
<Shortcut key="D" ctrl={true} />
|
||||
</Menubar.Item>
|
||||
<Menubar.Separator />
|
||||
<Menubar.Item on:click={exportSelectedFiles} disabled={$selectedFiles.size == 0}>
|
||||
<Download size="16" class="mr-1" />
|
||||
{$_('menu.export')}
|
||||
<Menubar.Shortcut>⌘S</Menubar.Shortcut>
|
||||
<Shortcut key="S" ctrl={true} />
|
||||
</Menubar.Item>
|
||||
<Menubar.Item on:click={exportAllFiles} disabled={$files.length == 0}>
|
||||
<Download size="16" class="mr-1" />
|
||||
{$_('menu.export_all')}
|
||||
<Menubar.Shortcut>⇧⌘S</Menubar.Shortcut>
|
||||
<Shortcut key="S" ctrl={true} shift={true} />
|
||||
</Menubar.Item>
|
||||
</Menubar.Content>
|
||||
</Menubar.Menu>
|
||||
@@ -92,27 +93,34 @@
|
||||
<Menubar.Item>
|
||||
<Undo2 size="16" class="mr-1" />
|
||||
{$_('menu.undo')}
|
||||
<Menubar.Shortcut>⌘Z</Menubar.Shortcut>
|
||||
<Shortcut key="Z" ctrl={true} />
|
||||
</Menubar.Item>
|
||||
<Menubar.Item>
|
||||
<Redo2 size="16" class="mr-1" />
|
||||
{$_('menu.redo')}
|
||||
<Menubar.Shortcut>⇧⌘Z</Menubar.Shortcut>
|
||||
<Shortcut key="Z" ctrl={true} shift={true} />
|
||||
</Menubar.Item>
|
||||
<Menubar.Separator />
|
||||
<Menubar.Item on:click={() => $selectFiles.selectAllFiles()}>
|
||||
<span class="w-4 mr-1"></span>
|
||||
{$_('menu.select_all')}
|
||||
<Shortcut key="A" ctrl={true} />
|
||||
</Menubar.Item>
|
||||
<Menubar.Separator />
|
||||
<Menubar.Item on:click={removeSelectedFiles} disabled={$selectedFiles.size == 0}>
|
||||
<Trash2 size="16" class="mr-1" />
|
||||
{$_('menu.delete')}
|
||||
<Menubar.Shortcut>⌘⌫</Menubar.Shortcut></Menubar.Item
|
||||
>
|
||||
<Shortcut key="⌫" ctrl={true} />
|
||||
</Menubar.Item>
|
||||
<Menubar.Item
|
||||
class="text-destructive data-[highlighted]:text-destructive"
|
||||
on:click={removeAllFiles}
|
||||
disabled={$files.length == 0}
|
||||
>
|
||||
<Trash2 size="16" class="mr-1" />
|
||||
{$_('menu.delete_all')}<Menubar.Shortcut>⇧⌘⌫</Menubar.Shortcut></Menubar.Item
|
||||
>
|
||||
{$_('menu.delete_all')}
|
||||
<Shortcut key="⌫" ctrl={true} shift={true} />
|
||||
</Menubar.Item>
|
||||
</Menubar.Content>
|
||||
</Menubar.Menu>
|
||||
<Menubar.Menu>
|
||||
|
21
website/src/lib/components/Shortcut.svelte
Normal file
21
website/src/lib/components/Shortcut.svelte
Normal file
@@ -0,0 +1,21 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { _ } from 'svelte-i18n';
|
||||
|
||||
export let key: string;
|
||||
export let shift: boolean = false;
|
||||
export let ctrl: boolean = false;
|
||||
export let click: boolean = false;
|
||||
|
||||
let isMac = false;
|
||||
|
||||
onMount(() => {
|
||||
isMac = navigator.userAgent.toUpperCase().indexOf('MAC') >= 0;
|
||||
});
|
||||
</script>
|
||||
|
||||
<span class="ml-auto pl-2 text-xs tracking-widest text-muted-foreground"
|
||||
>{shift ? '⇧' : ''}{ctrl ? (isMac ? '⌘' : $_('menu.ctrl') + '+') : ''}{key}{click
|
||||
? $_('menu.click')
|
||||
: ''}</span
|
||||
>
|
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import * as Card from '$lib/components/ui/card';
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
import Shortcut from '$lib/components/Shortcut.svelte';
|
||||
import { Trash2 } from 'lucide-svelte';
|
||||
|
||||
import { _ } from 'svelte-i18n';
|
||||
@@ -15,8 +16,11 @@
|
||||
class="w-full px-2 py-1 h-6 justify-start"
|
||||
variant="ghost"
|
||||
on:click={() => element.dispatchEvent(new CustomEvent('delete'))}
|
||||
><Trash2 size="16" class="mr-1" /> {$_('menu.delete')}</Button
|
||||
>
|
||||
<Trash2 size="16" class="mr-1" />
|
||||
{$_('menu.delete')}
|
||||
<Shortcut key="" shift={true} click={true} />
|
||||
</Button>
|
||||
</Card.Content>
|
||||
</Card.Root>
|
||||
</div>
|
||||
|
@@ -130,13 +130,19 @@ export class RoutingControls {
|
||||
});
|
||||
marker.on('dragend', this.moveAnchor.bind(this));
|
||||
marker.getElement().addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
|
||||
if (Date.now() - lastDragEvent < 100) { // Prevent click event during drag
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.shiftKey) {
|
||||
this.deleteAnchor(anchor);
|
||||
return;
|
||||
}
|
||||
|
||||
marker.setPopup(this.popup);
|
||||
marker.togglePopup();
|
||||
e.stopPropagation();
|
||||
|
||||
let deleteThisAnchor = this.getDeleteAnchor(anchor);
|
||||
this.popupElement.addEventListener('delete', deleteThisAnchor); // Register the delete event for this anchor
|
||||
|
@@ -0,0 +1,35 @@
|
||||
<script lang="ts">
|
||||
import { ContextMenu as ContextMenuPrimitive } from "bits-ui";
|
||||
import Check from "lucide-svelte/icons/check";
|
||||
import { cn } from "$lib/utils.js";
|
||||
|
||||
type $$Props = ContextMenuPrimitive.CheckboxItemProps;
|
||||
type $$Events = ContextMenuPrimitive.CheckboxItemEvents;
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export let checked: $$Props["checked"] = undefined;
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<ContextMenuPrimitive.CheckboxItem
|
||||
bind:checked
|
||||
class={cn(
|
||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[disabled]:pointer-events-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:opacity-50",
|
||||
className
|
||||
)}
|
||||
{...$$restProps}
|
||||
on:click
|
||||
on:keydown
|
||||
on:focusin
|
||||
on:focusout
|
||||
on:pointerdown
|
||||
on:pointerleave
|
||||
on:pointermove
|
||||
>
|
||||
<span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
||||
<ContextMenuPrimitive.CheckboxIndicator>
|
||||
<Check class="h-4 w-4" />
|
||||
</ContextMenuPrimitive.CheckboxIndicator>
|
||||
</span>
|
||||
<slot />
|
||||
</ContextMenuPrimitive.CheckboxItem>
|
@@ -0,0 +1,24 @@
|
||||
<script lang="ts">
|
||||
import { ContextMenu as ContextMenuPrimitive } from "bits-ui";
|
||||
import { cn, flyAndScale } from "$lib/utils.js";
|
||||
|
||||
type $$Props = ContextMenuPrimitive.ContentProps;
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export let transition: $$Props["transition"] = flyAndScale;
|
||||
export let transitionConfig: $$Props["transitionConfig"] = undefined;
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<ContextMenuPrimitive.Content
|
||||
{transition}
|
||||
{transitionConfig}
|
||||
class={cn(
|
||||
"z-50 min-w-[8rem] rounded-md border bg-popover p-1 text-popover-foreground shadow-md focus:outline-none",
|
||||
className
|
||||
)}
|
||||
{...$$restProps}
|
||||
on:keydown
|
||||
>
|
||||
<slot />
|
||||
</ContextMenuPrimitive.Content>
|
@@ -0,0 +1,31 @@
|
||||
<script lang="ts">
|
||||
import { ContextMenu as ContextMenuPrimitive } from "bits-ui";
|
||||
import { cn } from "$lib/utils.js";
|
||||
|
||||
type $$Props = ContextMenuPrimitive.ItemProps & {
|
||||
inset?: boolean;
|
||||
};
|
||||
type $$Events = ContextMenuPrimitive.ItemEvents;
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export let inset: $$Props["inset"] = undefined;
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<ContextMenuPrimitive.Item
|
||||
class={cn(
|
||||
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled]:pointer-events-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:opacity-50",
|
||||
inset && "pl-8",
|
||||
className
|
||||
)}
|
||||
{...$$restProps}
|
||||
on:click
|
||||
on:keydown
|
||||
on:focusin
|
||||
on:focusout
|
||||
on:pointerdown
|
||||
on:pointerleave
|
||||
on:pointermove
|
||||
>
|
||||
<slot />
|
||||
</ContextMenuPrimitive.Item>
|
@@ -0,0 +1,19 @@
|
||||
<script lang="ts">
|
||||
import { ContextMenu as ContextMenuPrimitive } from "bits-ui";
|
||||
import { cn } from "$lib/utils.js";
|
||||
|
||||
type $$Props = ContextMenuPrimitive.LabelProps & {
|
||||
inset?: boolean;
|
||||
};
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export let inset: $$Props["inset"] = undefined;
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<ContextMenuPrimitive.Label
|
||||
class={cn("px-2 py-1.5 text-sm font-semibold text-foreground", inset && "pl-8", className)}
|
||||
{...$$restProps}
|
||||
>
|
||||
<slot />
|
||||
</ContextMenuPrimitive.Label>
|
@@ -0,0 +1,11 @@
|
||||
<script lang="ts">
|
||||
import { ContextMenu as ContextMenuPrimitive } from "bits-ui";
|
||||
|
||||
type $$Props = ContextMenuPrimitive.RadioGroupProps;
|
||||
|
||||
export let value: $$Props["value"] = undefined;
|
||||
</script>
|
||||
|
||||
<ContextMenuPrimitive.RadioGroup {...$$restProps} bind:value>
|
||||
<slot />
|
||||
</ContextMenuPrimitive.RadioGroup>
|
@@ -0,0 +1,35 @@
|
||||
<script lang="ts">
|
||||
import { ContextMenu as ContextMenuPrimitive } from "bits-ui";
|
||||
import Circle from "lucide-svelte/icons/circle";
|
||||
import { cn } from "$lib/utils.js";
|
||||
|
||||
type $$Props = ContextMenuPrimitive.RadioItemProps;
|
||||
type $$Events = ContextMenuPrimitive.RadioItemEvents;
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export let value: ContextMenuPrimitive.RadioItemProps["value"];
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<ContextMenuPrimitive.RadioItem
|
||||
class={cn(
|
||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[disabled]:pointer-events-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:opacity-50",
|
||||
className
|
||||
)}
|
||||
{value}
|
||||
{...$$restProps}
|
||||
on:click
|
||||
on:keydown
|
||||
on:focusin
|
||||
on:focusout
|
||||
on:pointerdown
|
||||
on:pointerleave
|
||||
on:pointermove
|
||||
>
|
||||
<span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
||||
<ContextMenuPrimitive.RadioIndicator>
|
||||
<Circle class="h-2 w-2 fill-current" />
|
||||
</ContextMenuPrimitive.RadioIndicator>
|
||||
</span>
|
||||
<slot />
|
||||
</ContextMenuPrimitive.RadioItem>
|
@@ -0,0 +1,14 @@
|
||||
<script lang="ts">
|
||||
import { ContextMenu as ContextMenuPrimitive } from "bits-ui";
|
||||
import { cn } from "$lib/utils.js";
|
||||
|
||||
type $$Props = ContextMenuPrimitive.SeparatorProps;
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<ContextMenuPrimitive.Separator
|
||||
class={cn("-mx-1 my-1 h-px bg-border", className)}
|
||||
{...$$restProps}
|
||||
/>
|
@@ -0,0 +1,16 @@
|
||||
<script lang="ts">
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
import { cn } from "$lib/utils.js";
|
||||
|
||||
type $$Props = HTMLAttributes<HTMLSpanElement>;
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<span
|
||||
class={cn("ml-auto text-xs tracking-widest text-muted-foreground", className)}
|
||||
{...$$restProps}
|
||||
>
|
||||
<slot />
|
||||
</span>
|
@@ -0,0 +1,29 @@
|
||||
<script lang="ts">
|
||||
import { ContextMenu as ContextMenuPrimitive } from "bits-ui";
|
||||
import { cn, flyAndScale } from "$lib/utils.js";
|
||||
|
||||
type $$Props = ContextMenuPrimitive.SubContentProps;
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export let transition: $$Props["transition"] = flyAndScale;
|
||||
export let transitionConfig: $$Props["transitionConfig"] = {
|
||||
x: -10,
|
||||
y: 0,
|
||||
};
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<ContextMenuPrimitive.SubContent
|
||||
{transition}
|
||||
{transitionConfig}
|
||||
class={cn(
|
||||
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md focus:outline-none",
|
||||
className
|
||||
)}
|
||||
{...$$restProps}
|
||||
on:keydown
|
||||
on:focusout
|
||||
on:pointermove
|
||||
>
|
||||
<slot />
|
||||
</ContextMenuPrimitive.SubContent>
|
@@ -0,0 +1,32 @@
|
||||
<script lang="ts">
|
||||
import { ContextMenu as ContextMenuPrimitive } from "bits-ui";
|
||||
import ChevronRight from "lucide-svelte/icons/chevron-right";
|
||||
import { cn } from "$lib/utils.js";
|
||||
|
||||
type $$Props = ContextMenuPrimitive.SubTriggerProps & {
|
||||
inset?: boolean;
|
||||
};
|
||||
type $$Events = ContextMenuPrimitive.SubTriggerEvents;
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export let inset: $$Props["inset"] = undefined;
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<ContextMenuPrimitive.SubTrigger
|
||||
class={cn(
|
||||
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[highlighted]:bg-accent data-[state=open]:bg-accent data-[highlighted]:text-accent-foreground data-[state=open]:text-accent-foreground",
|
||||
inset && "pl-8",
|
||||
className
|
||||
)}
|
||||
{...$$restProps}
|
||||
on:click
|
||||
on:keydown
|
||||
on:focusin
|
||||
on:focusout
|
||||
on:pointerleave
|
||||
on:pointermove
|
||||
>
|
||||
<slot />
|
||||
<ChevronRight class="ml-auto h-4 w-4" />
|
||||
</ContextMenuPrimitive.SubTrigger>
|
49
website/src/lib/components/ui/context-menu/index.ts
Normal file
49
website/src/lib/components/ui/context-menu/index.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { ContextMenu as ContextMenuPrimitive } from "bits-ui";
|
||||
|
||||
import Item from "./context-menu-item.svelte";
|
||||
import Label from "./context-menu-label.svelte";
|
||||
import Content from "./context-menu-content.svelte";
|
||||
import Shortcut from "./context-menu-shortcut.svelte";
|
||||
import RadioItem from "./context-menu-radio-item.svelte";
|
||||
import Separator from "./context-menu-separator.svelte";
|
||||
import RadioGroup from "./context-menu-radio-group.svelte";
|
||||
import SubContent from "./context-menu-sub-content.svelte";
|
||||
import SubTrigger from "./context-menu-sub-trigger.svelte";
|
||||
import CheckboxItem from "./context-menu-checkbox-item.svelte";
|
||||
|
||||
const Sub = ContextMenuPrimitive.Sub;
|
||||
const Root = ContextMenuPrimitive.Root;
|
||||
const Trigger = ContextMenuPrimitive.Trigger;
|
||||
const Group = ContextMenuPrimitive.Group;
|
||||
|
||||
export {
|
||||
Sub,
|
||||
Root,
|
||||
Item,
|
||||
Label,
|
||||
Group,
|
||||
Trigger,
|
||||
Content,
|
||||
Shortcut,
|
||||
Separator,
|
||||
RadioItem,
|
||||
SubContent,
|
||||
SubTrigger,
|
||||
RadioGroup,
|
||||
CheckboxItem,
|
||||
//
|
||||
Root as ContextMenu,
|
||||
Sub as ContextMenuSub,
|
||||
Item as ContextMenuItem,
|
||||
Label as ContextMenuLabel,
|
||||
Group as ContextMenuGroup,
|
||||
Content as ContextMenuContent,
|
||||
Trigger as ContextMenuTrigger,
|
||||
Shortcut as ContextMenuShortcut,
|
||||
RadioItem as ContextMenuRadioItem,
|
||||
Separator as ContextMenuSeparator,
|
||||
RadioGroup as ContextMenuRadioGroup,
|
||||
SubContent as ContextMenuSubContent,
|
||||
SubTrigger as ContextMenuSubTrigger,
|
||||
CheckboxItem as ContextMenuCheckboxItem,
|
||||
};
|
@@ -13,6 +13,7 @@
|
||||
"redo": "Redo",
|
||||
"delete": "Delete",
|
||||
"delete_all": "Delete all",
|
||||
"select_all": "Select all",
|
||||
"settings": "Settings",
|
||||
"distance_units": "Distance units",
|
||||
"metric": "Metric",
|
||||
@@ -28,7 +29,9 @@
|
||||
"distance_markers": "Show distance markers",
|
||||
"direction_markers": "Show direction markers",
|
||||
"about": "About",
|
||||
"donate": "Donate"
|
||||
"donate": "Donate",
|
||||
"ctrl": "Ctrl",
|
||||
"click": "Click"
|
||||
},
|
||||
"toolbar": {
|
||||
"routing": {
|
||||
|
Reference in New Issue
Block a user