file tabs

This commit is contained in:
vcoppe
2024-04-19 16:13:08 +02:00
parent 675b1bd919
commit 13af33903b
12 changed files with 207 additions and 10 deletions

View File

@@ -2,18 +2,16 @@
import { files, selectedFiles, addSelectFile, selectFile } from '$lib/stores';
import { ScrollArea } from '$lib/components/ui/scroll-area/index.js';
import { Button } from '$lib/components/ui/button';
import { Label } from '$lib/components/ui/label';
</script>
<div class="flex flex-col h-full w-full">
<Label class="w-full">Files</Label>
<ScrollArea class="w-full h-full">
<div class="flex flex-col">
<div class="absolute h-10 -translate-y-10 w-fit max-w-full bg-secondary rounded-t px-1">
<ScrollArea orientation="horizontal" class="w-full h-full" scrollbarXClasses="h-2">
<div class="flex flex-row gap-1">
{#each $files as file}
<Button
variant={$selectedFiles.has(file) ? 'outline' : 'secondary'}
class="w-full {$selectedFiles.has(file) ? 'hover:bg-background' : 'hover:bg-secondary'}"
<button
class="my-1 px-1.5 py-1 rounded {$selectedFiles.has(file)
? 'bg-background shadow'
: 'bg-secondary'}"
on:click={(e) => {
if (e.shiftKey) {
addSelectFile(file);
@@ -23,7 +21,7 @@
}}
>
{file.metadata.name}
</Button>
</button>
{/each}
</div>
</ScrollArea>

View File

@@ -0,0 +1,64 @@
<script lang="ts">
import * as Card from '$lib/components/ui/card';
import GPXDataItem from '$lib/components/GPXDataItem.svelte';
import { GPXStatistics } from 'gpx';
import { selectedFiles } from '$lib/stores';
import { MoveDownRight, MoveUpRight, Ruler, Timer, Zap } from 'lucide-svelte';
let gpxData: GPXStatistics = new GPXStatistics();
$: {
gpxData = new GPXStatistics();
$selectedFiles.forEach((file) => {
gpxData.mergeWith(file.statistics);
});
}
function toHHMMSS(seconds: number) {
var hours = Math.floor(seconds / 3600);
var minutes = Math.floor(seconds / 60) % 60;
var seconds = Math.round(seconds % 60);
return [hours, minutes, seconds]
.map((v) => (v < 10 ? '0' + v : v))
.filter((v, i) => v !== '00' || i > 0)
.join(':');
}
</script>
<Card.Root class="h-full overflow-hidden border-none">
<Card.Content class="flex flex-col flex-wrap gap-4 p-2">
<GPXDataItem>
<span slot="data" class="flex flex-row items-center">
<Ruler size="18" class="mr-1" />
{gpxData.distance.total.toFixed(2)} km
</span>
<span slot="tooltip">Distance</span>
</GPXDataItem>
<GPXDataItem>
<span slot="data" class="flex flex-row items-center">
<MoveUpRight size="18" class="mr-1" />
{gpxData.elevation.gain.toFixed(0)} m
<MoveDownRight size="18" class="mx-1" />
{gpxData.elevation.loss.toFixed(0)} m
</span>
<span slot="tooltip">Elevation</span>
</GPXDataItem>
<GPXDataItem>
<span slot="data" class="flex flex-row items-center">
<Zap size="18" class="mr-1" />
{gpxData.speed.moving.toFixed(2)} km/h
</span>
<span slot="tooltip">Time</span>
</GPXDataItem>
<GPXDataItem>
<span slot="data" class="flex flex-row items-center">
<Timer size="18" class="mr-1" />
{toHHMMSS(gpxData.time.moving)} / {toHHMMSS(gpxData.time.total)}
</span>
<span slot="tooltip">Moving time / Total time</span>
</GPXDataItem>
</Card.Content>
</Card.Root>

View File

@@ -0,0 +1,12 @@
<script lang="ts">
import * as Tooltip from '$lib/components/ui/tooltip/index.js';
</script>
<Tooltip.Root>
<Tooltip.Trigger>
<slot name="data" />
</Tooltip.Trigger>
<Tooltip.Content side="top">
<slot name="tooltip" />
</Tooltip.Content>
</Tooltip.Root>

View File

@@ -113,4 +113,12 @@
@apply h-full;
@apply overflow-hidden;
}
div :global(.mapboxgl-ctrl-bottom-left) {
@apply bottom-10;
}
div :global(.mapboxgl-ctrl-bottom-right) {
@apply bottom-10;
}
</style>

