Swatch Panel, Logic and UI Updates

This commit is contained in:
Conor_Mack 2020-06-22 16:32:57 +01:00
parent c80f9f8819
commit a0416bd067
4 changed files with 129 additions and 37 deletions

View File

@ -6,8 +6,9 @@
export let borderRadius = "" export let borderRadius = ""
export let height = "" export let height = ""
export let width = "" export let width = ""
export let margin = ""
$: style = buildStyle({backgroundSize, borderRadius, height, width}) $: style = buildStyle({backgroundSize, borderRadius, height, width, margin})
</script> </script>
@ -19,6 +20,6 @@
} }
</style> </style>
<div transition:fade {style}> <div in:fade {style}>
<slot /> <slot />
</div> </div>

View File

@ -1,6 +1,7 @@
<script> <script>
import { onMount, createEventDispatcher } from "svelte"; import { onMount, createEventDispatcher } from "svelte";
import { fade } from 'svelte/transition'; import { fade } from 'svelte/transition';
import Swatch from "./Swatch.svelte";
import CheckedBackground from "./CheckedBackground.svelte" import CheckedBackground from "./CheckedBackground.svelte"
import {buildStyle} from "./helpers.js" import {buildStyle} from "./helpers.js"
import { import {
@ -14,13 +15,16 @@
import Input from "./Input.svelte"; import Input from "./Input.svelte";
export let value = "#3ec1d3ff"; export let value = "#3ec1d3ff";
export let swatches = [] //TODO: Safe swatches - limit to 12. warn in console
export let disableSwatches = false
export let format = "hexa"; export let format = "hexa";
export let open = false;
let recentColors = []
export let pickerHeight = 0; export let pickerHeight = 0;
export let pickerWidth = 0; export let pickerWidth = 0;
let adder = null;
let h = null; let h = null;
let s = null; let s = null;
let v = null; let v = null;
@ -29,7 +33,10 @@
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
onMount(() => { onMount(() => {
if(!swatches.length > 0) {
//Don't use locally stored recent colors if swatches have been passed as props
getRecentColors() getRecentColors()
}
if (format) { if (format) {
convertAndSetHSVA() convertAndSetHSVA()
@ -39,17 +46,17 @@
function getRecentColors() { function getRecentColors() {
let colorStore = localStorage.getItem("cp:recent-colors") let colorStore = localStorage.getItem("cp:recent-colors")
if (colorStore) { if (colorStore) {
recentColors = JSON.parse(colorStore) swatches = JSON.parse(colorStore)
} }
} }
function setRecentColor(color) { function setRecentColor(color) {
if (recentColors.length === 6) { if (swatches.length === 12) {
recentColors.splice(0, 1) swatches.splice(0, 1)
} }
if (!recentColors.includes(color)) { if (!swatches.includes(color)) {
recentColors = [...recentColors, color] swatches = [...swatches, color]
localStorage.setItem("cp:recent-colors", JSON.stringify(recentColors)) localStorage.setItem("cp:recent-colors", JSON.stringify(swatches))
} }
} }
@ -70,7 +77,6 @@
s = detail.s; s = detail.s;
v = detail.v; v = detail.v;
value = convertHsvaToFormat([h, s, v, a], format); value = convertHsvaToFormat([h, s, v, a], format);
setRecentColor(value)
dispatchValue() dispatchValue()
} }
@ -78,7 +84,6 @@
h = color; h = color;
value = convertHsvaToFormat([h, s, v, a], format); value = convertHsvaToFormat([h, s, v, a], format);
if(!isDrag) { if(!isDrag) {
setRecentColor(value)
dispatchValue() dispatchValue()
} }
} }
@ -87,7 +92,6 @@
a = color === "1.00" ? "1" : color; a = color === "1.00" ? "1" : color;
value = convertHsvaToFormat([h, s, v, a], format); value = convertHsvaToFormat([h, s, v, a], format);
if(!isDrag) { if(!isDrag) {
setRecentColor(value)
dispatchValue() dispatchValue()
} }
} }
@ -111,13 +115,26 @@
function dispatchInputChange() { function dispatchInputChange() {
if(format) { if(format) {
setRecentColor(value)
dispatchValue() dispatchValue()
} }
} }
function addSwatch() {
if(format) {
dispatch("addswatch", value)
setRecentColor(value)
}
}
function applyRecentColor(color) { function removeSwatch(idx) {
let removedSwatch = swatches.splice(idx, 1);
swatches = swatches
dispatch("removeswatch", removedSwatch)
localStorage.setItem("cp:recent-colors", JSON.stringify(swatches))
}
function applySwatch(color) {
if(value !== color) { if(value !== color) {
format = getColorFormat(color) format = getColorFormat(color)
if(format) { if(format) {
@ -127,8 +144,10 @@
} }
} }
} }
$: border = (v > 90 && s < 5) ? "1px dashed #dedada" : "" $: border = (v > 90 && s < 5) ? "1px dashed #dedada" : ""
$: style = buildStyle({background: value, border}) $: style = buildStyle({background: value, border})
$: shrink = swatches.length > 0
</script> </script>
<style> <style>
@ -173,28 +192,40 @@
border-radius: 50%; border-radius: 50%;
} }
.recent-color-panel { .swatch-panel {
flex: 0 0 15px; flex: 0 0 15px;
display: grid; display: flex;
grid-gap: 10px; flex-flow: row wrap;
justify-content: flex-start; justify-content: flex-start;
grid-auto-flow: column; padding: 0 5px;
padding: 5px; max-height: 56px;
margin-left: 6px;
} }
.recent-color { .adder {
cursor: pointer; flex: 1;
border-radius: 6px;
border: 1px solid #dedada;
height: 20px; height: 20px;
width: 20px; display: flex;
transition: flex 0.5s;
justify-content: center;
align-items: center;
background: #f1f3f4;
cursor: pointer;
border: 1px solid #d4d4d4;
border-radius: 8px;
margin-left: 5px;
margin-top: 3px;
font-weight: 500;
}
.shrink {
flex: 0 0 20px;
} }
.format-input-panel { .format-input-panel {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
padding-top: 3px;
} }
</style> </style>
@ -226,13 +257,18 @@
</div> </div>
</div> </div>
{#if recentColors.length > 0} {#if !disableSwatches}
<div transition:fade class="recent-color-panel"> <div transition:fade class="swatch-panel">
{#each recentColors as color} {#if swatches.length > 0}
<CheckedBackground borderRadius="6px"> {#each swatches as color, idx}
<div transition:fade class="recent-color" style={`background: ${color};`} on:click={() => applyRecentColor(color)} /> <Swatch {color} on:click={() => applySwatch(color)} on:removeswatch={() => removeSwatch(idx)} />
</CheckedBackground>
{/each} {/each}
{/if}
{#if swatches.length !== 12}
<div bind:this={adder} transition:fade class="adder" on:click={addSwatch} class:shrink>
<span>&plus;</span>
</div>
{/if}
</div> </div>
{/if} {/if}

View File

@ -8,6 +8,8 @@
import {getColorFormat} from "./utils.js" import {getColorFormat} from "./utils.js"
export let value = "#3ec1d3ff" export let value = "#3ec1d3ff"
export let swatches = []
export let disableSwatches = false
export let open = false; export let open = false;
export let width = "25px" export let width = "25px"
export let height = "25px" export let height = "25px"
@ -99,7 +101,7 @@
{#if open} {#if open}
<div transition:fade class="picker-container" style={pickerStyle}> <div transition:fade class="picker-container" style={pickerStyle}>
<Colorpicker on:change={onColorChange} bind:format bind:value bind:pickerHeight bind:pickerWidth /> <Colorpicker on:change={onColorChange} on:addswatch on:removeswatch bind:format bind:value bind:pickerHeight bind:pickerWidth {swatches} {disableSwatches} {open} />
</div> </div>
<div on:click|self={() => open = false} class="overlay"></div> <div on:click|self={() => open = false} class="overlay"></div>
{/if} {/if}

View File

@ -0,0 +1,53 @@
<script>
import {createEventDispatcher} from "svelte"
import { fade } from 'svelte/transition';
import CheckedBackground from "./CheckedBackground.svelte"
export let hovered = false
export let color = "#fff"
const dispatch = createEventDispatcher()
</script>
<style>
.swatch {
position: relative;
cursor: pointer;
border-radius: 6px;
border: 1px solid #dedada;
height: 20px;
width: 20px;
}
.space {
padding: 3px 5px;
}
.remove-icon {
position: absolute;
right: 0;
top: -5px;
right: -4px;
width:10px;
height: 10px;
border-radius: 50%;
background-color: #800000;
color: #fff;
display: flex;
justify-content: center;
align-items: center;
}
</style>
<div class="space">
<CheckedBackground borderRadius="6px">
<div in:fade class="swatch" style={`background: ${color};`} on:click|self on:mouseover={() => hovered = true} on:mouseleave={() => hovered = false}>
{#if hovered}
<div in:fade class="remove-icon" on:click|self={()=> dispatch("removeswatch")}>
<span on:click|self={()=> dispatch("removeswatch")}>&times;</span>
</div>
{/if}
</div>
</CheckedBackground>
</div>