添加拾色器组件

This commit is contained in:
KeiferJu 2020-05-21 13:32:03 +08:00
parent a9407b257d
commit c308a83a1b
14 changed files with 923 additions and 28 deletions

View File

@ -0,0 +1,60 @@
<script context="module">
export async function preload() {
const res = await this.fetch(`components/colorPicker.json`);
const jsdoc = await res.json();
return { jsdoc };
}
</script>
<script>
import {
ColorPicker
} from 'svelma-pro'
import DocHeader from '../../components/DocHeader.svelte'
import Example from '../../components/Example.svelte'
import JSDoc from '../../components/JSDoc.svelte'
export let jsdoc
let color = "#1ec131";
function change(e) {
console.log(e.detail)
}
</script>
<DocHeader title="ColorPicker" subtitle="拾色器" />
<Example code={`<script>
import { ColorPicker } from 'svelma-pro'
let color = "#1ec131";
function change(e){
console.log(e.detail)
}
</script>
<ColorPicker {color} on:change={change} />
`}>
<div slot="preview">
<ColorPicker {color} on:change={change} />
</div>
</Example>
<hr class="is-medium" />
<p class="title is-4">面板模式</p>
<Example code={`<script>
import { ColorPicker } from 'svelma-pro'
let color = "#1ec131";
</script>
<ColorPicker {color} on:change={change} mode="2"/>
`}>
<div slot="preview">
<ColorPicker {color} mode="2"/>
</div>
</Example>
<JSDoc {jsdoc} showEvent="true"></JSDoc>

View File

@ -2330,5 +2330,45 @@
"defaultvalue": "center",
"name": "navPosition",
"values": "center,start,end"
}]
}],
"ColorPicker": [
{
"description": "初始化色值,支持hex,rgba,hsla格式色值",
"type": [
"String"
],
"defaultvalue":"#1ec131",
"name": "color",
"values": "hex,rgba,hsla"
},{
"description": "显示模式,模式1表示按钮模式,2表示面板模式",
"type": [
"Number"
],
"defaultvalue":"1",
"name": "mode",
"values": "1,2"
},{
"description": "按钮模式下宽度",
"type": [
"String"
],
"defaultvalue":"200px",
"name": "width",
"values": ""
},{
"description": "色值类别,0:hex,1:rgba,2:hsla",
"type": [
"Number"
],
"defaultvalue":"0",
"name": "fieldsIndex",
"values": "0,1,2"
},{
"isEvent": true,
"description": "选择改变事件",
"name": "change",
"values": ""
}
]
}

View File