View File

@@ -0,0 +1,13 @@
<script lang="ts">
import type { HTMLAttributes } from "svelte/elements";
import { cn } from "$lib/utils.js";
type $$Props = HTMLAttributes<HTMLDivElement>;
let className: $$Props["class"] = undefined;
export { className as class };
</script>
<div class={cn("p-6 pt-0", className)} {...$$restProps}>
<slot />
</div>

View File

@@ -0,0 +1,13 @@
<script lang="ts">
import type { HTMLAttributes } from "svelte/elements";
import { cn } from "$lib/utils.js";
type $$Props = HTMLAttributes<HTMLParagraphElement>;
let className: $$Props["class"] = undefined;
export { className as class };
</script>
<p class={cn("text-sm text-muted-foreground", className)} {...$$restProps}>
<slot />
</p>

View File

@@ -0,0 +1,13 @@
<script lang="ts">
import type { HTMLAttributes } from "svelte/elements";
import { cn } from "$lib/utils.js";
type $$Props = HTMLAttributes<HTMLDivElement>;
let className: $$Props["class"] = undefined;
export { className as class };
</script>
<div class={cn("flex items-center p-6 pt-0", className)} {...$$restProps}>
<slot />
</div>

View File

@@ -0,0 +1,13 @@
<script lang="ts">
import type { HTMLAttributes } from "svelte/elements";
import { cn } from "$lib/utils.js";
type $$Props = HTMLAttributes<HTMLDivElement>;
let className: $$Props["class"] = undefined;
export { className as class };
</script>
<div class={cn("flex flex-col space-y-1.5 p-6", className)} {...$$restProps}>
<slot />
</div>

View File

@@ -0,0 +1,21 @@
<script lang="ts">
import type { HTMLAttributes } from "svelte/elements";
import type { HeadingLevel } from "./index.js";
import { cn } from "$lib/utils.js";
type $$Props = HTMLAttributes<HTMLHeadingElement> & {
tag?: HeadingLevel;
};
let className: $$Props["class"] = undefined;
export let tag: $$Props["tag"] = "h3";
export { className as class };
</script>
<svelte:element
this={tag}
class={cn("text-lg font-semibold leading-none tracking-tight", className)}
{...$$restProps}
>
<slot />
</svelte:element>

View File

@@ -0,0 +1,16 @@
<script lang="ts">
import type { HTMLAttributes } from "svelte/elements";
import { cn } from "$lib/utils.js";
type $$Props = HTMLAttributes<HTMLDivElement>;
let className: $$Props["class"] = undefined;
export { className as class };
</script>
<div
class={cn("rounded-lg border bg-card text-card-foreground shadow-sm", className)}
{...$$restProps}
>
<slot />
</div>

View File

@@ -0,0 +1,24 @@
import Root from "./card.svelte";
import Content from "./card-content.svelte";
import Description from "./card-description.svelte";
import Footer from "./card-footer.svelte";
import Header from "./card-header.svelte";
import Title from "./card-title.svelte";
export {
Root,
Content,
Description,
Footer,
Header,
Title,
//
Root as Card,
Content as CardContent,
Description as CardDescription,
Footer as CardFooter,
Header as CardHeader,
Title as CardTitle,
};
export type HeadingLevel = "h1" | "h2" | "h3" | "h4" | "h5" | "h6";

View File

@@ -1,6 +1,7 @@
<script lang="ts">
import Data from '$lib/components/Data.svelte';
import FileList from '$lib/components/FileList.svelte';
import GPXData from '$lib/components/GPXData.svelte';
import Map from '$lib/components/Map.svelte';
import Menu from '$lib/components/Menu.svelte';
import Toolbar from '$lib/components/Toolbar.svelte';
@@ -17,5 +18,6 @@
</div>
<div class="h-60 flex flex-row">
<FileList />
<GPXData />
</div>
</div>