mirror of
				https://github.com/gpxstudio/gpx.studio.git
				synced 2025-11-04 05:21:09 +00:00 
			
		
		
		
	scrollable poi content, closes #124
This commit is contained in:
		@@ -11,6 +11,7 @@
 | 
			
		||||
	import sanitizeHtml from 'sanitize-html';
 | 
			
		||||
	import type { Waypoint } from 'gpx';
 | 
			
		||||
	import type { PopupItem } from '$lib/components/MapPopup';
 | 
			
		||||
	import { ScrollArea } from '$lib/components/ui/scroll-area/index.js';
 | 
			
		||||
 | 
			
		||||
	export let waypoint: PopupItem<Waypoint>;
 | 
			
		||||
 | 
			
		||||
@@ -43,7 +44,7 @@
 | 
			
		||||
			{/if}
 | 
			
		||||
		</Card.Title>
 | 
			
		||||
	</Card.Header>
 | 
			
		||||
	<Card.Content class="flex flex-col p-0 text-sm">
 | 
			
		||||
	<Card.Content class="flex flex-col text-sm p-0">
 | 
			
		||||
		<div class="flex flex-row items-center text-muted-foreground text-xs whitespace-nowrap">
 | 
			
		||||
			{#if symbolKey}
 | 
			
		||||
				<span>
 | 
			
		||||
@@ -66,12 +67,14 @@
 | 
			
		||||
				<WithUnits value={waypoint.item.ele} type="elevation" />
 | 
			
		||||
			{/if}
 | 
			
		||||
		</div>
 | 
			
		||||
		{#if waypoint.item.desc}
 | 
			
		||||
			<span class="whitespace-pre-wrap">{@html sanitize(waypoint.item.desc)}</span>
 | 
			
		||||
		{/if}
 | 
			
		||||
		{#if waypoint.item.cmt && waypoint.item.cmt !== waypoint.item.desc}
 | 
			
		||||
			<span class="whitespace-pre-wrap">{@html sanitize(waypoint.item.cmt)}</span>
 | 
			
		||||
		{/if}
 | 
			
		||||
		<ScrollArea class="flex flex-col" viewportClasses="max-h-[30dvh]">
 | 
			
		||||
			{#if waypoint.item.desc}
 | 
			
		||||
				<span class="whitespace-pre-wrap">{@html sanitize(waypoint.item.desc)}</span>
 | 
			
		||||
			{/if}
 | 
			
		||||
			{#if waypoint.item.cmt && waypoint.item.cmt !== waypoint.item.desc}
 | 
			
		||||
				<span class="whitespace-pre-wrap">{@html sanitize(waypoint.item.cmt)}</span>
 | 
			
		||||
			{/if}
 | 
			
		||||
		</ScrollArea>
 | 
			
		||||
		{#if $currentTool === Tool.WAYPOINT}
 | 
			
		||||
			<Button
 | 
			
		||||
				class="mt-2 w-full px-2 py-1 h-8 justify-start"
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@
 | 
			
		||||
	import { _ } from 'svelte-i18n';
 | 
			
		||||
	import { dbUtils } from '$lib/db';
 | 
			
		||||
	import type { PopupItem } from '$lib/components/MapPopup';
 | 
			
		||||
	import { ScrollArea } from '$lib/components/ui/scroll-area/index.js';
 | 
			
		||||
 | 
			
		||||
	export let poi: PopupItem<any>;
 | 
			
		||||
 | 
			
		||||
@@ -42,29 +43,31 @@
 | 
			
		||||
			</div>
 | 
			
		||||
		</Card.Title>
 | 
			
		||||
	</Card.Header>
 | 
			
		||||
	{#if tags.image || tags['image:0']}
 | 
			
		||||
		<div class="w-full rounded-md overflow-clip my-2 max-w-96 mx-auto">
 | 
			
		||||
			<!-- svelte-ignore a11y-missing-attribute -->
 | 
			
		||||
			<img src={tags.image ?? tags['image:0']} />
 | 
			
		||||
		</div>
 | 
			
		||||
	{/if}
 | 
			
		||||
	<Card.Content class="flex flex-col p-0 text-sm mt-1 whitespace-normal break-all">
 | 
			
		||||
		<div class="grid grid-cols-[auto_auto] gap-x-3">
 | 
			
		||||
			{#each Object.entries(tags) as [key, value]}
 | 
			
		||||
				{#if key !== 'name' && !key.includes('image')}
 | 
			
		||||
					<span class="font-mono">{key}</span>
 | 
			
		||||
					{#if key === 'website' || key === 'contact:website' || key === 'contact:facebook' || key === 'contact:instagram' || key === 'contact:twitter'}
 | 
			
		||||
						<a href={value} target="_blank" class="text-link underline">{value}</a>
 | 
			
		||||
					{:else if key === 'phone' || key === 'contact:phone'}
 | 
			
		||||
						<a href={'tel:' + value} class="text-link underline">{value}</a>
 | 
			
		||||
					{:else if key === 'email' || key === 'contact:email'}
 | 
			
		||||
						<a href={'mailto:' + value} class="text-link underline">{value}</a>
 | 
			
		||||
					{:else}
 | 
			
		||||
						<span>{value}</span>
 | 
			
		||||
		<ScrollArea class="flex flex-col" viewportClasses="max-h-[30dvh]">
 | 
			
		||||
			{#if tags.image || tags['image:0']}
 | 
			
		||||
				<div class="w-full rounded-md overflow-clip my-2 max-w-96 mx-auto">
 | 
			
		||||
					<!-- svelte-ignore a11y-missing-attribute -->
 | 
			
		||||
					<img src={tags.image ?? tags['image:0']} />
 | 
			
		||||
				</div>
 | 
			
		||||
			{/if}
 | 
			
		||||
			<div class="grid grid-cols-[auto_auto] gap-x-3">
 | 
			
		||||
				{#each Object.entries(tags) as [key, value]}
 | 
			
		||||
					{#if key !== 'name' && !key.includes('image')}
 | 
			
		||||
						<span class="font-mono">{key}</span>
 | 
			
		||||
						{#if key === 'website' || key.startsWith('website:') || key === 'contact:website' || key === 'contact:facebook' || key === 'contact:instagram' || key === 'contact:twitter'}
 | 
			
		||||
							<a href={value} target="_blank" class="text-link underline">{value}</a>
 | 
			
		||||
						{:else if key === 'phone' || key === 'contact:phone'}
 | 
			
		||||
							<a href={'tel:' + value} class="text-link underline">{value}</a>
 | 
			
		||||
						{:else if key === 'email' || key === 'contact:email'}
 | 
			
		||||
							<a href={'mailto:' + value} class="text-link underline">{value}</a>
 | 
			
		||||
						{:else}
 | 
			
		||||
							<span>{value}</span>
 | 
			
		||||
						{/if}
 | 
			
		||||
					{/if}
 | 
			
		||||
				{/if}
 | 
			
		||||
			{/each}
 | 
			
		||||
		</div>
 | 
			
		||||
				{/each}
 | 
			
		||||
			</div>
 | 
			
		||||
		</ScrollArea>
 | 
			
		||||
		<Button
 | 
			
		||||
			class="mt-2"
 | 
			
		||||
			variant="outline"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,31 +1,33 @@
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
	import { ScrollArea as ScrollAreaPrimitive } from "bits-ui";
 | 
			
		||||
	import { Scrollbar } from "./index.js";
 | 
			
		||||
	import { cn } from "$lib/utils.js";
 | 
			
		||||
	import { ScrollArea as ScrollAreaPrimitive } from 'bits-ui';
 | 
			
		||||
	import { Scrollbar } from './index.js';
 | 
			
		||||
	import { cn } from '$lib/utils.js';
 | 
			
		||||
 | 
			
		||||
	type $$Props = ScrollAreaPrimitive.Props & {
 | 
			
		||||
		orientation?: "vertical" | "horizontal" | "both";
 | 
			
		||||
		orientation?: 'vertical' | 'horizontal' | 'both';
 | 
			
		||||
		scrollbarXClasses?: string;
 | 
			
		||||
		scrollbarYClasses?: string;
 | 
			
		||||
		viewportClasses?: string;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	let className: $$Props["class"] = undefined;
 | 
			
		||||
	let className: $$Props['class'] = undefined;
 | 
			
		||||
	export { className as class };
 | 
			
		||||
	export let orientation = "vertical";
 | 
			
		||||
	export let scrollbarXClasses: string = "";
 | 
			
		||||
	export let scrollbarYClasses: string = "";
 | 
			
		||||
	export let orientation = 'vertical';
 | 
			
		||||
	export let scrollbarXClasses: string = '';
 | 
			
		||||
	export let scrollbarYClasses: string = '';
 | 
			
		||||
	export let viewportClasses: string = '';
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<ScrollAreaPrimitive.Root {...$$restProps} class={cn("relative overflow-hidden", className)}>
 | 
			
		||||
	<ScrollAreaPrimitive.Viewport class="h-full w-full rounded-[inherit]">
 | 
			
		||||
<ScrollAreaPrimitive.Root {...$$restProps} class={cn('relative overflow-hidden', className)}>
 | 
			
		||||
	<ScrollAreaPrimitive.Viewport class={cn('h-full w-full rounded-[inherit]', viewportClasses)}>
 | 
			
		||||
		<ScrollAreaPrimitive.Content>
 | 
			
		||||
			<slot />
 | 
			
		||||
		</ScrollAreaPrimitive.Content>
 | 
			
		||||
	</ScrollAreaPrimitive.Viewport>
 | 
			
		||||
	{#if orientation === "vertical" || orientation === "both"}
 | 
			
		||||
	{#if orientation === 'vertical' || orientation === 'both'}
 | 
			
		||||
		<Scrollbar orientation="vertical" class={scrollbarYClasses} />
 | 
			
		||||
	{/if}
 | 
			
		||||
	{#if orientation === "horizontal" || orientation === "both"}
 | 
			
		||||
	{#if orientation === 'horizontal' || orientation === 'both'}
 | 
			
		||||
		<Scrollbar orientation="horizontal" class={scrollbarXClasses} />
 | 
			
		||||
	{/if}
 | 
			
		||||
	<ScrollAreaPrimitive.Corner />
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user