85 lines
2.0 KiB
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>
|