149 lines
2.9 KiB
Svelte
149 lines
2.9 KiB
Svelte
|
<script lang="ts">
|
||
|
import { createEventDispatcher, SvelteComponent } from "svelte";
|
||
|
import type { IEntry } from "upend/types";
|
||
|
import UpLink from "./UpLink.svelte";
|
||
|
import type { Component, UpType, Widget } from "../lib/types";
|
||
|
import Table from "./widgets/Table.svelte";
|
||
|
const dispatcher = createEventDispatcher();
|
||
|
|
||
|
export let attributes: [string, IEntry][];
|
||
|
export let type: UpType | undefined = undefined;
|
||
|
export let address: String;
|
||
|
export let title: String | undefined = undefined;
|
||
|
export let editable = false;
|
||
|
export let reverse = false;
|
||
|
|
||
|
let currentWidget = "table";
|
||
|
|
||
|
let availableWidgets: Widget[] = [];
|
||
|
$: {
|
||
|
availableWidgets = [
|
||
|
{
|
||
|
name: "table",
|
||
|
icon: "table",
|
||
|
components: [
|
||
|
{
|
||
|
component: Table,
|
||
|
},
|
||
|
],
|
||
|
},
|
||
|
];
|
||
|
|
||
|
if (type?.widgetInfo) {
|
||
|
availableWidgets = [type.widgetInfo, ...availableWidgets];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
let components: Component[] = [];
|
||
|
$: {
|
||
|
components = availableWidgets.find(
|
||
|
(w) => w.name === currentWidget
|
||
|
)!.components;
|
||
|
}
|
||
|
|
||
|
function processChange() {
|
||
|
// noop
|
||
|
}
|
||
|
|
||
|
</script>
|
||
|
|
||
|
<section class="attribute-view">
|
||
|
<header>
|
||
|
<h3>
|
||
|
{#if type}
|
||
|
<UpLink to={{ entity: type.address }}>
|
||
|
{#if type.icon}
|
||
|
<sl-icon name={type.icon} />
|
||
|
{/if}
|
||
|
{type.name || "???"}
|
||
|
</UpLink>
|
||
|
{:else}
|
||
|
{title || "???"}
|
||
|
{/if}
|
||
|
</h3>
|
||
|
|
||
|
{#if availableWidgets.length > 1 || editable}
|
||
|
<div class="views">
|
||
|
{#each availableWidgets as widget (widget.name)}
|
||
|
<sl-icon-button
|
||
|
name={widget.icon || "question-diamond"}
|
||
|
class:active={widget.name === currentWidget}
|
||
|
on:click={() => (currentWidget = widget.name)}
|
||
|
/>
|
||
|
{/each}
|
||
|
</div>
|
||
|
{/if}
|
||
|
</header>
|
||
|
|
||
|
{#each components as component}
|
||
|
<svelte:component
|
||
|
this={component.component}
|
||
|
{...component.props || {}}
|
||
|
{attributes}
|
||
|
{editable}
|
||
|
{reverse}
|
||
|
on:edit={processChange}
|
||
|
/>
|
||
|
{/each}
|
||
|
</section>
|
||
|
|
||
|
<style scoped lang="scss">
|
||
|
section {
|
||
|
position: relative;
|
||
|
overflow: visible;
|
||
|
|
||
|
margin-top: 1.66em;
|
||
|
padding: 1ex 1em;
|
||
|
|
||
|
border: 1px solid var(--foreground);
|
||
|
border-radius: 4px;
|
||
|
|
||
|
header {
|
||
|
margin-bottom: 0.2em;
|
||
|
|
||
|
& > * {
|
||
|
position: absolute;
|
||
|
top: -0.66em;
|
||
|
|
||
|
margin: 0;
|
||
|
|
||
|
background: var(--background);
|
||
|
font-weight: 600;
|
||
|
|
||
|
line-height: 1;
|
||
|
padding: 0 0.75ex;
|
||
|
|
||
|
sl-icon {
|
||
|
margin-bottom: -2px;
|
||
|
}
|
||
|
|
||
|
a {
|
||
|
text-decoration: none;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
h3 {
|
||
|
left: 1ex;
|
||
|
}
|
||
|
|
||
|
.views {
|
||
|
right: 1ex;
|
||
|
|
||
|
font-size: 18px;
|
||
|
|
||
|
sl-icon-button {
|
||
|
&::part(base) {
|
||
|
padding: 0 calc(0.75ex / 2);
|
||
|
}
|
||
|
|
||
|
&.active {
|
||
|
&::part(base) {
|
||
|
color: var(--foreground);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
</style>
|