Stable property panel
This commit is contained in:
parent
12ef145973
commit
a4c65eb803
|
@ -79,7 +79,8 @@
|
|||
"rollup-plugin-svelte": "^5.0.3",
|
||||
"rollup-plugin-terser": "^4.0.4",
|
||||
"rollup-plugin-url": "^2.2.2",
|
||||
"svelte": "^3.0.0"
|
||||
"svelte": "^3.0.0",
|
||||
"svelte-color-picker": "^1.0.7"
|
||||
},
|
||||
"gitHead": "115189f72a850bfb52b65ec61d932531bf327072"
|
||||
}
|
||||
|
|
|
@ -121,7 +121,9 @@ export const generate_css = style => {
|
|||
return (str += `${key}: ${value};\n`)
|
||||
}
|
||||
} else if (Array.isArray(value)) {
|
||||
return (str += `${key}: ${value.map(v => `${v}px`).join(" ")};\n`)
|
||||
return (str += `${key}: ${value
|
||||
.map(v => (!/px$/.test(v) ? `${v}px` : v))
|
||||
.join(" ")};\n`)
|
||||
}
|
||||
}, "")
|
||||
|
||||
|
|
|
@ -1,13 +1,78 @@
|
|||
<script>
|
||||
import { onMount, beforeUpdate, afterUpdate } from "svelte"
|
||||
import { onMount } from "svelte"
|
||||
import { HsvPicker } from "svelte-color-picker"
|
||||
|
||||
export let value = null
|
||||
export let onChange = () => {}
|
||||
export let swatches = []
|
||||
// export let initialValue = "#ffffff"
|
||||
export let onChange = color => {}
|
||||
export let open = false
|
||||
let value = "#ffffff"
|
||||
|
||||
let picker
|
||||
let cp = null
|
||||
let _justMounted = true //see onColorChange
|
||||
let pickerHeight = 275
|
||||
let colorPreview
|
||||
let pickerTopPosition = null
|
||||
|
||||
function rbgaToHexa({ r, g, b, a }) {
|
||||
r = r.toString(16)
|
||||
g = g.toString(16)
|
||||
b = b.toString(16)
|
||||
a = Math.round(a * 255).toString(16)
|
||||
|
||||
if (r.length == 1) r = "0" + r
|
||||
if (g.length == 1) g = "0" + g
|
||||
if (b.length == 1) b = "0" + b
|
||||
if (a.length == 1) a = "0" + a
|
||||
|
||||
return "#" + r + g + b + a
|
||||
}
|
||||
|
||||
function onColourChange(rgba) {
|
||||
value = rbgaToHexa(rgba.detail)
|
||||
|
||||
//Hack: so that color change doesn't fire onMount
|
||||
if (!_justMounted) {
|
||||
// onChange(value)
|
||||
}
|
||||
_justMounted = false
|
||||
}
|
||||
|
||||
function toggleColorpicker(isOpen) {
|
||||
if (isOpen) {
|
||||
const {
|
||||
y: previewYPosition,
|
||||
height: previewHeight,
|
||||
} = colorPreview.getBoundingClientRect()
|
||||
|
||||
let wiggleRoom = window.innerHeight - previewYPosition
|
||||
let displayTop = wiggleRoom < pickerHeight
|
||||
|
||||
if (displayTop) {
|
||||
pickerTopPosition = previewYPosition - (pickerHeight - window.scrollY)
|
||||
} else {
|
||||
pickerTopPosition = null
|
||||
}
|
||||
}
|
||||
open = isOpen
|
||||
}
|
||||
|
||||
$: style = open ? "display: block;" : "display: none;"
|
||||
$: pickerStyle = pickerTopPosition ? `top: ${pickerTopPosition}px;` : ""
|
||||
</script>
|
||||
|
||||
<div
|
||||
bind:this={colorPreview}
|
||||
on:click={() => toggleColorpicker(true)}
|
||||
class="color-preview"
|
||||
style={`background: ${value}`} />
|
||||
|
||||
<div class="colorpicker" {style}>
|
||||
<div class="overlay" on:click|self={() => toggleColorpicker(false)} />
|
||||
<div class="cp" style={pickerStyle}>
|
||||
<HsvPicker on:colorChange={onColourChange} startColor={value} />
|
||||
</div>
|
||||
</div>
|
||||
<!--
|
||||
OLD LOCAL STORAGE OPTIONS. INCLUDING FOR ADDING LATER
|
||||
function getRecentColors() {
|
||||
let colorStore = localStorage.getItem("bb:recentColors")
|
||||
if (!!colorStore) {
|
||||
|
@ -25,44 +90,27 @@
|
|||
picker.addSwatch(color)
|
||||
localStorage.setItem("bb:recentColors", JSON.stringify(swatches))
|
||||
}
|
||||
} -->
|
||||
|
||||
<style>
|
||||
.overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
/* background: rgba(5, 5, 5, 0.25); */
|
||||
}
|
||||
|
||||
function createPicker() {
|
||||
picker = Pickr.create({
|
||||
el: cp,
|
||||
theme: "nano",
|
||||
default: value || "#000000",
|
||||
|
||||
swatches,
|
||||
closeWithKey: "Escape",
|
||||
|
||||
components: {
|
||||
preview: true,
|
||||
opacity: true,
|
||||
hue: true,
|
||||
|
||||
interaction: {
|
||||
hex: true,
|
||||
rgba: true,
|
||||
input: true,
|
||||
save: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
.cp {
|
||||
position: absolute;
|
||||
right: 25px;
|
||||
}
|
||||
|
||||
afterUpdate(() => {
|
||||
picker.setColor(value)
|
||||
})
|
||||
|
||||
onMount(() => {
|
||||
getRecentColors()
|
||||
createPicker()
|
||||
return () => {
|
||||
picker.destroyAndRemove()
|
||||
picker = null
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<div bind:this={cp} class="color-picker" />
|
||||
.color-preview {
|
||||
height: 30px;
|
||||
width: 100%;
|
||||
margin: 5px;
|
||||
cursor: pointer;
|
||||
border: 1px solid gainsboro;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -3,13 +3,15 @@
|
|||
|
||||
export let meta = []
|
||||
export let label = ""
|
||||
export let values = []
|
||||
export let value = [0, 0, 0, 0]
|
||||
export let type = "number"
|
||||
export let onChange = () => {}
|
||||
|
||||
let _values = values.map(v => v)
|
||||
|
||||
// $: onChange(_values)
|
||||
function handleChange(val, idx) {
|
||||
value.splice(idx, 1, val)
|
||||
value = value
|
||||
onChange(value)
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="input-container">
|
||||
|
@ -19,8 +21,8 @@
|
|||
<input
|
||||
{type}
|
||||
placeholder={placeholder || ''}
|
||||
value={values[i]}
|
||||
on:input={e => (_values[i] = e.target.value)} />
|
||||
value={value[i] === 0 ? '' : value[i]}
|
||||
on:change={e => handleChange(e.target.value || 0, i)} />
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -36,8 +38,6 @@
|
|||
|
||||
.inputs {
|
||||
flex: 1;
|
||||
/* display: flex;
|
||||
justify-content: space-between; */
|
||||
}
|
||||
|
||||
input {
|
||||
|
|
|
@ -4,21 +4,22 @@
|
|||
export let label = ""
|
||||
export let control = null
|
||||
export let key = ""
|
||||
export let value = ""
|
||||
export let value
|
||||
export let props = {}
|
||||
export let onChange = () => {}
|
||||
|
||||
function handleChange(key, v) {
|
||||
if (v.target) {
|
||||
let val = props.valueType ? v.target[props.valueType] : v.target.value
|
||||
let val = props.valueKey ? v.target[props.valueKey] : v.target.value
|
||||
onChange(key, val)
|
||||
} else {
|
||||
onChange(key, v)
|
||||
}
|
||||
}
|
||||
|
||||
const handleValueType = value =>
|
||||
props.valueType ? { [props.valueType]: value } : { value }
|
||||
//Incase the component has a different value key name
|
||||
const handlevalueKey = value =>
|
||||
props.valueKey ? { [props.valueKey]: value } : { value }
|
||||
</script>
|
||||
|
||||
<div class="property-control">
|
||||
|
@ -26,7 +27,7 @@
|
|||
<div class="control">
|
||||
<svelte:component
|
||||
this={control}
|
||||
{...handleValueType(value)}
|
||||
{...handlevalueKey(value)}
|
||||
on:change={val => handleChange(key, val)}
|
||||
onChange={val => handleChange(key, val)}
|
||||
{...props} />
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<script>
|
||||
import PropertyControl from "./PropertyControl.svelte"
|
||||
import InputGroup from "../common/Inputs/InputGroup.svelte"
|
||||
import Colorpicker from "../common/Colorpicker.svelte"
|
||||
import { excludeProps } from "./propertyCategories.js"
|
||||
|
||||
export let panelDefinition = []
|
||||
|
@ -15,6 +16,8 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<Colorpicker />
|
||||
|
||||
{#if panelDefinition.length > 0}
|
||||
{#each panelDefinition as definition}
|
||||
{#if propExistsOnComponentDef(definition.key)}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import Input from "../common/Input.svelte"
|
||||
import OptionSelect from "./OptionSelect.svelte"
|
||||
import InputGroup from "../common/Inputs/InputGroup.svelte"
|
||||
import Colorpicker from "../common/Colorpicker.svelte"
|
||||
/*
|
||||
TODO: Allow for default values for all properties
|
||||
*/
|
||||
|
@ -101,8 +102,7 @@ export const typography = [
|
|||
{
|
||||
label: "Color",
|
||||
key: "color",
|
||||
control: OptionSelect,
|
||||
options: ["black", "red", "white", "blue", "green"],
|
||||
control: Colorpicker,
|
||||
},
|
||||
{
|
||||
label: "align",
|
||||
|
@ -118,14 +118,7 @@ export const background = [
|
|||
{
|
||||
label: "Background",
|
||||
key: "background",
|
||||
control: OptionSelect,
|
||||
options: [
|
||||
{ label: "white" },
|
||||
{ label: "red" },
|
||||
{ label: "blue" },
|
||||
{ label: "green" },
|
||||
{ label: "black" },
|
||||
],
|
||||
control: Colorpicker,
|
||||
},
|
||||
{ label: "Image", key: "image", control: Input }, //custom
|
||||
]
|
||||
|
@ -133,7 +126,7 @@ export const background = [
|
|||
export const border = [
|
||||
{ label: "Radius", key: "border-radius", control: Input },
|
||||
{ label: "Width", key: "border-width", control: Input }, //custom
|
||||
{ label: "Color", key: "border-color", control: Input },
|
||||
{ label: "Color", key: "border-color", control: Colorpicker },
|
||||
{ label: "Style", key: "border-style", control: Input },
|
||||
]
|
||||
|
||||
|
|
|
@ -189,7 +189,7 @@ export default {
|
|||
{
|
||||
label: "Disabled",
|
||||
key: "disabled",
|
||||
valueType: "checked",
|
||||
valueKey: "checked",
|
||||
control: Checkbox,
|
||||
},
|
||||
]
|
||||
|
@ -219,7 +219,7 @@ export default {
|
|||
{
|
||||
label: "Open New Tab",
|
||||
key: "openInNewTab",
|
||||
valueType: "checked",
|
||||
valueKey: "checked",
|
||||
control: Checkbox,
|
||||
},
|
||||
],
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -17,12 +17,10 @@
|
|||
|
||||
<button
|
||||
bind:this={theButton}
|
||||
class="{className}
|
||||
class={className}
|
||||
disabled={disabled || false}
|
||||
on:click={clickHandler}>
|
||||
{#if !_bb.props._children || _bb.props._children.length === 0}
|
||||
{text}
|
||||
{/if}
|
||||
{#if !_bb.props._children || _bb.props._children.length === 0}{text}{/if}
|
||||
</button>
|
||||
|
||||
<style>
|
||||
|
|
Loading…
Reference in New Issue