mirror of
https://github.com/shoelace-style/webawesome.git
synced 2026-01-12 12:09:26 +00:00
Moar progress
This commit is contained in:
6
package-lock.json
generated
6
package-lock.json
generated
@@ -130,9 +130,9 @@
|
||||
"integrity": "sha512-sLqWxCzC5/QHLhziXSCAksBxHfOnQlhPRVgPK0egEw+ktWvG75T2k+aYWVjVh9+WKeT3tlG3ZNbZQvZLmfuOIw=="
|
||||
},
|
||||
"@stencil/core": {
|
||||
"version": "1.12.6",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-1.12.6.tgz",
|
||||
"integrity": "sha512-fOHG9x92wxlQOlp9YRouLlejFShtfvZEx4LFjNi7bqTX/nHTetdv3Ir+J+SanebjBuJgKiAmLIwXviQ0Geq23w==",
|
||||
"version": "1.12.7",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-1.12.7.tgz",
|
||||
"integrity": "sha512-Ob+xncjuHebjSHqOGh9acXx0Jw2rSTzGP1XiYNKYQnoFtcvKpGqLhr2ibWqS1Z40aEwgI/OvYYldfWsp/C+0mw==",
|
||||
"requires": {
|
||||
"typescript": "3.8.3"
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@popperjs/core": "^2.1.1",
|
||||
"@stencil/core": "^1.12.6",
|
||||
"@stencil/core": "^1.12.7",
|
||||
"@stencil/sass": "^1.1.1",
|
||||
"color-convert": "^2.0.1",
|
||||
"feather-icons": "^4.28.0",
|
||||
|
||||
8
src/components.d.ts
vendored
8
src/components.d.ts
vendored
@@ -97,6 +97,10 @@ export namespace Components {
|
||||
"value": string;
|
||||
}
|
||||
interface SlColorPicker {
|
||||
/**
|
||||
* The format to use for the generated color `value`. If opacity is enabled, these will translate to HEXA, RGBA, and HSLA respectively. Note that browser support for HEXA doesn't include pre-Chromium Edge, so it's usually safer to use RGBA or HSLA when using opacity.
|
||||
*/
|
||||
"format": "hex" | "rgb" | "hsl";
|
||||
/**
|
||||
* Whether to show the opacity slider.
|
||||
*/
|
||||
@@ -836,6 +840,10 @@ declare namespace LocalJSX {
|
||||
"value"?: string;
|
||||
}
|
||||
interface SlColorPicker {
|
||||
/**
|
||||
* The format to use for the generated color `value`. If opacity is enabled, these will translate to HEXA, RGBA, and HSLA respectively. Note that browser support for HEXA doesn't include pre-Chromium Edge, so it's usually safer to use RGBA or HSLA when using opacity.
|
||||
*/
|
||||
"format"?: "hex" | "rgb" | "hsl";
|
||||
/**
|
||||
* Whether to show the opacity slider.
|
||||
*/
|
||||
|
||||
@@ -59,7 +59,8 @@
|
||||
border: solid 2px white;
|
||||
margin-top: calc(var(--grid-handle-size) / -2);
|
||||
margin-left: calc(var(--grid-handle-size) / -2);
|
||||
transition: var(--sl-transition-fast) box-shadow;
|
||||
transition: var(--sl-transition-fast) box-shadow, var(--sl-transition-x-fast) top ease,
|
||||
var(--sl-transition-x-fast) left ease;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
@@ -99,7 +100,8 @@
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25);
|
||||
margin-left: calc(var(--slider-handle-size) / -2);
|
||||
transition: var(--sl-transition-fast) box-shadow;
|
||||
transition: var(--sl-transition-fast) box-shadow, var(--sl-transition-x-fast) top ease,
|
||||
var(--sl-transition-x-fast) left ease;
|
||||
cursor: pointer;
|
||||
|
||||
&:focus {
|
||||
@@ -123,11 +125,6 @@
|
||||
}
|
||||
|
||||
.sl-color-picker__alpha {
|
||||
background-image: linear-gradient(45deg, #eee 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #eee 75%),
|
||||
linear-gradient(45deg, transparent 75%, #eee 75%), linear-gradient(45deg, #eee 25%, transparent 25%);
|
||||
background-size: 10px 10px;
|
||||
background-position: 0 0, 0 0, -5px -5px, 5px 5px;
|
||||
|
||||
.sl-color-picker__alpha-gradient {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
@@ -143,10 +140,6 @@
|
||||
position: relative;
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
background-image: linear-gradient(45deg, #eee 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #eee 75%),
|
||||
linear-gradient(45deg, transparent 75%, #eee 75%), linear-gradient(45deg, #eee 25%, transparent 25%);
|
||||
background-size: 10px 10px;
|
||||
background-position: 0 0, 0 0, -5px -5px, 5px 5px;
|
||||
border-radius: 50%;
|
||||
margin-left: var(--sl-spacing-medium);
|
||||
|
||||
@@ -188,14 +181,31 @@
|
||||
|
||||
.sl-color-picker__swatch {
|
||||
flex: 0 0 auto;
|
||||
position: relative;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 2px;
|
||||
border: solid 1px rgba(0, 0, 0, 0.125);
|
||||
cursor: pointer;
|
||||
|
||||
.sl-color-picker__swatch-color {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: solid 1px rgba(0, 0, 0, 0.125);
|
||||
border-radius: inherit;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
box-shadow: var(--sl-focus-ring-box-shadow);
|
||||
}
|
||||
}
|
||||
|
||||
.sl-color-picker__transparent-bg {
|
||||
background-image: linear-gradient(45deg, #eee 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #eee 75%),
|
||||
linear-gradient(45deg, transparent 75%, #eee 75%), linear-gradient(45deg, #eee 25%, transparent 25%);
|
||||
background-size: 10px 10px;
|
||||
background-position: 0 0, 0 0, -5px -5px, 5px 5px;
|
||||
}
|
||||
|
||||
@@ -29,16 +29,24 @@ export class ColorPicker {
|
||||
this.handleGridKeyDown = this.handleGridKeyDown.bind(this);
|
||||
this.handleHueDrag = this.handleHueDrag.bind(this);
|
||||
this.handleHueKeyDown = this.handleHueKeyDown.bind(this);
|
||||
this.handleUserInput = this.handleUserInput.bind(this);
|
||||
}
|
||||
|
||||
@State() hue = 0;
|
||||
@State() saturation = 100;
|
||||
@State() lightness = 50;
|
||||
@State() lightness = 100;
|
||||
@State() alpha = 100;
|
||||
|
||||
/** The current color. */
|
||||
@Prop({ mutable: true, reflect: true }) value = '';
|
||||
|
||||
/**
|
||||
* The format to use for the generated color `value`. If opacity is enabled, these will translate to HEXA, RGBA, and
|
||||
* HSLA respectively. Note that browser support for HEXA doesn't include pre-Chromium Edge, so it's usually safer to
|
||||
* use RGBA or HSLA when using opacity.
|
||||
*/
|
||||
@Prop() format: 'hex' | 'rgb' | 'hsl' = 'hex';
|
||||
|
||||
/** Whether to show the opacity slider. */
|
||||
@Prop() opacity = false;
|
||||
|
||||
@@ -62,6 +70,46 @@ export class ColorPicker {
|
||||
'#fff'
|
||||
];
|
||||
|
||||
componentDidLoad() {
|
||||
this.syncValue();
|
||||
}
|
||||
|
||||
getHex() {
|
||||
const hsl = [this.hue, this.saturation, this.lightness];
|
||||
const hex = convert.hsl.hex(hsl);
|
||||
const alpha = Math.ceil((this.alpha * 255) / 100 + 0x10000)
|
||||
.toString(16)
|
||||
.substr(-2)
|
||||
.toUpperCase();
|
||||
|
||||
if (this.opacity) {
|
||||
return `#${hex}${alpha}`;
|
||||
} else {
|
||||
return `#${hex}`;
|
||||
}
|
||||
}
|
||||
|
||||
getRGB() {
|
||||
const hsl = [this.hue, this.saturation, this.lightness];
|
||||
const rgb = convert.hsl.rgb(hsl);
|
||||
|
||||
if (this.opacity) {
|
||||
return `rgba(${rgb[0]}, ${rgb[1]}, ${rgb[2]}, ${this.alpha}%)`;
|
||||
} else {
|
||||
return `rgb(${rgb[0]}, ${rgb[1]}, ${rgb[2]})`;
|
||||
}
|
||||
}
|
||||
|
||||
getHSL() {
|
||||
const hsl = [this.hue, this.saturation, this.lightness];
|
||||
|
||||
if (this.opacity) {
|
||||
return `hsla(${hsl[0]}, ${hsl[1]}%, ${hsl[2]}%, ${this.alpha}%)`;
|
||||
} else {
|
||||
return `hsl(${hsl[0]}, ${hsl[1]}%, ${hsl[2]}%)`;
|
||||
}
|
||||
}
|
||||
|
||||
handleHueInput(event: Event) {
|
||||
const target = event.target as HTMLInputElement;
|
||||
this.hue = clamp(Number(target.value), 0, 360);
|
||||
@@ -91,6 +139,7 @@ export class ColorPicker {
|
||||
|
||||
this.handleDrag(event, container, x => {
|
||||
this.alpha = clamp(Math.round((x / width) * 100), 0, 100);
|
||||
this.syncValue();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -103,6 +152,7 @@ export class ColorPicker {
|
||||
|
||||
this.handleDrag(event, container, x => {
|
||||
this.hue = clamp(Math.round((x / width) * 360), 0, 360);
|
||||
this.syncValue();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -116,6 +166,7 @@ export class ColorPicker {
|
||||
this.handleDrag(event, container, (x, y) => {
|
||||
this.saturation = clamp(Math.round((x / width) * 100), 0, 100);
|
||||
this.lightness = clamp(Math.round(100 - (y / height) * 100), 0, 100);
|
||||
this.syncValue();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -215,26 +266,92 @@ export class ColorPicker {
|
||||
}
|
||||
}
|
||||
|
||||
handleUserInput(event: KeyboardEvent) {
|
||||
const target = event.target as HTMLInputElement;
|
||||
// this.setColor(target.value);
|
||||
}
|
||||
|
||||
parseColor(color: string) {
|
||||
const hexPattern = /#?([a-f0-9]{1,2})([a-f0-9]{1,2})([a-f0-9]{1,2})([a-f0-9]{1,2})?/i;
|
||||
let hue = 0;
|
||||
let saturation = 0;
|
||||
let lightness = 0;
|
||||
let alpha = 100;
|
||||
|
||||
color = color.trim().toLowerCase();
|
||||
|
||||
// Parse RGB
|
||||
if (/^rgba?/i.test(color)) {
|
||||
const rgb = color.replace(/[^\d,.%]/g, '').split(',');
|
||||
[hue, saturation, lightness] = convert.rgb.hsl(rgb);
|
||||
|
||||
if (rgb[3] && rgb[3].indexOf('%') > -1) {
|
||||
alpha = Number(rgb[3].replace('%', ''));
|
||||
} else if (rgb[3]) {
|
||||
alpha = Number(rgb[3]) * 100;
|
||||
}
|
||||
}
|
||||
|
||||
// Parse HSL
|
||||
if (/^hsla?/i.test(color)) {
|
||||
const hsl = color.replace(/[^\d,.%]/g, '').split(',');
|
||||
hue = Number(hsl[0]);
|
||||
saturation = Number(hsl[0]);
|
||||
lightness = Number(hsl[0]);
|
||||
|
||||
if (hsl[3] && hsl[3].indexOf('%') > -1) {
|
||||
alpha = Number(hsl[3].replace('%', ''));
|
||||
} else if (hsl[3]) {
|
||||
alpha = Number(hsl[3]) * 100;
|
||||
}
|
||||
}
|
||||
|
||||
// Parse hex
|
||||
if (hexPattern.test(color)) {
|
||||
const hex = color.match(hexPattern).slice(1, 5);
|
||||
[hue, saturation, lightness] = convert.hex.hsl(hex.join(''));
|
||||
|
||||
if (hex[3]) {
|
||||
alpha = Math.round((parseInt(hex[3], 16) / 255) * 100);
|
||||
console.log(hex[3], alpha);
|
||||
|
||||
// const alpha = (Math.round((this.alpha * 255) / 100) + 0x10000).toString(16).substr(-2).toUpperCase();
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
hue,
|
||||
saturation,
|
||||
lightness,
|
||||
alpha
|
||||
};
|
||||
}
|
||||
|
||||
setColor(color: string) {
|
||||
//
|
||||
// TODO:
|
||||
//
|
||||
// - detect what format the color is in
|
||||
// - parse it
|
||||
// - convert to HSL and update HSLA
|
||||
//
|
||||
const hsla = this.parseColor(color);
|
||||
this.hue = hsla.hue;
|
||||
this.saturation = hsla.saturation;
|
||||
this.lightness = hsla.lightness;
|
||||
this.alpha = this.opacity ? hsla.alpha : 100;
|
||||
this.syncValue();
|
||||
}
|
||||
|
||||
syncValue() {
|
||||
if (this.format === 'hsl') {
|
||||
this.value = this.getHSL();
|
||||
} else if (this.format === 'rgb') {
|
||||
this.value = this.getRGB();
|
||||
} else {
|
||||
this.value = this.getHex();
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const hsl = [this.hue, this.saturation, this.lightness];
|
||||
// const rgb = convert.hsl.rgb(hsl);
|
||||
const hex = convert.hsl.hex(hsl);
|
||||
const x = this.saturation;
|
||||
const y = 100 - this.lightness;
|
||||
|
||||
return (
|
||||
<div ref={el => (this.trigger = el)} class="sl-color-picker">
|
||||
<div class="sl-color-picker__trigger">Trigger</div>
|
||||
<div ref={el => (this.menu = el)} class="sl-color-picker__menu">
|
||||
<div
|
||||
ref={el => (this.grid = el)}
|
||||
@@ -286,7 +403,7 @@ export class ColorPicker {
|
||||
{this.opacity && (
|
||||
<div
|
||||
ref={el => (this.alphaSlider = el)}
|
||||
class="sl-color-picker__alpha sl-color-picker__slider"
|
||||
class="sl-color-picker__alpha sl-color-picker__slider sl-color-picker__transparent-bg"
|
||||
onMouseDown={this.handleAlphaDrag}
|
||||
onTouchStart={this.handleAlphaDrag}
|
||||
>
|
||||
@@ -319,7 +436,7 @@ export class ColorPicker {
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="sl-color-picker__preview"
|
||||
class="sl-color-picker__preview sl-color-picker__transparent-bg"
|
||||
style={{
|
||||
color: `hsla(${this.hue}deg, ${this.saturation}%, ${this.lightness}%, ${this.alpha}%)`
|
||||
}}
|
||||
@@ -327,17 +444,28 @@ export class ColorPicker {
|
||||
</div>
|
||||
|
||||
<div class="sl-color-picker__inputs">
|
||||
<div class="sl-color-picker__input sl-color-picker__input--hex">
|
||||
<sl-input size="small" type="text" pattern="[a-fA-F\d]+" value={hex}>
|
||||
<span slot="prefix">#</span>
|
||||
</sl-input>
|
||||
<div class="sl-color-picker__input">
|
||||
<sl-input
|
||||
size="small"
|
||||
type="text"
|
||||
pattern="[a-fA-F\d]+"
|
||||
value={this.value}
|
||||
onInput={this.handleUserInput}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{this.swatches && (
|
||||
<div class="sl-color-picker__swatches">
|
||||
{this.swatches.map(swatch => (
|
||||
<div class="sl-color-picker__swatch" style={{ backgroundColor: swatch }} tabIndex={0}></div>
|
||||
// @ts-ignore
|
||||
<div
|
||||
class="sl-color-picker__swatch sl-color-picker__transparent-bg"
|
||||
tabIndex={0}
|
||||
onClick={() => this.setColor(swatch)} // eslint-disable-line
|
||||
>
|
||||
<div class="sl-color-picker__swatch-color" style={{ backgroundColor: swatch }} />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Color Picker
|
||||
|
||||
```html preview
|
||||
<sl-color-picker opacity></sl-color-picker>
|
||||
<sl-color-picker opacity format="hex"></sl-color-picker>
|
||||
```
|
||||
|
||||
|
||||
@@ -10,11 +10,12 @@
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Attribute | Description | Type | Default |
|
||||
| ---------- | --------- | ------------------------------------------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `opacity` | `opacity` | Whether to show the opacity slider. | `boolean` | `false` |
|
||||
| `swatches` | -- | An array of predefined color swatches to display. | `string[]` | `[ '#d0021b', '#f5a623', '#f8e71c', '#8b572a', '#7ed321', '#417505', '#bd10e0', '#9013fe', '#4a90e2', '#50e3c2', '#b8e986', '#000', '#444', '#888', '#ccc', '#fff' ]` |
|
||||
| `value` | `value` | The current color. | `string` | `''` |
|
||||
| Property | Attribute | Description | Type | Default |
|
||||
| ---------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `format` | `format` | The format to use for the generated color `value`. If opacity is enabled, these will translate to HEXA, RGBA, and HSLA respectively. Note that browser support for HEXA doesn't include pre-Chromium Edge, so it's usually safer to use RGBA or HSLA when using opacity. | `"hex" \| "hsl" \| "rgb"` | `'hex'` |
|
||||
| `opacity` | `opacity` | Whether to show the opacity slider. | `boolean` | `false` |
|
||||
| `swatches` | -- | An array of predefined color swatches to display. | `string[]` | `[ '#d0021b', '#f5a623', '#f8e71c', '#8b572a', '#7ed321', '#417505', '#bd10e0', '#9013fe', '#4a90e2', '#50e3c2', '#b8e986', '#000', '#444', '#888', '#ccc', '#fff' ]` |
|
||||
| `value` | `value` | The current color. | `string` | `''` |
|
||||
|
||||
|
||||
## Dependencies
|
||||
|
||||
Reference in New Issue
Block a user