1
0
Fork 0
mirror of synced 2024-08-23 05:51:29 +12:00

Multiple improvement to option configuration

This commit is contained in:
Andrew Kingston 2024-05-21 13:59:33 +01:00
parent f30142831e
commit d9a00cc6d4

View file

@ -2,7 +2,7 @@
import { flip } from "svelte/animate"
import { dndzone } from "svelte-dnd-action"
import { Icon, Popover } from "@budibase/bbui"
import { onMount } from "svelte"
import { onMount, tick } from "svelte"
import { Constants } from "@budibase/frontend-core"
export let constraints
@ -22,13 +22,16 @@
anchors.pop(undefined)
}
const addNewInput = () => {
const newOption = `Option ${constraints.inclusion.length + 1}`
options = [...options, { name: newOption, id: Math.random() }]
constraints.inclusion = [...constraints.inclusion, newOption]
optionColors[newOption] = Constants.OptionColours[(options.length - 1) % 9]
const addNewInput = async () => {
const newName = `Option ${constraints.inclusion.length + 1}`
const id = Math.random()
options = [...options, { name: newName, id }]
constraints.inclusion = [...constraints.inclusion, newName]
optionColors[newName] = Constants.OptionColours[(options.length - 1) % 9]
colorPopovers.push(undefined)
anchors.push(undefined)
await tick()
document.getElementById(`option-${id}`)?.focus()
}
const handleDndConsider = e => {
@ -75,154 +78,101 @@
<!-- svelte-ignore a11y-no-static-element-interactions -->
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div>
<div
class="actions"
use:dndzone={{
items: options,
flipDurationMs,
dropTargetStyle: { outline: "none" },
}}
on:consider={handleDndConsider}
on:finalize={handleDndFinalize}
>
{#each options as option, idx (`${option.id}-${idx}`)}
<div
class="options"
use:dndzone={{
items: options,
flipDurationMs,
dropTargetStyle: { outline: "none" },
}}
on:consider={handleDndConsider}
on:finalize={handleDndFinalize}
>
{#each options as option, idx (`${option.id}-${idx}`)}
<div class="option" animate:flip={{ duration: flipDurationMs }}>
<div class="drag-handle">
<Icon name="DragHandle" size="L" />
</div>
<div
class="no-border action-container"
animate:flip={{ duration: flipDurationMs }}
bind:this={anchors[idx]}
class="color-picker"
on:click={e => openColorPickerPopover(idx, e.target)}
>
<div class="child drag-handle-spacing">
<Icon name="DragHandle" size="L" />
</div>
<div
bind:this={anchors[idx]}
class="child color-picker"
on:click={e => openColorPickerPopover(idx, e.target)}
class="circle"
style="--color:{optionColors?.[option.name] ||
'hsla(0, 1%, 50%, 0.3)'}"
>
<div
class="circle"
style="--color:{optionColors?.[option.name] ||
'hsla(0, 1%, 50%, 0.3)'}"
<Popover
bind:this={colorPopovers[idx]}
anchor={anchors[idx]}
align="left"
offset={0}
animate={false}
>
<Popover
bind:this={colorPopovers[idx]}
anchor={anchors[idx]}
align="left"
offset={0}
animate={false}
>
<div class="colors" data-ignore-click-outside="true">
{#each Constants.OptionColours as color}
<div
on:click={() => handleColorChange(option.name, color, idx)}
style="--color:{color};"
class="circle circle-hover"
/>
{/each}
</div>
</Popover>
</div>
</div>
<div class="child">
<input
class="input-field"
type="text"
on:change={e => handleNameChange(option.name, idx, e.target.value)}
value={option.name}
placeholder="Option name"
/>
</div>
<div class="child">
<Icon name="Close" hoverable size="S" on:click={removeInput(idx)} />
<div class="colors" data-ignore-click-outside="true">
{#each Constants.OptionColours as color}
<div
on:click={() => handleColorChange(option.name, color, idx)}
style="--color:{color};"
class="circle circle-hover"
/>
{/each}
</div>
</Popover>
</div>
</div>
{/each}
</div>
<input
class="option-name"
type="text"
on:change={e => handleNameChange(option.name, idx, e.target.value)}
value={option.name}
placeholder="Option name"
id="option-{option.id}"
/>
<Icon name="Close" hoverable size="S" on:click={removeInput(idx)} />
</div>
{/each}
<div on:click={addNewInput} class="add-option">
<Icon hoverable name="Add" />
<Icon name="Add" />
<div>Add option</div>
</div>
</div>
<style>
.action-container {
background-color: var(--spectrum-alias-background-color-primary);
border-radius: 0px;
/* Container */
.options {
overflow: hidden;
border-radius: 4px;
border: 1px solid var(--spectrum-global-color-gray-300);
background-color: var(--spectrum-global-color-gray-50);
}
.options > * {
height: 32px;
}
/* Options row */
.option {
transition: background-color 130ms ease-in-out, color 130ms ease-in-out,
border-color 130ms ease-in-out;
display: flex;
flex-direction: row;
align-items: center;
}
.no-border {
border-bottom: none;
}
.action-container:last-child {
border-bottom: 1px solid var(--spectrum-global-color-gray-300) !important;
}
.child {
height: 30px;
}
.child:hover,
.child:focus {
background: var(--spectrum-global-color-gray-200);
}
.add-option {
display: flex;
flex-direction: row;
align-items: center;
padding: var(--spacing-m);
border-bottom: 1px solid var(--spectrum-global-color-gray-300);
gap: var(--spacing-m);
cursor: pointer;
padding: 0 var(--spacing-m) 0 var(--spacing-s);
}
.option:hover,
.option:focus {
background: var(--spectrum-global-color-gray-100);
}
.input-field {
border: none;
outline: none;
background-color: transparent;
width: 100%;
color: var(--text);
/* Option row components */
.color-picker {
align-self: stretch;
display: grid;
place-items: center;
}
.child input[type="text"] {
padding-left: 10px;
}
.input-field:hover,
.input-field:focus {
background: var(--spectrum-global-color-gray-200);
}
.action-container > :nth-child(1) {
flex-grow: 1;
justify-content: center;
display: flex;
}
.action-container > :nth-child(2) {
flex-grow: 1;
display: flex;
justify-content: center;
align-items: center;
}
.action-container > :nth-child(3) {
flex-grow: 4;
display: flex;
}
.action-container > :nth-child(4) {
flex-grow: 1;
justify-content: center;
display: flex;
}
.color-picker:hover {
cursor: pointer;
}
.circle {
height: 20px;
width: 20px;
@ -230,18 +180,39 @@
border-radius: 50%;
display: inline-block;
box-sizing: border-box;
border: 1px solid transparent;
transition: border 130ms ease-out;
}
.circle-hover:hover {
border: 1px solid var(--spectrum-global-color-blue-400);
.circle:hover {
border: 1px solid var(--spectrum-global-color-blue-600);
cursor: pointer;
}
.colors {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-columns: 1fr 1fr 1fr 1fr;
gap: var(--spacing-xl);
justify-items: center;
margin: var(--spacing-m);
}
.option-name {
border: none;
outline: none;
background-color: transparent;
width: 100%;
color: var(--text);
}
/* Add option */
.add-option {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
padding: var(--spacing-m);
gap: var(--spacing-m);
}
.add-option:hover {
cursor: pointer !important;
background: var(--spectrum-global-color-gray-200);
}
</style>