@react-stately/color 3.5.4-nightly.4569 → 3.5.4-nightly.4578
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Color.main.js +37 -34
- package/dist/Color.main.js.map +1 -1
- package/dist/Color.mjs +37 -35
- package/dist/Color.module.js +37 -35
- package/dist/Color.module.js.map +1 -1
- package/dist/import.mjs +6 -2
- package/dist/main.js +7 -0
- package/dist/main.js.map +1 -1
- package/dist/module.js +6 -2
- package/dist/module.js.map +1 -1
- package/dist/types.d.ts +33 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/useColorAreaState.main.js +6 -2
- package/dist/useColorAreaState.main.js.map +1 -1
- package/dist/useColorAreaState.mjs +7 -3
- package/dist/useColorAreaState.module.js +7 -3
- package/dist/useColorAreaState.module.js.map +1 -1
- package/dist/useColorChannelFieldState.main.js +48 -0
- package/dist/useColorChannelFieldState.main.js.map +1 -0
- package/dist/useColorChannelFieldState.mjs +43 -0
- package/dist/useColorChannelFieldState.module.js +43 -0
- package/dist/useColorChannelFieldState.module.js.map +1 -0
- package/dist/useColorPickerState.main.js +27 -0
- package/dist/useColorPickerState.main.js.map +1 -0
- package/dist/useColorPickerState.mjs +22 -0
- package/dist/useColorPickerState.module.js +22 -0
- package/dist/useColorPickerState.module.js.map +1 -0
- package/dist/useColorSliderState.main.js +10 -3
- package/dist/useColorSliderState.main.js.map +1 -1
- package/dist/useColorSliderState.mjs +10 -3
- package/dist/useColorSliderState.module.js +10 -3
- package/dist/useColorSliderState.module.js.map +1 -1
- package/dist/useColorWheelState.main.js +9 -2
- package/dist/useColorWheelState.main.js.map +1 -1
- package/dist/useColorWheelState.mjs +10 -3
- package/dist/useColorWheelState.module.js +10 -3
- package/dist/useColorWheelState.module.js.map +1 -1
- package/package.json +11 -9
- package/src/Color.ts +55 -38
- package/src/index.ts +5 -1
- package/src/useColorAreaState.ts +3 -1
- package/src/useColorChannelFieldState.ts +49 -0
- package/src/useColorPickerState.ts +27 -0
- package/src/useColorSliderState.ts +9 -4
- package/src/useColorWheelState.ts +12 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":";;;;;;;;;;AAAA;;;;;;;;;;CAUC;;;
|
|
1
|
+
{"mappings":"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","sources":["packages/@react-stately/color/src/useColorWheelState.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {Color, ColorWheelProps} from '@react-types/color';\nimport {normalizeColor, parseColor} from './Color';\nimport {useControlledState} from '@react-stately/utils';\nimport {useMemo, useRef, useState} from 'react';\n\nexport interface ColorWheelState {\n /** The current color value represented by the color wheel. */\n readonly value: Color,\n /** Sets the color value represented by the color wheel, and triggers `onChange`. */\n setValue(value: string | Color): void,\n\n /** The current value of the hue channel displayed by the color wheel. */\n readonly hue: number,\n /** Sets the hue channel of the current color value and triggers `onChange`. */\n setHue(value: number): void,\n\n /** Sets the hue channel of the current color value based on the given coordinates and radius of the color wheel, and triggers `onChange`. */\n setHueFromPoint(x: number, y: number, radius: number): void,\n /** Returns the coordinates of the thumb relative to the center point of the color wheel. */\n getThumbPosition(radius: number): {x: number, y: number},\n\n /** Increments the hue by the given amount (defaults to 1). */\n increment(stepSize?: number): void,\n /** Decrements the hue by the given amount (defaults to 1). */\n decrement(stepSize?: number): void,\n\n /** Whether the color wheel is currently being dragged. */\n readonly isDragging: boolean,\n /** Sets whether the color wheel is being dragged. */\n setDragging(value: boolean): void,\n /** Returns the color that should be displayed in the color wheel instead of `value`. */\n getDisplayColor(): Color,\n /** The step value of the hue channel, used when incrementing and decrementing. */\n step: number,\n /** The page step value of the hue channel, used when incrementing and decrementing. */\n pageStep: number,\n\n /** Whether the color wheel is disabled. */\n readonly isDisabled: boolean\n}\n\nconst DEFAULT_COLOR = parseColor('hsl(0, 100%, 50%)');\n\nfunction roundToStep(value: number, step: number): number {\n return Math.round(value / step) * step;\n}\n\nfunction mod(n: number, m: number) {\n return ((n % m) + m) % m;\n}\n\nfunction roundDown(v: number) {\n let r = Math.floor(v);\n if (r === v) {\n return v - 1;\n } else {\n return r;\n }\n}\n\nfunction degToRad(deg: number) {\n return deg * Math.PI / 180;\n}\n\nfunction radToDeg(rad: number) {\n return rad * 180 / Math.PI;\n}\n\n// 0deg = 3 o'clock. increases clockwise\nfunction angleToCartesian(angle: number, radius: number): {x: number, y: number} {\n let rad = degToRad(360 - angle + 90);\n let x = Math.sin(rad) * (radius);\n let y = Math.cos(rad) * (radius);\n return {x, y};\n}\n\nfunction cartesianToAngle(x: number, y: number, radius: number): number {\n let deg = radToDeg(Math.atan2(y / radius, x / radius));\n return (deg + 360) % 360;\n}\n\n/**\n * Provides state management for a color wheel component.\n * Color wheels allow users to adjust the hue of an HSL or HSB color value on a circular track.\n */\nexport function useColorWheelState(props: ColorWheelProps): ColorWheelState {\n let {defaultValue, onChange, onChangeEnd} = props;\n\n if (!props.value && !defaultValue) {\n defaultValue = DEFAULT_COLOR;\n }\n\n let [stateValue, setValueState] = useControlledState(normalizeColor(props.value), normalizeColor(defaultValue), onChange);\n let value = useMemo(() => {\n let colorSpace = stateValue.getColorSpace();\n return colorSpace === 'hsl' || colorSpace === 'hsb' ? stateValue : stateValue.toFormat('hsl');\n }, [stateValue]);\n let valueRef = useRef(value);\n let setValue = (value: Color) => {\n valueRef.current = value;\n setValueState(value);\n };\n\n let channelRange = value.getChannelRange('hue');\n let {minValue: minValueX, maxValue: maxValueX, step: step, pageSize: pageStep} = channelRange;\n let [isDragging, setDragging] = useState(false);\n let isDraggingRef = useRef(false);\n\n let hue = value.getChannelValue('hue');\n function setHue(v: number) {\n if (v > 360) {\n // Make sure you can always get back to 0.\n v = 0;\n }\n v = roundToStep(mod(v, 360), step);\n if (hue !== v) {\n let color = value.withChannelValue('hue', v);\n setValue(color);\n }\n }\n\n return {\n value,\n step,\n pageStep,\n setValue(v) {\n let color = normalizeColor(v);\n setValue(color);\n },\n hue,\n setHue,\n setHueFromPoint(x, y, radius) {\n setHue(cartesianToAngle(x, y, radius));\n },\n getThumbPosition(radius) {\n return angleToCartesian(value.getChannelValue('hue'), radius);\n },\n increment(stepSize = 1) {\n let s = Math.max(stepSize, step);\n let newValue = hue + s;\n if (newValue >= maxValueX) {\n // Make sure you can always get back to 0.\n newValue = minValueX;\n }\n setHue(roundToStep(mod(newValue, 360), s));\n },\n decrement(stepSize = 1) {\n let s = Math.max(stepSize, step);\n if (hue === 0) {\n // We can't just subtract step because this might be the case:\n // |(previous step) - 0| < step size\n setHue(roundDown(360 / s) * s);\n } else {\n setHue(roundToStep(mod(hue - s, 360), s));\n }\n },\n setDragging(isDragging) {\n let wasDragging = isDraggingRef.current;\n isDraggingRef.current = isDragging;\n\n if (onChangeEnd && !isDragging && wasDragging) {\n onChangeEnd(valueRef.current);\n }\n\n setDragging(isDragging);\n },\n isDragging,\n getDisplayColor() {\n return value.toFormat('hsl').withChannelValue('saturation', 100).withChannelValue('lightness', 50).withChannelValue('alpha', 1);\n },\n isDisabled: props.isDisabled || false\n };\n}\n"],"names":[],"version":3,"file":"useColorWheelState.main.js.map"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {normalizeColor as $799cddbef784668f$export$4cde5df63f53f473, parseColor as $799cddbef784668f$export$6e865ea70d7724f} from "./Color.mjs";
|
|
2
2
|
import {useControlledState as $d4Pfi$useControlledState} from "@react-stately/utils";
|
|
3
|
-
import {useRef as $d4Pfi$useRef, useState as $d4Pfi$useState} from "react";
|
|
3
|
+
import {useMemo as $d4Pfi$useMemo, useRef as $d4Pfi$useRef, useState as $d4Pfi$useState} from "react";
|
|
4
4
|
|
|
5
5
|
/*
|
|
6
6
|
* Copyright 2020 Adobe. All rights reserved.
|
|
@@ -50,7 +50,13 @@ function $ee4262c74a467b07$var$cartesianToAngle(x, y, radius) {
|
|
|
50
50
|
function $ee4262c74a467b07$export$f4301076d9336137(props) {
|
|
51
51
|
let { defaultValue: defaultValue, onChange: onChange, onChangeEnd: onChangeEnd } = props;
|
|
52
52
|
if (!props.value && !defaultValue) defaultValue = $ee4262c74a467b07$var$DEFAULT_COLOR;
|
|
53
|
-
let [
|
|
53
|
+
let [stateValue, setValueState] = (0, $d4Pfi$useControlledState)((0, $799cddbef784668f$export$4cde5df63f53f473)(props.value), (0, $799cddbef784668f$export$4cde5df63f53f473)(defaultValue), onChange);
|
|
54
|
+
let value = (0, $d4Pfi$useMemo)(()=>{
|
|
55
|
+
let colorSpace = stateValue.getColorSpace();
|
|
56
|
+
return colorSpace === "hsl" || colorSpace === "hsb" ? stateValue : stateValue.toFormat("hsl");
|
|
57
|
+
}, [
|
|
58
|
+
stateValue
|
|
59
|
+
]);
|
|
54
60
|
let valueRef = (0, $d4Pfi$useRef)(value);
|
|
55
61
|
let setValue = (value)=>{
|
|
56
62
|
valueRef.current = value;
|
|
@@ -109,7 +115,8 @@ function $ee4262c74a467b07$export$f4301076d9336137(props) {
|
|
|
109
115
|
isDragging: isDragging,
|
|
110
116
|
getDisplayColor () {
|
|
111
117
|
return value.toFormat("hsl").withChannelValue("saturation", 100).withChannelValue("lightness", 50).withChannelValue("alpha", 1);
|
|
112
|
-
}
|
|
118
|
+
},
|
|
119
|
+
isDisabled: props.isDisabled || false
|
|
113
120
|
};
|
|
114
121
|
}
|
|
115
122
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {normalizeColor as $799cddbef784668f$export$4cde5df63f53f473, parseColor as $799cddbef784668f$export$6e865ea70d7724f} from "./Color.module.js";
|
|
2
2
|
import {useControlledState as $d4Pfi$useControlledState} from "@react-stately/utils";
|
|
3
|
-
import {useRef as $d4Pfi$useRef, useState as $d4Pfi$useState} from "react";
|
|
3
|
+
import {useMemo as $d4Pfi$useMemo, useRef as $d4Pfi$useRef, useState as $d4Pfi$useState} from "react";
|
|
4
4
|
|
|
5
5
|
/*
|
|
6
6
|
* Copyright 2020 Adobe. All rights reserved.
|
|
@@ -50,7 +50,13 @@ function $ee4262c74a467b07$var$cartesianToAngle(x, y, radius) {
|
|
|
50
50
|
function $ee4262c74a467b07$export$f4301076d9336137(props) {
|
|
51
51
|
let { defaultValue: defaultValue, onChange: onChange, onChangeEnd: onChangeEnd } = props;
|
|
52
52
|
if (!props.value && !defaultValue) defaultValue = $ee4262c74a467b07$var$DEFAULT_COLOR;
|
|
53
|
-
let [
|
|
53
|
+
let [stateValue, setValueState] = (0, $d4Pfi$useControlledState)((0, $799cddbef784668f$export$4cde5df63f53f473)(props.value), (0, $799cddbef784668f$export$4cde5df63f53f473)(defaultValue), onChange);
|
|
54
|
+
let value = (0, $d4Pfi$useMemo)(()=>{
|
|
55
|
+
let colorSpace = stateValue.getColorSpace();
|
|
56
|
+
return colorSpace === "hsl" || colorSpace === "hsb" ? stateValue : stateValue.toFormat("hsl");
|
|
57
|
+
}, [
|
|
58
|
+
stateValue
|
|
59
|
+
]);
|
|
54
60
|
let valueRef = (0, $d4Pfi$useRef)(value);
|
|
55
61
|
let setValue = (value)=>{
|
|
56
62
|
valueRef.current = value;
|
|
@@ -109,7 +115,8 @@ function $ee4262c74a467b07$export$f4301076d9336137(props) {
|
|
|
109
115
|
isDragging: isDragging,
|
|
110
116
|
getDisplayColor () {
|
|
111
117
|
return value.toFormat("hsl").withChannelValue("saturation", 100).withChannelValue("lightness", 50).withChannelValue("alpha", 1);
|
|
112
|
-
}
|
|
118
|
+
},
|
|
119
|
+
isDisabled: props.isDisabled || false
|
|
113
120
|
};
|
|
114
121
|
}
|
|
115
122
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":";;;;AAAA;;;;;;;;;;CAUC;;;
|
|
1
|
+
{"mappings":"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","sources":["packages/@react-stately/color/src/useColorWheelState.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {Color, ColorWheelProps} from '@react-types/color';\nimport {normalizeColor, parseColor} from './Color';\nimport {useControlledState} from '@react-stately/utils';\nimport {useMemo, useRef, useState} from 'react';\n\nexport interface ColorWheelState {\n /** The current color value represented by the color wheel. */\n readonly value: Color,\n /** Sets the color value represented by the color wheel, and triggers `onChange`. */\n setValue(value: string | Color): void,\n\n /** The current value of the hue channel displayed by the color wheel. */\n readonly hue: number,\n /** Sets the hue channel of the current color value and triggers `onChange`. */\n setHue(value: number): void,\n\n /** Sets the hue channel of the current color value based on the given coordinates and radius of the color wheel, and triggers `onChange`. */\n setHueFromPoint(x: number, y: number, radius: number): void,\n /** Returns the coordinates of the thumb relative to the center point of the color wheel. */\n getThumbPosition(radius: number): {x: number, y: number},\n\n /** Increments the hue by the given amount (defaults to 1). */\n increment(stepSize?: number): void,\n /** Decrements the hue by the given amount (defaults to 1). */\n decrement(stepSize?: number): void,\n\n /** Whether the color wheel is currently being dragged. */\n readonly isDragging: boolean,\n /** Sets whether the color wheel is being dragged. */\n setDragging(value: boolean): void,\n /** Returns the color that should be displayed in the color wheel instead of `value`. */\n getDisplayColor(): Color,\n /** The step value of the hue channel, used when incrementing and decrementing. */\n step: number,\n /** The page step value of the hue channel, used when incrementing and decrementing. */\n pageStep: number,\n\n /** Whether the color wheel is disabled. */\n readonly isDisabled: boolean\n}\n\nconst DEFAULT_COLOR = parseColor('hsl(0, 100%, 50%)');\n\nfunction roundToStep(value: number, step: number): number {\n return Math.round(value / step) * step;\n}\n\nfunction mod(n: number, m: number) {\n return ((n % m) + m) % m;\n}\n\nfunction roundDown(v: number) {\n let r = Math.floor(v);\n if (r === v) {\n return v - 1;\n } else {\n return r;\n }\n}\n\nfunction degToRad(deg: number) {\n return deg * Math.PI / 180;\n}\n\nfunction radToDeg(rad: number) {\n return rad * 180 / Math.PI;\n}\n\n// 0deg = 3 o'clock. increases clockwise\nfunction angleToCartesian(angle: number, radius: number): {x: number, y: number} {\n let rad = degToRad(360 - angle + 90);\n let x = Math.sin(rad) * (radius);\n let y = Math.cos(rad) * (radius);\n return {x, y};\n}\n\nfunction cartesianToAngle(x: number, y: number, radius: number): number {\n let deg = radToDeg(Math.atan2(y / radius, x / radius));\n return (deg + 360) % 360;\n}\n\n/**\n * Provides state management for a color wheel component.\n * Color wheels allow users to adjust the hue of an HSL or HSB color value on a circular track.\n */\nexport function useColorWheelState(props: ColorWheelProps): ColorWheelState {\n let {defaultValue, onChange, onChangeEnd} = props;\n\n if (!props.value && !defaultValue) {\n defaultValue = DEFAULT_COLOR;\n }\n\n let [stateValue, setValueState] = useControlledState(normalizeColor(props.value), normalizeColor(defaultValue), onChange);\n let value = useMemo(() => {\n let colorSpace = stateValue.getColorSpace();\n return colorSpace === 'hsl' || colorSpace === 'hsb' ? stateValue : stateValue.toFormat('hsl');\n }, [stateValue]);\n let valueRef = useRef(value);\n let setValue = (value: Color) => {\n valueRef.current = value;\n setValueState(value);\n };\n\n let channelRange = value.getChannelRange('hue');\n let {minValue: minValueX, maxValue: maxValueX, step: step, pageSize: pageStep} = channelRange;\n let [isDragging, setDragging] = useState(false);\n let isDraggingRef = useRef(false);\n\n let hue = value.getChannelValue('hue');\n function setHue(v: number) {\n if (v > 360) {\n // Make sure you can always get back to 0.\n v = 0;\n }\n v = roundToStep(mod(v, 360), step);\n if (hue !== v) {\n let color = value.withChannelValue('hue', v);\n setValue(color);\n }\n }\n\n return {\n value,\n step,\n pageStep,\n setValue(v) {\n let color = normalizeColor(v);\n setValue(color);\n },\n hue,\n setHue,\n setHueFromPoint(x, y, radius) {\n setHue(cartesianToAngle(x, y, radius));\n },\n getThumbPosition(radius) {\n return angleToCartesian(value.getChannelValue('hue'), radius);\n },\n increment(stepSize = 1) {\n let s = Math.max(stepSize, step);\n let newValue = hue + s;\n if (newValue >= maxValueX) {\n // Make sure you can always get back to 0.\n newValue = minValueX;\n }\n setHue(roundToStep(mod(newValue, 360), s));\n },\n decrement(stepSize = 1) {\n let s = Math.max(stepSize, step);\n if (hue === 0) {\n // We can't just subtract step because this might be the case:\n // |(previous step) - 0| < step size\n setHue(roundDown(360 / s) * s);\n } else {\n setHue(roundToStep(mod(hue - s, 360), s));\n }\n },\n setDragging(isDragging) {\n let wasDragging = isDraggingRef.current;\n isDraggingRef.current = isDragging;\n\n if (onChangeEnd && !isDragging && wasDragging) {\n onChangeEnd(valueRef.current);\n }\n\n setDragging(isDragging);\n },\n isDragging,\n getDisplayColor() {\n return value.toFormat('hsl').withChannelValue('saturation', 100).withChannelValue('lightness', 50).withChannelValue('alpha', 1);\n },\n isDisabled: props.isDisabled || false\n };\n}\n"],"names":[],"version":3,"file":"useColorWheelState.module.js.map"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-stately/color",
|
|
3
|
-
"version": "3.5.4-nightly.
|
|
3
|
+
"version": "3.5.4-nightly.4578+b09a14eb1",
|
|
4
4
|
"description": "Spectrum UI components in React",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"main": "dist/main.js",
|
|
@@ -22,13 +22,15 @@
|
|
|
22
22
|
"url": "https://github.com/adobe/react-spectrum"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@internationalized/number": "3.5.2-nightly.
|
|
26
|
-
"@internationalized/string": "3.2.2-nightly.
|
|
27
|
-
"@react-aria/i18n": "3.0.0-nightly.
|
|
28
|
-
"@react-stately/form": "3.0.2-nightly.
|
|
29
|
-
"@react-stately/
|
|
30
|
-
"@react-stately/
|
|
31
|
-
"@react-
|
|
25
|
+
"@internationalized/number": "3.5.2-nightly.4578+b09a14eb1",
|
|
26
|
+
"@internationalized/string": "3.2.2-nightly.4578+b09a14eb1",
|
|
27
|
+
"@react-aria/i18n": "3.0.0-nightly.2866+b09a14eb1",
|
|
28
|
+
"@react-stately/form": "3.0.2-nightly.4578+b09a14eb1",
|
|
29
|
+
"@react-stately/numberfield": "3.0.0-nightly.2866+b09a14eb1",
|
|
30
|
+
"@react-stately/slider": "3.5.3-nightly.4578+b09a14eb1",
|
|
31
|
+
"@react-stately/utils": "3.0.0-nightly.2866+b09a14eb1",
|
|
32
|
+
"@react-types/color": "3.0.0-nightly.4578+b09a14eb1",
|
|
33
|
+
"@react-types/shared": "3.0.0-nightly.2866+b09a14eb1",
|
|
32
34
|
"@swc/helpers": "^0.5.0"
|
|
33
35
|
},
|
|
34
36
|
"peerDependencies": {
|
|
@@ -37,5 +39,5 @@
|
|
|
37
39
|
"publishConfig": {
|
|
38
40
|
"access": "public"
|
|
39
41
|
},
|
|
40
|
-
"gitHead": "
|
|
42
|
+
"gitHead": "b09a14eb1854d9d52e08739e30aa8fae51f1595a"
|
|
41
43
|
}
|
package/src/Color.ts
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import {clamp, toFixedNumber} from '@react-stately/utils';
|
|
14
|
-
import {ColorAxes, ColorChannel, ColorChannelRange, ColorFormat, Color as IColor} from '@react-types/color';
|
|
14
|
+
import {ColorAxes, ColorChannel, ColorChannelRange, ColorFormat, ColorSpace, Color as IColor} from '@react-types/color';
|
|
15
15
|
// @ts-ignore
|
|
16
16
|
import intlMessages from '../intl/*.json';
|
|
17
17
|
import {LocalizedStringDictionary, LocalizedStringFormatter} from '@internationalized/string';
|
|
@@ -37,6 +37,18 @@ export function normalizeColor(v: string | IColor) {
|
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
/** Returns a list of color channels for a given color space. */
|
|
41
|
+
export function getColorChannels(colorSpace: ColorSpace) {
|
|
42
|
+
switch (colorSpace) {
|
|
43
|
+
case 'rgb':
|
|
44
|
+
return RGBColor.colorChannels;
|
|
45
|
+
case 'hsl':
|
|
46
|
+
return HSLColor.colorChannels;
|
|
47
|
+
case 'hsb':
|
|
48
|
+
return HSBColor.colorChannels;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
40
52
|
// Lightness threshold between orange and brown.
|
|
41
53
|
const ORANGE_LIGHTNESS_THRESHOLD = 0.68;
|
|
42
54
|
// Lightness threshold between pure yellow and "yellow green".
|
|
@@ -63,6 +75,7 @@ abstract class Color implements IColor {
|
|
|
63
75
|
abstract toString(format: ColorFormat | 'css'): string;
|
|
64
76
|
abstract clone(): IColor;
|
|
65
77
|
abstract getChannelRange(channel: ColorChannel): ColorChannelRange;
|
|
78
|
+
abstract getChannelFormatOptions(channel: ColorChannel): Intl.NumberFormatOptions;
|
|
66
79
|
abstract formatChannelValue(channel: ColorChannel, locale: string): string;
|
|
67
80
|
|
|
68
81
|
toHexInt(): number {
|
|
@@ -92,7 +105,8 @@ abstract class Color implements IColor {
|
|
|
92
105
|
return strings.getStringForLocale(channel, locale);
|
|
93
106
|
}
|
|
94
107
|
|
|
95
|
-
abstract getColorSpace():
|
|
108
|
+
abstract getColorSpace(): ColorSpace;
|
|
109
|
+
|
|
96
110
|
getColorSpaceAxes(xyChannels: {xChannel?: ColorChannel, yChannel?: ColorChannel}): ColorAxes {
|
|
97
111
|
let {xChannel, yChannel} = xyChannels;
|
|
98
112
|
let xCh = xChannel || this.getColorChannels().find(c => c !== yChannel);
|
|
@@ -240,7 +254,7 @@ class RGBColor extends Color {
|
|
|
240
254
|
return colors.length < 3 ? undefined : new RGBColor(colors[0], colors[1], colors[2], colors[3] ?? 1);
|
|
241
255
|
}
|
|
242
256
|
|
|
243
|
-
toString(format: ColorFormat | 'css') {
|
|
257
|
+
toString(format: ColorFormat | 'css' = 'css') {
|
|
244
258
|
switch (format) {
|
|
245
259
|
case 'hex':
|
|
246
260
|
return '#' + (this.red.toString(16).padStart(2, '0') + this.green.toString(16).padStart(2, '0') + this.blue.toString(16).padStart(2, '0')).toUpperCase();
|
|
@@ -377,29 +391,30 @@ class RGBColor extends Color {
|
|
|
377
391
|
}
|
|
378
392
|
}
|
|
379
393
|
|
|
380
|
-
|
|
381
|
-
let options: Intl.NumberFormatOptions;
|
|
382
|
-
let value = this.getChannelValue(channel);
|
|
394
|
+
getChannelFormatOptions(channel: ColorChannel): Intl.NumberFormatOptions {
|
|
383
395
|
switch (channel) {
|
|
384
396
|
case 'red':
|
|
385
397
|
case 'green':
|
|
386
398
|
case 'blue':
|
|
387
|
-
|
|
388
|
-
break;
|
|
399
|
+
return {style: 'decimal'};
|
|
389
400
|
case 'alpha':
|
|
390
|
-
|
|
391
|
-
break;
|
|
401
|
+
return {style: 'percent'};
|
|
392
402
|
default:
|
|
393
403
|
throw new Error('Unknown color channel: ' + channel);
|
|
394
404
|
}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
formatChannelValue(channel: ColorChannel, locale: string) {
|
|
408
|
+
let options = this.getChannelFormatOptions(channel);
|
|
409
|
+
let value = this.getChannelValue(channel);
|
|
395
410
|
return new NumberFormatter(locale, options).format(value);
|
|
396
411
|
}
|
|
397
412
|
|
|
398
|
-
getColorSpace():
|
|
413
|
+
getColorSpace(): ColorSpace {
|
|
399
414
|
return 'rgb';
|
|
400
415
|
}
|
|
401
416
|
|
|
402
|
-
|
|
417
|
+
static colorChannels: [ColorChannel, ColorChannel, ColorChannel] = ['red', 'green', 'blue'];
|
|
403
418
|
getColorChannels(): [ColorChannel, ColorChannel, ColorChannel] {
|
|
404
419
|
return RGBColor.colorChannels;
|
|
405
420
|
}
|
|
@@ -424,7 +439,7 @@ class HSBColor extends Color {
|
|
|
424
439
|
}
|
|
425
440
|
}
|
|
426
441
|
|
|
427
|
-
toString(format: ColorFormat | 'css') {
|
|
442
|
+
toString(format: ColorFormat | 'css' = 'css') {
|
|
428
443
|
switch (format) {
|
|
429
444
|
case 'css':
|
|
430
445
|
return this.toHSL().toString('css');
|
|
@@ -512,32 +527,33 @@ class HSBColor extends Color {
|
|
|
512
527
|
}
|
|
513
528
|
}
|
|
514
529
|
|
|
515
|
-
|
|
516
|
-
let options: Intl.NumberFormatOptions;
|
|
517
|
-
let value = this.getChannelValue(channel);
|
|
530
|
+
getChannelFormatOptions(channel: ColorChannel): Intl.NumberFormatOptions {
|
|
518
531
|
switch (channel) {
|
|
519
532
|
case 'hue':
|
|
520
|
-
|
|
521
|
-
break;
|
|
533
|
+
return {style: 'unit', unit: 'degree', unitDisplay: 'narrow'};
|
|
522
534
|
case 'saturation':
|
|
523
535
|
case 'brightness':
|
|
524
|
-
options = {style: 'percent'};
|
|
525
|
-
value /= 100;
|
|
526
|
-
break;
|
|
527
536
|
case 'alpha':
|
|
528
|
-
|
|
529
|
-
break;
|
|
537
|
+
return {style: 'percent'};
|
|
530
538
|
default:
|
|
531
539
|
throw new Error('Unknown color channel: ' + channel);
|
|
532
540
|
}
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
formatChannelValue(channel: ColorChannel, locale: string) {
|
|
544
|
+
let options = this.getChannelFormatOptions(channel);
|
|
545
|
+
let value = this.getChannelValue(channel);
|
|
546
|
+
if (channel === 'saturation' || channel === 'brightness') {
|
|
547
|
+
value /= 100;
|
|
548
|
+
}
|
|
533
549
|
return new NumberFormatter(locale, options).format(value);
|
|
534
550
|
}
|
|
535
551
|
|
|
536
|
-
getColorSpace():
|
|
552
|
+
getColorSpace(): ColorSpace {
|
|
537
553
|
return 'hsb';
|
|
538
554
|
}
|
|
539
555
|
|
|
540
|
-
|
|
556
|
+
static colorChannels: [ColorChannel, ColorChannel, ColorChannel] = ['hue', 'saturation', 'brightness'];
|
|
541
557
|
getColorChannels(): [ColorChannel, ColorChannel, ColorChannel] {
|
|
542
558
|
return HSBColor.colorChannels;
|
|
543
559
|
}
|
|
@@ -566,7 +582,7 @@ class HSLColor extends Color {
|
|
|
566
582
|
}
|
|
567
583
|
}
|
|
568
584
|
|
|
569
|
-
toString(format: ColorFormat | 'css') {
|
|
585
|
+
toString(format: ColorFormat | 'css' = 'css') {
|
|
570
586
|
switch (format) {
|
|
571
587
|
case 'hex':
|
|
572
588
|
return this.toRGB().toString('hex');
|
|
@@ -652,32 +668,33 @@ class HSLColor extends Color {
|
|
|
652
668
|
}
|
|
653
669
|
}
|
|
654
670
|
|
|
655
|
-
|
|
656
|
-
let options: Intl.NumberFormatOptions;
|
|
657
|
-
let value = this.getChannelValue(channel);
|
|
671
|
+
getChannelFormatOptions(channel: ColorChannel): Intl.NumberFormatOptions {
|
|
658
672
|
switch (channel) {
|
|
659
673
|
case 'hue':
|
|
660
|
-
|
|
661
|
-
break;
|
|
674
|
+
return {style: 'unit', unit: 'degree', unitDisplay: 'narrow'};
|
|
662
675
|
case 'saturation':
|
|
663
676
|
case 'lightness':
|
|
664
|
-
options = {style: 'percent'};
|
|
665
|
-
value /= 100;
|
|
666
|
-
break;
|
|
667
677
|
case 'alpha':
|
|
668
|
-
|
|
669
|
-
break;
|
|
678
|
+
return {style: 'percent'};
|
|
670
679
|
default:
|
|
671
680
|
throw new Error('Unknown color channel: ' + channel);
|
|
672
681
|
}
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
formatChannelValue(channel: ColorChannel, locale: string) {
|
|
685
|
+
let options = this.getChannelFormatOptions(channel);
|
|
686
|
+
let value = this.getChannelValue(channel);
|
|
687
|
+
if (channel === 'saturation' || channel === 'lightness') {
|
|
688
|
+
value /= 100;
|
|
689
|
+
}
|
|
673
690
|
return new NumberFormatter(locale, options).format(value);
|
|
674
691
|
}
|
|
675
692
|
|
|
676
|
-
getColorSpace():
|
|
693
|
+
getColorSpace(): ColorSpace {
|
|
677
694
|
return 'hsl';
|
|
678
695
|
}
|
|
679
696
|
|
|
680
|
-
|
|
697
|
+
static colorChannels: [ColorChannel, ColorChannel, ColorChannel] = ['hue', 'saturation', 'lightness'];
|
|
681
698
|
getColorChannels(): [ColorChannel, ColorChannel, ColorChannel] {
|
|
682
699
|
return HSLColor.colorChannels;
|
|
683
700
|
}
|
package/src/index.ts
CHANGED
|
@@ -14,12 +14,16 @@ export type {ColorAreaState} from './useColorAreaState';
|
|
|
14
14
|
export type {ColorSliderState} from './useColorSliderState';
|
|
15
15
|
export type {ColorWheelState} from './useColorWheelState';
|
|
16
16
|
export type {ColorFieldState} from './useColorFieldState';
|
|
17
|
+
export type {ColorChannelFieldProps, ColorChannelFieldState, ColorChannelFieldStateOptions} from './useColorChannelFieldState';
|
|
18
|
+
export type {ColorPickerProps, ColorPickerState} from './useColorPickerState';
|
|
17
19
|
|
|
18
|
-
export {parseColor} from './Color';
|
|
20
|
+
export {parseColor, getColorChannels} from './Color';
|
|
19
21
|
export {useColorAreaState} from './useColorAreaState';
|
|
20
22
|
export {useColorSliderState} from './useColorSliderState';
|
|
21
23
|
export {useColorWheelState} from './useColorWheelState';
|
|
22
24
|
export {useColorFieldState} from './useColorFieldState';
|
|
25
|
+
export {useColorChannelFieldState} from './useColorChannelFieldState';
|
|
26
|
+
export {useColorPickerState} from './useColorPickerState';
|
|
23
27
|
|
|
24
28
|
export type {Color, ColorAreaProps, ColorFieldProps, ColorWheelProps} from '@react-types/color';
|
|
25
29
|
export type {ColorSliderStateOptions} from './useColorSliderState';
|
package/src/useColorAreaState.ts
CHANGED
|
@@ -75,6 +75,7 @@ export function useColorAreaState(props: ColorAreaProps): ColorAreaState {
|
|
|
75
75
|
let {
|
|
76
76
|
value,
|
|
77
77
|
defaultValue,
|
|
78
|
+
colorSpace,
|
|
78
79
|
xChannel,
|
|
79
80
|
yChannel,
|
|
80
81
|
onChange,
|
|
@@ -85,7 +86,8 @@ export function useColorAreaState(props: ColorAreaProps): ColorAreaState {
|
|
|
85
86
|
defaultValue = DEFAULT_COLOR;
|
|
86
87
|
}
|
|
87
88
|
|
|
88
|
-
let [
|
|
89
|
+
let [colorValue, setColorState] = useControlledState(value && normalizeColor(value), defaultValue && normalizeColor(defaultValue), onChange);
|
|
90
|
+
let color = useMemo(() => colorSpace && colorValue ? colorValue.toFormat(colorSpace) : colorValue, [colorValue, colorSpace]);
|
|
89
91
|
let valueRef = useRef(color);
|
|
90
92
|
let setColor = (color: Color) => {
|
|
91
93
|
valueRef.current = color;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import {Color, ColorChannel, ColorFieldProps, ColorSpace} from '@react-types/color';
|
|
2
|
+
import {NumberFieldState, useNumberFieldState} from '@react-stately/numberfield';
|
|
3
|
+
import {useColor} from './useColor';
|
|
4
|
+
import {useControlledState} from '@react-stately/utils';
|
|
5
|
+
import {useMemo} from 'react';
|
|
6
|
+
|
|
7
|
+
export interface ColorChannelFieldProps extends ColorFieldProps {
|
|
8
|
+
colorSpace?: ColorSpace,
|
|
9
|
+
channel: ColorChannel
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface ColorChannelFieldStateOptions extends ColorChannelFieldProps {
|
|
13
|
+
locale: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface ColorChannelFieldState extends NumberFieldState {
|
|
17
|
+
colorValue: Color
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Provides state management for a color channel field, allowing users to edit the
|
|
22
|
+
* value of an individual color channel.
|
|
23
|
+
*/
|
|
24
|
+
export function useColorChannelFieldState(props: ColorChannelFieldStateOptions): ColorChannelFieldState {
|
|
25
|
+
let {channel, colorSpace, locale} = props;
|
|
26
|
+
let initialValue = useColor(props.value);
|
|
27
|
+
let initialDefaultValue = useColor(props.defaultValue || '#0000')!;
|
|
28
|
+
let [colorValue, setColor] = useControlledState(initialValue || undefined, initialDefaultValue, props.onChange);
|
|
29
|
+
let color = useMemo(() => colorSpace && colorValue ? colorValue.toFormat(colorSpace) : colorValue, [colorValue, colorSpace]);
|
|
30
|
+
let value = color.getChannelValue(channel);
|
|
31
|
+
let range = color.getChannelRange(channel);
|
|
32
|
+
let formatOptions = useMemo(() => color.getChannelFormatOptions(channel), [color, channel]);
|
|
33
|
+
let multiplier = formatOptions.style === 'percent' && range.maxValue === 100 ? 100 : 1;
|
|
34
|
+
|
|
35
|
+
let numberFieldState = useNumberFieldState({
|
|
36
|
+
locale,
|
|
37
|
+
value: value / multiplier,
|
|
38
|
+
onChange: (v) => setColor(color.withChannelValue(channel, v * multiplier)),
|
|
39
|
+
minValue: range.minValue / multiplier,
|
|
40
|
+
maxValue: range.maxValue / multiplier,
|
|
41
|
+
step: range.step / multiplier,
|
|
42
|
+
formatOptions
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
...numberFieldState,
|
|
47
|
+
colorValue: color
|
|
48
|
+
};
|
|
49
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import {Color} from '@react-types/color';
|
|
2
|
+
import {parseColor} from './Color';
|
|
3
|
+
import {useColor} from './useColor';
|
|
4
|
+
import {useControlledState} from '@react-stately/utils';
|
|
5
|
+
import {ValueBase} from '@react-types/shared';
|
|
6
|
+
|
|
7
|
+
export interface ColorPickerProps extends ValueBase<string | Color | null, Color> {}
|
|
8
|
+
|
|
9
|
+
export interface ColorPickerState {
|
|
10
|
+
/** The current color value of the color picker. */
|
|
11
|
+
color: Color,
|
|
12
|
+
/** Sets the current color value of the color picker. */
|
|
13
|
+
setColor(color: Color | null): void
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function useColorPickerState(props: ColorPickerProps): ColorPickerState {
|
|
17
|
+
let value = useColor(props.value);
|
|
18
|
+
let defaultValue = useColor(props.defaultValue || '#0000')!;
|
|
19
|
+
let [color, setColor] = useControlledState(value || undefined, defaultValue, props.onChange);
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
color,
|
|
23
|
+
setColor(color) {
|
|
24
|
+
setColor(color || parseColor('#0000'));
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
}
|
|
@@ -14,6 +14,7 @@ import {Color, ColorSliderProps} from '@react-types/color';
|
|
|
14
14
|
import {normalizeColor, parseColor} from './Color';
|
|
15
15
|
import {SliderState, useSliderState} from '@react-stately/slider';
|
|
16
16
|
import {useControlledState} from '@react-stately/utils';
|
|
17
|
+
import {useMemo} from 'react';
|
|
17
18
|
|
|
18
19
|
export interface ColorSliderState extends SliderState {
|
|
19
20
|
/** The current color value represented by the color slider. */
|
|
@@ -21,7 +22,9 @@ export interface ColorSliderState extends SliderState {
|
|
|
21
22
|
/** Sets the current color value. If a string is passed, it will be parsed to a Color. */
|
|
22
23
|
setValue(value: string | Color): void,
|
|
23
24
|
/** Returns the color that should be displayed in the slider instead of `value` or the optional parameter. */
|
|
24
|
-
getDisplayColor(): Color
|
|
25
|
+
getDisplayColor(): Color,
|
|
26
|
+
/** Whether the color slider is currently being dragged. */
|
|
27
|
+
readonly isDragging: boolean
|
|
25
28
|
}
|
|
26
29
|
|
|
27
30
|
|
|
@@ -35,12 +38,13 @@ export interface ColorSliderStateOptions extends ColorSliderProps {
|
|
|
35
38
|
* Color sliders allow users to adjust an individual channel of a color value.
|
|
36
39
|
*/
|
|
37
40
|
export function useColorSliderState(props: ColorSliderStateOptions): ColorSliderState {
|
|
38
|
-
let {channel, value, defaultValue, onChange, locale, ...otherProps} = props;
|
|
41
|
+
let {channel, colorSpace, value, defaultValue, onChange, locale, ...otherProps} = props;
|
|
39
42
|
if (value == null && defaultValue == null) {
|
|
40
43
|
throw new Error('useColorSliderState requires a value or defaultValue');
|
|
41
44
|
}
|
|
42
45
|
|
|
43
|
-
let [
|
|
46
|
+
let [colorValue, setColor] = useControlledState(value && normalizeColor(value), defaultValue && normalizeColor(defaultValue), onChange);
|
|
47
|
+
let color = useMemo(() => colorSpace && colorValue ? colorValue.toFormat(colorSpace) : colorValue, [colorValue, colorSpace]);
|
|
44
48
|
let sliderState = useSliderState({
|
|
45
49
|
...color.getChannelRange(channel),
|
|
46
50
|
...otherProps,
|
|
@@ -87,6 +91,7 @@ export function useColorSliderState(props: ColorSliderStateOptions): ColorSlider
|
|
|
87
91
|
return color.formatChannelValue(channel, locale);
|
|
88
92
|
},
|
|
89
93
|
step,
|
|
90
|
-
pageSize
|
|
94
|
+
pageSize,
|
|
95
|
+
isDragging: sliderState.isThumbDragging(0)
|
|
91
96
|
};
|
|
92
97
|
}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
import {Color, ColorWheelProps} from '@react-types/color';
|
|
14
14
|
import {normalizeColor, parseColor} from './Color';
|
|
15
15
|
import {useControlledState} from '@react-stately/utils';
|
|
16
|
-
import {useRef, useState} from 'react';
|
|
16
|
+
import {useMemo, useRef, useState} from 'react';
|
|
17
17
|
|
|
18
18
|
export interface ColorWheelState {
|
|
19
19
|
/** The current color value represented by the color wheel. */
|
|
@@ -45,7 +45,10 @@ export interface ColorWheelState {
|
|
|
45
45
|
/** The step value of the hue channel, used when incrementing and decrementing. */
|
|
46
46
|
step: number,
|
|
47
47
|
/** The page step value of the hue channel, used when incrementing and decrementing. */
|
|
48
|
-
pageStep: number
|
|
48
|
+
pageStep: number,
|
|
49
|
+
|
|
50
|
+
/** Whether the color wheel is disabled. */
|
|
51
|
+
readonly isDisabled: boolean
|
|
49
52
|
}
|
|
50
53
|
|
|
51
54
|
const DEFAULT_COLOR = parseColor('hsl(0, 100%, 50%)');
|
|
@@ -99,7 +102,11 @@ export function useColorWheelState(props: ColorWheelProps): ColorWheelState {
|
|
|
99
102
|
defaultValue = DEFAULT_COLOR;
|
|
100
103
|
}
|
|
101
104
|
|
|
102
|
-
let [
|
|
105
|
+
let [stateValue, setValueState] = useControlledState(normalizeColor(props.value), normalizeColor(defaultValue), onChange);
|
|
106
|
+
let value = useMemo(() => {
|
|
107
|
+
let colorSpace = stateValue.getColorSpace();
|
|
108
|
+
return colorSpace === 'hsl' || colorSpace === 'hsb' ? stateValue : stateValue.toFormat('hsl');
|
|
109
|
+
}, [stateValue]);
|
|
103
110
|
let valueRef = useRef(value);
|
|
104
111
|
let setValue = (value: Color) => {
|
|
105
112
|
valueRef.current = value;
|
|
@@ -172,6 +179,7 @@ export function useColorWheelState(props: ColorWheelProps): ColorWheelState {
|
|
|
172
179
|
isDragging,
|
|
173
180
|
getDisplayColor() {
|
|
174
181
|
return value.toFormat('hsl').withChannelValue('saturation', 100).withChannelValue('lightness', 50).withChannelValue('alpha', 1);
|
|
175
|
-
}
|
|
182
|
+
},
|
|
183
|
+
isDisabled: props.isDisabled || false
|
|
176
184
|
};
|
|
177
185
|
}
|