Integrating Colorpicker with Builder
This commit is contained in:
parent
dbc490994b
commit
4a00e2257f
|
@ -22,14 +22,11 @@
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
format = getColorFormat(value);
|
|
||||||
if (format) {
|
if (format) {
|
||||||
convertAndSetHSVA()
|
convertAndSetHSVA()
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const hsvaIsNull = () => [h, s, v, a].every(c => c === null);
|
|
||||||
|
|
||||||
function convertAndSetHSVA() {
|
function convertAndSetHSVA() {
|
||||||
let hsva = convertToHSVA(value, format);
|
let hsva = convertToHSVA(value, format);
|
||||||
setHSVA(hsva);
|
setHSVA(hsva);
|
||||||
|
@ -53,17 +50,16 @@
|
||||||
function setHue(hue) {
|
function setHue(hue) {
|
||||||
h = hue;
|
h = hue;
|
||||||
value = convertHsvaToFormat([h, s, v, a], format);
|
value = convertHsvaToFormat([h, s, v, a], format);
|
||||||
dispatch("change", value)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function setAlpha(alpha) {
|
function setAlpha(alpha) {
|
||||||
a = alpha === "1.00" ? "1" :alpha;
|
a = alpha === "1.00" ? "1" :alpha;
|
||||||
value = convertHsvaToFormat([h, s, v, a], format);
|
value = convertHsvaToFormat([h, s, v, a], format);
|
||||||
dispatch("change", value)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeFormatAndConvert(f) {
|
function changeFormatAndConvert(f) {
|
||||||
format = f;
|
format = f;
|
||||||
|
console.log(f)
|
||||||
value = convertHsvaToFormat([h, s, v, a], format);
|
value = convertHsvaToFormat([h, s, v, a], format);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,14 +69,16 @@
|
||||||
format = f;
|
format = f;
|
||||||
value = text
|
value = text
|
||||||
convertAndSetHSVA()
|
convertAndSetHSVA()
|
||||||
|
dispatch("change", value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.colorpicker-container {
|
.colorpicker-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
font-size: 12px;
|
font-size: 11px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: 300px;
|
height: 300px;
|
||||||
|
@ -104,7 +102,6 @@
|
||||||
grid-gap: 15px;
|
grid-gap: 15px;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
/* padding: 8px; */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.selected-color {
|
.selected-color {
|
||||||
|
|
|
@ -1,37 +1,84 @@
|
||||||
<script>
|
<script>
|
||||||
import Colorpicker from "./Colorpicker.svelte"
|
import Colorpicker from "./Colorpicker.svelte"
|
||||||
import {createEventDispatcher} from "svelte"
|
import {createEventDispatcher, afterUpdate, beforeUpdate} from "svelte"
|
||||||
import {buildStyle} from "./helpers.js"
|
import {buildStyle} from "./helpers.js"
|
||||||
import { fade } from 'svelte/transition';
|
import { fade } from 'svelte/transition';
|
||||||
|
import {getColorFormat} from "./utils.js"
|
||||||
|
|
||||||
export let value = "#3ec1d3ff"
|
export let value = "#3ec1d3ff"
|
||||||
export let format = "hexa";
|
export let open = false;
|
||||||
export let width = "25px"
|
export let width = "25px"
|
||||||
export let open = true;
|
export let height = "25px"
|
||||||
export let fullwidth = false;
|
|
||||||
|
|
||||||
|
let format = "hexa";
|
||||||
|
let dimensions = {top: 0, left: 0}
|
||||||
let colorPreview = null
|
let colorPreview = null
|
||||||
let positionSide = "top"
|
|
||||||
|
|
||||||
$: width = fullwidth ? "100%" : width
|
let previewHeight = null
|
||||||
$: style = buildStyle({width, background: value})
|
let previewWidth = null
|
||||||
$: colorStyle = buildStyle({[positionSide]: `28px`})
|
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()
|
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) {
|
function openColorpicker(event) {
|
||||||
if(colorPreview) {
|
if(colorPreview) {
|
||||||
const {top: spaceAbove, width, bottom} = colorPreview.getBoundingClientRect()
|
const {top: spaceAbove, width, bottom, right, left: spaceLeft} = colorPreview.getBoundingClientRect()
|
||||||
const spaceBelow = window.innerHeight - bottom;
|
const {innerHeight, innerWidth} = window
|
||||||
|
|
||||||
|
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}
|
||||||
|
|
||||||
if (spaceAbove > spaceBelow) {
|
|
||||||
positionSide = "bottom"
|
|
||||||
} else {
|
|
||||||
positionSide = "top"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
open = true;
|
open = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function onColorChange(color) {
|
function onColorChange(color) {
|
||||||
value = color.detail;
|
value = color.detail;
|
||||||
|
@ -40,31 +87,48 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="color-preview-container">
|
<div class="color-preview-container">
|
||||||
<div bind:this={colorPreview} class="color-preview" {style} on:click={openColorpicker}></div>
|
{#if !errorMsg}
|
||||||
|
<div bind:this={colorPreview} bind:clientHeight={previewHeight} bind:clientWidth={previewWidth} class="color-preview" style={previewStyle} on:click={openColorpicker}></div>
|
||||||
{#if open}
|
{#if open}
|
||||||
<div class="color-preview" style={colorStyle}>
|
<div class="picker-container" bind:clientHeight={pickerHeight} bind:clientWidth={pickerWidth} style={pickerStyle}>
|
||||||
<Colorpicker on:change={onColorChange} {format} {value} />
|
<Colorpicker on:change={onColorChange} {format} {value} />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
{#if open}
|
|
||||||
<div on:click|self={() => open = false} class="overlay"></div>
|
<div on:click|self={() => open = false} class="overlay"></div>
|
||||||
{/if}
|
{/if}
|
||||||
|
{:else}
|
||||||
|
<div class="color-preview preview-error" style={errorPreviewStyle}>
|
||||||
|
<span>×</span>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.color-preview-container{
|
.color-preview-container{
|
||||||
position: relative;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: row nowrap;
|
flex-flow: row nowrap;
|
||||||
height: fit-content;
|
height: fit-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
.color-preview {
|
.color-preview {
|
||||||
position: absolute;
|
|
||||||
flex: 1;
|
flex: 1;
|
||||||
height: 25px;
|
|
||||||
z-index: 2;
|
|
||||||
border-radius: 3px;
|
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{
|
.overlay{
|
||||||
|
@ -73,6 +137,7 @@
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
z-index: 1;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,2 @@
|
||||||
import Colorpreview from './Colorpreview.svelte';
|
import Colorpreview from "./Colorpreview.svelte"
|
||||||
|
export default Colorpreview
|
||||||
export default Colorpreview;
|
|
||||||
|
|
|
@ -127,9 +127,11 @@ export const rgbaToHSVA = rgba => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const hslaToHSVA = ([h, s, l, a = 1]) => {
|
export const hslaToHSVA = ([h, s, l, a = 1]) => {
|
||||||
let hsv = _hslToHSV([h, s, l]);
|
let sat = s.replace(/%/, "")
|
||||||
return [...hsv, a];
|
let lum = l.replace(/%/, "")
|
||||||
};
|
let hsv = _hslToHSV([h, sat, lum])
|
||||||
|
return [...hsv, a]
|
||||||
|
}
|
||||||
|
|
||||||
export const hsvaToHexa = (hsva, asString = false) => {
|
export const hsvaToHexa = (hsva, asString = false) => {
|
||||||
const [r, g, b, a] = hsvaToRgba(hsva);
|
const [r, g, b, a] = hsvaToRgba(hsva);
|
||||||
|
|
|
@ -102,8 +102,6 @@
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow-x: hidden;
|
|
||||||
overflow-y: hidden;
|
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
@ -121,6 +119,5 @@
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
overflow-y: auto;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
<FlatButtonGroup value={selectedCategory} {buttonProps} {onChange} />
|
<FlatButtonGroup value={selectedCategory} {buttonProps} {onChange} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="positioned-wrapper">
|
||||||
<div class="design-view-property-groups">
|
<div class="design-view-property-groups">
|
||||||
{#if propertyGroupNames.length > 0}
|
{#if propertyGroupNames.length > 0}
|
||||||
{#each propertyGroupNames as groupName}
|
{#each propertyGroupNames as groupName}
|
||||||
|
@ -49,6 +50,7 @@
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.design-view-container {
|
.design-view-container {
|
||||||
|
@ -62,10 +64,15 @@
|
||||||
flex: 0 0 50px;
|
flex: 0 0 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.positioned-wrapper{
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
min-height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.design-view-property-groups {
|
.design-view-property-groups {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overflow-x: hidden;
|
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
if (v.target) {
|
if (v.target) {
|
||||||
let val = props.valueKey ? v.target[props.valueKey] : v.target.value
|
let val = props.valueKey ? v.target[props.valueKey] : v.target.value
|
||||||
onChange(key, val)
|
onChange(key, val)
|
||||||
|
}else if(v.detail) {
|
||||||
|
onChange(key, v.detail)
|
||||||
} else {
|
} else {
|
||||||
onChange(key, v)
|
onChange(key, v)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import Input from "../common/Input.svelte"
|
||||||
import OptionSelect from "./OptionSelect.svelte"
|
import OptionSelect from "./OptionSelect.svelte"
|
||||||
import InputGroup from "../common/Inputs/InputGroup.svelte"
|
import InputGroup from "../common/Inputs/InputGroup.svelte"
|
||||||
import FlatButtonGroup from "./FlatButtonGroup.svelte"
|
import FlatButtonGroup from "./FlatButtonGroup.svelte"
|
||||||
// import Colorpicker from "../common/Colorpicker.svelte"
|
import Colorpicker from "./Colorpicker"
|
||||||
/*
|
/*
|
||||||
TODO: Allow for default values for all properties
|
TODO: Allow for default values for all properties
|
||||||
*/
|
*/
|
||||||
|
@ -256,8 +256,8 @@ export const typography = [
|
||||||
{
|
{
|
||||||
label: "Color",
|
label: "Color",
|
||||||
key: "color",
|
key: "color",
|
||||||
control: Input,
|
control: Colorpicker,
|
||||||
placeholder: "hex",
|
defaultValue: "#000",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "align",
|
label: "align",
|
||||||
|
@ -305,7 +305,8 @@ export const background = [
|
||||||
{
|
{
|
||||||
label: "Color",
|
label: "Color",
|
||||||
key: "background",
|
key: "background",
|
||||||
control: Input,
|
control: Colorpicker,
|
||||||
|
defaultValue: "#000",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Image",
|
label: "Image",
|
||||||
|
@ -347,7 +348,8 @@ export const border = [
|
||||||
{
|
{
|
||||||
label: "Color",
|
label: "Color",
|
||||||
key: "border-color",
|
key: "border-color",
|
||||||
control: Input,
|
control: Colorpicker,
|
||||||
|
defaultValue: "#000",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Style",
|
label: "Style",
|
||||||
|
|
|
@ -103,7 +103,6 @@
|
||||||
background-color: var(--white);
|
background-color: var(--white);
|
||||||
min-height: 0px;
|
min-height: 0px;
|
||||||
height: calc(100vh - 69px);
|
height: calc(100vh - 69px);
|
||||||
overflow-y: hidden;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-group-header > div:nth-child(1) {
|
.nav-group-header > div:nth-child(1) {
|
||||||
|
|
Loading…
Reference in New Issue