2019-09-20 09:01:35 +02:00
|
|
|
<script>
|
|
|
|
import {
|
|
|
|
isString
|
|
|
|
} from "lodash/fp";
|
|
|
|
import IconButton from "../common/IconButton.svelte";
|
|
|
|
import {
|
|
|
|
isBinding, getBinding, setBinding
|
|
|
|
} from "../common/binding";
|
|
|
|
|
|
|
|
export let value="";
|
|
|
|
export let onChanged= () => {};
|
|
|
|
export let type="";
|
|
|
|
export let options=[];
|
|
|
|
|
|
|
|
let isBound=false;
|
|
|
|
let bindingPath="";
|
|
|
|
let bindingFallbackValue="";
|
2019-09-27 18:03:31 +02:00
|
|
|
let bindingSource="store";
|
2019-09-20 09:01:35 +02:00
|
|
|
let isExpanded = false;
|
|
|
|
let forceIsBound = false;
|
2019-09-27 18:03:31 +02:00
|
|
|
let canOnlyBind = false;
|
2019-09-20 09:01:35 +02:00
|
|
|
|
|
|
|
$: {
|
2019-09-27 18:03:31 +02:00
|
|
|
canOnlyBind = type === "state";
|
|
|
|
if(!forceIsBound && canOnlyBind)
|
|
|
|
forceIsBound = true;
|
|
|
|
|
2019-09-20 09:01:35 +02:00
|
|
|
isBound= forceIsBound || isBinding(value);
|
|
|
|
|
|
|
|
if(isBound) {
|
|
|
|
const binding = getBinding(value);
|
|
|
|
bindingPath= binding.path;
|
|
|
|
bindingFallbackValue= binding.fallback;
|
2019-09-27 18:03:31 +02:00
|
|
|
bindingSource = binding.source || "store";
|
2019-09-20 09:01:35 +02:00
|
|
|
} else {
|
|
|
|
bindingPath="";
|
|
|
|
bindingFallbackValue="";
|
2019-09-27 18:03:31 +02:00
|
|
|
bindingSource="store";
|
2019-09-20 09:01:35 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const clearBinding = () => {
|
|
|
|
forceIsBound = false;
|
|
|
|
onChanged("");
|
|
|
|
}
|
|
|
|
|
2019-09-27 18:03:31 +02:00
|
|
|
const bind = (path, fallback, source) => {
|
2019-09-20 09:01:35 +02:00
|
|
|
if(!path) {
|
|
|
|
clearBinding("");
|
|
|
|
return;
|
|
|
|
}
|
2019-09-27 18:03:31 +02:00
|
|
|
const binding = setBinding({path, fallback, source});
|
2019-09-20 09:01:35 +02:00
|
|
|
onChanged(binding);
|
|
|
|
}
|
|
|
|
|
|
|
|
const setBindingPath = ev => {
|
2019-09-27 18:03:31 +02:00
|
|
|
forceIsBound = canOnlyBind;
|
|
|
|
bind(ev.target.value, bindingFallbackValue, bindingSource)
|
2019-09-20 09:01:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
const setBindingFallback = ev => {
|
2019-09-27 18:03:31 +02:00
|
|
|
bind(bindingPath, ev.target.value, bindingSource);
|
2019-09-20 09:01:35 +02:00
|
|
|
}
|
|
|
|
|
2019-09-27 18:03:31 +02:00
|
|
|
const setBindingSource = ev => {
|
|
|
|
bind(bindingPath, bindingFallbackValue, ev.target.value);
|
|
|
|
}
|
2019-09-20 09:01:35 +02:00
|
|
|
|
|
|
|
const makeBinding = () => {
|
|
|
|
forceIsBound=true;
|
|
|
|
isExpanded=true;
|
|
|
|
}
|
|
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
{#if isBound}
|
|
|
|
<div>
|
|
|
|
<div class="bound-header">
|
|
|
|
<div>{isExpanded ? "" : bindingPath}</div>
|
|
|
|
<IconButton icon={isExpanded ? "chevron-up" : "chevron-down"}
|
|
|
|
size="12"
|
|
|
|
on:click={() => isExpanded=!isExpanded}/>
|
2019-09-27 18:03:31 +02:00
|
|
|
{#if !canOnlyBind}
|
2019-09-20 09:01:35 +02:00
|
|
|
<IconButton icon="trash"
|
|
|
|
size="12"
|
|
|
|
on:click={clearBinding}/>
|
2019-09-27 18:03:31 +02:00
|
|
|
{/if}
|
2019-09-20 09:01:35 +02:00
|
|
|
</div>
|
|
|
|
{#if isExpanded}
|
|
|
|
<div>
|
|
|
|
<div class="binding-prop-label">Binding Path</div>
|
|
|
|
<input class="uk-input uk-form-small"
|
|
|
|
value={bindingPath}
|
|
|
|
on:change={setBindingPath} >
|
|
|
|
<div class="binding-prop-label">Fallback Value</div>
|
|
|
|
<input class="uk-input uk-form-small"
|
|
|
|
value={bindingFallbackValue}
|
|
|
|
on:change={setBindingFallback} >
|
2019-09-27 18:03:31 +02:00
|
|
|
<div class="binding-prop-label">Binding Source</div>
|
|
|
|
<select class="uk-select uk-form-small"
|
|
|
|
value={bindingSource}
|
|
|
|
on:change={setBindingSource}>
|
|
|
|
|
|
|
|
<option>store</option>
|
|
|
|
<option>context</option>
|
|
|
|
|
|
|
|
</select>
|
2019-09-20 09:01:35 +02:00
|
|
|
</div>
|
|
|
|
{/if}
|
|
|
|
|
|
|
|
</div>
|
|
|
|
{:else}
|
|
|
|
<div class="unbound-container">
|
|
|
|
|
|
|
|
{#if type === "bool"}
|
|
|
|
|
|
|
|
<div>
|
|
|
|
<IconButton icon={value == true ? "check-square" : "square"}
|
|
|
|
size="19"
|
2019-10-18 18:32:03 +02:00
|
|
|
on:click={() => onChanged(!value)}/>
|
2019-09-20 09:01:35 +02:00
|
|
|
</div>
|
|
|
|
|
|
|
|
{:else if type === "options"}
|
|
|
|
|
|
|
|
<select class="uk-select uk-form-small"
|
|
|
|
value={value}
|
2019-10-18 18:32:03 +02:00
|
|
|
on:change={ev => onChanged(ev.target.value)}>
|
2019-09-20 09:01:35 +02:00
|
|
|
{#each options as option}
|
|
|
|
<option value={option}>{option}</option>
|
|
|
|
{/each}
|
|
|
|
</select>
|
|
|
|
|
|
|
|
{:else}
|
|
|
|
|
|
|
|
<input class="uk-input uk-form-small"
|
|
|
|
on:change={ev => onChanged(ev.target.value)}
|
|
|
|
bind:value={value}
|
|
|
|
style="flex: 1 0 auto;" >
|
|
|
|
|
|
|
|
|
|
|
|
{/if}
|
|
|
|
<IconButton icon="link"
|
|
|
|
size="12"
|
|
|
|
on:click={makeBinding} />
|
|
|
|
</div>
|
|
|
|
{/if}
|
|
|
|
|
|
|
|
|
|
|
|
<style>
|
|
|
|
|
|
|
|
.unbound-container {
|
|
|
|
display:flex;
|
2019-09-25 21:53:52 +02:00
|
|
|
margin: .5rem 0rem .5rem 0rem;
|
2019-09-20 09:01:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
.unbound-container > *:nth-child(1) {
|
|
|
|
width:auto;
|
|
|
|
flex: 1 0 auto;
|
2019-09-25 21:53:52 +02:00
|
|
|
font-size: 0.8rem;
|
|
|
|
color: var(--secondary100);
|
|
|
|
border-radius: .2rem;
|
2019-09-20 09:01:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
.bound-header {
|
|
|
|
display: flex;
|
|
|
|
}
|
|
|
|
|
|
|
|
.bound-header > div:nth-child(1) {
|
|
|
|
flex: 1 0 auto;
|
|
|
|
width: 30px;
|
2019-09-25 21:53:52 +02:00
|
|
|
color: var(--secondary50);
|
2019-09-20 09:01:35 +02:00
|
|
|
padding-left: 5px;
|
|
|
|
}
|
|
|
|
|
|
|
|
.binding-prop-label {
|
2019-09-25 21:53:52 +02:00
|
|
|
color: var(--secondary50);
|
2019-09-20 09:01:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
</style>
|