Integrating Colorpicker with Builder

This commit is contained in:
Conor_Mack 2020-06-17 16:46:03 +01:00
parent ab15bd479c
commit ab5b7ccb39
9 changed files with 121 additions and 51 deletions

View File

@ -22,14 +22,11 @@
const dispatch = createEventDispatcher();
onMount(() => {
format = getColorFormat(value);
if (format) {
convertAndSetHSVA()
}
});
const hsvaIsNull = () => [h, s, v, a].every(c => c === null);
function convertAndSetHSVA() {
let hsva = convertToHSVA(value, format);
setHSVA(hsva);
@ -53,17 +50,16 @@
function setHue(hue) {
h = hue;
value = convertHsvaToFormat([h, s, v, a], format);
dispatch("change", value)
}
function setAlpha(alpha) {
a = alpha === "1.00" ? "1" :alpha;
value = convertHsvaToFormat([h, s, v, a], format);
dispatch("change", value)
}
function changeFormatAndConvert(f) {
format = f;
console.log(f)
value = convertHsvaToFormat([h, s, v, a], format);
}
@ -73,14 +69,16 @@
format = f;
value = text
convertAndSetHSVA()
dispatch("change", value)
}
}
</script>
<style>
.colorpicker-container {
display: flex;
font-size: 12px;
font-size: 11px;
font-weight: 400;
flex-direction: column;
height: 300px;
@ -104,7 +102,6 @@
grid-gap: 15px;
justify-content: center;
align-items: center;
/* padding: 8px; */
}
.selected-color {

View File

@ -1,36 +1,83 @@
<script>
import Colorpicker from "./Colorpicker.svelte"
import {createEventDispatcher} from "svelte"
import {createEventDispatcher, afterUpdate, beforeUpdate} from "svelte"
import {buildStyle} from "./helpers.js"
import { fade } from 'svelte/transition';
import {getColorFormat} from "./utils.js"
export let value = "#3ec1d3ff"
export let format = "hexa";
export let open = false;
export let width = "25px"
export let open = true;
export let fullwidth = false;
export let height = "25px"
let format = "hexa";
let dimensions = {top: 0, left: 0}
let colorPreview = null
let positionSide = "top"
$: width = fullwidth ? "100%" : width
$: style = buildStyle({width, background: value})
$: colorStyle = buildStyle({[positionSide]: `28px`})
let previewHeight = null
let previewWidth = null
let pickerWidth = 250
let pickerHeight = 300
let anchorEl = null
let parentNodes = [];
let errorMsg = null
$: previewStyle = buildStyle({width, height, background: value})
$: errorPreviewStyle = buildStyle({width, height})
$: pickerStyle = buildStyle({top: `${dimensions.top}px`, left: `${dimensions.left}px`})
const dispatch = createEventDispatcher()
beforeUpdate(() => {
format = getColorFormat(value)
if(!format) {
errorMsg = `Colorpicker - ${value} is an unknown color format. Please use a hex, rgb or hsl value`
console.error(errorMsg)
}else{
errorMsg = null
}
})
afterUpdate(() => {
if(colorPreview && colorPreview.offsetParent && !anchorEl) {
//Anchor relative to closest positioned ancestor element. If none, then anchor to body
anchorEl = colorPreview.offsetParent
let curEl = colorPreview
let els = []
//Travel up dom tree from preview element to find parent elements that scroll
while(!anchorEl.isSameNode(curEl)) {
curEl = curEl.parentNode
let elOverflow = window.getComputedStyle(curEl).getPropertyValue("overflow")
if(/scroll|auto/.test(elOverflow)) {
els.push(curEl)
}
}
parentNodes = els
}
})
function openColorpicker(event) {
if(colorPreview) {
const {top: spaceAbove, width, bottom} = colorPreview.getBoundingClientRect()
const spaceBelow = window.innerHeight - bottom;
const {top: spaceAbove, width, bottom, right, left: spaceLeft} = colorPreview.getBoundingClientRect()
const {innerHeight, innerWidth} = window
if (spaceAbove > spaceBelow) {
positionSide = "bottom"
} else {
positionSide = "top"
}
const {offsetLeft, offsetTop} = colorPreview
//get the scrollTop value for all scrollable parent elements
let scrollTop = parentNodes.reduce((scrollAcc, el) => scrollAcc += el.scrollTop, 0);
const spaceBelow = (innerHeight - spaceAbove) - previewHeight
const top = spaceAbove > spaceBelow ? (offsetTop - pickerHeight) - scrollTop : (offsetTop + previewHeight) - scrollTop
//TOO: Testing and Scroll Awareness for x Scroll
const spaceRight = (innerWidth - spaceLeft) + previewWidth
const left = spaceRight > spaceLeft ? (offsetLeft + previewWidth) + pickerWidth : offsetLeft - pickerWidth
dimensions = {top, left}
open = true;
}
open = true;
}
function onColorChange(color) {
@ -40,31 +87,48 @@
</script>
<div class="color-preview-container">
<div bind:this={colorPreview} class="color-preview" {style} on:click={openColorpicker}></div>
{#if open}
<div class="color-preview" style={colorStyle}>
{#if !errorMsg}
<div bind:this={colorPreview} bind:clientHeight={previewHeight} bind:clientWidth={previewWidth} class="color-preview" style={previewStyle} on:click={openColorpicker}></div>
{#if open}
<div class="picker-container" bind:clientHeight={pickerHeight} bind:clientWidth={pickerWidth} style={pickerStyle}>
<Colorpicker on:change={onColorChange} {format} {value} />
</div>
<div on:click|self={() => open = false} class="overlay"></div>
{/if}
{:else}
<div class="color-preview preview-error" style={errorPreviewStyle}>
<span>&times;</span>
</div>
{/if}
</div>
{#if open}
<div on:click|self={() => open = false} class="overlay"></div>
{/if}
<style>
.color-preview-container{
position: relative;
display: flex;
flex-flow: row nowrap;
height: fit-content;
}
.color-preview {
position: absolute;
flex: 1;
height: 25px;
z-index: 2;
border-radius: 3px;
border: 1px solid #dedada;
}
.preview-error {
background: #cccccc;
color: #808080;
text-align: center;
font-size: 18px;
cursor: not-allowed;
}
.picker-container {
position: absolute;
z-index: 3;
width: fit-content;
height: fit-content;
}
.overlay{
@ -73,6 +137,7 @@
bottom: 0;
left: 0;
right: 0;
z-index: 1;
z-index: 2;
}
</style>
</style>

View File

@ -1,3 +1,2 @@
import Colorpreview from './Colorpreview.svelte';
export default Colorpreview;
import Colorpreview from "./Colorpreview.svelte"
export default Colorpreview

View File

@ -127,9 +127,11 @@ export const rgbaToHSVA = rgba => {
};
export const hslaToHSVA = ([h, s, l, a = 1]) => {
let hsv = _hslToHSV([h, s, l]);
return [...hsv, a];
};
let sat = s.replace(/%/, "")
let lum = l.replace(/%/, "")
let hsv = _hslToHSV([h, sat, lum])
return [...hsv, a]
}
export const hsvaToHexa = (hsva, asString = false) => {
const [r, g, b, a] = hsvaToRgba(hsva);

View File

@ -102,8 +102,6 @@
height: 100%;
display: flex;
flex-direction: column;
overflow-x: hidden;
overflow-y: hidden;
padding: 20px;
box-sizing: border-box;
}
@ -121,6 +119,5 @@
margin-top: 20px;
flex: 1 1 auto;
min-height: 0;
overflow-y: auto;
}
</style>

View File

@ -31,6 +31,7 @@
<FlatButtonGroup value={selectedCategory} {buttonProps} {onChange} />
</div>
<div class="positioned-wrapper">
<div class="design-view-property-groups">
{#if propertyGroupNames.length > 0}
{#each propertyGroupNames as groupName}
@ -49,6 +50,7 @@
{/if}
</div>
</div>
</div>
<style>
.design-view-container {
@ -62,10 +64,15 @@
flex: 0 0 50px;
}
.positioned-wrapper{
position: relative;
display: flex;
min-height: 0;
}
.design-view-property-groups {
flex: 1;
overflow-y: auto;
overflow-x: hidden;
min-height: 0;
}

View File

@ -12,6 +12,8 @@
if (v.target) {
let val = props.valueKey ? v.target[props.valueKey] : v.target.value
onChange(key, val)
}else if(v.detail) {
onChange(key, v.detail)
} else {
onChange(key, v)
}

View File

@ -2,7 +2,7 @@ import Input from "../common/Input.svelte"
import OptionSelect from "./OptionSelect.svelte"
import InputGroup from "../common/Inputs/InputGroup.svelte"
import FlatButtonGroup from "./FlatButtonGroup.svelte"
// import Colorpicker from "../common/Colorpicker.svelte"
import Colorpicker from "./Colorpicker"
/*
TODO: Allow for default values for all properties
*/
@ -256,8 +256,8 @@ export const typography = [
{
label: "Color",
key: "color",
control: Input,
placeholder: "hex",
control: Colorpicker,
defaultValue: "#000",
},
{
label: "align",
@ -305,7 +305,8 @@ export const background = [
{
label: "Color",
key: "background",
control: Input,
control: Colorpicker,
defaultValue: "#000",
},
{
label: "Image",
@ -347,7 +348,8 @@ export const border = [
{
label: "Color",
key: "border-color",
control: Input,
control: Colorpicker,
defaultValue: "#000",
},
{
label: "Style",

View File

@ -103,7 +103,6 @@
background-color: var(--white);
min-height: 0px;
height: calc(100vh - 69px);
overflow-y: hidden;
}
.nav-group-header > div:nth-child(1) {