upend/webui/src/lib/components/display/UpLink.svelte

85 lines
2.0 KiB
Svelte

<script lang="ts">
import { getContext } from 'svelte';
import { readable } from 'svelte/store';
import type { Address, VALUE_TYPE } from '@upnd/upend/types';
import type { BrowseContext } from '$lib/util/browse';
import api from '$lib/api';
import { goto } from '$app/navigation';
export let passthrough = false;
export let title: string | undefined = undefined;
export let text = false;
export let to: {
entity?: Address;
attribute?: string;
surfaceAttribute?: string;
value?: { t: VALUE_TYPE; c: string };
};
const NOOP = '#';
let targetHref = NOOP;
$: {
if (to.entity) {
targetHref = to.entity;
} else if (to.attribute) {
api.componentsToAddress({ t: 'Attribute', c: to.attribute }).then((address) => {
targetHref = address;
});
} else if (to.surfaceAttribute) {
targetHref = `surface:${to.surfaceAttribute}`;
}
}
const context = getContext('browse') as BrowseContext | undefined;
const index = context ? context.index : readable(0);
const addresses = context ? context.addresses : readable([]);
function onClick(ev: MouseEvent) {
if (window.location.pathname.startsWith('/browse')) {
let newAddresses = $addresses.concat();
// Shift to append to the end instead of replacing
if (ev.shiftKey) {
newAddresses = newAddresses.concat([targetHref]);
} else {
if ($addresses[$index] !== targetHref) {
newAddresses = newAddresses.slice(0, $index + 1).concat([targetHref]);
}
}
goto('/browse/' + newAddresses.join(','));
return true;
} else {
goto(`/browse/${targetHref}`);
}
}
</script>
<a
class="uplink"
class:text
class:passthrough
class:unresolved={targetHref === NOOP}
href="/browse/{targetHref}"
on:click|preventDefault={onClick}
{title}
>
<slot />
</a>
<style lang="scss">
:global(.uplink) {
text-decoration: none;
max-width: 100%;
}
:global(.uplink.text) {
text-decoration: underline;
}
:global(.uplink.passthrough) {
display: contents;
}
:global(.uplink.unresolved) {
pointer-events: none;
}
</style>