Wrote color values component.
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
screenshots
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
import { useReducer } from "react";
|
||||||
|
|
||||||
|
import { Color } from "colorlib";
|
||||||
|
|
||||||
|
import { colorReducer, createColorActions } from "@hooks/color";
|
||||||
|
|
||||||
|
import { HexEditor } from "./ValueEditor";
|
||||||
|
|
||||||
|
const initialState = {
|
||||||
|
color: Color.from_hex("000"),
|
||||||
|
};
|
||||||
|
|
||||||
|
function TestWrapper() {
|
||||||
|
const [state, dispatch] = useReducer(colorReducer, initialState);
|
||||||
|
const actions = createColorActions(dispatch);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<HexEditor color={state.color.hex} actions={actions.hex} />
|
||||||
|
<p>
|
||||||
|
Color: #<span data-cy="current-color">{state.color.hex.to_code()}</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("hex editor tests", () => {
|
||||||
|
it("edits the hex value", () => {
|
||||||
|
cy.mount(<TestWrapper />);
|
||||||
|
|
||||||
|
// Verify initial state
|
||||||
|
cy.dataCy("current-color").as("color").should("have.text", "000000");
|
||||||
|
|
||||||
|
// Should select text on focus
|
||||||
|
cy.dataCy("hex-value-input")
|
||||||
|
.as("value")
|
||||||
|
.focus()
|
||||||
|
.should("have.prop", "selectionStart", 0)
|
||||||
|
.should("have.prop", "selectionEnd")
|
||||||
|
.should("be.gt", 0);
|
||||||
|
|
||||||
|
// Hex short code should be maintained while editing
|
||||||
|
cy.get("@value").type("{rightArrow}").type("{backspace}");
|
||||||
|
cy.get("@value").should("have.value", "#00000");
|
||||||
|
cy.get("@color").should("have.text", "000000");
|
||||||
|
|
||||||
|
cy.get("@value").type("{backspace}").type("{backspace}");
|
||||||
|
cy.get("@value").should("have.value", "#000");
|
||||||
|
cy.get("@color").should("have.text", "000000");
|
||||||
|
|
||||||
|
cy.get("@value").blur();
|
||||||
|
cy.get("@value").should("have.value", "#000000");
|
||||||
|
cy.get("@color").should("have.text", "000000");
|
||||||
|
|
||||||
|
// Type a new value
|
||||||
|
cy.get("@value").focus().type("{backspace}");
|
||||||
|
cy.get("@value").should("have.value", "");
|
||||||
|
cy.get("@color").should("have.text", "000000");
|
||||||
|
|
||||||
|
cy.get("@value").type("ab");
|
||||||
|
cy.get("@value").should("have.value", "ab");
|
||||||
|
cy.get("@color").should("have.text", "000000");
|
||||||
|
|
||||||
|
cy.get("@value").type("c");
|
||||||
|
cy.get("@value").should("have.value", "#ABC");
|
||||||
|
cy.get("@color").should("have.text", "AABBCC");
|
||||||
|
|
||||||
|
cy.get("@value").blur();
|
||||||
|
cy.get("@value").should("have.value", "#AABBCC");
|
||||||
|
cy.get("@color").should("have.text", "AABBCC");
|
||||||
|
|
||||||
|
// Invalid blur resets to last valid color
|
||||||
|
cy.get("@value").focus().type("Invalid");
|
||||||
|
cy.get("@value").blur();
|
||||||
|
cy.get("@value").should("have.value", "#AABBCC");
|
||||||
|
cy.get("@color").should("have.text", "AABBCC");
|
||||||
|
|
||||||
|
// Escape blurs input
|
||||||
|
cy.get("@value").focus();
|
||||||
|
cy.get("@value").should("have.focus");
|
||||||
|
cy.get("@value").type("{esc}");
|
||||||
|
cy.get("@value").should("not.have.focus");
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
import { useReducer } from "react";
|
||||||
|
|
||||||
|
import { Color } from "colorlib";
|
||||||
|
|
||||||
|
import { roundTo } from "@/util";
|
||||||
|
import { colorReducer, createColorActions } from "@hooks/color";
|
||||||
|
|
||||||
|
import SpaceEditor from "./SpaceEditor";
|
||||||
|
|
||||||
|
const initialState = {
|
||||||
|
color: Color.from_hex("2edd9d"),
|
||||||
|
};
|
||||||
|
|
||||||
|
function TestWrapper() {
|
||||||
|
const [state, dispatch] = useReducer(colorReducer, initialState);
|
||||||
|
const actions = createColorActions(dispatch);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: "100%",
|
||||||
|
height: 300,
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SpaceEditor
|
||||||
|
space="HCL"
|
||||||
|
color={state.color.hcl}
|
||||||
|
actions={actions.hcl}
|
||||||
|
/>
|
||||||
|
<SpaceEditor
|
||||||
|
space="HSV"
|
||||||
|
color={state.color.hsv}
|
||||||
|
actions={actions.hsv}
|
||||||
|
/>
|
||||||
|
<SpaceEditor
|
||||||
|
space="RGB"
|
||||||
|
color={state.color.rgb}
|
||||||
|
actions={actions.rgb}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{ fontFamily: "monospace" }}>
|
||||||
|
<p data-cy="hcl-value">
|
||||||
|
HCL ({roundTo(state.color.hcl.h, 0)}, {roundTo(state.color.hcl.c, 2)},{" "}
|
||||||
|
{roundTo(state.color.hcl.l, 2)})
|
||||||
|
</p>
|
||||||
|
<p data-cy="hsv-value">
|
||||||
|
HSV ({roundTo(state.color.hsv.h, 0)}, {roundTo(state.color.hsv.s, 2)},{" "}
|
||||||
|
{roundTo(state.color.hsv.v, 2)})
|
||||||
|
</p>
|
||||||
|
<p data-cy="rgb-value">
|
||||||
|
RGB ({roundTo(state.color.rgb.r, 0)}, {roundTo(state.color.rgb.g, 0)},{" "}
|
||||||
|
{roundTo(state.color.rgb.b, 0)})
|
||||||
|
</p>
|
||||||
|
<p data-cy="hex-value">HEX: #{state.color.hex.to_code()}</p>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("space editor tests", () => {
|
||||||
|
it("can edit color values", () => {
|
||||||
|
cy.mount(<TestWrapper />);
|
||||||
|
|
||||||
|
// Confirm initial values
|
||||||
|
cy.dataCy("RGB-editor").within(() => {
|
||||||
|
cy.dataCy("R-value-input").should("have.value", 46);
|
||||||
|
cy.dataCy("G-value-input").should("have.value", 221);
|
||||||
|
cy.dataCy("B-value-input").should("have.value", 157);
|
||||||
|
});
|
||||||
|
|
||||||
|
cy.dataCy("HSV-editor").within(() => {
|
||||||
|
cy.dataCy("H-value-input").should("have.value", 158);
|
||||||
|
cy.dataCy("S-value-input").should("have.value", 79);
|
||||||
|
cy.dataCy("V-value-input").should("have.value", 87);
|
||||||
|
});
|
||||||
|
|
||||||
|
cy.dataCy("HCL-editor").within(() => {
|
||||||
|
cy.dataCy("H-value-input").should("have.value", 158);
|
||||||
|
cy.dataCy("C-value-input").should("have.value", 79);
|
||||||
|
cy.dataCy("L-value-input").should("have.value", 70);
|
||||||
|
});
|
||||||
|
|
||||||
|
cy.dataCy("rgb-value").should("have.text", "RGB (46, 221, 157)");
|
||||||
|
cy.dataCy("hsv-value").should("have.text", "HSV (158, 0.79, 0.87)");
|
||||||
|
cy.dataCy("hcl-value").should("have.text", "HCL (158, 0.79, 0.7)");
|
||||||
|
cy.dataCy("hex-value").should("have.text", "HEX: #2EDD9D");
|
||||||
|
|
||||||
|
// Update the color values
|
||||||
|
cy.wait(50); // ensure render
|
||||||
|
cy.dataCy("HCL-editor").within(() => {
|
||||||
|
cy.dataCy("H-slider").click();
|
||||||
|
cy.dataCy("C-decrement-button").click();
|
||||||
|
cy.dataCy("L-value-input").type("25");
|
||||||
|
});
|
||||||
|
|
||||||
|
cy.dataCy("rgb-value").should("have.text", "RGB (17, 76, 75)");
|
||||||
|
cy.dataCy("hsv-value").should("have.text", "HSV (179, 0.78, 0.3)");
|
||||||
|
cy.dataCy("hcl-value").should("have.text", "HCL (179, 0.78, 0.25)");
|
||||||
|
cy.dataCy("hex-value").should("have.text", "HEX: #104B4A");
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
import { createContext, useContext, useReducer } from "react";
|
||||||
|
import type { ReactNode } from "react";
|
||||||
|
|
||||||
|
import * as colorlib from "colorlib";
|
||||||
|
|
||||||
|
import { colorReducer, createColorActions } from "@hooks/color";
|
||||||
|
import type { ColorActions } from "@hooks/color";
|
||||||
|
|
||||||
|
interface SelectedColorContextType {
|
||||||
|
selectedColor: colorlib.Color;
|
||||||
|
selectedColorActions: ColorActions;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const SelectedColorContext = createContext<
|
||||||
|
SelectedColorContextType | undefined
|
||||||
|
>(undefined);
|
||||||
|
|
||||||
|
export const SelectedColorProvider = ({
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
children: ReactNode;
|
||||||
|
}) => {
|
||||||
|
const initialState = {
|
||||||
|
color: colorlib.Color.from_hex("00C9FA"),
|
||||||
|
};
|
||||||
|
const [colorState, colorDispatch] = useReducer(colorReducer, initialState);
|
||||||
|
const colorActions = createColorActions(colorDispatch);
|
||||||
|
|
||||||
|
const value = {
|
||||||
|
selectedColor: colorState.color,
|
||||||
|
selectedColorActions: colorActions,
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SelectedColorContext.Provider value={value}>
|
||||||
|
{children}
|
||||||
|
</SelectedColorContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user