@ -99,6 +99,7 @@ module.export = {
<!-- main.js或者client.js全局引入 -->
<script>
import 'bulma/css/bulma.css'
import 'svelma-pro/svelma-pro.css'
</script>
`}>
</Codeview>

29
package-lock.json generated
View File

@ -1,6 +1,6 @@
{
"name": "svelma-pro",
"version": "1.0.6",
"version": "1.1.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@ -1953,14 +1953,6 @@
}
}
},
"dom7": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/dom7/-/dom7-2.1.3.tgz",
"integrity": "sha512-QTxHHDox+M6ZFz1zHPAHZKI3JOHY5iY4i9BK2uctlggxKQwRhO3q3HHFq1BKsT25Bm/ySSj70K6Wk/G4bs9rMQ==",
"requires": {
"ssr-window": "^1.0.1"
}
},
"dot-prop": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-3.0.0.tgz",
@ -10385,11 +10377,6 @@
"tweetnacl": "~0.14.0"
}
},
"ssr-window": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/ssr-window/-/ssr-window-1.0.1.tgz",
"integrity": "sha512-dgFqB+f00LJTEgb6UXhx0h+SrG50LJvti2yMKMqAgzfUmUXZrLSv2fjULF7AWGwK25EXu8+smLR3jYsJQChPsg=="
},
"standard-version": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/standard-version/-/standard-version-6.0.1.tgz",
@ -10815,15 +10802,6 @@
"strip-indent": "^2.0.0"
}
},
"swiper": {
"version": "5.3.8",
"resolved": "https://registry.npmjs.org/swiper/-/swiper-5.3.8.tgz",
"integrity": "sha512-bCxrayTgzC2bZBRuFwAx7T4exWeHqMADBpcuTQ7PNCOIIzJRPqNh4ySIvW06LEEU3Q0KncaNre4hrn+jXcWivQ==",
"requires": {
"dom7": "^2.1.3",
"ssr-window": "^1.0.1"
}
},
"tar": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz",
@ -10893,6 +10871,11 @@
"readable-stream": "2 || 3"
}
},
"tinycolor2": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.1.tgz",
"integrity": "sha1-9PrTM0R7wLB9TcjpIJ2POaisd+g="
},
"tinydate": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/tinydate/-/tinydate-1.0.1.tgz",

View File

@ -2,7 +2,7 @@
"name": "svelma-pro",
"svelte": "src/index.js",
"description": "Based on svelma project extension and modification",
"version": "1.0.9",
"version": "1.1.0",
"author": "KeiferJu",
"license": "MIT",
"keywords": [
@ -27,7 +27,8 @@
"src"
],
"peerDependencies": {
"bulma": "^0.8.0"
"bulma": "^0.8.0",
"tinycolor2": "^1.4.1"
},
"devDependencies": {
"autoprefixer": "^9.6.0",

View File

@ -0,0 +1,41 @@
<style>
.alpha{
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAJUlEQVQoU2N88eLFfwY0ICEhwYguxjgUFKI7GsTH5m4M3w1ChQCnziae7MntdQAAAABJRU5ErkJggg==);
background-repeat: repeat;
}
.alpha-in{
width: 100%;
height: 100%;
}
.horizontal{
background-size: auto 100%;
width: 100%;
}
.vertical{
background-size: 100% auto;
height: 100%;
}
</style>
<script>
import Slider from "./Slider.svelte";
let className = "";
export {className as class};
export let a = 1;
export let vertical = false;
export let color = "#fff" // style like string
$: toGradient = vertical ? "bottom" : "right";
//$: style = `background: linear-gradient(to ${vertical ? "bottom" : "right"}, transparent 0%, ${color} 100%)`;
</script>
<div class="alpha {className}" class:vertical class:horizontal={!vertical}>
<div class="alpha-in" style="background: linear-gradient(to {toGradient}, transparent 0%, {color} 100%)">
<Slider bind:value={a} {vertical} on:input on:input={(event) => console.log(event.detail)} />
</div>
</div>

View File

@ -0,0 +1,380 @@
<svelte:options accessors={true} />
<style>
.color-picker{
display: flex;
flex-direction: column;
width: 14.5em;
box-shadow: 0 0 2px rgba(0,0,0,.3), 0 4px 8px rgba(0,0,0,.3);
background: #fff;
}
.color-picker :global(.saturation-value){
height: 9em; /* 14.5 / 1.618 */
}
.sliders-and-square{
display: flex;
flex-direction: row;
margin-top: 1em;
}
.square-wrap{
width: 2em;
height: 2em;
border-radius: 1.5em;
margin: auto 1.25em auto 0.75em;
flex: none;
overflow: hidden;
}
.sliders{
display: flex;
flex-direction: column;
flex: 1;
margin: auto 1em auto 0;
}
.alpha-wrap{
margin-top: 0.75em;
}
.inputs-and-changer{
display: flex;
flex-direction: row;
padding: 1em 0.5em;
}
.changer-wrap{
box-sizing: border-box;
width: 2em;
flex: none;
margin: auto;
padding-left: 0.5em;
}
.changer-up, .changer-down{
margin: auto;
cursor: pointer;
}
.changer-up {
width: 0;
height: 0;
border-left: 0.5em solid transparent;
border-right: 0.5em solid transparent;
border-bottom: 0.5em solid #666;
}
.changer-down {
width: 0;
height: 0;
border-left: 0.5em solid transparent;
border-right: 0.5em solid transparent;
border-top: 0.5em solid #666;
margin-top: 0.5em;
}
.inputs-wrap{
flex: 1;
}
input{
text-align: center;
outline: 0;
box-shadow: none;
font-family: inherit;
font-size: 0.7em;
display: block;
width: auto;
border: #ddd 1px solid;
border-radius: 0.1em;
padding: 0.25em 0;
}
.hex{
width: 100%;
margin: auto;
}
.rgba-wrap, .hsla-wrap{
display: flex;
}
.rgba-wrap > div:not(:first-child),
.hsla-wrap > div:not(:first-child){
margin-left: 0.5em;
}
.rgba-wrap input,
.hsla-wrap input{
width: 100%;
}
.percent-input{
position: relative;
}
.percent-input:after{
content: "%";
display: block;
position: absolute;
top: 50%;
transform: translate(-50%);
right: 0.25em;
}
label{
display: block;
text-transform: uppercase;
text-align: center;
margin-top: 0.5em;
font-size: 0.8em;
color: #666;
}
</style>
<script>
import {createEventDispatcher} from "svelte";
const dispatch = createEventDispatcher();
// input
import tinycolor from "tinycolor2";
import {getValidColor} from "./utils.js"
import SaturationValue from "./SaturationValue.svelte";
import Alpha from "./Alpha.svelte"
import Hue from "./Hue.svelte";
import ColorSquare from "./ColorSquare.svelte";
// RED
export let h = 0;
export let s = 1;
export let v = 1;
export let l = 0.5;
export let r = 255;
export let g = 0;
export let b = 0;
export let hex = "#ff0000";
export let a = 1;
export let color;
$: color = {r, g, b, h, s, l, v, a, hex};
export let startColor = "#ff0000"; // all tinycolor colors
export let disableAlpha = false;
export let fieldsIndex = 0;
export const setColor = (args) => update(args, false);
const update = (args, dispatch=true) => {
// is not enough with color.isValidColor
const color = getValidColor(args);
if(!color) return;
const format = color.getFormat();
// we dont use hex8
(format === "hex" || format === "hex8") && color.setAlpha(a);
const _rgba = color.toRgb();
const _hsla = color.toHsl();
const _hsva = color.toHsv();
const _hex = `#${color.toHex()}`;
r = args.r != null ? args.r : _rgba.r;
g = args.g != null ? args.g : _rgba.g;
b = args.b != null ? args.b : _rgba.b;
h = args.h != null ? args.h : _hsla.h;
s = args.s != null ? args.s : _hsla.s;
l = args.l != null ? args.l : _hsla.l;
v = args.v != null ? args.v : _hsva.v;
a = args.a != null ? args.a : _rgba.a;
hex = format === "hex" ? args : _hex;
dispatch && dispatchInput();
}
const updateAlpha = (alpha) => {
if(isNaN(alpha) || alpha < 0 || alpha > 1)
return;
a = alpha;
dispatchInput()
}
const dispatchInput = () =>{
const value = getcolorValue();
dispatch("input", value)
} ;
const onlyChars = (chars) => (event) => chars.indexOf(String.fromCharCode(event.charCode)) === -1 && event.preventDefault();
const onlyNumbers = onlyChars("0123456789");
const onlyNumbersAndDot = onlyChars("0123456789.");
update(startColor, false);
function getcolorValue(){
switch(fieldsIndex){
case 1:
const rgba = `rgba(${color.r},${color.g},${color.b},${color.a})`;
return rgba;
break;
case 2:
const hsla = `hsla(${Math.round(color.h) % 360},${Math.round(color.s * 100)}%,${Math.round(color.l * 100)}%,${Math.round(color.a * 100) / 100})`;
return hsla;
break;
default:
const hex = color.hex;
return hex;
}
}
</script>
<div class="color-picker">
<div class="saturation-value-wrap">
<SaturationValue {h} {s} {v} on:input={(event) => update({h, s: event.detail.s, v: event.detail.v, a})} />
</div>
<div class="sliders-and-square">
<div class="square-wrap">
<ColorSquare color="rgba({r}, {g}, {b}, {a})"/>
</div>
<div class="sliders">
<div class="hue-wrap">
<Hue {h} on:input={event => update({h: event.detail, s, v, a})} />
</div>
{#if !disableAlpha}
<div class="alpha-wrap">
<Alpha bind:a color={hex} on:input={dispatchInput}/>
</div>
{/if}
</div>
</div>
<div class="inputs-and-changer">
<div class="inputs-wrap">
{#if fieldsIndex === 0}
<div class="input-wrap hex-wrap">
<input
class="hex"
type="text"
value={hex}
maxlength={7}
on:keypress={onlyChars("#0123456789abcdefABCFDEF")}
on:input={event => update(event.target.value)}
/>
<label>hex</label>
</div>
{:else if fieldsIndex === 1}
<div class="rgba-wrap">
<div class="input-wrap">
<input
class="rgba"
type="text"
value={r}
maxlength={3}
on:keypress={onlyNumbers}
on:input={event => update({r: parseInt(event.target.value), g, b, a})}
/>
<label>r</label>
</div>
<div class="input-wrap">
<input
class="rgba"
type="text"
value={g}
maxlength={3}
on:keypress={onlyNumbers}
on:input={event => update({r, g: parseInt(event.target.value), b, a})}
/>
<label>g</label>
</div>
<div class="input-wrap">
<input class="rgba"
type="text"
value={b}
maxlength={3}
on:keypress={onlyNumbers}
on:input={event => update({r, g, b: parseInt(event.target.value), a})}
/>
<label>b</label>
</div>
{#if !disableAlpha}
<div class="input-wrap">
<input
class="rgba"
type="text"
value={Math.round(a * 100) / 100}
maxlength={4}
on:keypress={onlyNumbersAndDot}
on:input={event => updateAlpha(parseFloat(event.target.value))}
/>
<label>a</label>
</div>
{/if}
</div>
{:else if fieldsIndex === 2}
<div class="hsla-wrap">
<div class="input-wrap">
<input class="hsla"
value={Math.round(h) % 360}
type="text"
maxlength={3}
on:keypress={onlyNumbers}
on:input={event => update({h: parseInt(event.target.value), s, l, a})}
/>
<label>h</label>
</div>
<div class="input-wrap">
<input
class="hsla percent-input"
value="{Math.round(s * 100)}%"
type="text"
maxlength={4}
on:keypress={onlyNumbers}
on:input={event => update({h, s: parseFloat(event.target.value) / 100, l, a})}
/>
<label>s</label>
</div>
<div class="input-wrap">
<input
class="hsla percent-input"
value="{Math.round(l * 100)}%"
type="text"
maxlength={4}
on:keypress={onlyNumbers}
on:input={event => update({h, s, l: parseFloat(event.target.value) / 100, a})}
/>
<label>l</label>
</div>
{#if !disableAlpha}
<div class="input-wrap">
<input
class="hsla"
value={Math.round(a * 100) / 100}
type="text"
maxlength={4}
on:keypress={onlyNumbersAndDot}
on:input={event => updateAlpha(parseFloat(event.target.value))}
/>
<label>a</label>
</div>
{/if}
</div>
{/if}
</div>
<div class="changer-wrap">
<div class="changer-up" on:click={() => fieldsIndex = (fieldsIndex === 0 ? 2 : (fieldsIndex - 1) % 3)}></div>
<div class="changer-down" on:click={() => fieldsIndex = (fieldsIndex + 1) % 3}></div>
</div>
</div>
</div>

View File

@ -0,0 +1,66 @@
<script>
import { onMount } from "svelte";
import Chrome from "./Chrome.svelte";
import {createEventDispatcher} from "svelte";
const dispatch = createEventDispatcher();
export let color = "#1ec131";
export let fieldsIndex = 0; // 0 hex 1 rgba 2 hsla
export let mode = 1; // 1 input点击模式 2 直接显示
export let width = "200px";
let active = false;
onMount(() => {});
function openChrome(event) {
if (!active) {
active = true;
}
}
function closeChrome() {
active = false;
}
const handleInput = event => {
color = event.detail;
dispatch("change", event.detail);
};
</script>
<style lang="scss">
.smx-color-picker {
width: 100%;
position: relative;
}
.smx-color-picker input{
width: 100%;
}
.smx-color-panel {
position: absolute;
top: -105px;
right: -250px;
}
</style>
<svelte:window on:click={closeChrome}/>
{#if mode === 1}
<div class="smx-color-picker" style="width: {width}">
<input
type="text"
class="input"
on:click|stopPropagation={openChrome}
value={color}
style="background: {color};"
readonly />
{#if active}
<div class="smx-color-panel" on:click|stopPropagation>
<Chrome startColor={color} on:input={handleInput} fieldsIndex={fieldsIndex}/>
</div>
{/if}
</div>
{:else}
<Chrome startColor={color} on:input={handleInput} fieldsIndex={fieldsIndex}/>
{/if}

View File

@ -0,0 +1,22 @@
<style>
.color-square{
width: 100%;
height: 100%;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAJUlEQVQoU2N88eLFfwY0ICEhwYguxjgUFKI7GsTH5m4M3w1ChQCnziae7MntdQAAAABJRU5ErkJggg==);
background-repeat: repeat;
background-size: 50% auto;
}
.color-square-in{
width: 100%;
height: 100%;
}
</style>
<script>
export let color;
</script>
<div class="color-square">
<div class="color-square-in" style="background: {color}"></div>
</div>

View File

@ -0,0 +1,40 @@
<style>
.horizontal{
background: linear-gradient(to right, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
}
.vertical{
background: linear-gradient(to bottom, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
}
</style>
<script>
import {createEventDispatcher} from "svelte";
const dispatch = createEventDispatcher();
import Slider from "./Slider.svelte";
let className = "";
export {className as class};
export let h = 0;
export let vertical = false;
export const set = (newValue) => {
h = newValue;
sliderValue = newValue / 360;
}
let slider;
$: sliderValue = h / 360;
const handle = (event) => {
h = Math.floor(sliderValue * 360);
dispatch("input", h);
}
</script>
<div class="hue {className}" class:vertical class:horizontal={!vertical}>
<Slider bind:value={sliderValue} {vertical} on:input={handle}/>
</div>

View File

@ -0,0 +1,111 @@
<style>
.saturation-value{
height: calc(100% / 1.618); /* NUMERO AUREO */
position: relative;
overflow: hidden;
}
.saturation, .value{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
}
.saturation{
background: linear-gradient(to right, #fff, rgba(255,255,255,0));
}
.value{
background: linear-gradient(to top, #000, rgba(0,0,0,0));
}
.pointer{
box-sizing: border-box;
width: 15px;
height: 15px;
transform: translate(-50%, -50%);
top: 50%;
left: 50%;
border-radius: 10px;
box-shadow: rgba(255,255,255,1) 0 0 2px 2px inset, rgba(0,0,0,0.2) 0 0 2px 2px;
position: absolute;
}
</style>
<script>
import {createEventDispatcher} from "svelte";
const dispatch = createEventDispatcher();
// input, inputstart, inputend {s, v}
import {limitatePercent} from "./utils.js";
let className = "";
export {className as class};
export let h = 180;
export let s = 0;
export let v = 0;
$: pureColor = `hsl(${h}, 100%, 50%)`
// DOM
let square;
let pointer;
$: pointerX = s;
$: pointerY = -(v - 1); // v = 1 - x // x = -(v - 1)
let pointerOffsetX = 0;
let pointerOffsetY = 0;
const handleMousemove = (event) => {
const {x, y, width, height} = square.getBoundingClientRect();
s = limitatePercent((event.x - x + pointerOffsetX) / width);
v = 1 - limitatePercent((event.y - y + pointerOffsetY) / height);
dispatch("input", {s, v});
}
const startMove = () => {
//dispatch("inputstart", {s, v})
handleMousemove(event);
self.addEventListener("mousemove", handleMousemove);
self.addEventListener("mouseup", handleMouseup);
}
const handleMouseup = () => {
self.removeEventListener("mousemove", handleMousemove);
self.removeEventListener("mouseup", handleMouseup);
//dispatch("inputend", {s, v});
}
const handlePointerMousedown = (event) => {
const {x, y, width, height} = pointer.getBoundingClientRect();
pointerOffsetX = (width / 2) - (event.x - x);
pointerOffsetY = (height / 2) - (event.y - y);
startMove(event);
}
const handleSquareMousedown = (event) => {
pointerOffsetX = pointerOffsetY = 0;
startMove(event);
}
</script>
<div
class="saturation-value {className}"
bind:this={square}
style="background-color: {pureColor}"
on:mousedown|preventDefault={handleSquareMousedown}
>
<div class="saturation"></div>
<div class="value"></div>
<div
class="pointer"
bind:this={pointer}
on:mousedown|preventDefault|stopPropagation={handlePointerMousedown}
style="left: {pointerX * 100}%; top: {pointerY * 100}%"
></div>
</div>

View File

@ -0,0 +1,115 @@
<style>
.slider{
position: relative;
}
.horizontal{
width: 100%;
height: var(--slider-height, 0.6em);
--slider-size: var(--slider-height, 0.6em);
}
.vertical{
height: 100%;
width: var(--slider-width, 0.6em);
--slider-size: var(--slider-width, 0.6em);
}
.pointer{
width: calc(var(--slider-size) * 1.333);
height: calc(var(--slider-size) * 1.333);
position: absolute;
top: 0;
left: 0;
border-radius: 100000px; /* circle */
background:#f8f8f8;
box-shadow: 0 1px 4px 0 rgba(0,0,0,0.37);
}
.horizontal > .pointer{
left: var(--value);
transform: translateX(-50%);
margin-top: calc(var(--slider-size) * -0.25);
}
.vertical > .pointer{
top: var(--value);
transform: translateY(-50%);
margin-left: calc(var(--slider-size) * -0.25);
}
</style>
<script>
import {createEventDispatcher} from "svelte";
const dispatch = createEventDispatcher();
import {limitatePercent} from "./utils.js";
let className = "";
export {className as class};
export let value = 0;
export let vertical = false;
export const set = (newValue) => value = newValue;
let pointerOffsetX = 0;
let pointerOffsetY = 0;
let prevValue = value;
let slider;
let pointer;
const handleMousemove = (event) => {
const {x, y, width, height} = slider.getBoundingClientRect();
if(vertical){
value = limitatePercent((event.y - y + pointerOffsetY) / height);
} else {
value = limitatePercent((event.x - x + pointerOffsetX) / width);
}
if(value !== prevValue){
prevValue = value;
dispatch("input", value);
}
}
const startMove = (event) => {
handleMousemove(event);
self.addEventListener("mousemove", handleMousemove);
self.addEventListener("mouseup", handleMouseup);
}
const handleMouseup = () => {
self.removeEventListener("mousemove", handleMousemove);
self.removeEventListener("mousedown", handleMouseup)
}
const handleSliderMousemove = (event) => {
pointerOffsetX = pointerOffsetY = 0;
startMove(event);
}
const handlePointerMousedown = (event) => {
const {x, y, width, height} = pointer.getBoundingClientRect();
pointerOffsetX = (width / 2) - (event.x - x);
pointerOffsetY = (height / 2) - (event.y - y);
startMove(event);
}
</script>
<div
bind:this={slider}
class="slider {className}"
class:vertical
class:horizontal={!vertical}
on:mousedown|preventDefault={handleSliderMousemove}
>
<div
bind:this={pointer}
class="pointer"
on:mousedown|preventDefault|stopPropagation={handlePointerMousedown}
style="--value: {value * 100}%"
></div>
</div>

View File

@ -0,0 +1,31 @@
import tinycolor from "tinycolor2";
export const limitatePercent = (num) => Math.max(0, Math.min(1, num));
export const getValidColor = (input) => {
if(typeof input !== "string"){
for(const key in input){
if(isNaN(input[key])){
return false;
}
}
const {h, s, l, v, r, g, b, a} = input;
if(
(h !== null && (h < 0 || h > 360)) ||
(a !== null && (a < 0 || a > 1)) ||
(s !== null && (s < 0 || s > 1)) ||
(v !== null && (v < 0 || v > 1)) ||
(l !== null && (l < 0 || l > 1)) ||
(r !== null && (r < 0 || r > 255)) ||
(g !== null && (g < 0 || g > 255)) ||
(b !== null && (b < 0 || b > 255))
) return false;
}
const color = tinycolor(input);
return color.isValid() && color;
}

View File

@ -32,6 +32,8 @@ import {
NavItem,
NavLayout
} from './components/Nav'
import ColorPicker from './components/ColorPicker/ColorPicker.svelte';
export {
Button,
Collapse,
@ -59,7 +61,8 @@ export {
Carousel,
Nav,
NavItem,
NavLayout
NavLayout,
ColorPicker
}
export const Svelma = {
@ -89,5 +92,6 @@ export const Svelma = {
Carousel,
Nav,
NavItem,
NavLayout
NavLayout,
ColorPicker
}