InplaceEdit and TreeView component.
This commit is contained in:
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
0
src/app.css
Normal file
0
src/app.css
Normal file
58
src/lib/InPlaceEdit.svelte
Normal file
58
src/lib/InPlaceEdit.svelte
Normal file
@@ -0,0 +1,58 @@
|
||||
<script>
|
||||
import { createEventDispatcher, onMount } from 'svelte'
|
||||
|
||||
export let value, required = true
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
let editing = false, original
|
||||
|
||||
onMount(() => {
|
||||
original = value
|
||||
})
|
||||
|
||||
function edit() {
|
||||
editing = true
|
||||
}
|
||||
|
||||
function submit() {
|
||||
if (value != original) {
|
||||
dispatch('submit', value)
|
||||
}
|
||||
|
||||
editing = false
|
||||
}
|
||||
|
||||
function keydown(event) {
|
||||
if (event.key == 'Escape') {
|
||||
event.preventDefault()
|
||||
value = original
|
||||
editing = false
|
||||
}
|
||||
}
|
||||
|
||||
function focus(element) {
|
||||
element.focus()
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if editing}
|
||||
<form on:submit|preventDefault={submit} on:keydown={keydown}>
|
||||
<input bind:value on:blur={submit} {required} use:focus/>
|
||||
</form>
|
||||
{:else}
|
||||
<div on:click={edit}>
|
||||
{value}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
input {
|
||||
border: none;
|
||||
background: none;
|
||||
font-size: inherit;
|
||||
color: inherit;
|
||||
font-weight: inherit;
|
||||
text-align: inherit;
|
||||
box-shadow: none;
|
||||
}
|
||||
</style>
|
||||
54
src/lib/TreeView.svelte
Normal file
54
src/lib/TreeView.svelte
Normal file
@@ -0,0 +1,54 @@
|
||||
<script context="module">
|
||||
// retain module scoped expansion state for each tree node
|
||||
const _expansionState = {
|
||||
/* treeNodeId: expanded <boolean> */
|
||||
}
|
||||
</script>
|
||||
<script>
|
||||
// import { slide } from 'svelte/transition'
|
||||
export let tree
|
||||
const {label, children} = tree
|
||||
|
||||
let expanded = _expansionState[label] || false
|
||||
const toggleExpansion = () => {
|
||||
expanded = _expansionState[label] = !expanded
|
||||
}
|
||||
$: arrowDown = expanded
|
||||
</script>
|
||||
|
||||
<ul><!-- transition:slide -->
|
||||
<li>
|
||||
{#if children}
|
||||
<span on:click={toggleExpansion}>
|
||||
<span class="arrow" class:arrowDown>▶</span>
|
||||
{label}
|
||||
</span>
|
||||
{#if expanded}
|
||||
{#each children as child}
|
||||
<svelte:self tree={child} />
|
||||
{/each}
|
||||
{/if}
|
||||
{:else}
|
||||
<span>
|
||||
<span class="no-arrow"/>
|
||||
{label}
|
||||
</span>
|
||||
{/if}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<style>
|
||||
ul {
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
padding-left: 1.2rem;
|
||||
user-select: none;
|
||||
}
|
||||
.no-arrow { padding-left: 1.0rem; }
|
||||
.arrow {
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
/* transition: transform 200ms; */
|
||||
}
|
||||
.arrowDown { transform: rotate(90deg); }
|
||||
</style>
|
||||
Reference in New Issue
Block a user