2024-08-26 13:09:46 +02:00
|
|
|
|
<script lang="ts">
|
2024-09-11 01:46:55 +02:00
|
|
|
|
import type { GeocodeResult } from "../../Logic/Search/GeocodingProvider"
|
2025-03-13 23:42:52 +01:00
|
|
|
|
import { GeocodingUtils } from "../../Logic/Search/GeocodingProvider"
|
2024-08-26 13:09:46 +02:00
|
|
|
|
import { GeoOperations } from "../../Logic/GeoOperations"
|
|
|
|
|
import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
|
|
|
|
|
import { UIEventSource } from "../../Logic/UIEventSource"
|
|
|
|
|
import TagRenderingConfig from "../../Models/ThemeConfig/TagRenderingConfig"
|
|
|
|
|
import Icon from "../Map/Icon.svelte"
|
|
|
|
|
import TagRenderingAnswer from "../Popup/TagRendering/TagRenderingAnswer.svelte"
|
2025-01-02 03:56:42 +01:00
|
|
|
|
import DefaultIcon from "../Map/DefaultIcon.svelte"
|
2025-03-13 23:42:52 +01:00
|
|
|
|
import type { MapProperties } from "../../Models/MapProperties"
|
|
|
|
|
import ThemeConfig from "../../Models/ThemeConfig/ThemeConfig"
|
|
|
|
|
import FeaturePropertiesStore from "../../Logic/FeatureSource/Actors/FeaturePropertiesStore"
|
|
|
|
|
import SearchState from "../../Logic/State/SearchState"
|
|
|
|
|
import ArrowUp from "@babeard/svelte-heroicons/mini/ArrowUp"
|
2025-04-25 18:04:25 +02:00
|
|
|
|
import { createEventDispatcher } from "svelte"
|
2024-08-26 13:09:46 +02:00
|
|
|
|
|
|
|
|
|
export let entry: GeocodeResult
|
2025-03-13 23:42:52 +01:00
|
|
|
|
export let state: {
|
2025-03-17 02:54:12 +01:00
|
|
|
|
mapProperties: MapProperties
|
|
|
|
|
theme?: ThemeConfig
|
|
|
|
|
featureProperties?: FeaturePropertiesStore
|
2025-03-13 23:42:52 +01:00
|
|
|
|
searchState: Partial<SearchState>
|
|
|
|
|
}
|
2024-08-26 13:09:46 +02:00
|
|
|
|
|
|
|
|
|
let layer: LayerConfig
|
|
|
|
|
let tags: UIEventSource<Record<string, string>>
|
|
|
|
|
let descriptionTr: TagRenderingConfig = undefined
|
|
|
|
|
if (entry.feature?.properties?.id) {
|
2024-10-17 04:06:03 +02:00
|
|
|
|
layer = state.theme.getMatchingLayer(entry.feature.properties)
|
2025-03-13 23:42:52 +01:00
|
|
|
|
tags = state.featureProperties?.getStore(entry.feature.properties.id)
|
2024-10-19 14:44:55 +02:00
|
|
|
|
descriptionTr = layer?.tagRenderings?.find((tr) => tr.labels.indexOf("description") >= 0)
|
2024-08-26 13:09:46 +02:00
|
|
|
|
}
|
|
|
|
|
|
2024-10-19 14:44:55 +02:00
|
|
|
|
let distance = state.mapProperties.location.mapD((l) =>
|
|
|
|
|
GeoOperations.distanceBetween([l.lon, l.lat], [entry.lon, entry.lat])
|
|
|
|
|
)
|
|
|
|
|
let bearing = state.mapProperties.location.mapD((l) =>
|
|
|
|
|
GeoOperations.bearing([l.lon, l.lat], [entry.lon, entry.lat])
|
|
|
|
|
)
|
2024-08-26 13:09:46 +02:00
|
|
|
|
let mapRotation = state.mapProperties.rotation
|
2024-10-19 14:44:55 +02:00
|
|
|
|
let inView = state.mapProperties.bounds.mapD((bounds) => bounds.contains([entry.lon, entry.lat]))
|
2024-08-26 13:09:46 +02:00
|
|
|
|
|
2025-04-25 18:04:25 +02:00
|
|
|
|
let dispatch = createEventDispatcher<{ select: GeocodeResult }>()
|
2024-08-26 13:09:46 +02:00
|
|
|
|
function select() {
|
2025-04-25 18:04:25 +02:00
|
|
|
|
dispatch("select", entry)
|
2024-08-26 13:09:46 +02:00
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
|
2024-10-19 14:44:55 +02:00
|
|
|
|
<button class="unstyled link-no-underline searchresult w-full" on:click={() => select()}>
|
|
|
|
|
<div class="flex w-full items-center gap-y-2 p-2">
|
2024-08-26 13:09:46 +02:00
|
|
|
|
{#if layer}
|
2025-03-11 03:45:11 +01:00
|
|
|
|
<div class="h-6 w-6">
|
|
|
|
|
<DefaultIcon {layer} properties={entry.feature.properties} />
|
2024-10-09 00:10:56 +02:00
|
|
|
|
</div>
|
2024-08-26 13:09:46 +02:00
|
|
|
|
{:else if entry.category}
|
2024-10-19 14:44:55 +02:00
|
|
|
|
<Icon
|
|
|
|
|
icon={GeocodingUtils.categoryToIcon[entry.category]}
|
|
|
|
|
clss="w-6 h-6 shrink-0"
|
|
|
|
|
color="#aaa"
|
|
|
|
|
/>
|
2024-08-26 13:09:46 +02:00
|
|
|
|
{/if}
|
2024-10-19 14:44:55 +02:00
|
|
|
|
<div class="flex w-full flex-col items-start pl-2">
|
|
|
|
|
<div class="flex w-full flex-wrap justify-between gap-x-2">
|
2024-08-26 13:09:46 +02:00
|
|
|
|
<b class="nowrap">
|
|
|
|
|
{#if layer && $tags?.id}
|
2024-10-19 14:44:55 +02:00
|
|
|
|
<TagRenderingAnswer
|
|
|
|
|
config={layer.title}
|
|
|
|
|
selectedElement={entry.feature}
|
|
|
|
|
{state}
|
|
|
|
|
{tags}
|
|
|
|
|
{layer}
|
|
|
|
|
/>
|
2024-08-26 13:09:46 +02:00
|
|
|
|
{:else}
|
|
|
|
|
{entry.display_name ?? entry.osm_id}
|
|
|
|
|
{/if}
|
|
|
|
|
</b>
|
|
|
|
|
{#if $distance > 50}
|
2024-10-19 14:44:55 +02:00
|
|
|
|
<div class="flex items-center gap-x-1">
|
2024-08-26 13:09:46 +02:00
|
|
|
|
{#if $bearing && !$inView}
|
2024-10-19 14:44:55 +02:00
|
|
|
|
<ArrowUp
|
|
|
|
|
class="h-4 w-4 shrink-0"
|
|
|
|
|
style={`transform: rotate(${$bearing - $mapRotation}deg)`}
|
|
|
|
|
/>
|
2024-08-26 13:09:46 +02:00
|
|
|
|
{/if}
|
|
|
|
|
{#if $distance}
|
|
|
|
|
{GeoOperations.distanceToHuman($distance)}
|
|
|
|
|
{/if}
|
|
|
|
|
</div>
|
|
|
|
|
{/if}
|
|
|
|
|
</div>
|
|
|
|
|
<div class="flex flex-wrap gap-x-2">
|
2024-09-10 02:19:55 +02:00
|
|
|
|
{#if descriptionTr && tags}
|
2024-10-19 14:44:55 +02:00
|
|
|
|
<TagRenderingAnswer
|
|
|
|
|
defaultSize="subtle"
|
|
|
|
|
noIcons={true}
|
|
|
|
|
config={descriptionTr}
|
|
|
|
|
{tags}
|
|
|
|
|
{state}
|
|
|
|
|
selectedElement={entry.feature}
|
|
|
|
|
{layer}
|
|
|
|
|
/>
|
2024-08-26 13:09:46 +02:00
|
|
|
|
{/if}
|
2024-09-10 02:19:55 +02:00
|
|
|
|
{#if descriptionTr && tags && entry.description}
|
2024-08-26 13:09:46 +02:00
|
|
|
|
–
|
|
|
|
|
{/if}
|
|
|
|
|
{#if entry.description}
|
2024-10-19 14:44:55 +02:00
|
|
|
|
<div class="subtle flex w-full justify-between">
|
2024-08-26 13:09:46 +02:00
|
|
|
|
{entry.description}
|
|
|
|
|
</div>
|
|
|
|
|
{/if}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</button>
|