From eb1b4d64287007e183b106da674d4926caf7df73 Mon Sep 17 00:00:00 2001 From: Indra Kumar Gurjar Date: Thu, 16 Sep 2021 20:01:07 +0530 Subject: [PATCH] feat(ColorPicker): Add a new Coral Color Picker component. (#179) * Add a new Coral Color Picker component. * dependency at tiny * Fix axe * lint * add package-lock * update examples * @trivial * Fixed * Add formats support. * Tests ColorArea * fix(#179): Suggested changes to ColorArea to improve accessibility 1. ColorArea is currently just for Saturation and Brightness/Value. With luminosity, 50% is fully saturated, 100% is white and 0% is black, so its important to be clear about which values the slider controls. 2. We should use `aria-valuetext` to report the value of each slider. 3. The ColorPicker overlay should have aria-live="off", otherwise the value change to the text input announces assertively instead of the value of the slider that changed. 4. I added a degree symbol to the aria-valuetext of the Hue slider. * Tests ColorSliderHue * Test ColorProperties. * test * Test ColorPicker * coverage * large style * support large * Add 1 second debounce for change event. * cleanup * add translation provided by translation team. Co-authored-by: igurjar Co-authored-by: Michael Jordan Co-authored-by: Mohit Arora --- .../examples/index.html | 123 +++++ coral-component-colorpicker/gulpfile.js | 13 + .../i18n/translations.js | 356 ++++++++++++ coral-component-colorpicker/index.js | 44 ++ .../src/scripts/ColorArea.js | 514 ++++++++++++++++++ .../src/scripts/ColorFormats.js | 25 + .../src/scripts/ColorHandle.js | 133 +++++ .../src/scripts/ColorPicker.js | 368 +++++++++++++ .../src/scripts/ColorProperties.js | 264 +++++++++ .../src/scripts/ColorSlider.js | 425 +++++++++++++++ .../src/scripts/ColorSliderHue.js | 50 ++ .../src/scripts/ColorUtil.js | 121 +++++ .../src/styles/colorarea/dark.styl | 21 + .../src/styles/colorarea/darkest.styl | 21 + .../src/styles/colorarea/index.styl | 34 ++ .../src/styles/colorarea/large.styl | 25 + .../src/styles/colorarea/light.styl | 21 + .../src/styles/colorarea/lightest.styl | 21 + .../src/styles/colorarea/medium.styl | 23 + .../src/styles/colorarea/size.styl | 57 ++ .../src/styles/colorarea/skin.styl | 44 ++ .../src/styles/colorhandle/dark.styl | 21 + .../src/styles/colorhandle/darkest.styl | 21 + .../src/styles/colorhandle/index.styl | 31 ++ .../src/styles/colorhandle/large.styl | 29 + .../src/styles/colorhandle/light.styl | 21 + .../src/styles/colorhandle/lightest.styl | 21 + .../src/styles/colorhandle/medium.styl | 27 + .../src/styles/colorhandle/size.styl | 61 +++ .../src/styles/colorhandle/skin.styl | 56 ++ .../src/styles/colorslider/dark.styl | 21 + .../src/styles/colorslider/darkest.styl | 21 + .../src/styles/colorslider/index.styl | 32 ++ .../src/styles/colorslider/large.styl | 40 ++ .../src/styles/colorslider/light.styl | 21 + .../src/styles/colorslider/lightest.styl | 21 + .../src/styles/colorslider/medium.styl | 37 ++ .../src/styles/colorslider/size.styl | 82 +++ .../src/styles/colorslider/skin.styl | 50 ++ .../src/styles/dark.styl | 22 + .../src/styles/darkest.styl | 22 + .../src/styles/embed/ColorBlank.svg | 11 + .../src/styles/embed/Transparency.svg | 11 + .../src/styles/index.styl | 126 +++++ .../src/styles/large.styl | 26 + .../src/styles/light.styl | 22 + .../src/styles/lightest.styl | 22 + .../src/styles/medium.styl | 19 + .../src/styles/size.styl | 40 ++ .../src/styles/skin.styl | 31 ++ .../src/templates/base.html | 15 + .../src/templates/colorArea.html | 4 + .../src/templates/colorHandle.html | 2 + .../src/templates/colorProperties.html | 22 + .../src/templates/colorSlider.html | 5 + .../src/tests/snippets/ColorArea.html | 1 + .../src/tests/snippets/ColorPicker.html | 1 + .../snippets/ColorPicker.labelledBy.html | 4 + .../src/tests/snippets/ColorProperties.html | 1 + .../src/tests/snippets/ColorSliderHue.html | 1 + coral-component-colorpicker/src/tests/spec.js | 16 + .../src/tests/test.ColorArea.js | 501 +++++++++++++++++ .../src/tests/test.ColorPicker.js | 330 +++++++++++ .../src/tests/test.ColorProperties.js | 262 +++++++++ .../src/tests/test.ColorSliderHue.js | 340 ++++++++++++ examples/index.html | 1 + index.js | 1 + package-lock.json | 23 +- package.json | 1 + src/tests/spec.js | 1 + 70 files changed, 5193 insertions(+), 7 deletions(-) create mode 100644 coral-component-colorpicker/examples/index.html create mode 100644 coral-component-colorpicker/gulpfile.js create mode 100644 coral-component-colorpicker/i18n/translations.js create mode 100644 coral-component-colorpicker/index.js create mode 100644 coral-component-colorpicker/src/scripts/ColorArea.js create mode 100644 coral-component-colorpicker/src/scripts/ColorFormats.js create mode 100644 coral-component-colorpicker/src/scripts/ColorHandle.js create mode 100644 coral-component-colorpicker/src/scripts/ColorPicker.js create mode 100644 coral-component-colorpicker/src/scripts/ColorProperties.js create mode 100644 coral-component-colorpicker/src/scripts/ColorSlider.js create mode 100644 coral-component-colorpicker/src/scripts/ColorSliderHue.js create mode 100644 coral-component-colorpicker/src/scripts/ColorUtil.js create mode 100644 coral-component-colorpicker/src/styles/colorarea/dark.styl create mode 100644 coral-component-colorpicker/src/styles/colorarea/darkest.styl create mode 100644 coral-component-colorpicker/src/styles/colorarea/index.styl create mode 100644 coral-component-colorpicker/src/styles/colorarea/large.styl create mode 100644 coral-component-colorpicker/src/styles/colorarea/light.styl create mode 100644 coral-component-colorpicker/src/styles/colorarea/lightest.styl create mode 100644 coral-component-colorpicker/src/styles/colorarea/medium.styl create mode 100644 coral-component-colorpicker/src/styles/colorarea/size.styl create mode 100644 coral-component-colorpicker/src/styles/colorarea/skin.styl create mode 100644 coral-component-colorpicker/src/styles/colorhandle/dark.styl create mode 100644 coral-component-colorpicker/src/styles/colorhandle/darkest.styl create mode 100644 coral-component-colorpicker/src/styles/colorhandle/index.styl create mode 100644 coral-component-colorpicker/src/styles/colorhandle/large.styl create mode 100644 coral-component-colorpicker/src/styles/colorhandle/light.styl create mode 100644 coral-component-colorpicker/src/styles/colorhandle/lightest.styl create mode 100644 coral-component-colorpicker/src/styles/colorhandle/medium.styl create mode 100644 coral-component-colorpicker/src/styles/colorhandle/size.styl create mode 100644 coral-component-colorpicker/src/styles/colorhandle/skin.styl create mode 100644 coral-component-colorpicker/src/styles/colorslider/dark.styl create mode 100644 coral-component-colorpicker/src/styles/colorslider/darkest.styl create mode 100644 coral-component-colorpicker/src/styles/colorslider/index.styl create mode 100644 coral-component-colorpicker/src/styles/colorslider/large.styl create mode 100644 coral-component-colorpicker/src/styles/colorslider/light.styl create mode 100644 coral-component-colorpicker/src/styles/colorslider/lightest.styl create mode 100644 coral-component-colorpicker/src/styles/colorslider/medium.styl create mode 100644 coral-component-colorpicker/src/styles/colorslider/size.styl create mode 100644 coral-component-colorpicker/src/styles/colorslider/skin.styl create mode 100644 coral-component-colorpicker/src/styles/dark.styl create mode 100644 coral-component-colorpicker/src/styles/darkest.styl create mode 100644 coral-component-colorpicker/src/styles/embed/ColorBlank.svg create mode 100644 coral-component-colorpicker/src/styles/embed/Transparency.svg create mode 100644 coral-component-colorpicker/src/styles/index.styl create mode 100644 coral-component-colorpicker/src/styles/large.styl create mode 100644 coral-component-colorpicker/src/styles/light.styl create mode 100644 coral-component-colorpicker/src/styles/lightest.styl create mode 100644 coral-component-colorpicker/src/styles/medium.styl create mode 100644 coral-component-colorpicker/src/styles/size.styl create mode 100644 coral-component-colorpicker/src/styles/skin.styl create mode 100644 coral-component-colorpicker/src/templates/base.html create mode 100644 coral-component-colorpicker/src/templates/colorArea.html create mode 100644 coral-component-colorpicker/src/templates/colorHandle.html create mode 100644 coral-component-colorpicker/src/templates/colorProperties.html create mode 100644 coral-component-colorpicker/src/templates/colorSlider.html create mode 100644 coral-component-colorpicker/src/tests/snippets/ColorArea.html create mode 100644 coral-component-colorpicker/src/tests/snippets/ColorPicker.html create mode 100644 coral-component-colorpicker/src/tests/snippets/ColorPicker.labelledBy.html create mode 100644 coral-component-colorpicker/src/tests/snippets/ColorProperties.html create mode 100644 coral-component-colorpicker/src/tests/snippets/ColorSliderHue.html create mode 100644 coral-component-colorpicker/src/tests/spec.js create mode 100644 coral-component-colorpicker/src/tests/test.ColorArea.js create mode 100644 coral-component-colorpicker/src/tests/test.ColorPicker.js create mode 100644 coral-component-colorpicker/src/tests/test.ColorProperties.js create mode 100644 coral-component-colorpicker/src/tests/test.ColorSliderHue.js diff --git a/coral-component-colorpicker/examples/index.html b/coral-component-colorpicker/examples/index.html new file mode 100644 index 0000000000..0e2b5e2737 --- /dev/null +++ b/coral-component-colorpicker/examples/index.html @@ -0,0 +1,123 @@ + + + + + + Coral.ColorPicker + + + + + + + + + + + + + + +
+
+ Theme: + Light | + Lightest | + Dark | + Darkest + Scale: + Medium | + Large +
+ +

Color Picker

+ +

Usage notes

+
+

+ Color pickers are used as color form fields. +

+ +

Default

+
+
+ + +
+
+ +

Disabled

+
+
+ + +
+
+ +

Invalid Value

+
+
+ + +
+
+ +

Formats

+
+
+ + +
+
+ +

Invalid Formats Ignored

+
+
+ + +
+
+ +

Value Converted In Format

+
+
+ + +
+
+ +

ReadOnly

+
+
+ + +
+
+
+ + diff --git a/coral-component-colorpicker/gulpfile.js b/coral-component-colorpicker/gulpfile.js new file mode 100644 index 0000000000..0e3874c2a8 --- /dev/null +++ b/coral-component-colorpicker/gulpfile.js @@ -0,0 +1,13 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +require('../coral-gulp')(require('gulp')); diff --git a/coral-component-colorpicker/i18n/translations.js b/coral-component-colorpicker/i18n/translations.js new file mode 100644 index 0000000000..380f674787 --- /dev/null +++ b/coral-component-colorpicker/i18n/translations.js @@ -0,0 +1,356 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +export default { + "en-US": { + "Hex": "Hex", + "Hex3": "Hex3", + "Hex4": "Hex4", + "Hex8": "Hex8", + "RGB": "RGB", + "HSV": "HSV", + "HSL": "HSL", + "Name": "Name", + "Hue": "Hue", + "Color Value": "Color Value", + "Enter Color Value": "Enter Color Value", + "Color Picker": "Color Picker", + "Saturation and Brightness": "Saturation and Brightness", + "Saturation": "Saturation", + "Brightness": "Brightness", + "Select Color Format": "Select Color Format" + }, + "cs-CZ": { + "Brightness": "Jas", + "Color Picker": "Výběr barvy", + "Color Value": "Barevná hodnota", + "Enter Color Value": "Zadejte barevnou hodnotu", + "HSL": "HSL", + "HSV": "HSV", + "Hex": "Hex", + "Hex3": "Hex3", + "Hex4": "Hex4", + "Hex8": "Hex8", + "Hue": "Odstín", + "Name": "Název", + "RGB": "RGB", + "Saturation": "Sytost", + "Saturation and Brightness": "Sytost a jas", + "Select Color Format": "Vyberte formát barvy" + }, + "da-DK": { + "Brightness": "Lysstyrke", + "Color Picker": "Farvevælger", + "Color Value": "Farveværdi", + "Enter Color Value": "Angiv farveværdi", + "HSL": "HSL", + "HSV": "HSV", + "Hex": "Hex", + "Hex3": "Hex3", + "Hex4": "Hex4", + "Hex8": "Hex8", + "Hue": "Farvetone", + "Name": "Navn", + "RGB": "RGB", + "Saturation": "Mætning", + "Saturation and Brightness": "Mætning og lysstyrke", + "Select Color Format": "Vælg farveformat" + }, + "de-DE": { + "Brightness": "Helligkeit", + "Color Picker": "Farbwähler", + "Color Value": "Farbwert", + "Enter Color Value": "Farbwert eingeben", + "HSL": "HSL", + "HSV": "HSV", + "Hex": "Hex", + "Hex3": "Hex3", + "Hex4": "Hex4", + "Hex8": "Hex8", + "Hue": "Farbton", + "Name": "Name", + "RGB": "RGB", + "Saturation": "Sättigung", + "Saturation and Brightness": "Sättigung und Helligkeit", + "Select Color Format": "Farbformat auswählen" + }, + "es-ES": { + "Brightness": "Brillo", + "Color Picker": "Selector de color", + "Color Value": "Valor del color", + "Enter Color Value": "Indique el valor del color", + "HSL": "HSL", + "HSV": "HSV", + "Hex": "Valor hexadecimal", + "Hex3": "Hex3", + "Hex4": "Hex4", + "Hex8": "Hex8", + "Hue": "Tono", + "Name": "Nombre", + "RGB": "RGB", + "Saturation": "Saturación", + "Saturation and Brightness": "Saturación y brillo", + "Select Color Format": "Seleccione el formato del color" + }, + "fi-FI": { + "Brightness": "Kirkkaus", + "Color Picker": "Värimuokkain", + "Color Value": "Värin arvo", + "Enter Color Value": "Syötä värin arvo", + "HSL": "HSL", + "HSV": "HSV", + "Hex": "Hex", + "Hex3": "Hex3", + "Hex4": "Hex4", + "Hex8": "Hex8", + "Hue": "Sävy", + "Name": "Nimi", + "RGB": "RGB", + "Saturation": "Kylläisyys", + "Saturation and Brightness": "Kylläisyys ja kirkkaus", + "Select Color Format": "Valitse värimuoto" + }, + "fr-FR": { + "Brightness": "Luminosité", + "Color Picker": "Sélecteur de couleurs", + "Color Value": "Valeur de la couleur", + "Enter Color Value": "Saisir la valeur de la couleur", + "HSL": "HSL", + "HSV": "HSV", + "Hex": "Hex", + "Hex3": "Hex3", + "Hex4": "Hex4", + "Hex8": "Hex8", + "Hue": "Teinte", + "Name": "Nom", + "RGB": "RGB", + "Saturation": "Saturation", + "Saturation and Brightness": "Saturation et luminosité", + "Select Color Format": "Sélectionner le format de couleur" + }, + "it-IT": { + "Brightness": "Luminosità", + "Color Picker": "Selettore colore", + "Color Value": "Valore colore", + "Enter Color Value": "Immetti il valore del colore", + "HSL": "HSL", + "HSV": "HSV", + "Hex": "Hex", + "Hex3": "Hex3", + "Hex4": "Hex4", + "Hex8": "Hex8", + "Hue": "Tonalità", + "Name": "Nome", + "RGB": "RGB", + "Saturation": "Saturazione", + "Saturation and Brightness": "Saturazione e luminosità", + "Select Color Format": "Seleziona il formato del colore" + }, + "ja-JP": { + "Brightness": "明るさ", + "Color Picker": "カラーピッカー", + "Color Value": "カラー値", + "Enter Color Value": "カラー値を入力", + "HSL": "HSL", + "HSV": "HSV", + "Hex": "16 進数", + "Hex3": "Hex3", + "Hex4": "Hex4", + "Hex8": "Hex8", + "Hue": "色相", + "Name": "名前", + "RGB": "RGB", + "Saturation": "彩度", + "Saturation and Brightness": "彩度と明るさ", + "Select Color Format": "カラー形式を選択" + }, + "ko-KR": { + "Brightness": "명도", + "Color Picker": "색상 피커", + "Color Value": "색상 값", + "Enter Color Value": "색상 값 입력", + "HSL": "HSL", + "HSV": "HSV", + "Hex": "Hex", + "Hex3": "Hex3", + "Hex4": "Hex4", + "Hex8": "Hex8", + "Hue": "색조", + "Name": "이름", + "RGB": "RGB", + "Saturation": "채도", + "Saturation and Brightness": "채도 및 명도", + "Select Color Format": "색상 포맷 선택" + }, + "nb-NO": { + "Brightness": "Lysstyrke", + "Color Picker": "Fargevelger", + "Color Value": "Fargeverdi", + "Enter Color Value": "Angi fargeverdi", + "HSL": "HSL", + "HSV": "HSV", + "Hex": "Hex", + "Hex3": "Hex3", + "Hex4": "Hex4", + "Hex8": "Hex8", + "Hue": "Fargetone", + "Name": "Navn", + "RGB": "RGB", + "Saturation": "Metning", + "Saturation and Brightness": "Metning og lysstyrke", + "Select Color Format": "Velg fargeformat" + }, + "nl-NL": { + "Brightness": "Helderheid", + "Color Picker": "Kleurkiezer", + "Color Value": "Kleurwaarde", + "Enter Color Value": "Kleurwaarde invoeren", + "HSL": "HSL", + "HSV": "HSV", + "Hex": "Hex", + "Hex3": "Hex3", + "Hex4": "Hex4", + "Hex8": "Hex8", + "Hue": "Kleurtoon", + "Name": "Naam", + "RGB": "RGB", + "Saturation": "Verzadiging", + "Saturation and Brightness": "Verzadiging en helderheid", + "Select Color Format": "Kleuropmaak selecteren" + }, + "pl-PL": { + "Brightness": "Jasność", + "Color Picker": "Próbnik kolorów", + "Color Value": "Wartość koloru", + "Enter Color Value": "Wprowadź wartość koloru", + "HSL": "HSL", + "HSV": "HSV", + "Hex": "Hex", + "Hex3": "Hex3", + "Hex4": "Hex4", + "Hex8": "Hex8", + "Hue": "Odcień", + "Name": "Nazwa", + "RGB": "RGB", + "Saturation": "Nasycenie", + "Saturation and Brightness": "Nasycenie i jasność", + "Select Color Format": "Wybierz format kolorów" + }, + "pt-BR": { + "Brightness": "Brilho", + "Color Picker": "Seletor de cores", + "Color Value": "Valor da cor", + "Enter Color Value": "Insira o valor da cor", + "HSL": "HSL", + "HSV": "HSV", + "Hex": "Hexadecimal", + "Hex3": "Hex3", + "Hex4": "Hex4", + "Hex8": "Hex8", + "Hue": "Matiz", + "Name": "Nome", + "RGB": "RGB", + "Saturation": "Saturação", + "Saturation and Brightness": "Saturação e brilho", + "Select Color Format": "Selecione o formato da cor" + }, + "ru-RU": { + "Brightness": "Яркость", + "Color Picker": "Палитра цветов", + "Color Value": "Значение цвета", + "Enter Color Value": "Введите значение цвета", + "HSL": "HSL", + "HSV": "HSV", + "Hex": "Hex", + "Hex3": "Hex3", + "Hex4": "Hex4", + "Hex8": "Hex8", + "Hue": "Hue", + "Name": "Имя", + "RGB": "RGB", + "Saturation": "Насыщенность", + "Saturation and Brightness": "Насыщенность и яркость", + "Select Color Format": "Выберите формат цвета" + }, + "sv-SE": { + "Brightness": "Ljusstyrka", + "Color Picker": "Färgväljaren", + "Color Value": "Färgvärde", + "Enter Color Value": "Ange färgvärde", + "HSL": "HSL", + "HSV": "HSV", + "Hex": "Hex", + "Hex3": "Hex3", + "Hex4": "Hex4", + "Hex8": "Hex8", + "Hue": "Nyans", + "Name": "Namn", + "RGB": "RGB", + "Saturation": "Mättnad", + "Saturation and Brightness": "Mättnad och ljusstyrka", + "Select Color Format": "Välj färgformat" + }, + "tr-TR": { + "Brightness": "Parlaklık", + "Color Picker": "Renk Seçici", + "Color Value": "Renk Değeri", + "Enter Color Value": "Renk Değerini Gir", + "HSL": "HSL", + "HSV": "HSV", + "Hex": "Hex", + "Hex3": "Hex3", + "Hex4": "Hex4", + "Hex8": "Hex8", + "Hue": "Ton", + "Name": "Adı", + "RGB": "RGB", + "Saturation": "Doygunluk", + "Saturation and Brightness": "Doygunluk ve Parlaklık", + "Select Color Format": "Renk Formatını Seç" + }, + "zh-CN": { + "Brightness": "亮度", + "Color Picker": "拾色器", + "Color Value": "颜色值", + "Enter Color Value": "输入颜色值", + "HSL": "HSL", + "HSV": "HSV", + "Hex": "Hex", + "Hex3": "Hex3", + "Hex4": "Hex4", + "Hex8": "Hex8", + "Hue": "色相", + "Name": "名称", + "RGB": "RGB", + "Saturation": "饱和度", + "Saturation and Brightness": "饱和度和亮度", + "Select Color Format": "选择颜色格式" + }, + "zh-TW": { + "Brightness": "亮度", + "Color Picker": "檢色器", + "Color Value": "顏色值", + "Enter Color Value": "輸入顏色值", + "HSL": "HSL", + "HSV": "HSV", + "Hex": "Hex", + "Hex3": "Hex3", + "Hex4": "Hex4", + "Hex8": "Hex8", + "Hue": "色相", + "Name": "名稱", + "RGB": "RGB", + "Saturation": "飽和度", + "Saturation and Brightness": "飽和度和亮度", + "Select Color Format": "選取顏色格式" + } +} diff --git a/coral-component-colorpicker/index.js b/coral-component-colorpicker/index.js new file mode 100644 index 0000000000..ff3c658013 --- /dev/null +++ b/coral-component-colorpicker/index.js @@ -0,0 +1,44 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +import '../coral-theme-spectrum'; +import '../coral-externals'; +import '../coral-compat'; + +import ColorPicker from './src/scripts/ColorPicker'; +import ColorProperties from './src/scripts/ColorProperties'; +import ColorArea from './src/scripts/ColorArea'; +import ColorSliderHue from './src/scripts/ColorSliderHue'; +import ColorHandle from './src/scripts/ColorHandle'; +import translations from './i18n/translations'; +import {strings, commons} from '../coral-utils'; + +import './src/styles/index.css'; + +// i18n +commons.extend(strings, { + 'coral-component-colorpicker': translations +}); + +// Expose component on the Coral namespace +commons._define('coral-colorpicker', ColorPicker); +commons._define('coral-colorpicker-colorproperties', ColorProperties); +commons._define('coral-colorpicker-colorarea', ColorArea); +commons._define('coral-colorpicker-colorsliderhue', ColorSliderHue); +commons._define('coral-colorpicker-colorhandle', ColorHandle); + +ColorPicker.ColorProperties = ColorProperties; +ColorPicker.ColorHandle = ColorHandle; +ColorPicker.ColorArea = ColorArea; +ColorPicker.ColorSliderHue = ColorSliderHue; + +export {ColorPicker}; \ No newline at end of file diff --git a/coral-component-colorpicker/src/scripts/ColorArea.js b/coral-component-colorpicker/src/scripts/ColorArea.js new file mode 100644 index 0000000000..4ef803bf50 --- /dev/null +++ b/coral-component-colorpicker/src/scripts/ColorArea.js @@ -0,0 +1,514 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +import {BaseComponent} from '../../../coral-base-component'; +import colorArea from '../templates/colorArea'; +import {validate, transform, events, commons, i18n, Keys} from '../../../coral-utils'; +import { TinyColor } from '@ctrl/tinycolor'; +import colorUtil from "./ColorUtil"; + +const CLASSNAME = '_coral-ColorPicker-ColorArea'; + +/** + @class Coral.ColorPicker.ColorArea + @classdesc A ColorPicker area component to select Saturation and Value + @htmltag coral-colorpicker-colorarea + @extends {HTMLElement} + @extends {BaseComponent} + */ +class ColorArea extends BaseComponent(HTMLElement) { + constructor() { + super(); + + this._delegateEvents(commons.extend(this._events, { + 'key:up': '_handleKey', + 'key:right': '_handleKey', + 'key:down': '_handleKey', + 'key:left': '_handleKey', + 'key:pageUp': '_handleKey', + 'key:pageDown': '_handleKey', + 'key:home': '_handleKey', + 'key:end': '_handleKey', + + 'input': '_onInputChangeHandler', + + 'touchstart': '_onMouseDown', + 'mousedown': '_onMouseDown', + 'capture:focus': '_focus', + 'capture:blur': '_blur' + })); + + // Templates + this._elements = {}; + colorArea.call(this._elements, {commons, i18n}); + // default values + this._x = 1; + this._y = 1; + this._hue = 120; + this._minX = 0; + this._minY = 0; + this._maxX = 1; + this._maxY = 1; + this._stepX = 0.01; + this._stepY = 0.01; + } + + /** @ignore */ + render() { + super.render(); + + this.classList.add(CLASSNAME); + + const frag = document.createDocumentFragment(); + + // Render template + frag.appendChild(this._elements.colorAreaGradient); + frag.appendChild(this._elements.colorHandle); + frag.appendChild(this._elements.sliderX); + frag.appendChild(this._elements.sliderY); + + // Support cloneNode + while (this.firstChild) { + const child = this.firstChild; + if (child.nodeType === Node.ELEMENT_NODE && child.hasAttribute('handle')) { + this.removeChild(child); + } + else { + frag.appendChild(child); + } + } + + this.appendChild(frag); + + // These should be used to set a property since property handler aren't called until elements are attached to dom. + // Attribute values are delivered to change-listeners even if element isn't attached to dom yet, so attributes + // can be set to e.g. this._elements.colorHandle. + this._handle = this.querySelector('._coral-ColorPicker-ColorArea-colorHandle'); + this._sliderX = this.querySelector('._coral-ColorPicker-ColorArea-slider[name="x"]'); + this._sliderY = this.querySelector('._coral-ColorPicker-ColorArea-slider[name="y"]'); + this._gradient = this.querySelector('._coral-ColorPicker-ColorArea-gradient'); + this._updateHue(this._hue); + this.x = this._x; + this.y = this._y; + this._updateHandle(this._hue, this.x, this.y, this.color); + this._reflectAttribute('color', this.color); + } + + /** + The ColorArea label. + @default '' + @type {String} + @htmlattribute label + @htmlattributereflected + */ + get label() { + return this._label; + } + + set label(value) { + this._label = value; + this._reflectAttribute('label', this._label); + if(this._elements.sliderX.getAttribute('aria-label') !== this._label) { + this._elements.sliderX.setAttribute('aria-label', this._label); + this._elements.sliderY.setAttribute('aria-label', this._label); + } + } + + /** + The ColorArea x value. value should be in multiple of x-step size. + @default 1 + @type {String} + @htmlattribute label + @htmlattributereflected + */ + get x() { + return this._x; + } + + set x(value) { + let rawX = Number(value, 10); + if(parseFloat(rawX).toFixed(3) !== parseFloat(this._x).toFixed(3)) { + if(isNaN(rawX)) { + rawX = this._minX; + } + this._x = this._snapValueToStep(rawX, this._minX, this._maxX, this._stepX); + this._reflectAttribute('x', this._x); + this.color = this._toHsvString(this._hue, this._x, this.y); + } + this._elements.sliderX.setAttribute('aria-valuetext', `${i18n.get('Saturation')}: ${Math.round(this._x / (this._maxX - this._minX) * 100)}%`); + this._elements.sliderX.setAttribute('title', this.color); + this._elements.sliderX.setAttribute('value', this._x); + } + + /** @private */ + _toHsvString(hue, x, y) { + const s = `${Math.round(this._x / (this._maxX - this._minX) * 100)}%`; + const v = `${Math.round(this._y / (this._maxY - this._minY) * 100)}%`; + return `hsv(${this._hue}, ${s}, ${v})`; + } + + /** + The ColorArea y value. value should be in multiple of y-step size. + @default 1 + @type {String} + @htmlattribute label + @htmlattributereflected + */ + get y() { + return this._y; + } + + set y(value) { + let rawY = Number(value, 10); + if(parseFloat(rawY).toFixed(3) !== parseFloat(this._y).toFixed(3)) { + if(isNaN(rawY)) { + rawY = this._minY; + } + this._y = this._snapValueToStep(rawY, this._minY, this._maxY, this._stepY); + this._reflectAttribute('y', this._y); + this.color = this._toHsvString(this._hue, this.x, this._y); + } + this._elements.sliderY.setAttribute('aria-valuetext', `${i18n.get('Brightness')}: ${Math.round(this._y / (this._maxY - this._minY) * 100)}%`); + this._elements.sliderY.setAttribute('title', this.color); + this._elements.sliderY.setAttribute('value', this._y); + } + + /** + The ColorArea color string in hsla format. + @default hsla(0, 100%, 50%, 1) + @type {String} + @htmlattribute color + @htmlattributereflected + */ + get color() { + return colorUtil.toHslString(this._hue, new TinyColor({h:this._hue, s:this.x, v:this.y}).toHslString()); + } + + set color(value) { + let color = new TinyColor(value); + if(!color.isValid) { + color = new TinyColor("hsla(120, 100%, 50%, 1)"); + value = color.toHslString(); + } + + // if color strings are equal or colors are equivalent + if(this.color === value || new TinyColor(this.color).toString(color.format) === color) { + return; + } + + const {h,s,v} = colorUtil.extractHsv(value); + if(h !== this._hue) { + this._updateHue(colorUtil.getHue(value)); + } + if(s !== this._x) { + this.x = s; + } + if(v !== this.Y) { + this.y = v; + } + this._updateHandle(this._hue, this.x, this.y, this.color); + this._reflectAttribute('color', this.color); + } + + /** @ignore */ + static get observedAttributes() { + return super.observedAttributes.concat([ + 'label', + 'x', + 'y', + 'disabled', + 'color' + ]); + } + + /** + Whether this field is disabled or not. + @type {Boolean} + @default false + @htmlattribute disabled + @htmlattributereflected + */ + get disabled() { + return this._disabled || false; + } + + set disabled(value) { + this._disabled = transform.booleanAttr(value); + this._reflectAttribute('disabled', this._disabled); + + this.classList.toggle('is-disabled', this._disabled); + this[this._disabled ? 'setAttribute' : 'removeAttribute']('aria-disabled', this._disabled); + this._elements.sliderX[this._disabled ? 'setAttribute' : 'removeAttribute']('disabled', this._disabled); + this._elements.sliderY[this._disabled ? 'setAttribute' : 'removeAttribute']('disabled', this._disabled); + this._elements.colorHandle[this._disabled ? 'setAttribute' : 'removeAttribute']('disabled', this._disabled); + } + + focus() { + this._sliderX.focus(); + } + + /** @private **/ + _updateHue(hue) { + this._hue = hue; + if(this._gradient){ + this._gradient.style.background = `linear-gradient(to top, black 0%, hsla(${this._hue}, 100%, 0%, 0) 100%), + linear-gradient(to right, white 0%, hsla(${this._hue}, 100%, 0%, 0) 100%), + hsl(${this._hue}, 100%, 50%)`; + } + } + + /** @private */ + _snapValueToStep(rawValue, min, max, step) { + const remainder = (rawValue - min) % step; + let snappedValue = rawValue; + + if (Math.abs(remainder) * 2 >= step) { + snappedValue = rawValue - remainder + step; + } + else { + snappedValue = rawValue - remainder; + } + if (snappedValue < min) { + snappedValue = min; + } + else if (snappedValue > max) { + snappedValue = min + Math.floor((max - min) / step) * step; + } + return snappedValue; + } + + /** @private */ + _updateHandle(hue, x, y, colorStr) { + let percent = 100 - ((y - this._minY) / (this._maxY - this._minY) * 100); + if(this._handle) { + this._handle.style.top = `${percent}%`; + } + + percent = (x - this._minX) / (this._maxX - this._minX) * 100; + if(this._handle) { + this._handle.style.left = `${percent}%`; + } + this._elements.colorHandle.setAttribute('color', colorStr); + } + + /** @private */ + _focusHandle(isFocused) { + if(this._handle) { + if(isFocused === true) { + this._handle.focus(); + } + else { + this._handle.blur(); + } + } + } + + /** @private */ + _changeValue(x, y) { + if(this.x !== x || this.y !== y) { + var currX = this.x; + var currY = this.y; + this.x = x; + this.y = y; + if(this.x !== currX || this.y !== currY) { + this.trigger('change'); + } + } + } + + _focusX() { + this._sliderX.focus(); + } + + _focusY() { + this._sliderY.focus(); + } +/******* Events Handling **************/ + + /** @private */ + _onInputChangeHandler(event) { + this._focusHandle(true); + event.stopPropagation(); + if(event.target === this._sliderX) { + this._changeValue(event.target.value, this.y); + } + else { + this._changeValue(this.x, event.target.value); + } + } + + /** @private */ + _handleKey(event) { + this._focusHandle(true); + event.preventDefault(); + event.stopPropagation(); + let y = this.y; + let x = this.x; + // increase + if (event.keyCode === Keys.keyToCode('up') || + event.keyCode === Keys.keyToCode('pageUp')) { + y += this._stepY; + this._focusY(); + } + // decrease + else if (event.keyCode === Keys.keyToCode('down') || + event.keyCode === Keys.keyToCode('pageDown')) { + y -= this._stepY; + this._focusY(); + } + + // increase + if (event.keyCode === Keys.keyToCode('right')) { + x += this._stepX; + this._focusX(); + } + // decrease + else if (event.keyCode === Keys.keyToCode('left')) { + x -= this._stepX; + this._focusX(); + } + + // min + else if (event.keyCode === Keys.keyToCode('home')) { + x = this._minX; + y = this._minY; + this._focusX(); + } + // max + else if (event.keyCode === Keys.keyToCode('end')) { + x = this._maxX; + y = this._maxY; + this._focusX(); + } + + this._changeValue(x, y); + } + + /** @private */ + _onMouseDown() { + if (event instanceof MouseEvent) { + if ((event.which || event.button) !== 1) { + return; + } + } + event.preventDefault(); + + this._handle.classList.add('is-dragged'); + document.body.classList.add('u-coral-closedHand'); + this.focus(); + this._focusHandle(true); + + const {x,y} = this._getValuesFromCoord(this._getPoint(event)); + this._changeValue(x, y); + + const classNameSelector = "." + CLASSNAME; + this._draggingHandler = this._handleDragging.bind(this); + this._mouseUpHandler = this._mouseUp.bind(this); + + events.on('mousemove.CoralArea', this._draggingHandler); + events.on('mouseup.CoralArea', this._mouseUpHandler); + + events.on('touchmove.CoralArea', this._draggingHandler); + events.on('touchend.CoralArea', this._mouseUpHandler); + events.on('touchcancel.CoralArea', this._mouseUpHandler); + } + + /** @private */ + _getValuesFromCoord(point) { + const boundingClientRect = this.getBoundingClientRect(); + const height = boundingClientRect.height; + const width = boundingClientRect.width; + let posY = point.clientY; + let posX = point.clientX; + + if(posY < boundingClientRect.top) { + posY = boundingClientRect.top; + } + else if(posY > boundingClientRect.bottom) { + posY = boundingClientRect.bottom; + } + + if(posX < boundingClientRect.left) { + posX = boundingClientRect.left; + } + else if(posX > boundingClientRect.right) { + posX = boundingClientRect.right; + } + + let positionFraction = (height -(posY - boundingClientRect.top)) / height; + const rawY = this._minY + positionFraction * (this._maxY - this._minY); + + positionFraction = (posX - boundingClientRect.left) / width; + const rawX = this._minX + positionFraction * (this._maxX - this._minX); + + return {x: rawX, y: rawY}; + } + + /** @private */ + _handleDragging(event) { + const {x,y} = this._getValuesFromCoord(this._getPoint(event)); + this._changeValue(x, y); + event.preventDefault(); + } + + /** @private */ + _mouseUp(event) { + this._handle.style.cursor = 'grab'; + this._handle.classList.remove('is-dragged'); + document.body.classList.remove('u-coral-closedHand'); + this._focusHandle(false); + const classNameSelector = "." + CLASSNAME; + + events.off('mousemove.CoralArea', this._draggingHandler); + events.off('touchmove.CoralArea', this._draggingHandler); + events.off('mouseup.CoralArea', this._mouseUpHandler); + events.off('touchend.CoralArea', this._mouseUpHandler); + events.off('touchcancel.CoralArea', this._mouseUpHandler); + + this._currentHandle = null; + this._draggingHandler = null; + this._mouseUpHandler = null; + } + + /** + @private + @return {Object} which contains the real coordinates + */ + _getPoint(event) { + if (event.changedTouches && event.changedTouches.length > 0) { + return event.changedTouches[0]; + } + else if (event.touches && event.touches.length > 0) { + return event.touches[0]; + } + + return event; + } + + /** + Handles "focusin" event. + + @private + */ + _focus(event) { + this._focusHandle(true); + } + + /** + Handles "focusout" event. + + @private + */ + _blur(event) { + this._focusHandle(false); + } +} +export default ColorArea; \ No newline at end of file diff --git a/coral-component-colorpicker/src/scripts/ColorFormats.js b/coral-component-colorpicker/src/scripts/ColorFormats.js new file mode 100644 index 0000000000..4c85d268e3 --- /dev/null +++ b/coral-component-colorpicker/src/scripts/ColorFormats.js @@ -0,0 +1,25 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + + const ColorFormats = { + HSL: "hsl", + HSV: "hsv", + RGB: "rgb", + PRGB: "prgb", + HEX : "hex", + HEX3: "hex3", + HEX4: "hex4", + HEX8: "hex8", + NAME: "name" +}; + +export default ColorFormats; diff --git a/coral-component-colorpicker/src/scripts/ColorHandle.js b/coral-component-colorpicker/src/scripts/ColorHandle.js new file mode 100644 index 0000000000..d5aa45b3b9 --- /dev/null +++ b/coral-component-colorpicker/src/scripts/ColorHandle.js @@ -0,0 +1,133 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +import {BaseComponent} from '../../../coral-base-component'; +import subView from '../templates/colorHandle'; +import {validate, transform, commons, i18n} from '../../../coral-utils'; +import { TinyColor } from '@ctrl/tinycolor'; +import colorUtil from "./ColorUtil"; + +const CLASSNAME = '_coral-ColorPicker-colorHandle'; + +/** + @class Coral.ColorPicker.ColorHandle + @classdesc A ColorHandle component + @htmltag coral-colorpicker-colorhandle + @extends {HTMLElement} + @extends {BaseComponent} + */ +class ColorHandle extends BaseComponent(HTMLElement) { + /** @ignore */ + constructor() { + super(); + + this._delegateEvents(commons.extend(this._events, { + })); + + // Templates + this._elements = {}; + subView.call(this._elements, {commons, i18n}); + this._color = new TinyColor("hsla(0, 100%, 50%, 1)"); + this._hue = 0; + } + + /** @ignore */ + render() { + super.render(); + + this.classList.add(CLASSNAME); + + const frag = document.createDocumentFragment(); + + // Render template + frag.appendChild(this._elements.colorHandleSubView); + + // Support cloneNode + while (this.firstChild) { + const child = this.firstChild; + if (child.nodeType === Node.ELEMENT_NODE && child.hasAttribute('handle')) { + this.removeChild(child); + } + else { + frag.appendChild(child); + } + } + + this.appendChild(frag); + + this._subView = this.querySelector("._coral-ColorPicker-colorHandle-color"); + this.color = colorUtil.toHslString(this._hue, this._color.toHslString()); + } + + /** @ignore */ + focus() { + this.classList.add("is-focused"); + } + + /** @ignore */ + blur() { + this.classList.remove("is-focused"); + } + + /** + Whether this field is disabled or not. + @type {Boolean} + @default false + @htmlattribute disabled + @htmlattributereflected + */ + get disabled() { + return this._disabled || false; + } + + set disabled(value) { + this._disabled = transform.booleanAttr(value); + this._reflectAttribute('disabled', this._disabled); + + this.classList.toggle('is-disabled', this._disabled); + this[this._disabled ? 'setAttribute' : 'removeAttribute']('aria-disabled', this._disabled); + } + + /** + The ColorSlider color. + @default hsla(0, 100%, 50%, 1) + @type {String} + @htmlattribute label + @htmlattributereflected + */ + get color() { + return this._color.toHslString(); + } + + set color(value) { + let color = new TinyColor(value); + if(!color.isValid) { + color = new TinyColor("hsla(0, 100%, 50%, 1)"); + value = color.toHslString(); + } + this._color = color; + this._hue = colorUtil.getHue(value); + this._reflectAttribute('color', colorUtil.toHslString(this._hue, this._color.toHslString())); + if(this._subView){ + this._subView.style["background-color"] = colorUtil.toHslString(this._hue, this._color.toHslString()); + } + } + + /** @ignore */ + static get observedAttributes() { + return super.observedAttributes.concat([ + 'disabled', + 'color' + ]); + } + +} +export default ColorHandle; \ No newline at end of file diff --git a/coral-component-colorpicker/src/scripts/ColorPicker.js b/coral-component-colorpicker/src/scripts/ColorPicker.js new file mode 100644 index 0000000000..bc9562643d --- /dev/null +++ b/coral-component-colorpicker/src/scripts/ColorPicker.js @@ -0,0 +1,368 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +import {BaseComponent} from '../../../coral-base-component'; +import {BaseFormField} from '../../../coral-base-formfield'; +import ColorFormats from './ColorFormats'; +import '../../../coral-component-textfield'; +import '../../../coral-component-button'; +import '../../../coral-component-popover'; +import base from '../templates/base'; +import {validate, transform, commons, i18n} from '../../../coral-utils'; +import { TinyColor } from '@ctrl/tinycolor'; +import colorUtil from "./ColorUtil"; + +const CLASSNAME = '_coral-ColorPicker'; + +/** + @class Coral.ColorPicker + @classdesc A ColorPicker component than can be used as a form field to select from a list of color options. + @htmltag coral-colorpicker + @extends {HTMLElement} + @extends {BaseComponent} + @extends {BaseFormField} + */ +class ColorPicker extends BaseFormField(BaseComponent(HTMLElement)) { + /** @ignore */ + constructor() { + super(); + // Prepare templates + this._elements = {}; + base.call(this._elements, {commons, i18n}); + + const overlay = this._elements.overlay; + const overlayId = overlay.id; + + // Extend form field events + const events = commons.extend(this._events, { + 'key:down ._coral-ColorPicker-input:not([readonly])': '_onKeyDown', + 'key:down [handle="colorPreview"]': '_onKeyDown', + 'click [handle="colorPreview"]': '_onColorPreviewClick', + 'key:esc input': '_onKeyEsc', + 'key:enter input': '_onKeyEsc', + 'capture:change [handle="input"]': '_onColorInputChange', + 'change [handle="propertiesView"]': '_onPropertyChange' + }); + + // Overlay + events[`global:capture:coral-overlay:beforeopen #${overlayId}`] = '_beforeOverlayOpen'; + events[`global:capture:coral-overlay:close #${overlayId}`] = '_onOverlayClose'; + events[`global:key:esc #${overlayId}`] = '_onKeyEsc'; + + // Events + this._delegateEvents(events); + this.value = ""; + this._format = ColorFormats.HSL; + this._sendChaneEvent = this._chaneEventDebounced(); + } + + /** @ignore */ + connectedCallback() { + super.connectedCallback(); + + const overlay = this._elements.overlay; + // Cannot be open by default when rendered + overlay.removeAttribute('open'); + // Restore in DOM + if (overlay._parent) { + overlay._parent.appendChild(overlay); + } + } + + /** @ignore */ + disconnectedCallback() { + super.disconnectedCallback(); + + const overlay = this._elements.overlay; + // In case it was moved out don't forget to remove it + if (!this.contains(overlay)) { + overlay._parent = overlay._repositioned ? document.body : this; + overlay.remove(); + } + } + + /** @ignore */ + render() { + super.render(); + + this.classList.add(CLASSNAME); + + this.setAttribute('role', 'group'); + + const frag = document.createDocumentFragment(); + + // Render template + frag.appendChild(this._elements.input); + frag.appendChild(this._elements.buttonWrapper); + frag.appendChild(this._elements.overlay); + + // Support cloneNode + while (this.firstChild) { + const child = this.firstChild; + if (child.nodeType === Node.ELEMENT_NODE && child.hasAttribute('handle')) { + this.removeChild(child); + } + else { + frag.appendChild(child); + } + } + + this.appendChild(frag); + + // These should be used to set a property since property handler aren't called until elements are attached to dom. + // Attribute values are delivered to change-listeners even if element isn't attached to dom yet, so attributes + // can be set to e.g. this._elements.colorPreview. + this._input = this.querySelector("[handle='input']"); + this._preview = this.querySelector("[handle='colorPreview']"); + this._overlay = this.querySelector("[handle='overlay']"); + this._overlay.setAttribute('aria-live', 'off'); + this._properties = this._overlay.querySelector("[handle='propertiesView']"); + this._update(this._value); + } + + /** @ignore */ + static get observedAttributes() { + return super.observedAttributes.concat([ + 'value', + 'formats', + 'disabled', + 'label', + 'labelledby', + 'readonly' + ]); + } + + + /** @ignore */ + static get _attributePropertyMap() { + return commons.extend(super._attributePropertyMap, { + labelledby: 'labelledBy', + readonly: 'readOnly' + }); + } + /** + The ColorPicker label. + @default 'Select Color' + @type {String} + @htmlattribute label + @htmlattributereflected + */ + get label() { + return this._label || i18n.get('Color Picker'); + } + + set label(value) { + this._label = value; + this._reflectAttribute('label', this.label); + this._elements.input.setAttribute('aria-label', this.label); + } + + /** + Inherited from {@link BaseFormField#labelledBy}. + */ + get labelledBy() { + return super.labelledBy; + } + + set labelledBy(value) { + super.labelledBy = value; + + // Sync input aria-labelledby + this._elements.input[value ? 'setAttribute' : 'removeAttribute']('aria-labelledby', value); + + // in case the user focuses the buttons, he will still get a notion of the usage of the component + if (this.labelledBy) { + this.setAttribute('aria-labelledby', this.labelledBy); + this._elements.colorPreview.setAttribute('aria-labelledby', + [this.labelledBy, + this._elements.colorPreview.label.id].join(' ')); + } + else { + this.removeAttribute('aria-labelledby'); + this._elements.colorPreview.removeAttribute('aria-labelledby'); + } + } + + /** + Whether this field is disabled or not. + @type {Boolean} + @default false + @htmlattribute disabled + @htmlattributereflected + */ + get disabled() { + return this._disabled || false; + } + + set disabled(value) { + this._disabled = transform.booleanAttr(value); + this._reflectAttribute('disabled', this._disabled); + this[this._disabled ? 'setAttribute' : 'removeAttribute']('aria-disabled', this._disabled); + this.classList.toggle('is-disabled', this._disabled); + this._elements.input[this._disabled ? 'setAttribute' : 'removeAttribute']('disabled', this._disabled); + this._elements.colorPreview[this._disabled ? 'setAttribute' : 'removeAttribute']('disabled', this._disabled); + } + + /** + Whether this field is readOnly or not. Indicating that the user cannot modify the value of the control. + @type {Boolean} + @default false + @htmlattribute readonly + @htmlattributereflected + */ + get readOnly() { + return this._readOnly || false; + } + + set readOnly(value) { + this._readOnly = transform.booleanAttr(value); + this._reflectAttribute('readonly', this._readOnly); + this._elements.input[this._readOnly ? 'setAttribute' : 'removeAttribute']('readonly', this._readOnly); + this._elements.colorPreview[(this.disabled || this._readOnly) ? 'setAttribute' : 'removeAttribute']('disabled', this.disabled || this._readOnly); + } + + /** + The ColorPicker value. value should be a valid color in supported format. + @default Empty + @type {String} + @htmlattribute label + @htmlattributereflected + */ + get value() { + return this._value; + } + + set value(value) { + this._update(value); + } + + /** + The ColorPicker formats. comma separated formats should be in supported formats. + Any invalid/unsupported format is ignored. + Values selected in any other format will be converted to this format. + @default ColorFormats.HSL + @type {String} + @htmlattribute formats + @htmlattributereflected + */ + get formats() { + return this._formats || ""; + } + + set formats(value) { + let formats = value.split(','); + formats = colorUtil.getValidFormats(formats); + if(formats.length > 0) { + this._formats = formats; + this._format = formats[0]; + this._reflectAttribute('formats', this._formats); + this._elements.propertiesView.setAttribute('formats', value); + // refresh color in this new format + this._update(colorUtil.formatColorString(this.value, this._format)); + } + } + + /** @private */ + _update(value) { + if(this.value === value) { + return; + } + + // sync UI for empty value + this.classList[ (value == "") ? 'add' : 'remove']('_coral-ColorPicker--novalue'); + this._elements.colorPreview.classList[ (value == "") ? 'add' : 'remove']('_coral-ColorPicker-preview--novalue'); + // Empty value isn't invalid. + let color = new TinyColor(value); + let isInvalid = (value !== "" && !color.isValid); + this[isInvalid ? 'setAttribute' : 'removeAttribute']('invalid', "true"); + this._elements.input[isInvalid ? 'setAttribute' : 'removeAttribute']('invalid', "true"); + if(color.isValid && (!this._formats || this._formats.indexOf(color.format) !== -1)) { + this._format = color.format; + } + this._value = (value == "" || !color.isValid) ? value : colorUtil.formatColorString(value, this._format); + this._elements.input.value = this._value; + this._elements.propertiesView.setAttribute('color', this._value); + this._elements.colorPreview.style["background-color"] = new TinyColor(this._value).toHslString(); + } + + _debounce(func, timeout = 1000) { + let timer; + return (...args) => { + clearTimeout(timer); + timer = setTimeout(() => { func.apply(this, args); }, timeout); + }; + } + + _chaneEventDebounced() { + var self = this; + return this._debounce(function() { + self.trigger('change'); + }, 1000); + } + + /** @private */ + _change(color) { + this._update(color); + var self = this; + this._sendChaneEvent(); + } + /***************** Interaction handlers***********/ + /** @private */ + _onKeyDown(event) { + event.stopPropagation(); + // restore focus to appropriate element when overlay closes + this._elements.overlay.returnFocusTo(event.matchedTarget); + this._elements.overlay.open = true; + } + + /** @private */ + _onKeyEsc(event) { + if (!this._elements.overlay.open) { + return; + } + + event.stopPropagation(); + + this._elements.overlay.open = false; + } + + /** @private */ + _onColorPreviewClick(event) { + // restore focus to appropriate element when overlay closes + this._elements.overlay.returnFocusTo(event.matchedTarget); + } + + /** @private */ + _beforeOverlayOpen() { + // set aria-expanded state + this._elements.input.setAttribute('aria-expanded', true); + this._elements.colorPreview.setAttribute('aria-expanded', true); + } + + _onOverlayClose() { + // set aria-expanded state + this._elements.input.setAttribute('aria-expanded', true); + this._elements.colorPreview.setAttribute('aria-expanded', false); + } + + /** @private */ + _onColorInputChange(event) { + this._update(this._input.value); + } + + /** @private */ + _onPropertyChange(event) { + event.stopImmediatePropagation(); + this._change(this._properties.color); + } +} +export default ColorPicker; \ No newline at end of file diff --git a/coral-component-colorpicker/src/scripts/ColorProperties.js b/coral-component-colorpicker/src/scripts/ColorProperties.js new file mode 100644 index 0000000000..d0416039cf --- /dev/null +++ b/coral-component-colorpicker/src/scripts/ColorProperties.js @@ -0,0 +1,264 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +import {BaseComponent} from '../../../coral-base-component'; +import '../../../coral-component-select'; +import ColorFormats from './ColorFormats'; +import propertiesSubview from '../templates/colorProperties'; +import {validate, transform, commons, i18n} from '../../../coral-utils'; +import { TinyColor } from '@ctrl/tinycolor'; +import colorUtil from "./ColorUtil"; + +const CLASSNAME = '_coral-ColorPicker-properties'; + +/** + @class Coral.ColorPicker.ColorProperties + @classdesc A ColorPicker Color properties component + @htmltag coral-colorpicker-properties + @extends {HTMLElement} + @extends {BaseComponent} + */ +class ColorProperties extends BaseComponent(HTMLElement) { + constructor() { + super(); + + this._delegateEvents(commons.extend(this._events, { + 'change [handle="propertyHue"]': '_onHueChange', + 'change [handle="propertySL"]': '_onSLChange', + 'change [handle="formatSelector"]': '_onFormatChange', + 'capture:change [handle="colorInput"]': '_onColorInputChange' + })); + + // Templates + this._elements = {}; + propertiesSubview.call(this._elements, {commons, i18n}); + this._hue = 240; + this._s = 1; + this._l = 0.5; + this._a = 1; + this._format = ColorFormats.HSV; + } + + render() { + super.render(); + + this.classList.add(CLASSNAME); + + const frag = document.createDocumentFragment(); + + // Render template + frag.appendChild(this._elements.propertiesSubview); + + // Support cloneNode + while (this.firstChild) { + const child = this.firstChild; + if (child.nodeType === Node.ELEMENT_NODE && child.hasAttribute('handle')) { + this.removeChild(child); + } + else { + frag.appendChild(child); + } + } + + this.appendChild(frag); + //these should be used to set a property since property handler aren't called until elements are attached to dom. + // Attribute values are delivered to change-listeners even if element isn't attached to dom yet. + this._colorArea = this.querySelector("[handle='propertySL']"); + this._colorSliderHue = this.querySelector("[handle='propertyHue']"); + this._formatSelector = this.querySelector("[handle='formatSelector']"); + this._colorInput = this.querySelector("[handle='colorInput']"); + // update color in all subviews + this._updateFormat(this._format); + this._updateHue(this._hue); + this._updateSL(this._s, this._l); + this._updateAlpha(this._a); + this._updateValue(); + } + + /** + Whether this field is disabled or not. + @type {Boolean} + @default false + @htmlattribute disabled + @htmlattributereflected + */ + get disabled() { + return this._disabled || false; + } + + set disabled(value) { + this._disabled = transform.booleanAttr(value); + this._reflectAttribute('disabled', this._disabled); + this[this._disabled ? 'setAttribute' : 'removeAttribute']('aria-disabled', this._disabled); + this.classList.toggle('is-disabled', this._disabled); + + this._elements.propertySL[this._disabled ? 'setAttribute' : 'removeAttribute']('disabled', this._disabled); + this._elements.propertyHue[this._disabled ? 'setAttribute' : 'removeAttribute']('disabled', this._disabled); + this._elements.formatSelector[this._disabled ? 'setAttribute' : 'removeAttribute']('disabled', this._disabled); + this._elements.colorInput[this._disabled ? 'setAttribute' : 'removeAttribute']('disabled', this._disabled); + } + + /** + The ColorProperties formats. comma separated formats should be in supported formats. + First format will be used as default format. + Values selected in any other format will be converted to default format. + @default ColorFormats.HSL + @type {Array} + @htmlattribute formats + @htmlattributereflected + */ + get formats() { + return this._formats || ""; + } + + set formats(value) { + if(value == "") { + return; + } + let formats = value.split(','); + formats = colorUtil.getValidFormats(formats); + if(formats.length > 0) { + this._formats = formats; + this._format = formats[0]; + this._elements.formatSelector.setAttribute('value', this._format); + // update input value to this format + this._elements.colorInput.value = this.color; + // populate format selector list + let selList = this._elements.formatSelector.querySelectorAll('coral-select-item'); + selList.forEach(function(element) { + if(formats.indexOf(element.value) == -1) { + element.remove(); + } + }); + this._reflectAttribute('formats', this._formats); + } + } + + /** + The ColorProperties color string. + @default hsla(0, 100%, 50%, 1) + @type {String} + @htmlattribute color + @htmlattributereflected + */ + get color() { + return colorUtil.formatColorString(colorUtil.toHslString(this._hue, this._getColorFromProps()), this._format); + } + + set color(value) { + let color = new TinyColor(value); + if(!color.isValid) { + color = new TinyColor("hsla(240, 100%, 50%, 1)"); + value = color.toHslString(); + } + + if(this.color === value) { + return; + } + + this._updateFormat(color.format); + this._updateHue(colorUtil.getHue(value)); + this._updateSL(color.toHsl().s, color.toHsl().l); + this._updateAlpha(color.a); + this._updateValue(); + } + + /** @ignore */ + static get observedAttributes() { + return super.observedAttributes.concat([ + 'disabled', + 'color', + 'formats' + ]); + } + + /** @private */ + _onHueChange(event) { + event.stopImmediatePropagation(); + this._updateHue(this._colorSliderHue.value); + this.trigger('change'); + } + + /** @private */ + _onSLChange(event) { + event.stopImmediatePropagation(); + const color = new TinyColor({h: this._hue, s: this._colorArea.x, v: this._colorArea.y}); + this._updateSL(color.toHsl().s, color.toHsl().l); + this.trigger('change'); + } + + /** @private */ + _onFormatChange(event) { + event.stopImmediatePropagation(); + this._updateFormat(this._formatSelector.value); + this.trigger('change'); + } + + /** @private */ + _onColorInputChange(event) { + event.stopImmediatePropagation(); + this.color = this._colorInput.value; + this.trigger('change'); + } + + /** @private */ + _updateFormat(format) { + this._format = format; + this._elements.formatSelector.setAttribute('value', this._format); + this._updateValue(); + } + + /** @private */ + _updateHue(hue) { + this._hue = Math.round(hue); + const color = this._getColorFromProps(); + this._elements.propertyHue.setAttribute('color', colorUtil.toHslString(this._hue, color.toHslString())); + // need to update hue in ColorArea but not s and v, so get s and v from ColorArea + this._elements.propertySL.setAttribute('color', this._toHsvString(this._hue, this._elements.propertySL.x, this._elements.propertySL.y)); + this._updateValue(); + } + + /** @private */ + _updateSL(s, l) { + this._s = s; + this._l = l; + const color = new TinyColor({h:this._hue, s:this._s, l:this._l}); + this._elements.propertySL.setAttribute('color', colorUtil.toHslString(this._hue, color.toHslString())); + this._updateValue(); + } + + /** @private */ + _updateAlpha(a) { + this._a = a; + this._updateValue(); + } + + /** @private */ + _toHsvString(hue, x, y) { + const s = `${Math.round(x * 100)}%`; + const v = `${Math.round(y * 100)}%`; + return `hsv(${this._hue}, ${s}, ${v})`; + } + + /** @private */ + _getColorFromProps() { + return new TinyColor({h:this._hue, s:this._s, l:this._l, a:this._a}); + } + + /** @private */ + _updateValue() { + this._reflectAttribute('color', this.color); + this._elements.colorInput.value = this.color; + } +} + +export default ColorProperties; diff --git a/coral-component-colorpicker/src/scripts/ColorSlider.js b/coral-component-colorpicker/src/scripts/ColorSlider.js new file mode 100644 index 0000000000..8a4a30c2c6 --- /dev/null +++ b/coral-component-colorpicker/src/scripts/ColorSlider.js @@ -0,0 +1,425 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +import {BaseComponent} from '../../../coral-base-component'; +import view from '../templates/colorSlider'; +import {validate, transform, events, commons, i18n, Keys} from '../../../coral-utils'; +import { TinyColor } from '@ctrl/tinycolor'; +import colorUtil from "./ColorUtil"; + +const CLASSNAME = '_coral-ColorPicker-ColorSlider'; + +/** + @@base ColorSlider + @classdesc A ColorPicker color slider component + @extends {HTMLElement} + @extends {BaseComponent} + */ +class ColorSlider extends BaseComponent(HTMLElement) { + /** @ignore */ + constructor() { + super(); + + this._delegateEvents(commons.extend(this._events, { + 'key:up': '_handleKey', + 'key:right': '_handleKey', + 'key:down': '_handleKey', + 'key:left': '_handleKey', + 'key:pageUp': '_handleKey', + 'key:pageDown': '_handleKey', + 'key:home': '_handleKey', + 'key:end': '_handleKey', + + 'input': '_onInputChangeHandler', + + 'touchstart': '_onMouseDown', + 'mousedown': '_onMouseDown', + 'capture:focus': '_focus', + 'capture:blur': '_blur' + })); + + // Templates + this._elements = {}; + view.call(this._elements, {commons, i18n}); + + // default value + this._label = ""; + this._value = 180; + this._color = new TinyColor("hsla(180, 100%, 50%, 1)"); + this._hue = 180; + this._min = 0; + this._max = 100; + this._step = 1; + } + + /** @ignore */ + render() { + super.render(); + + this.classList.add(CLASSNAME); + + const frag = document.createDocumentFragment(); + + // Render template + frag.appendChild(this._elements.checkerboard); + frag.appendChild(this._elements.colorHandle); + frag.appendChild(this._elements.slider); + + // Support cloneNode + while (this.firstChild) { + const child = this.firstChild; + if (child.nodeType === Node.ELEMENT_NODE && child.hasAttribute('handle')) { + this.removeChild(child); + } + else { + frag.appendChild(child); + } + } + + this.appendChild(frag); + + this._syncInputSliderAttrs(); + // These should be used to set a property since property handler aren't called until elements are attached to dom. + // Attribute values are delivered to change-listeners even if element isn't attached to dom yet, so attributes + // can be set to e.g. this._elements.colorHandle. + this._handle = this.querySelector('._coral-ColorPicker-ColorSlider-colorHandle'); + this._slider = this.querySelector('._coral-ColorPicker-ColorSlider-slider'); + this._updateValue(this._hue); + } + + /** + The ColorSlider label. + @default 'Hue' + @type {String} + @htmlattribute label + @htmlattributereflected + */ + get label() { + return this._label; + } + + set label(value) { + this._label = value; + this._reflectAttribute('label', this._label); + this._syncInputSliderAttrs(); + } + + /** + The ColorSlider value. value should be in multiple of step size. + @default 0 + @type {String} + @htmlattribute label + @htmlattributereflected + */ + get value() { + return this._value; + } + + set value(value) { + if(this._value !== value) { + this._updateValue(value); + } + } + + /** + The ColorSlider color string in hsla format. + @default hsla(0, 100%, 50%, 1) + @type {String} + @htmlattribute color + @htmlattributereflected + */ + get color() { + return colorUtil.toHslString(this._hue, this._color.toHslString()); + } + + set color(value) { + if(this.color === value) { + return; + } + let color = new TinyColor(value); + if(!color.isValid) { + color = new TinyColor("hsla(180, 100%, 50%, 1)"); + value = color.toHslString(); + } + this._hue = colorUtil.getHue(value); + this._updateValue(this._hue); + } + + /** @ignore */ + static get observedAttributes() { + return super.observedAttributes.concat([ + 'label', + 'value', + 'disabled', + 'color' + ]); + } + + /** + Whether this field is disabled or not. + @type {Boolean} + @default false + @htmlattribute disabled + @htmlattributereflected + */ + get disabled() { + return this._disabled || false; + } + + set disabled(value) { + this._disabled = transform.booleanAttr(value); + this._reflectAttribute('disabled', this._disabled); + + this.classList.toggle('is-disabled', this._disabled); + this[this._disabled ? 'setAttribute' : 'removeAttribute']('aria-disabled', this._disabled); + this._elements.slider[this._disabled ? 'setAttribute' : 'removeAttribute']('disabled', this._disabled); + this._elements.colorHandle[this._disabled ? 'setAttribute' : 'removeAttribute']('disabled', this._disabled); + } + + focus() { + this._slider.focus(); + } + + /** @private */ + _colorFromValue(value) { + return new TinyColor({ h: value, s: 1, l: .5, a:1 }); + } + + /** @private */ + _syncInputSliderAttrs() { + if(Number(this._elements.slider.getAttribute('min')) !== this._min) { + this._elements.slider.setAttribute('min', this._min); + } + + if(Number(this._elements.slider.getAttribute('max')) !== this._max) { + this._elements.slider.setAttribute('max', this._max); + } + + if(Number(this._elements.slider.getAttribute('step')) !== this._step) { + this._elements.slider.setAttribute('step', this._step); + } + + if(this._elements.slider.getAttribute('aria-label') !== this._label) { + this._elements.slider.setAttribute('aria-label', this._label); + } + } + + /** @private */ + _snapValueToStep(rawValue, min, max, step) { + const remainder = (rawValue - min) % step; + let snappedValue = rawValue; + + if (Math.abs(remainder) * 2 >= step) { + snappedValue = rawValue - remainder + step; + } + else { + snappedValue = rawValue - remainder; + } + if (snappedValue < min) { + snappedValue = min; + } + else if (snappedValue > max) { + snappedValue = min + Math.floor((max - min) / step) * step; + } + return snappedValue; + } + + /** @private */ + _updateHandlePosition() { + const percent = 100 - ((this._value - this._min) / (this._max - this._min) * 100); + if(this._handle) { + this._handle.style.top = `${percent}%`; + } + } + + /** @private */ + _focusHandle(isFocused) { + if(this._handle) { + if(isFocused === true) { + this._handle.focus(); + } + else { + this._handle.blur(); + } + } + } + + /** @private */ + _updateValue(value) { + let rawValue = Number(value, 10); + if(isNaN(rawValue)) { + rawValue = this._min; + } + + this._value = this._snapValueToStep(rawValue, this._min, this._max, this._step); + this._hue = this._value; + // update color + this._color = this._colorFromValue(this._value); + this._elements.colorHandle.setAttribute('color', colorUtil.toHslString(this._hue, this._color.toHslString())); + this._reflectAttribute('color', colorUtil.toHslString(this._hue, this._color.toHslString())); + this._reflectAttribute('value', this._value); + this._elements.slider.setAttribute('value', this._value); + this._updateHandlePosition(); + } + + /** @private */ + _changeValue(value) { + if(value !== this.value) { + var currVal = this.value; + this._updateValue(value); + if(currVal !== this.value) { + this.trigger('change'); + } + } + } + +/******* Events Handling **************/ + + /** @private */ + _onInputChangeHandler(event) { + this.focus(); + this._focusHandle(true); + event.stopPropagation(); + this._changeValue(event.target.value); + } + + /** @private */ + _handleKey(event) { + this.focus(); + this._focusHandle(true); + event.preventDefault(); + event.stopPropagation(); + let value = this._value; + // increase + if (event.keyCode === Keys.keyToCode('up') || + event.keyCode === Keys.keyToCode('right') || + event.keyCode === Keys.keyToCode('pageUp')) { + value += this._step; + } + // decrease + else if (event.keyCode === Keys.keyToCode('down') || + event.keyCode === Keys.keyToCode('left') || + event.keyCode === Keys.keyToCode('pageDown')) { + value -= this._step; + } + // min + else if (event.keyCode === Keys.keyToCode('home')) { + value = this._min; + } + // max + else if (event.keyCode === Keys.keyToCode('end')) { + value = this._max; + } + this._changeValue(value); + } + + /** @private */ + _onMouseDown() { + if (event instanceof MouseEvent) { + if ((event.which || event.button) !== 1) { + return; + } + } + event.preventDefault(); + + this._handle.classList.add('is-dragged'); + document.body.classList.add('u-coral-closedHand'); + this.focus(); + this._focusHandle(true); + this._changeValue(this._getValueFromCoord(this._getPoint(event).clientY)); + + const classNameSelector = "." + CLASSNAME; + this._draggingHandler = this._handleDragging.bind(this); + this._mouseUpHandler = this._mouseUp.bind(this); + + events.on('mousemove.CoralSlider', this._draggingHandler); + events.on('mouseup.CoralSlider', this._mouseUpHandler); + + events.on('touchmove.CoralSlider', this._draggingHandler); + events.on('touchend.CoralSlider', this._mouseUpHandler); + events.on('touchcancel.CoralSlider', this._mouseUpHandler); + } + + /** @private */ + _getValueFromCoord(posY) { + const boundingClientRect = this.getBoundingClientRect(); + const height = boundingClientRect.height; + if(posY < boundingClientRect.top) { + posY = boundingClientRect.top; + } + else if(posY > boundingClientRect.bottom) { + posY = boundingClientRect.bottom; + } + const positionFraction = (height -(posY - boundingClientRect.top)) / height; + const rawValue = this._min + positionFraction * (this._max - this._min); + return this._snapValueToStep(rawValue, this._min, this._max, this._step); + } + + /** @private */ + _handleDragging(event) { + this._changeValue(this._getValueFromCoord(this._getPoint(event).clientY)); + event.preventDefault(); + } + + /** @private */ + _mouseUp(event) { + this._handle.style.cursor = 'grab'; + this._handle.classList.remove('is-dragged'); + document.body.classList.remove('u-coral-closedHand'); + this._focusHandle(false); + const classNameSelector = "." + CLASSNAME; + + events.off('mousemove.CoralSlider', this._draggingHandler); + events.off('touchmove.CoralSlider', this._draggingHandler); + events.off('mouseup.CoralSlider', this._mouseUpHandler); + events.off('touchend.CoralSlider', this._mouseUpHandler); + events.off('touchcancel.CoralSlider', this._mouseUpHandler); + + this._currentHandle = null; + this._draggingHandler = null; + this._mouseUpHandler = null; + } + + /** + @private + @return {Object} which contains the real coordinates + */ + _getPoint(event) { + if (event.changedTouches && event.changedTouches.length > 0) { + return event.changedTouches[0]; + } + else if (event.touches && event.touches.length > 0) { + return event.touches[0]; + } + + return event; + } + + /** + Handles "focusin" event. + + @private + */ + _focus(event) { + this._focusHandle(true); + } + + /** + Handles "focusout" event. + + @private + */ + _blur(event) { + this._focusHandle(false); + } + +} +export default ColorSlider; \ No newline at end of file diff --git a/coral-component-colorpicker/src/scripts/ColorSliderHue.js b/coral-component-colorpicker/src/scripts/ColorSliderHue.js new file mode 100644 index 0000000000..23168ef781 --- /dev/null +++ b/coral-component-colorpicker/src/scripts/ColorSliderHue.js @@ -0,0 +1,50 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +import ColorSlider from './ColorSlider'; +import { TinyColor } from '@ctrl/tinycolor'; + +const CLASSNAME = '_coral-ColorPicker-ColorSlider-hue'; + +/** + @class Coral.ColorPicker.ColorSliderHue + @classdesc A ColorPicker color slider hue component to select Hue + @htmltag coral-colorpicker-colorsliderhue + @extends {ColorSlider} + */ +class ColorSliderHue extends ColorSlider { + /** @ignore */ + constructor() { + super(); + this._min = 0; + this._max = 360; + this._step = 1; + } + + /** @private */ + _updateValue(value) { + super._updateValue(value); + this._elements.slider.setAttribute('aria-valuetext', `${this.value}°`); + } + + /** @ignore */ + render() { + super.render(); + this.classList.add(CLASSNAME); + this._updateValue(this.value); + } + + /** @private */ + _colorFromValue(value) { + return new TinyColor({ h: value, s: 1, l: .50, a:1 }); + } +} +export default ColorSliderHue; \ No newline at end of file diff --git a/coral-component-colorpicker/src/scripts/ColorUtil.js b/coral-component-colorpicker/src/scripts/ColorUtil.js new file mode 100644 index 0000000000..7f74442131 --- /dev/null +++ b/coral-component-colorpicker/src/scripts/ColorUtil.js @@ -0,0 +1,121 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +import { TinyColor } from '@ctrl/tinycolor'; +import ColorFormats from './ColorFormats'; + +class ColorUtil { + + constructor() {} + /** + Utility function to convert a color to Hsl string. + + @param {String} hue + The hue value which is preserved in color conversion. + @param {String} colorString + The color string + */ + toHslString(hue, colorString) { + const color = new TinyColor(colorString); + const hueExp = /(^hs[v|l]a?\()\d{1,3}/; + return color.toHslString().replace(hueExp, `$1${hue}`); + } + + /** + Utility function to convert a color to Hsv string. + + @param {String} hue + The hue value which is preserved in color conversion. + @param {String} colorString + The color string + */ + toHsvString(hue, colorString) { + const color = new TinyColor(colorString); + const hueExp = /(^hs[v|l]a?\()\d{1,3}/; + return color.toHsvString().replace(hueExp, `$1${hue}`); + } + + /** + Utility function to extract h,s and v from a color string. + @param {String} colorString + The color string + */ + extractHsv(colorString) { + const exp = /^hsva?\((\d{1,3}),\s*(\d{1,3}%),\s*(\d{1,3}%)/; + if(!colorString.startsWith("hsv")) { + colorString = new TinyColor(colorString).toHsvString(); + } + let groups = exp.exec(colorString); + const h = parseInt(groups[1]); + const s = parseInt(groups[2])/100; + const v = parseInt(groups[3])/100; + return {h:h, s:s, v:v}; + } + + /** + Utility function to extract hue. + @param {String} colorString + The color string + */ + getHue(colorString) { + if(colorString.startsWith('hs')) { + const hueExp = /^hs[v|l]a?\((\d{1,3})/; + const values = hueExp.exec(colorString); + const [, h] = values; + return Number(h); + } + else { + return new TinyColor(colorString).toHsv().h; + } + } + + /** + Utility function to validate given formats in supported formats and return a list of formats. + Any invalid/unsupported format is ignored. + @param {Array} formats + An array of formats to validate + */ + getValidFormats(formats) { + const supportedFormats = Object.values(ColorFormats); + let validFormats = []; + formats.forEach(function(value){ + if(supportedFormats.indexOf(value) !== -1) { + validFormats.push(value); + } + }); + return validFormats; + } + + /** + Utility function to convert a color into a desired format. + @param {String} color + The color string + @param {String} format + A color format + */ + formatColorString(color, format) { + const hue = this.getHue(color); + if(format === ColorFormats.HSV) { + return this.toHsvString(hue, color); + } + else if(format === ColorFormats.HSL) { + return this.toHslString(hue, color); + } + else { + return new TinyColor(color).toString(format); + } + } + +} + +const colorUtil = new ColorUtil(); +export default colorUtil; + \ No newline at end of file diff --git a/coral-component-colorpicker/src/styles/colorarea/dark.styl b/coral-component-colorpicker/src/styles/colorarea/dark.styl new file mode 100644 index 0000000000..c55dad42aa --- /dev/null +++ b/coral-component-colorpicker/src/styles/colorarea/dark.styl @@ -0,0 +1,21 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +@require '../../../../coral-theme-spectrum/src/styles/vars.css'; + +$colorpicker-colorarea-fill-color-disabled = var(--spectrum-dark-colorarea-fill-color-disabled, var(--spectrum-dark-global-color-gray-300)); +$colorpicker-colorarea-colorarea-border-color = var(--spectrum-dark-colorarea-border-color); +$colorpicker-colorarea-colorarea-border-color-disabled = var(--spectrum-dark-colorarea-border-color-disabled, var(--spectrum-dark-global-color-gray-300)); + +.coral--dark { + @import 'skin.styl' +} \ No newline at end of file diff --git a/coral-component-colorpicker/src/styles/colorarea/darkest.styl b/coral-component-colorpicker/src/styles/colorarea/darkest.styl new file mode 100644 index 0000000000..147f1e44e2 --- /dev/null +++ b/coral-component-colorpicker/src/styles/colorarea/darkest.styl @@ -0,0 +1,21 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +@require '../../../../coral-theme-spectrum/src/styles/vars.css'; + +$colorpicker-colorarea-fill-color-disabled = var(--spectrum-darkest-colorarea-fill-color-disabled, var(--spectrum-darkest-global-color-gray-300)); +$colorpicker-colorarea-colorarea-border-color = var(--spectrum-darkest-colorarea-border-color); +$colorpicker-colorarea-colorarea-border-color-disabled = var(--spectrum-darkest-colorarea-border-color-disabled, var(--spectrum-darkest-global-color-gray-300)); + +.coral--darkest { + @import 'skin.styl' +} \ No newline at end of file diff --git a/coral-component-colorpicker/src/styles/colorarea/index.styl b/coral-component-colorpicker/src/styles/colorarea/index.styl new file mode 100644 index 0000000000..aa3bbe097c --- /dev/null +++ b/coral-component-colorpicker/src/styles/colorarea/index.styl @@ -0,0 +1,34 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +@require '../../../../coral-theme-spectrum/src/styles/vars.css'; + +._coral-ColorPicker-ColorArea.is-disabled ._coral-ColorPicker-ColorArea-gradient { + display: none; +} + +._coral-ColorPicker-ColorArea-slider { + opacity: 0.0001; + position: absolute; + top: 0; left: 0; + width: 100%; height: 100%; + z-index: 0; + margin: 0; + pointer-events: none; +} + +@require 'medium'; +@require 'large'; +@require 'light'; +@require 'lightest'; +@require 'dark'; +@require 'darkest'; \ No newline at end of file diff --git a/coral-component-colorpicker/src/styles/colorarea/large.styl b/coral-component-colorpicker/src/styles/colorarea/large.styl new file mode 100644 index 0000000000..1c71f8ec03 --- /dev/null +++ b/coral-component-colorpicker/src/styles/colorarea/large.styl @@ -0,0 +1,25 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +.coral--large { + ._coral-ColorPicker-ColorArea { + --colorarea-width: var(--spectrum-large-colorarea-default-width, var(--spectrum-large-global-dimension-size-2400)); + --colorarea-height: var(--spectrum-large-colorarea-default-height, var(--spectrum-large-global-dimension-size-2400)); + --colorarea-border-radius: var(--spectrum-large-colorarea-border-radius, var(--spectrum-large-alias-border-radius-regular)); + } + + ._coral-ColorPicker-ColorArea.is-focused ._coral-ColorPicker-ColorArea-colorHandle { + --colorarea-colorhandle-size: var(--spectrum-large-colorhandle-size); + } + + @import 'size.styl' +} \ No newline at end of file diff --git a/coral-component-colorpicker/src/styles/colorarea/light.styl b/coral-component-colorpicker/src/styles/colorarea/light.styl new file mode 100644 index 0000000000..6d1b200b89 --- /dev/null +++ b/coral-component-colorpicker/src/styles/colorarea/light.styl @@ -0,0 +1,21 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +@require '../../../../coral-theme-spectrum/src/styles/vars.css'; + +$colorpicker-colorarea-fill-color-disabled = var(--spectrum-light-colorarea-fill-color-disabled, var(--spectrum-light-global-color-gray-300)); +$colorpicker-colorarea-colorarea-border-color = var(--spectrum-light-colorarea-border-color); +$colorpicker-colorarea-colorarea-border-color-disabled = var(--spectrum-light-colorarea-border-color-disabled, var(--spectrum-light-global-color-gray-300)); + +.coral--light { + @import 'skin.styl' +} \ No newline at end of file diff --git a/coral-component-colorpicker/src/styles/colorarea/lightest.styl b/coral-component-colorpicker/src/styles/colorarea/lightest.styl new file mode 100644 index 0000000000..d5d0716bea --- /dev/null +++ b/coral-component-colorpicker/src/styles/colorarea/lightest.styl @@ -0,0 +1,21 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +@require '../../../../coral-theme-spectrum/src/styles/vars.css'; + +$colorpicker-colorarea-fill-color-disabled = var(--spectrum-lightest-colorarea-fill-color-disabled, var(--spectrum-lightest-global-color-gray-300)); +$colorpicker-colorarea-colorarea-border-color = var(--spectrum-lightest-colorarea-border-color); +$colorpicker-colorarea-colorarea-border-color-disabled = var(--spectrum-lightest-colorarea-border-color-disabled, var(--spectrum-lightest-global-color-gray-300)); + +.coral--lightest { + @import 'skin.styl' +} \ No newline at end of file diff --git a/coral-component-colorpicker/src/styles/colorarea/medium.styl b/coral-component-colorpicker/src/styles/colorarea/medium.styl new file mode 100644 index 0000000000..967c6219ac --- /dev/null +++ b/coral-component-colorpicker/src/styles/colorarea/medium.styl @@ -0,0 +1,23 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + + ._coral-ColorPicker-ColorArea { + --colorarea-width: var(--spectrum-medium-colorarea-default-width, var(--spectrum-medium-global-dimension-size-2400)); + --colorarea-height: var(--spectrum-medium-colorarea-default-height, var(--spectrum-medium-global-dimension-size-2400)); + --colorarea-border-radius: var(--spectrum-medium-colorarea-border-radius, var(--spectrum-medium-alias-border-radius-regular)); + } + + ._coral-ColorPicker-ColorArea.is-focused ._coral-ColorPicker-ColorArea-colorHandle { + --colorarea-colorhandle-size: var(--spectrum-medium-colorhandle-size); + } + + @import 'size.styl' \ No newline at end of file diff --git a/coral-component-colorpicker/src/styles/colorarea/size.styl b/coral-component-colorpicker/src/styles/colorarea/size.styl new file mode 100644 index 0000000000..3183234b10 --- /dev/null +++ b/coral-component-colorpicker/src/styles/colorarea/size.styl @@ -0,0 +1,57 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + + ._coral-ColorPicker-ColorArea { + position: relative; + display: inline-block; + width: var(--colorarea-width); + height: var(--colorarea-height); + border-radius: var(--colorarea-border-radius); + cursor: default; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + + &.is-focused { + z-index: 2; + } + + &.is-disabled { + pointer-events: none; + } + + &:before { + content: ''; + z-index: 1; + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + border-radius: var(--colorarea-border-radius); + } +} + +._coral-ColorPicker-ColorArea.is-focused ._coral-ColorPicker-ColorArea-colorHandle{ + width: calc(var(--colorarea-colorhandle-size) * 2); + height: calc(var(--colorarea-colorhandle-size) * 2); + + margin-left: calc(-1 * var(--colorarea-colorhandle-size)); + margin-top: calc(-1 * var(--colorarea-colorhandle-size)); +} + +._coral-ColorPicker-ColorArea ._coral-ColorPicker-ColorArea-gradient { + width: 100%; + height: 100%; + border-radius: var(--colorarea-border-radius); +} diff --git a/coral-component-colorpicker/src/styles/colorarea/skin.styl b/coral-component-colorpicker/src/styles/colorarea/skin.styl new file mode 100644 index 0000000000..2c21af79ed --- /dev/null +++ b/coral-component-colorpicker/src/styles/colorarea/skin.styl @@ -0,0 +1,44 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +@require '../../../../coral-theme-spectrum/src/styles/vars.css'; + +._coral-ColorPicker-ColorArea { + &.is-disabled { + background: $colorpicker-colorarea-fill-color-disabled; + } + + &.is-disabled:before { + // box-shadow: inset 0 0 0 var(--spectrum-medium-colorarea-border-size, var(--spectrum-alias-border-size-thin)) + // $colorpicker-colorarea-colorarea-border-color-disabled; + } +} + +._coral-ColorPicker-ColorArea:before { + // box-shadow: inset 0 0 0 var(--spectrum-medium-colorarea-border-size, var(--spectrum-alias-border-size-thin)) $colorpicker-colorarea-colorarea-border-color; +} + +._coral-ColorPicker-ColorArea-gradient { + background: linear-gradient(to top, black 0%, hsla(0, 100%, 0%, 0) 100%), // L + linear-gradient(to right, white 0%, hsla(0, 100%, 0%, 0) 100%), // S + hsl(0, 100%, 50%); // Hue + forced-color-adjust: none; +} + +@media (forced-colors: active) { + ._coral-ColorPicker-ColorArea { + --spectrum-colorarea-fill-color-disabled : GrayText; + } + ._coral-ColorPicker-ColorArea.is-disabled { + forced-color-adjust: none; + } +} \ No newline at end of file diff --git a/coral-component-colorpicker/src/styles/colorhandle/dark.styl b/coral-component-colorpicker/src/styles/colorhandle/dark.styl new file mode 100644 index 0000000000..379ee2ee0b --- /dev/null +++ b/coral-component-colorpicker/src/styles/colorhandle/dark.styl @@ -0,0 +1,21 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +@require '../../../../coral-theme-spectrum/src/styles/vars.css'; + +$colorhandle-inner-border-color = var(--spectrum-dark-colorhandle-inner-border-color); +$colorhandle-inner-border-color-disabled = var(--spectrum-dark-colorhandle-inner-border-color-disabled); +$colorhandle-fill-color-disabled = var(--spectrum-dark-colorhandle-fill-color-disabled); + +.coral--dark { + @import 'skin.styl' +} \ No newline at end of file diff --git a/coral-component-colorpicker/src/styles/colorhandle/darkest.styl b/coral-component-colorpicker/src/styles/colorhandle/darkest.styl new file mode 100644 index 0000000000..f50681fe96 --- /dev/null +++ b/coral-component-colorpicker/src/styles/colorhandle/darkest.styl @@ -0,0 +1,21 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +@require '../../../../coral-theme-spectrum/src/styles/vars.css'; + +$colorhandle-inner-border-color = var(--spectrum-darkest-colorhandle-inner-border-color); +$colorhandle-inner-border-color-disabled = var(--spectrum-darkest-colorhandle-inner-border-color-disabled); +$colorhandle-fill-color-disabled = var(--spectrum-darkest-colorhandle-fill-color-disabled); + +.coral--darkest { + @import 'skin.styl' +} \ No newline at end of file diff --git a/coral-component-colorpicker/src/styles/colorhandle/index.styl b/coral-component-colorpicker/src/styles/colorhandle/index.styl new file mode 100644 index 0000000000..10fa98eeea --- /dev/null +++ b/coral-component-colorpicker/src/styles/colorhandle/index.styl @@ -0,0 +1,31 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +@require '../../../../coral-theme-spectrum/src/styles/vars.css'; + +._coral-ColorHandle.is-disabled ._coral-ColorPicker-colorHandle-color { + display: none; + pointer-events: none; +} + +._coral-ColorPicker-colorHandle-color { + border-radius: 100%; + width: 100%; + height: 100%; +} + +@require 'medium'; +@require 'large'; +@require 'light'; +@require 'lightest'; +@require 'dark'; +@require 'darkest'; \ No newline at end of file diff --git a/coral-component-colorpicker/src/styles/colorhandle/large.styl b/coral-component-colorpicker/src/styles/colorhandle/large.styl new file mode 100644 index 0000000000..9bdac2d45a --- /dev/null +++ b/coral-component-colorpicker/src/styles/colorhandle/large.styl @@ -0,0 +1,29 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +.coral--large { + ._coral-ColorPicker-colorHandle { + --colorhandle-dimen-size-200: var(--spectrum-large-global-dimension-size-200); + --colorhandle-background-offset: calc(-1 * var(--spectrum-large-global-dimension-size-25)); + --colorhandle-checkerboard-size: var(--spectrum-large-global-dimension-size-100); + --colorhandle-hitarea-size: var(--spectrum-large-global-dimension-size-300); + --colorhandle-size: var(--spectrum-large-colorhandle-size); + --colorhandle-inner-border-size: var(--spectrum-large-colorhandle-inner-border-size); + } + + ._coral-ColorPicker-colorHandle.is-focused, + ._coral-ColorPicker-colorHandle.focus-ring { + --colorhandle-size: var(--spectrum-large-colorhandle-size); + --colorhandle-hitarea-size: var(--spectrum-large-global-dimension-size-300); + } + @import 'size.styl' +} \ No newline at end of file diff --git a/coral-component-colorpicker/src/styles/colorhandle/light.styl b/coral-component-colorpicker/src/styles/colorhandle/light.styl new file mode 100644 index 0000000000..0a9bb8564d --- /dev/null +++ b/coral-component-colorpicker/src/styles/colorhandle/light.styl @@ -0,0 +1,21 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +@require '../../../../coral-theme-spectrum/src/styles/vars.css'; + +$colorhandle-inner-border-color = var(--spectrum-light-colorhandle-inner-border-color); +$colorhandle-inner-border-color-disabled = var(--spectrum-light-colorhandle-inner-border-color-disabled); +$colorhandle-fill-color-disabled = var(--spectrum-light-colorhandle-fill-color-disabled); + +.coral--light { + @import 'skin.styl' +} \ No newline at end of file diff --git a/coral-component-colorpicker/src/styles/colorhandle/lightest.styl b/coral-component-colorpicker/src/styles/colorhandle/lightest.styl new file mode 100644 index 0000000000..b099d1d731 --- /dev/null +++ b/coral-component-colorpicker/src/styles/colorhandle/lightest.styl @@ -0,0 +1,21 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +@require '../../../../coral-theme-spectrum/src/styles/vars.css'; + +$colorhandle-inner-border-color = var(--spectrum-lightest-colorhandle-inner-border-color); +$colorhandle-inner-border-color-disabled = var(--spectrum-lightest-colorhandle-inner-border-color-disabled); +$colorhandle-fill-color-disabled = var(--spectrum-lightest-colorhandle-fill-color-disabled); + +.coral--lightest { + @import 'skin.styl' +} \ No newline at end of file diff --git a/coral-component-colorpicker/src/styles/colorhandle/medium.styl b/coral-component-colorpicker/src/styles/colorhandle/medium.styl new file mode 100644 index 0000000000..51da609530 --- /dev/null +++ b/coral-component-colorpicker/src/styles/colorhandle/medium.styl @@ -0,0 +1,27 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +._coral-ColorPicker-colorHandle { + --colorhandle-dimen-size-200: var(--spectrum-medium-global-dimension-size-200); + --colorhandle-background-offset: calc(-1 * var(--spectrum-medium-global-dimension-size-25)); + --colorhandle-checkerboard-size: var(--spectrum-medium-global-dimension-size-100); + --colorhandle-hitarea-size: var(--spectrum-medium-global-dimension-size-300); + --colorhandle-size: var(--spectrum-medium-colorhandle-size); + --colorhandle-inner-border-size: var(--spectrum-medium-colorhandle-inner-border-size); +} + +._coral-ColorPicker-colorHandle.is-focused, +._coral-ColorPicker-colorHandle.focus-ring { + --colorhandle-size: var(--spectrum-medium-colorhandle-size); + --colorhandle-hitarea-size: var(--spectrum-medium-global-dimension-size-300); +} +@import 'size.styl' \ No newline at end of file diff --git a/coral-component-colorpicker/src/styles/colorhandle/size.styl b/coral-component-colorpicker/src/styles/colorhandle/size.styl new file mode 100644 index 0000000000..c07b9a266f --- /dev/null +++ b/coral-component-colorpicker/src/styles/colorhandle/size.styl @@ -0,0 +1,61 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +$colorhandle-animation-duration = var(--spectrum-global-animation-duration-100); +$colorhandle-animation-easing = ease-in-out; + +._coral-ColorPicker-colorHandle { + display: block; + position: absolute; + z-index: 1; + box-sizing: border-box; + width: var(--colorhandle-size); + height: var(--colorhandle-size); + margin-left: calc(-1*var(--colorhandle-size)/2); + margin-top: calc(-1*var(--colorhandle-size)/2); + border-width: var(--colorhandle-inner-border-size); + border-style: solid; + border-radius: 100%; + background-size: var(--colorhandle-dimen-size-200) var(--colorhandle-dimen-size-200); + background-position: + var(--colorhandle-background-offset) var(--colorhandle-background-offset), + var(--colorhandle-background-offset) calc(var(--colorhandle-checkerboard-size) + var(--colorhandle-background-offset)), + calc(var(--colorhandle-checkerboard-size) + var(--colorhandle-background-offset)) calc(-1 * var(--colorhandle-checkerboard-size) + var(--colorhandle-background-offset)), + calc(-1 * var(--colorhandle-checkerboard-size) + var(--colorhandle-background-offset)) var(--colorhandle-background-offset); + + transition: + width $colorhandle-animation-duration $colorhandle-animation-easing, + height $colorhandle-animation-duration $colorhandle-animation-easing, + border-width $colorhandle-animation-duration $colorhandle-animation-easing, + margin-left $colorhandle-animation-duration $colorhandle-animation-easing, + margin-top $colorhandle-animation-duration $colorhandle-animation-easing; +} + +._coral-ColorPicker-colorHandle.is-focused, +._coral-ColorPicker-colorHandle.focus-ring { + width: calc(var(--colorhandle-size)* 2); + height: calc(var(--colorhandle-size) * 2); + margin-left: calc(-1 * var(--colorhandle-size)); + margin-top: calc(-1 * var(--colorhandle-size)); +} + +._coral-ColorPicker-colorHandle:after { + border-radius: 100%; + content: ''; + left: calc(50% - var(--colorhandle-hitarea-size) / 2); + top: calc(50% - var(--colorhandle-hitarea-size) / 2); + position: absolute; + display: block; + width: var(--colorhandle-hitarea-size); + height: var(--colorhandle-hitarea-size); +} + diff --git a/coral-component-colorpicker/src/styles/colorhandle/skin.styl b/coral-component-colorpicker/src/styles/colorhandle/skin.styl new file mode 100644 index 0000000000..785aea063e --- /dev/null +++ b/coral-component-colorpicker/src/styles/colorhandle/skin.styl @@ -0,0 +1,56 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +@require '../../../../coral-theme-spectrum/src/styles/vars.css'; + +._coral-ColorPicker-colorHandle { + --spectrum-colorhandle-background-offset: calc(-1 * var(--spectrum-global-dimension-static-size-25, 2px)); + --spectrum-colorhandle-checkerboard-size: var(--spectrum-global-dimension-static-size-100, 8px); + --spectrum-colorhandle-outer-border-color: rgba(0, 0, 0, 0.42); +} + +_coral-ColorPicker-colorHandle-color { + --spectrum-colorhandle-outer-border-color: rgba(0, 0, 0, 0.42); +} + +._coral-ColorPicker-colorHandle{ + border-color: $colorhandle-inner-border-color; + box-shadow: 0 0 0 var(--spectrum-medium-colorhandle-outer-border-size, var(--spectrum-global-dimension-static-size-10)) var(--spectrum-colorhandle-outer-border-color, var(--spectrum-alias-colorhandle-outer-border-color)); + + background-color: var(--spectrum-global-color-static-white, rgb(255, 255, 255)); + background-image: + linear-gradient(-45deg, transparent 75.5%, var(--spectrum-global-color-static-gray-500) 75.5%), + linear-gradient(45deg, transparent 75.5%, var(--spectrum-global-color-static-gray-500) 75.5%), + linear-gradient(-45deg, var(--spectrum-global-color-static-gray-500) 25.5%, transparent 25.5%), + linear-gradient(45deg, var(--spectrum-global-color-static-gray-500) 25.5%, transparent 25.5%); +} + +._coral-ColorPicker-colorHandle.is-disabled { + border-color: $colorhandle-inner-border-color-disabled; + background: $colorhandle-fill-color-disabled; + box-shadow: none; +} + +._coral-ColorPicker-colorHandle-color { + box-shadow: 0 0 0 var(--spectrum-medium-colorhandle-outer-border-size) var(--spectrum-colorhandle-outer-border-color, var(--spectrum-alias-colorhandle-outer-border-color)); +} + +@media (forced-colors: active) { + ._coral-ColorPicker-colorHandle { + --spectrum-colorhandle-inner-border-color-disabled : GrayText; + --spectrum-colorhandle-fill-color-disabled: Canvas; + --spectrum-colorhandle-inner-border-color: CanvasText; + } + ._coral-ColorPicker-colorHandle.is-disabled { + forced-color-adjust: none; + } +} \ No newline at end of file diff --git a/coral-component-colorpicker/src/styles/colorslider/dark.styl b/coral-component-colorpicker/src/styles/colorslider/dark.styl new file mode 100644 index 0000000000..ac169feb07 --- /dev/null +++ b/coral-component-colorpicker/src/styles/colorslider/dark.styl @@ -0,0 +1,21 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +@require '../../../../coral-theme-spectrum/src/styles/vars.css'; + +$colorpicker-colorslider-fill-color-disabled = var(--spectrum-dark-colorslider-fill-color-disabled, var(--spectrum-dark-global-color-gray-300)); +$colorpicker-colorslider-border-color = var(--spectrum-dark-colorslider-border-color); +$colorpicker-colorslider-border-color-disabled = var(--spectrum-dark-colorslider-border-color-disabled, var(--spectrum-dark-global-color-gray-300)); + +.coral--dark { + @import 'skin.styl' +} \ No newline at end of file diff --git a/coral-component-colorpicker/src/styles/colorslider/darkest.styl b/coral-component-colorpicker/src/styles/colorslider/darkest.styl new file mode 100644 index 0000000000..17f981a52c --- /dev/null +++ b/coral-component-colorpicker/src/styles/colorslider/darkest.styl @@ -0,0 +1,21 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +@require '../../../../coral-theme-spectrum/src/styles/vars.css'; + +$colorpicker-colorslider-fill-color-disabled = var(--spectrum-darkest-colorslider-fill-color-disabled, var(--spectrum-dark-global-color-gray-300)); +$colorpicker-colorslider-border-color = var(--spectrum-darkest-colorslider-border-color); +$colorpicker-colorslider-border-color-disabled = var(--spectrum-darkest-colorslider-border-color-disabled, var(--spectrum-dark-global-color-gray-300)); + +.coral--darkest { + @import 'skin.styl' +} \ No newline at end of file diff --git a/coral-component-colorpicker/src/styles/colorslider/index.styl b/coral-component-colorpicker/src/styles/colorslider/index.styl new file mode 100644 index 0000000000..eb76c4889a --- /dev/null +++ b/coral-component-colorpicker/src/styles/colorslider/index.styl @@ -0,0 +1,32 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +@require '../../../coral-theme-spectrum/src/styles/vars.css'; + +._coral-ColorPicker-ColorSlider-slider { + opacity: 0.0001; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 0; + margin: 0; + pointer-events: none; +} + +@require 'medium'; +@require 'large'; +@require 'light'; +@require 'lightest'; +@require 'dark'; +@require 'darkest'; \ No newline at end of file diff --git a/coral-component-colorpicker/src/styles/colorslider/large.styl b/coral-component-colorpicker/src/styles/colorslider/large.styl new file mode 100644 index 0000000000..5241cab0ea --- /dev/null +++ b/coral-component-colorpicker/src/styles/colorslider/large.styl @@ -0,0 +1,40 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +.coral--large { + ._coral-ColorPicker-ColorSlider-colorHandle { + --colorslider-handle-hitarea-border-radius: 0%; + --colorslider-handle-hitarea-width: var( + -spectrum-large-global-dimension-size-300 + ); + --colorslider-handle-hitarea-height: var( + -spectrum-large-global-dimension-size-300 + ); + } + + ._coral-ColorPicker-ColorSlider.is-focused ._coral-ColorPicker-ColorSlider-colorHandle { + --colorslider-colorhandle-size: var(--spectrum-large-colorhandle-size); + } + + ._coral-ColorPicker-ColorSlider { + --colorslider-vertical-width: var(--spectrum-large-colorslider-vertical-width, var(--spectrum-large-global-dimension-size-300)); + --colorslider-vertical-height: var(--spectrum-large-colorslider-vertical-default-height, var(-spectrum-large-global-dimension-size-2400)); + } + + ._coral-ColorPicker-ColorSlider-checkerboard, + ._coral-ColorPicker-ColorSlider-gradient { + --colorslider-dimen-size-200: var(--spectrum-large-global-dimension-size-200); + --colorslider-dimen-size-100: var(--spectrum-large-global-dimension-size-100); + --colorslider-border-radius: var(--spectrum-large-colorslider-border-radius); + } + @import 'size.styl' +} \ No newline at end of file diff --git a/coral-component-colorpicker/src/styles/colorslider/light.styl b/coral-component-colorpicker/src/styles/colorslider/light.styl new file mode 100644 index 0000000000..ae56784d40 --- /dev/null +++ b/coral-component-colorpicker/src/styles/colorslider/light.styl @@ -0,0 +1,21 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +@require '../../../../coral-theme-spectrum/src/styles/vars.css'; + +$colorpicker-colorslider-fill-color-disabled = var(--spectrum-light-colorslider-fill-color-disabled, var(--spectrum-dark-global-color-gray-300)); +$colorpicker-colorslider-border-color = var(--spectrum-light-colorslider-border-color); +$colorpicker-colorslider-border-color-disabled = var(--spectrum-light-colorslider-border-color-disabled, var(--spectrum-dark-global-color-gray-300)); + +.coral--light { + @import 'skin.styl' +} \ No newline at end of file diff --git a/coral-component-colorpicker/src/styles/colorslider/lightest.styl b/coral-component-colorpicker/src/styles/colorslider/lightest.styl new file mode 100644 index 0000000000..d96b55a204 --- /dev/null +++ b/coral-component-colorpicker/src/styles/colorslider/lightest.styl @@ -0,0 +1,21 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +@require '../../../../coral-theme-spectrum/src/styles/vars.css'; + +$colorpicker-colorslider-fill-color-disabled = var(--spectrum-lightest-colorslider-fill-color-disabled, var(--spectrum-dark-global-color-gray-300)); +$colorpicker-colorslider-border-color = var(--spectrum-lightest-colorslider-border-color); +$colorpicker-colorslider-border-color-disabled = var(--spectrum-lightest-colorslider-border-color-disabled, var(--spectrum-dark-global-color-gray-300)); + +.coral--lightest { + @import 'skin.styl' +} \ No newline at end of file diff --git a/coral-component-colorpicker/src/styles/colorslider/medium.styl b/coral-component-colorpicker/src/styles/colorslider/medium.styl new file mode 100644 index 0000000000..8d1eb22eeb --- /dev/null +++ b/coral-component-colorpicker/src/styles/colorslider/medium.styl @@ -0,0 +1,37 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +._coral-ColorPicker-ColorSlider-colorHandle { + --colorslider-handle-hitarea-border-radius: 0%; + --colorslider-handle-hitarea-width: var( + -spectrum-medium-global-dimension-size-300 + ); + --colorslider-handle-hitarea-height: var( + -spectrum-medium-global-dimension-size-300 + ); +} +._coral-ColorPicker-ColorSlider.is-focused ._coral-ColorPicker-ColorSlider-colorHandle { + --colorslider-colorhandle-size: var(--spectrum-medium-colorhandle-size); +} + +._coral-ColorPicker-ColorSlider { + --colorslider-vertical-width: var(--spectrum-medium-colorslider-vertical-width, var(--spectrum-medium-global-dimension-size-300)); + --colorslider-vertical-height: var(--spectrum-medium-colorslider-vertical-default-height, var(-spectrum-medium-global-dimension-size-2400)); +} + +._coral-ColorPicker-ColorSlider-checkerboard, +._coral-ColorPicker-ColorSlider-gradient { + --colorslider-dimen-size-200: var(--spectrum-medium-global-dimension-size-200); + --colorslider-dimen-size-100: var(--spectrum-medium-global-dimension-size-100); + --colorslider-border-radius: var(--spectrum-medium-colorslider-border-radius); +} +@import 'size.styl' \ No newline at end of file diff --git a/coral-component-colorpicker/src/styles/colorslider/size.styl b/coral-component-colorpicker/src/styles/colorslider/size.styl new file mode 100644 index 0000000000..70c4c29491 --- /dev/null +++ b/coral-component-colorpicker/src/styles/colorslider/size.styl @@ -0,0 +1,82 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +._coral-ColorPicker-ColorSlider.is-focused ._coral-ColorPicker-ColorSlider-colorHandle { + width: calc(var(--colorslider-colorhandle-size) * 2); + height: calc(var(--colorslider-colorhandle-size) * 2); + + margin-left: calc(-1 * var(--colorslider-colorhandle-size)); + margin-top: calc(-1 * var(--colorslider-colorhandle-size)); +} + +._coral-ColorPicker-ColorSlider { + position: relative; + display: block; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + cursor: default; + + //specific to vertical slider + display: inline-block; + width: var(--colorslider-vertical-width); + height: var(--colorslider-vertical-height); + + &.is-focused { + z-index: 2; + } + + &.is-disabled { + pointer-events: none; + } +} + +._coral-ColorPicker-ColorSlider-colorHandle { + //specific to vertical slider + left: 50%; + top: 0; + + &:after { + border-radius: var(--colorslider-handle-hitarea-border-radius); + width: var(--colorslider-handle-hitarea-width); + height: var(--colorslider-handle-hitarea-height); + } +} + + +._coral-ColorPicker-ColorSlider-checkerboard { + background-size: var(--colorslider-dimen-size-200, 16px) + var(--colorslider-dimen-size-200, 16px); + background-position: 0 0, + 0 var(--colorslider-dimen-size-100, 8px), + var(--colorslider-dimen-size-100, 8px) calc(-1 * var(--colorslider-dimen-size-100, 8px)), + calc(-1 * var(--colorslider-dimen-size-100, 8px)) 0; + &:before { + content: ""; + z-index: 1; + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + border-radius: var(--colorslider-border-radius, var(--spectrum-alias-border-radius-regular)); + } +} + +._coral-ColorPicker-ColorSlider-checkerboard, +._coral-ColorPicker-ColorSlider-gradient { + width: 100%; + height: 100%; + border-radius: var(--colorslider-border-radius, var(--spectrum-alias-border-radius-regular)); +} + diff --git a/coral-component-colorpicker/src/styles/colorslider/skin.styl b/coral-component-colorpicker/src/styles/colorslider/skin.styl new file mode 100644 index 0000000000..c37078a7de --- /dev/null +++ b/coral-component-colorpicker/src/styles/colorslider/skin.styl @@ -0,0 +1,50 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +._coral-ColorPicker-ColorSlider-checkerboard { + background-color: var(--spectrum-global-color-static-white, rgb(255, 255, 255)); + background-image: + linear-gradient(-45deg, transparent 75.5%, var(--spectrum-global-color-static-gray-500) 75.5%), + linear-gradient(45deg, transparent 75.5%, var(--spectrum-global-color-static-gray-500) 75.5%), + linear-gradient(-45deg, var(--spectrum-global-color-static-gray-500) 25.5%, transparent 25.5%), + linear-gradient(45deg, var(--spectrum-global-color-static-gray-500) 25.5%, transparent 25.5%); +} + +._coral-ColorPicker-ColorSlider-checkerboard:before { +// box-shadow: inset 0 0 0 var(--spectrum-medium-colorslider-border-size, var(--spectrum-alias-border-size-thin)) $colorpicker-colorslider-border-color; +} + +._coral-ColorPicker-ColorSlider.is-disabled ._coral-ColorPicker-ColorSlider-checkerboard { + background: $colorpicker-colorslider-fill-color-disabled; +} + +._coral-ColorPicker-ColorSlider.is-disabled ._coral-ColorPicker-ColorSlider-gradient { + display: none +} + +._coral-ColorPicker-ColorSlider-hue ._coral-ColorPicker-ColorSlider-gradient { + background: linear-gradient(to top, hsl(0,100%,50%), hsl(60, 100%,50%), hsl(120, 100%,50%), hsl(180, 100%,50%), hsl(240, 100%,50%), hsl(300, 100%,50%), hsl(360, 100%,50%)); +} + +._coral-ColorPicker-ColorSlider.is-disabled ._coral-ColorPicker-ColorSlider-checkerboard:before { +// box-shadow: 0 0 0 var(--spectrum-medium-colorslider-border-size, var(--spectrum-alias-border-size-thin)) var($colorpicker-colorslider-border-color-disabled, var(--spectrum-global-color-gray-300)); +} + +@media (forced-colors: active) { + ._coral-ColorPicker-ColorSlider { + --spectrum-colorslider-border-color-disabled : GrayText; + --spectrum-colorslider-fill-color-disabled : Canvas; + } + ._coral-ColorPicker-ColorSlider { + forced-color-adjust: none; + } +} \ No newline at end of file diff --git a/coral-component-colorpicker/src/styles/dark.styl b/coral-component-colorpicker/src/styles/dark.styl new file mode 100644 index 0000000000..b90e2397b3 --- /dev/null +++ b/coral-component-colorpicker/src/styles/dark.styl @@ -0,0 +1,22 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +$colorpicker-colorarea-border-color = var(--spectrum-dark-colorarea-border-color); +$colorpicker-colorarea-border-color-hover = var(--spectrum-dark-colorarea-border-color-hover); +$colorpicker-colorarea-fill-color-disabled = var(--spectrum-dark-colorarea-fill-color-disabled); +$colorpicker-colorslider-border-color = var(--spectrum-dark-colorslider-border-color); +$colorpicker-colorslider-border-color-hover = var(--spectrum-dark-colorslider-border-color-hover); +$colorpicker-colorslider-fill-color-disabled = var(--spectrum-dark-colorslider-vertical-border-color-disabled); + +.coral--dark { + @import 'skin.styl' +} diff --git a/coral-component-colorpicker/src/styles/darkest.styl b/coral-component-colorpicker/src/styles/darkest.styl new file mode 100644 index 0000000000..57ddf9a9a1 --- /dev/null +++ b/coral-component-colorpicker/src/styles/darkest.styl @@ -0,0 +1,22 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +$colorpicker-colorarea-border-color = var(--spectrum-darkest-colorarea-border-color); +$colorpicker-colorarea-border-color-hover = var(--spectrum-darkest-colorarea-border-color-hover); +$colorpicker-colorarea-fill-color-disabled = var(--spectrum-darkest-colorarea-fill-color-disabled); +$colorpicker-colorslider-border-color = var(--spectrum-darkest-colorslider-border-color); +$colorpicker-colorslider-border-color-hover = var(--spectrum-darkest-colorslider-border-color-hover); +$colorpicker-colorslider-fill-color-disabled = var(--spectrum-darkest-colorslider-vertical-border-color-disabled); + +.coral--darkest { + @import 'skin.styl' +} diff --git a/coral-component-colorpicker/src/styles/embed/ColorBlank.svg b/coral-component-colorpicker/src/styles/embed/ColorBlank.svg new file mode 100644 index 0000000000..382abceef3 --- /dev/null +++ b/coral-component-colorpicker/src/styles/embed/ColorBlank.svg @@ -0,0 +1,11 @@ + + + + + + + diff --git a/coral-component-colorpicker/src/styles/embed/Transparency.svg b/coral-component-colorpicker/src/styles/embed/Transparency.svg new file mode 100644 index 0000000000..e3f886f614 --- /dev/null +++ b/coral-component-colorpicker/src/styles/embed/Transparency.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/coral-component-colorpicker/src/styles/index.styl b/coral-component-colorpicker/src/styles/index.styl new file mode 100644 index 0000000000..2cb1126f0a --- /dev/null +++ b/coral-component-colorpicker/src/styles/index.styl @@ -0,0 +1,126 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +@require '../../../coral-theme-spectrum/src/styles/vars.css'; +$colorpicker-transparency-url = './embed/Transparency.svg'; +$colorpicker-blank-url = './embed/ColorBlank.svg'; +$colorpicker-input-size = 38px; +$colorpicker-button-wrapper-offset = 2px; +$colorpicker-button-size = 28px; +$colorpicker-button-border-radius = var(--spectrum-medium-actionbutton-border-radius); +$colorpicker-button-border-width = var(--spectrum-medium-actionbutton-border-size); + +//overlay +._coral-ColorPicker { + position: relative; + display: inline-block; +} + +._coral-ColorPicker-input { + display: block; + // makes space for the color preview + padding-right: $colorpicker-input-size; + // allows the input to grow with the container + width: 100%; +} + +._coral-ColorPicker-buttonWrapper { + position: absolute; + right: $colorpicker-button-wrapper-offset; + top: $colorpicker-button-wrapper-offset; + + // set opacity < 1 to create new stacking context (for checker image to work) + opacity: .999; + + ._coral-ColorPicker-preview { + border-width: $colorpicker-button-border-width; + } +} + +._coral-ColorPicker-previewView { + display: inline-block; +} + +._coral-ColorPicker-button { + width: $colorpicker-button-size; + height: $colorpicker-button-size; + position: relative; + + padding: 0; + margin: 0; +} + +._coral-ColorPicker-preview { + border-radius: $colorpicker-button-border-radius; + box-sizing: border-box; + background-origin: border-box; + + &:before { + display: block; + position: absolute; + left: 0; + top: 0; + z-index: -1; + content: ""; + width: 100%; + height: 100%; + + background-image: svgImport($colorpicker-transparency-url); + background-repeat: no-repeat; + background-position: center; + background-size: 100%; + } +} + +._coral-ColorPicker-preview:not([disabled]):hover { + &:after { + display: block; + position: absolute; + left: 0; + top: 0; + z-index: 1; + content: ""; + width: 100%; + height: 100%; + } +} + +._coral-ColorPicker--novalue ._coral-ColorPicker-preview, +._coral-ColorPicker-preview--novalue, +._coral-ColorPicker.is-invalid ._coral-ColorPicker-preview { + background-image: svgImport($colorpicker-blank-url); + background-repeat: no-repeat; + background-position: center; + background-size: 100%; + + &:hover, &:focus { + background-image: svgImport($colorpicker-blank-url); + background-repeat: no-repeat; + background-position: center; + background-size: 100%; + } +} + +._coral-ColorPicker-overlay { + padding: 0px; + min-width: auto; +} + +@require 'medium'; +@require 'large'; +@require './colorhandle/index' +@require './colorarea/index' +@require './colorslider/index' +@require 'light'; +@require 'lightest'; +@require 'dark'; +@require 'darkest'; diff --git a/coral-component-colorpicker/src/styles/large.styl b/coral-component-colorpicker/src/styles/large.styl new file mode 100644 index 0000000000..c47a761669 --- /dev/null +++ b/coral-component-colorpicker/src/styles/large.styl @@ -0,0 +1,26 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +.coral--large { + ._coral-ColorPicker { + ._coral-ColorPicker-button { + height: 36px; + padding: 0 17px; + } + + --colorpicker-margin-size-200: var(--spectrum-large-global-dimension-size-200); + --colorpicker-dimen-size-900: var(--spectrum-large-global-dimension-size-900); + --colorpicker-dimen-size-25: var(--spectrum-large-global-dimension-size-25); + --colorpicker-dimen-size-2400: var(--spectrum-large-global-dimension-size-2400); + } + @import 'size.styl' +} \ No newline at end of file diff --git a/coral-component-colorpicker/src/styles/light.styl b/coral-component-colorpicker/src/styles/light.styl new file mode 100644 index 0000000000..a877546403 --- /dev/null +++ b/coral-component-colorpicker/src/styles/light.styl @@ -0,0 +1,22 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +$colorpicker-colorarea-border-color = var(--spectrum-light-colorarea-border-color); +$colorpicker-colorarea-border-color-hover = var(--spectrum-light-colorarea-border-color-hover); +$colorpicker-colorarea-fill-color-disabled = var(--spectrum-light-colorarea-fill-color-disabled); +$colorpicker-colorslider-border-color = var(--spectrum-light-colorslider-border-color); +$colorpicker-colorslider-border-color-hover = var(--spectrum-light-colorslider-border-color-hover); +$colorpicker-colorslider-fill-color-disabled = var(--spectrum-light-colorslider-vertical-border-color-disabled); + +.coral--light { + @import 'skin.styl' +} diff --git a/coral-component-colorpicker/src/styles/lightest.styl b/coral-component-colorpicker/src/styles/lightest.styl new file mode 100644 index 0000000000..55347f876b --- /dev/null +++ b/coral-component-colorpicker/src/styles/lightest.styl @@ -0,0 +1,22 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +$colorpicker-colorarea-border-color = var(--spectrum-lightest-colorarea-border-color); +$colorpicker-colorarea-border-color-hover = var(--spectrum-lightest-colorarea-border-color-hover); +$colorpicker-colorarea-fill-color-disabled = var(--spectrum-lightest-colorarea-fill-color-disabled); +$colorpicker-colorslider-border-color = var(--spectrum-lightest-colorslider-border-color); +$colorpicker-colorslider-border-color-hover = var(--spectrum-lightest-colorslider-border-color-hover); +$colorpicker-colorslider-fill-color-disabled = var(--spectrum-lightest-colorslider-vertical-border-color-disabled); + +.coral--lightest { + @import 'skin.styl' +} diff --git a/coral-component-colorpicker/src/styles/medium.styl b/coral-component-colorpicker/src/styles/medium.styl new file mode 100644 index 0000000000..340232c6a0 --- /dev/null +++ b/coral-component-colorpicker/src/styles/medium.styl @@ -0,0 +1,19 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +._coral-ColorPicker { + --colorpicker-margin-size-200: var(--spectrum-medium-global-dimension-size-200); + --colorpicker-dimen-size-900: var(--spectrum-medium-global-dimension-size-900); + --colorpicker-dimen-size-2400: var(--spectrum-medium-global-dimension-size-2400); + --colorpicker-dimen-size-25: var(--spectrum-medium-global-dimension-size-25); +} +@import 'size.styl' \ No newline at end of file diff --git a/coral-component-colorpicker/src/styles/size.styl b/coral-component-colorpicker/src/styles/size.styl new file mode 100644 index 0000000000..279e5afbfa --- /dev/null +++ b/coral-component-colorpicker/src/styles/size.styl @@ -0,0 +1,40 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +._coral-ColorPicker ._coral-ColorPicker-propertiesContainer1 { + display: flex; + padding: calc(var(--colorpicker-margin-size-200) + 1px); +} + +._coral-ColorPicker ._coral-ColorPicker-propertiesContainer1 ._coral-ColorPicker-ColorSlider { + margin-left: calc(var(--colorpicker-margin-size-200) + 1px); +} + +._coral-ColorPicker ._coral-ColorPicker-propertiesContainer2 { + width: var(--colorpicker-dimen-size-2400); + display: flex; + padding: calc(var(--colorpicker-margin-size-200) + 1px); + padding-top: 0px; +} + +._coral-ColorPicker ._coral-ColorPicker-inputField { + margin-left: var(--colorpicker-margin-size-200); +} + +._coral-ColorPicker ._coral-ColorPicker-formatSelector { + width: var(--colorpicker-dimen-size-900); + padding-bottom: var(--colorpicker-dimen-size-25); +} + +._coral-ColorPicker ._coral-ColorPicker-value { + margin-left: var(--colorpicker-margin-size-200); +} diff --git a/coral-component-colorpicker/src/styles/skin.styl b/coral-component-colorpicker/src/styles/skin.styl new file mode 100644 index 0000000000..f65ac59280 --- /dev/null +++ b/coral-component-colorpicker/src/styles/skin.styl @@ -0,0 +1,31 @@ +/** + * Copyright 2021 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +._coral-ColorPicker-ColorArea-gradient { + border-color: $colorpicker-colorarea-border-color; + &:hover { + border-color: $colorpicker-colorarea-border-color-hover; + } + &:disabled, &[disabled] { + background:$colorpicker-colorarea-fill-color-disabled; + } +} + +._coral-ColorPicker-ColorSlider { + border-color: $colorpicker-colorslider-border-color; + &:hover { + border-color: $colorpicker-colorslider-border-color-hover; + } + &:disabled, &[disabled] { + background:$colorpicker-colorslider-fill-color-disabled; + } +} diff --git a/coral-component-colorpicker/src/templates/base.html b/coral-component-colorpicker/src/templates/base.html new file mode 100644 index 0000000000..02b253ea43 --- /dev/null +++ b/coral-component-colorpicker/src/templates/base.html @@ -0,0 +1,15 @@ +var uid = data.commons.getUID(); +var uidBtn = data.commons.getUID(); +var uidInput = data.commons.getUID() + + + + + \ No newline at end of file diff --git a/coral-component-colorpicker/src/templates/colorArea.html b/coral-component-colorpicker/src/templates/colorArea.html new file mode 100644 index 0000000000..7390babb24 --- /dev/null +++ b/coral-component-colorpicker/src/templates/colorArea.html @@ -0,0 +1,4 @@ +