2022-01-09 21:24:49 +01:00
|
|
|
<script lang="ts">
|
2024-01-22 20:33:12 +01:00
|
|
|
import Selector, { type SELECTOR_TYPE, type SelectorValue } from './Selector.svelte';
|
|
|
|
import { createEventDispatcher } from 'svelte';
|
|
|
|
import type { IValue } from '@upnd/upend/types';
|
|
|
|
import IconButton from './IconButton.svelte';
|
2024-01-07 20:10:01 +01:00
|
|
|
|
2024-02-17 17:22:58 +01:00
|
|
|
const dispatch = createEventDispatcher<{ edit: SelectorValue }>();
|
2022-01-09 21:24:49 +01:00
|
|
|
|
2024-02-17 17:22:58 +01:00
|
|
|
export let editable = true;
|
2024-01-22 20:33:12 +01:00
|
|
|
export let value: IValue | undefined = undefined;
|
|
|
|
export let types: SELECTOR_TYPE[] | undefined = undefined;
|
|
|
|
let newValue: SelectorValue | undefined = value;
|
2022-02-07 16:32:49 +01:00
|
|
|
|
2024-01-22 20:33:12 +01:00
|
|
|
let editing = false;
|
2023-09-02 19:30:01 +02:00
|
|
|
|
2024-01-22 20:33:12 +01:00
|
|
|
let selector: Selector;
|
|
|
|
let hover = false;
|
|
|
|
let focus = false;
|
2023-09-02 19:30:01 +02:00
|
|
|
|
2024-01-22 20:33:12 +01:00
|
|
|
$: if (editing && selector) selector.focus();
|
|
|
|
$: if (!focus && !hover) editing = false;
|
2023-11-17 19:20:31 +01:00
|
|
|
|
2024-01-22 20:33:12 +01:00
|
|
|
function onInput(ev: CustomEvent<SelectorValue>) {
|
|
|
|
newValue = ev.detail;
|
|
|
|
selector.focus();
|
|
|
|
}
|
2022-01-09 21:24:49 +01:00
|
|
|
</script>
|
|
|
|
|
2024-01-22 20:33:12 +01:00
|
|
|
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
2023-09-02 19:30:01 +02:00
|
|
|
<div
|
2024-01-22 20:33:12 +01:00
|
|
|
class="editable"
|
|
|
|
class:editing
|
|
|
|
on:mouseenter={() => (hover = true)}
|
|
|
|
on:mouseleave={() => (hover = false)}
|
2023-09-02 19:30:01 +02:00
|
|
|
>
|
2024-01-22 20:33:12 +01:00
|
|
|
<div class="inner">
|
|
|
|
{#if editing}
|
|
|
|
<div
|
|
|
|
class="selector"
|
|
|
|
on:keydown={(ev) => {
|
|
|
|
if (ev.key === 'Escape') {
|
|
|
|
editing = false;
|
|
|
|
}
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
<Selector
|
|
|
|
{types}
|
2024-02-17 17:03:04 +01:00
|
|
|
initial={value}
|
2024-01-22 20:33:12 +01:00
|
|
|
bind:this={selector}
|
|
|
|
on:focus={(ev) => (focus = ev.detail)}
|
|
|
|
on:input={onInput}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
<IconButton
|
|
|
|
name="save"
|
|
|
|
on:click={() => {
|
2024-02-17 17:22:58 +01:00
|
|
|
if (newValue) dispatch('edit', newValue);
|
2024-01-22 20:33:12 +01:00
|
|
|
editing = false;
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
{:else}
|
|
|
|
<div class="content">
|
|
|
|
<slot />
|
|
|
|
</div>
|
2024-02-17 17:22:58 +01:00
|
|
|
{#if editable}
|
|
|
|
<div class="edit-icon">
|
|
|
|
<IconButton name="edit" on:click={() => (editing = true)} plain />
|
|
|
|
</div>
|
|
|
|
{/if}
|
2024-01-22 20:33:12 +01:00
|
|
|
{/if}
|
|
|
|
</div>
|
2022-01-09 21:24:49 +01:00
|
|
|
</div>
|
|
|
|
|
2023-09-02 19:30:01 +02:00
|
|
|
<style lang="scss">
|
2024-02-20 13:47:37 +01:00
|
|
|
.editable {
|
|
|
|
max-width: 100%;
|
|
|
|
}
|
|
|
|
|
2024-01-22 20:33:12 +01:00
|
|
|
.edit-icon {
|
|
|
|
opacity: 0;
|
|
|
|
transition: opacity 0.2s ease-in-out;
|
|
|
|
}
|
2023-09-02 19:30:01 +02:00
|
|
|
|
2024-01-22 20:33:12 +01:00
|
|
|
.editable:hover .edit-icon {
|
|
|
|
opacity: 0.8;
|
|
|
|
}
|
2023-09-02 19:30:01 +02:00
|
|
|
|
2024-01-22 20:33:12 +01:00
|
|
|
.inner {
|
|
|
|
display: flex;
|
|
|
|
gap: 0.25em;
|
|
|
|
align-items: center;
|
|
|
|
}
|
2022-01-09 21:24:49 +01:00
|
|
|
|
2024-01-22 20:33:12 +01:00
|
|
|
.content {
|
|
|
|
min-width: 0;
|
|
|
|
}
|
2024-01-07 20:10:01 +01:00
|
|
|
|
2024-01-22 20:33:12 +01:00
|
|
|
.selector {
|
|
|
|
flex-grow: 1;
|
|
|
|
min-width: 0;
|
|
|
|
}
|
2024-02-17 17:22:58 +01:00
|
|
|
|
|
|
|
.editing {
|
|
|
|
width: 100%;
|
|
|
|
}
|
2022-01-09 21:24:49 +01:00
|
|
|
</style>
|