@zag-js/color-picker 0.22.0 → 0.24.0
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/index.d.mts +107 -32
- package/dist/index.d.ts +107 -32
- package/dist/index.js +484 -294
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +483 -297
- package/dist/index.mjs.map +1 -1
- package/package.json +14 -12
- package/src/color-picker.anatomy.ts +11 -5
- package/src/color-picker.connect.ts +200 -125
- package/src/color-picker.dom.ts +22 -3
- package/src/color-picker.machine.ts +227 -125
- package/src/color-picker.parse.ts +4 -0
- package/src/color-picker.types.ts +116 -30
- package/src/index.ts +7 -6
- package/src/utils/get-channel-input-value.ts +45 -11
- package/src/utils/get-slider-background.ts +7 -7
- package/src/utils/get-channel-details.ts +0 -60
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
import type { Color, ColorAxes, ColorChannel, ColorFormat, ColorType } from "@zag-js/color-utils"
|
|
2
2
|
import type { StateMachine as S } from "@zag-js/core"
|
|
3
|
-
import type {
|
|
3
|
+
import type { InteractOutsideHandlers } from "@zag-js/dismissable"
|
|
4
|
+
import type { PositioningOptions } from "@zag-js/popper"
|
|
5
|
+
import type { CommonProperties, Context, MaybeElement, Orientation, PropTypes, RequiredBy } from "@zag-js/types"
|
|
6
|
+
import type { MaybeFunction } from "@zag-js/utils"
|
|
4
7
|
|
|
5
8
|
/* -----------------------------------------------------------------------------
|
|
6
9
|
* Callback details
|
|
7
10
|
* -----------------------------------------------------------------------------*/
|
|
8
11
|
|
|
9
12
|
export interface ValueChangeDetails {
|
|
10
|
-
value:
|
|
11
|
-
|
|
13
|
+
value: Color
|
|
14
|
+
valueAsString: string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface OpenChangeDetails {
|
|
18
|
+
open: boolean
|
|
12
19
|
}
|
|
13
20
|
|
|
14
21
|
/* -----------------------------------------------------------------------------
|
|
@@ -18,6 +25,11 @@ export interface ValueChangeDetails {
|
|
|
18
25
|
export type ExtendedColorChannel = ColorChannel | "hex" | "css"
|
|
19
26
|
|
|
20
27
|
type ElementIds = Partial<{
|
|
28
|
+
root: string
|
|
29
|
+
control: string
|
|
30
|
+
trigger: string
|
|
31
|
+
label: string
|
|
32
|
+
input: string
|
|
21
33
|
content: string
|
|
22
34
|
area: string
|
|
23
35
|
areaGradient: string
|
|
@@ -27,7 +39,7 @@ type ElementIds = Partial<{
|
|
|
27
39
|
channelSliderThumb(id: ColorChannel): string
|
|
28
40
|
}>
|
|
29
41
|
|
|
30
|
-
interface PublicContext extends CommonProperties {
|
|
42
|
+
interface PublicContext extends CommonProperties, InteractOutsideHandlers {
|
|
31
43
|
/**
|
|
32
44
|
* The ids of the elements in the color picker. Useful for composition.
|
|
33
45
|
*/
|
|
@@ -39,7 +51,7 @@ interface PublicContext extends CommonProperties {
|
|
|
39
51
|
/**
|
|
40
52
|
* The current color value
|
|
41
53
|
*/
|
|
42
|
-
value:
|
|
54
|
+
value: Color
|
|
43
55
|
/**
|
|
44
56
|
* Whether the color picker is disabled
|
|
45
57
|
*/
|
|
@@ -57,9 +69,40 @@ interface PublicContext extends CommonProperties {
|
|
|
57
69
|
*/
|
|
58
70
|
onValueChangeEnd?: (details: ValueChangeDetails) => void
|
|
59
71
|
/**
|
|
60
|
-
*
|
|
72
|
+
* Handler that is called when the user opens or closes the color picker.
|
|
73
|
+
*/
|
|
74
|
+
onOpenChange?: (details: OpenChangeDetails) => void
|
|
75
|
+
/**
|
|
76
|
+
* The name for the form input
|
|
61
77
|
*/
|
|
62
78
|
name?: string
|
|
79
|
+
/**
|
|
80
|
+
* The color format to use (rgb, hsl, hsb)
|
|
81
|
+
* @default "hsl"
|
|
82
|
+
*/
|
|
83
|
+
format?: ColorFormat
|
|
84
|
+
/**
|
|
85
|
+
* The alpha format to use (decimal, percent)
|
|
86
|
+
* @default "decimal"
|
|
87
|
+
*/
|
|
88
|
+
alphaFormat?: "decimal" | "percent"
|
|
89
|
+
/**
|
|
90
|
+
* The positioning options for the color picker
|
|
91
|
+
*/
|
|
92
|
+
positioning: PositioningOptions
|
|
93
|
+
/**
|
|
94
|
+
* Whether to automatically set focus on the first focusable
|
|
95
|
+
* content within the color picker when opened.
|
|
96
|
+
*/
|
|
97
|
+
autoFocus?: boolean
|
|
98
|
+
/**
|
|
99
|
+
* The initial focus element when the color picker is opened.
|
|
100
|
+
*/
|
|
101
|
+
initialFocusEl?: MaybeFunction<MaybeElement>
|
|
102
|
+
/**
|
|
103
|
+
* Whether the color picker is open
|
|
104
|
+
*/
|
|
105
|
+
open?: boolean
|
|
63
106
|
}
|
|
64
107
|
|
|
65
108
|
type PrivateContext = Context<{
|
|
@@ -83,6 +126,11 @@ type PrivateContext = Context<{
|
|
|
83
126
|
* Whether the checkbox's fieldset is disabled
|
|
84
127
|
*/
|
|
85
128
|
fieldsetDisabled: boolean
|
|
129
|
+
/**
|
|
130
|
+
* @internal
|
|
131
|
+
* The current placement of the color picker
|
|
132
|
+
*/
|
|
133
|
+
currentPlacement?: PositioningOptions["placement"]
|
|
86
134
|
}>
|
|
87
135
|
|
|
88
136
|
type ComputedContext = Readonly<{
|
|
@@ -100,7 +148,7 @@ type ComputedContext = Readonly<{
|
|
|
100
148
|
* @computed
|
|
101
149
|
* The color value as a Color object
|
|
102
150
|
*/
|
|
103
|
-
|
|
151
|
+
valueAsString: string
|
|
104
152
|
/**
|
|
105
153
|
* @computed
|
|
106
154
|
* Whether the color picker is disabled
|
|
@@ -113,7 +161,8 @@ export type UserDefinedContext = RequiredBy<PublicContext, "id">
|
|
|
113
161
|
export interface MachineContext extends PublicContext, PrivateContext, ComputedContext {}
|
|
114
162
|
|
|
115
163
|
export interface MachineState {
|
|
116
|
-
|
|
164
|
+
tags: "open" | "closed" | "dragging" | "focused"
|
|
165
|
+
value: "idle" | "focused" | "open" | "open:dragging"
|
|
117
166
|
}
|
|
118
167
|
|
|
119
168
|
export type State = S.State<MachineContext, MachineState>
|
|
@@ -124,43 +173,60 @@ export type Send = S.Send<S.AnyEventObject>
|
|
|
124
173
|
* Component API
|
|
125
174
|
* -----------------------------------------------------------------------------*/
|
|
126
175
|
|
|
127
|
-
export interface
|
|
176
|
+
export interface ChannelProps {
|
|
128
177
|
channel: ColorChannel
|
|
129
178
|
orientation?: Orientation
|
|
130
179
|
}
|
|
131
180
|
|
|
132
|
-
export interface
|
|
181
|
+
export interface ChannelInputProps {
|
|
133
182
|
channel: ExtendedColorChannel
|
|
134
183
|
orientation?: Orientation
|
|
135
184
|
}
|
|
136
185
|
|
|
137
|
-
export interface
|
|
138
|
-
xChannel
|
|
139
|
-
yChannel
|
|
186
|
+
export interface AreaProps {
|
|
187
|
+
xChannel?: ColorChannel
|
|
188
|
+
yChannel?: ColorChannel
|
|
140
189
|
}
|
|
141
190
|
|
|
142
|
-
export interface
|
|
143
|
-
|
|
191
|
+
export interface SwatchTriggerProps {
|
|
192
|
+
/**
|
|
193
|
+
* The color value
|
|
194
|
+
*/
|
|
144
195
|
value: string | Color
|
|
145
196
|
}
|
|
146
197
|
|
|
198
|
+
export interface SwatchProps {
|
|
199
|
+
/**
|
|
200
|
+
* The color value
|
|
201
|
+
*/
|
|
202
|
+
value: string | Color
|
|
203
|
+
/**
|
|
204
|
+
* Whether to include the alpha channel in the color
|
|
205
|
+
*/
|
|
206
|
+
respectAlpha?: boolean
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export interface TransparancyGridProps {
|
|
210
|
+
size: string
|
|
211
|
+
}
|
|
212
|
+
|
|
147
213
|
export interface MachineApi<T extends PropTypes = PropTypes> {
|
|
148
214
|
/**
|
|
149
215
|
* Whether the color picker is being dragged
|
|
150
216
|
*/
|
|
151
217
|
isDragging: boolean
|
|
152
218
|
/**
|
|
153
|
-
*
|
|
219
|
+
* Whether the color picker is open
|
|
154
220
|
*/
|
|
155
|
-
|
|
221
|
+
isOpen: boolean
|
|
156
222
|
/**
|
|
157
|
-
* The current color value (as a
|
|
223
|
+
* The current color value (as a string)
|
|
158
224
|
*/
|
|
159
|
-
|
|
225
|
+
value: Color
|
|
160
226
|
/**
|
|
161
|
-
* The
|
|
227
|
+
* The current color value (as a Color object)
|
|
162
228
|
*/
|
|
163
|
-
|
|
229
|
+
valueAsString: string
|
|
164
230
|
/**
|
|
165
231
|
* The current color channels of the color
|
|
166
232
|
*/
|
|
@@ -169,6 +235,10 @@ export interface MachineApi<T extends PropTypes = PropTypes> {
|
|
|
169
235
|
* Function to set the color value
|
|
170
236
|
*/
|
|
171
237
|
setColor(value: string | Color): void
|
|
238
|
+
/**
|
|
239
|
+
* Function to set the color value
|
|
240
|
+
*/
|
|
241
|
+
getChannelValue(channel: ColorChannel): string
|
|
172
242
|
/**
|
|
173
243
|
* Function to set the color value of a specific channel
|
|
174
244
|
*/
|
|
@@ -177,23 +247,39 @@ export interface MachineApi<T extends PropTypes = PropTypes> {
|
|
|
177
247
|
* Function to set the color format
|
|
178
248
|
*/
|
|
179
249
|
setFormat(format: ColorFormat): void
|
|
250
|
+
/**
|
|
251
|
+
* The alpha value of the color
|
|
252
|
+
*/
|
|
253
|
+
getAlpha(): number
|
|
180
254
|
/**
|
|
181
255
|
* Function to set the color alpha
|
|
182
256
|
*/
|
|
183
257
|
setAlpha(value: number): void
|
|
184
258
|
|
|
259
|
+
rootProps: T["element"]
|
|
260
|
+
labelProps: T["element"]
|
|
261
|
+
controlProps: T["element"]
|
|
262
|
+
triggerProps: T["button"]
|
|
263
|
+
positionerProps: T["element"]
|
|
185
264
|
contentProps: T["element"]
|
|
186
265
|
hiddenInputProps: T["input"]
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
266
|
+
|
|
267
|
+
getAreaProps(props?: AreaProps): T["element"]
|
|
268
|
+
getAreaBackgroundProps(props?: AreaProps): T["element"]
|
|
269
|
+
getAreaThumbProps(props?: AreaProps): T["element"]
|
|
270
|
+
|
|
271
|
+
getChannelSliderProps(props: ChannelProps): T["element"]
|
|
272
|
+
getChannelSliderTrackProps(props: ChannelProps): T["element"]
|
|
273
|
+
getChannelSliderThumbProps(props: ChannelProps): T["element"]
|
|
274
|
+
getChannelInputProps(props: ChannelInputProps): T["input"]
|
|
275
|
+
|
|
276
|
+
getTransparencyGridProps(props: TransparancyGridProps): T["element"]
|
|
277
|
+
|
|
194
278
|
eyeDropperTriggerProps: T["button"]
|
|
195
|
-
|
|
196
|
-
|
|
279
|
+
|
|
280
|
+
swatchGroupProps: T["element"]
|
|
281
|
+
getSwatchTriggerProps(props: SwatchTriggerProps): T["button"]
|
|
282
|
+
getSwatchProps(props: SwatchProps): T["element"]
|
|
197
283
|
}
|
|
198
284
|
|
|
199
285
|
/* -----------------------------------------------------------------------------
|
package/src/index.ts
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
export { anatomy } from "./color-picker.anatomy"
|
|
2
2
|
export { connect } from "./color-picker.connect"
|
|
3
3
|
export { machine } from "./color-picker.machine"
|
|
4
|
+
export { parse } from "./color-picker.parse"
|
|
4
5
|
export type {
|
|
6
|
+
MachineApi as Api,
|
|
7
|
+
AreaProps,
|
|
8
|
+
ChannelInputProps,
|
|
9
|
+
ChannelProps,
|
|
5
10
|
Color,
|
|
6
11
|
ColorAxes,
|
|
7
|
-
ColorFormat,
|
|
8
|
-
ColorAreaProps,
|
|
9
12
|
ColorChannel,
|
|
10
|
-
|
|
11
|
-
ColorChannelInputProps,
|
|
12
|
-
ColorSwatchProps,
|
|
13
|
+
ColorFormat,
|
|
13
14
|
ColorType,
|
|
14
15
|
UserDefinedContext as Context,
|
|
15
|
-
|
|
16
|
+
SwatchProps,
|
|
16
17
|
} from "./color-picker.types"
|
|
@@ -1,44 +1,78 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { parseColor, type Color, type ColorChannelRange } from "@zag-js/color-utils"
|
|
2
2
|
import type { ExtendedColorChannel } from "../color-picker.types"
|
|
3
3
|
|
|
4
|
-
export function
|
|
5
|
-
if (channel == null) return
|
|
4
|
+
export function getChannelValue(color: Color, channel: ExtendedColorChannel | null | undefined): string {
|
|
5
|
+
if (channel == null) return ""
|
|
6
|
+
|
|
7
|
+
if (channel === "hex") {
|
|
8
|
+
return color.toString("hex")
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
if (channel === "css") {
|
|
12
|
+
return color.toString("css")
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (channel in color) {
|
|
16
|
+
return color.getChannelValue(channel).toString()
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const isHSL = color.getFormat() === "hsl"
|
|
6
20
|
|
|
7
21
|
switch (channel) {
|
|
8
|
-
case "hex":
|
|
9
|
-
return color.toString("hex")
|
|
10
|
-
case "css":
|
|
11
|
-
return color.toString("css")
|
|
12
22
|
case "hue":
|
|
23
|
+
return isHSL
|
|
24
|
+
? color.toFormat("hsla").getChannelValue("hue").toString()
|
|
25
|
+
: color.toFormat("hsba").getChannelValue("hue").toString()
|
|
26
|
+
|
|
13
27
|
case "saturation":
|
|
28
|
+
return isHSL
|
|
29
|
+
? color.toFormat("hsl").getChannelValue("saturation").toString()
|
|
30
|
+
: color.toFormat("hsb").getChannelValue("saturation").toString()
|
|
31
|
+
|
|
14
32
|
case "lightness":
|
|
15
|
-
return color.toFormat("
|
|
33
|
+
return color.toFormat("hsla").getChannelValue("lightness").toString()
|
|
34
|
+
|
|
16
35
|
case "brightness":
|
|
17
|
-
return color.toFormat("
|
|
36
|
+
return color.toFormat("hsba").getChannelValue("brightness").toString()
|
|
37
|
+
|
|
18
38
|
case "red":
|
|
19
39
|
case "green":
|
|
20
40
|
case "blue":
|
|
21
|
-
return color.toFormat("
|
|
41
|
+
return color.toFormat("rgba").getChannelValue(channel).toString()
|
|
42
|
+
|
|
22
43
|
default:
|
|
23
44
|
return color.getChannelValue(channel).toString()
|
|
24
45
|
}
|
|
25
46
|
}
|
|
26
47
|
|
|
27
|
-
export function
|
|
48
|
+
export function getChannelRange(color: Color, channel: ExtendedColorChannel): ColorChannelRange | undefined {
|
|
28
49
|
switch (channel) {
|
|
29
50
|
case "hex":
|
|
51
|
+
const minColor = parseColor("#000000")
|
|
52
|
+
const maxColor = parseColor("#FFFFFF")
|
|
53
|
+
return {
|
|
54
|
+
minValue: minColor.toHexInt(),
|
|
55
|
+
maxValue: maxColor.toHexInt(),
|
|
56
|
+
pageSize: 10,
|
|
57
|
+
step: 1,
|
|
58
|
+
}
|
|
59
|
+
|
|
30
60
|
case "css":
|
|
31
61
|
return undefined
|
|
62
|
+
|
|
32
63
|
case "hue":
|
|
33
64
|
case "saturation":
|
|
34
65
|
case "lightness":
|
|
35
66
|
return color.toFormat("hsl").getChannelRange(channel)
|
|
67
|
+
|
|
36
68
|
case "brightness":
|
|
37
69
|
return color.toFormat("hsb").getChannelRange(channel)
|
|
70
|
+
|
|
38
71
|
case "red":
|
|
39
72
|
case "green":
|
|
40
73
|
case "blue":
|
|
41
74
|
return color.toFormat("rgb").getChannelRange(channel)
|
|
75
|
+
|
|
42
76
|
default:
|
|
43
77
|
return color.getChannelRange(channel)
|
|
44
78
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ChannelProps, MachineContext } from "../color-picker.types"
|
|
2
2
|
|
|
3
|
-
function
|
|
3
|
+
function getSliderBackgroundDirection(orientation: "vertical" | "horizontal", dir: "ltr" | "rtl") {
|
|
4
4
|
if (orientation === "vertical") {
|
|
5
5
|
return "top"
|
|
6
6
|
} else if (dir === "ltr") {
|
|
@@ -10,19 +10,19 @@ function getSliderBgDirection(orientation: "vertical" | "horizontal", dir: "ltr"
|
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
export const
|
|
13
|
+
export const getSliderBackground = (ctx: MachineContext, props: Required<ChannelProps>) => {
|
|
14
14
|
const { channel } = props
|
|
15
15
|
|
|
16
|
-
const dir =
|
|
17
|
-
const value = ctx.
|
|
16
|
+
const dir = getSliderBackgroundDirection(props.orientation, ctx.dir!)
|
|
17
|
+
const value = ctx.value
|
|
18
18
|
|
|
19
|
-
const { minValue, maxValue } =
|
|
19
|
+
const { minValue, maxValue } = value.getChannelRange(channel)
|
|
20
20
|
|
|
21
21
|
switch (channel) {
|
|
22
22
|
case "hue":
|
|
23
23
|
return `linear-gradient(to ${dir}, rgb(255, 0, 0) 0%, rgb(255, 255, 0) 17%, rgb(0, 255, 0) 33%, rgb(0, 255, 255) 50%, rgb(0, 0, 255) 67%, rgb(255, 0, 255) 83%, rgb(255, 0, 0) 100%)`
|
|
24
24
|
case "lightness": {
|
|
25
|
-
let start =
|
|
25
|
+
let start = value.withChannelValue(channel, minValue).toString("css")
|
|
26
26
|
let middle = value.withChannelValue(channel, (maxValue - minValue) / 2).toString("css")
|
|
27
27
|
let end = value.withChannelValue(channel, maxValue).toString("css")
|
|
28
28
|
return `linear-gradient(to ${dir}, ${start}, ${middle}, ${end})`
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import type { Color, ColorChannel, ColorType } from "@zag-js/color-utils"
|
|
2
|
-
import { getPercentValue, snapValueToStep } from "@zag-js/numeric-range"
|
|
3
|
-
|
|
4
|
-
export function getChannelDetails(color: Color, xChannel: ColorChannel, yChannel: ColorChannel) {
|
|
5
|
-
const channels = color.getColorSpaceAxes({ xChannel, yChannel })
|
|
6
|
-
|
|
7
|
-
const xChannelRange = color.getChannelRange(channels.xChannel)
|
|
8
|
-
const yChannelRange = color.getChannelRange(channels.yChannel)
|
|
9
|
-
|
|
10
|
-
const { minValue: minValueX, maxValue: maxValueX, step: stepX, pageSize: pageSizeX } = xChannelRange
|
|
11
|
-
const { minValue: minValueY, maxValue: maxValueY, step: stepY, pageSize: pageSizeY } = yChannelRange
|
|
12
|
-
|
|
13
|
-
const xValue = color.getChannelValue(channels.xChannel)
|
|
14
|
-
const yValue = color.getChannelValue(channels.yChannel)
|
|
15
|
-
|
|
16
|
-
return {
|
|
17
|
-
channels,
|
|
18
|
-
xChannelStep: stepX,
|
|
19
|
-
yChannelStep: stepY,
|
|
20
|
-
xChannelPageStep: pageSizeX,
|
|
21
|
-
yChannelPageStep: pageSizeY,
|
|
22
|
-
xValue,
|
|
23
|
-
yValue,
|
|
24
|
-
getThumbPosition() {
|
|
25
|
-
let x = (xValue - minValueX) / (maxValueX - minValueX)
|
|
26
|
-
let y = 1 - (yValue - minValueY) / (maxValueY - minValueY)
|
|
27
|
-
return { x, y }
|
|
28
|
-
},
|
|
29
|
-
incrementX(stepSize: number) {
|
|
30
|
-
return xValue + stepSize > maxValueX ? maxValueX : snapValueToStep(xValue + stepSize, minValueX, maxValueX, stepX)
|
|
31
|
-
},
|
|
32
|
-
incrementY(stepSize: number) {
|
|
33
|
-
return yValue + stepSize > maxValueY ? maxValueY : snapValueToStep(yValue + stepSize, minValueY, maxValueY, stepY)
|
|
34
|
-
},
|
|
35
|
-
decrementX(stepSize: number) {
|
|
36
|
-
return snapValueToStep(xValue - stepSize, minValueX, maxValueX, stepX)
|
|
37
|
-
},
|
|
38
|
-
decrementY(stepSize: number) {
|
|
39
|
-
return snapValueToStep(yValue - stepSize, minValueY, maxValueY, stepY)
|
|
40
|
-
},
|
|
41
|
-
getColorFromPoint(x: number, y: number) {
|
|
42
|
-
let newXValue = getPercentValue(x, minValueX, maxValueX, stepX)
|
|
43
|
-
let newYValue = getPercentValue(1 - y, minValueY, maxValueY, stepY)
|
|
44
|
-
|
|
45
|
-
let newColor: ColorType | undefined
|
|
46
|
-
|
|
47
|
-
if (newXValue !== xValue) {
|
|
48
|
-
newXValue = snapValueToStep(newXValue, minValueX, maxValueX, stepX)
|
|
49
|
-
newColor = color.withChannelValue(channels.xChannel, newXValue)
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (newYValue !== yValue) {
|
|
53
|
-
newYValue = snapValueToStep(newYValue, minValueY, maxValueY, stepY)
|
|
54
|
-
newColor = (newColor || color).withChannelValue(channels.yChannel, newYValue)
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return newColor
|
|
58
|
-
},
|
|
59
|
-
}
|
|
60
|
-
}
|