Integrating Colorpicker with Builder
This commit is contained in:
parent
dbc490994b
commit
4a00e2257f
|
@ -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 {
|
||||
|
|
|
@ -1,37 +1,84 @@
|
|||
<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
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
function onColorChange(color) {
|
||||
value = color.detail;
|
||||
|
@ -40,31 +87,48 @@
|
|||
</script>
|
||||
|
||||
<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}
|
||||
<div class="color-preview" style={colorStyle}>
|
||||
<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>×</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>
|
||||
|
||||
|
|
|
@ -1,3 +1,2 @@
|
|||
import Colorpreview from './Colorpreview.svelte';
|
||||
|
||||
export default Colorpreview;
|
||||
import Colorpreview from "./Colorpreview.svelte"
|
||||
export default Colorpreview
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue