Standardize to W3C naming for color.

This commit is contained in:
Dannon Baker
2023-10-31 08:06:37 -04:00
parent 67cf270c79
commit c70ecf6bf0
21 changed files with 299 additions and 299 deletions
@@ -0,0 +1,47 @@
import { mount } from "@vue/test-utils";
import { nextTick } from "vue";
import { colors } from "./colors";
import ColorSelector from "./ColorSelector.vue";
describe("ColorSelector", () => {
it("shows a button for each color and 'none'", () => {
const wrapper = mount(ColorSelector, { propsData: { color: "none" } });
const buttons = wrapper.findAll("button");
expect(buttons.length).toBe(Object.keys(colors).length + 1);
});
it("highlights the selected color", async () => {
const wrapper = mount(ColorSelector, { propsData: { color: "none" } });
const allSelected = wrapper.findAll(".selected");
expect(allSelected.length).toBe(1);
let selected = allSelected.wrappers[0];
expect(selected.element.getAttribute("title")).toBe("No Color");
const colorNames = Object.keys(colors);
for (let i = 0; i < colorNames.length; i++) {
const color = colorNames[i];
wrapper.setProps({ color });
await nextTick();
selected = wrapper.find(".selected");
expect(selected.element.getAttribute("title")).toContain(color);
}
});
it("emits the set color", async () => {
const wrapper = mount(ColorSelector, { propsData: { color: "none" } });
const colorNames = Object.keys(colors);
for (let i = 0; i < colorNames.length; i++) {
const color = colorNames[i];
await wrapper.find(`[title="Color ${color}"]`).trigger("click");
expect(wrapper.emitted()["set-color"][i][0]).toBe(color);
}
});
});
@@ -0,0 +1,100 @@
<script setup lang="ts">
import type { WorkflowCommentColor } from "@/stores/workflowEditorCommentStore";
import { brightColors, colors } from "./colors";
const props = defineProps<{
color: WorkflowCommentColor;
}>();
const emit = defineEmits<{
(e: "set-color", color: WorkflowCommentColor): void;
}>();
function onClickColor(color: WorkflowCommentColor) {
emit("set-color", color);
}
</script>
<template>
<div class="comment-color-selector">
<button
class="color-button prevent-zoom"
title="No Color"
data-color="none"
:class="{ selected: props.color === 'none' }"
@click="() => onClickColor('none')"></button>
<button
v-for="(hex, name) in colors"
:key="name"
class="color-button prevent-zoom"
:data-color="name"
:title="`Color ${name}`"
:class="{ selected: props.color === name }"
:style="{
'--color': hex,
'--color-bright': brightColors[name],
}"
@click="() => onClickColor(name)"></button>
</div>
</template>
<style scoped lang="scss">
@import "theme/blue.scss";
.comment-color-selector {
position: absolute;
z-index: 10000;
display: grid;
grid-template-rows: 1rem 1rem;
grid-template-columns: repeat(5, 1rem);
grid-auto-flow: column;
overflow: hidden;
border-radius: 0.25rem;
.color-button {
--color: #{$brand-primary};
--color-bright: #{$brand-secondary};
background-color: var(--color);
border-color: var(--color-bright);
border-width: 0;
border-radius: 0;
padding: 0;
width: 100%;
height: 100%;
display: grid;
place-items: center;
transition: none;
&:hover {
background-color: var(--color-bright);
}
&:focus,
&:focus-visible {
border-color: var(--color-bright);
border-width: 2px;
box-shadow: none;
}
&.selected::after {
content: "";
display: block;
width: 50%;
height: 50%;
border-radius: 50%;
background-color: var(--color-bright);
}
&.selected:hover::after {
background-color: var(--color);
}
}
}
</style>
@@ -1,47 +0,0 @@
import { mount } from "@vue/test-utils";
import { nextTick } from "vue";
import { colours } from "./colours";
import ColourSelector from "./ColourSelector.vue";
describe("ColourSelector", () => {
it("shows a button for each colour and 'none'", () => {
const wrapper = mount(ColourSelector, { propsData: { colour: "none" } });
const buttons = wrapper.findAll("button");
expect(buttons.length).toBe(Object.keys(colours).length + 1);
});
it("highlights the selected colour", async () => {
const wrapper = mount(ColourSelector, { propsData: { colour: "none" } });
const allSelected = wrapper.findAll(".selected");
expect(allSelected.length).toBe(1);
let selected = allSelected.wrappers[0];
expect(selected.element.getAttribute("title")).toBe("No Colour");
const colourNames = Object.keys(colours);
for (let i = 0; i < colourNames.length; i++) {
const colour = colourNames[i];
wrapper.setProps({ colour });
await nextTick();
selected = wrapper.find(".selected");
expect(selected.element.getAttribute("title")).toContain(colour);
}
});
it("emits the set colour", async () => {
const wrapper = mount(ColourSelector, { propsData: { colour: "none" } });
const colourNames = Object.keys(colours);
for (let i = 0; i < colourNames.length; i++) {
const colour = colourNames[i];
await wrapper.find(`[title="Colour ${colour}"]`).trigger("click");
expect(wrapper.emitted()["set-colour"][i][0]).toBe(colour);
}
});
});
@@ -1,100 +0,0 @@
<script setup lang="ts">
import type { WorkflowCommentColour } from "@/stores/workflowEditorCommentStore";
import { brightColours, colours } from "./colours";
const props = defineProps<{
colour: WorkflowCommentColour;
}>();
const emit = defineEmits<{
(e: "set-colour", colour: WorkflowCommentColour): void;
}>();
function onClickColour(colour: WorkflowCommentColour) {
emit("set-colour", colour);
}
</script>
<template>
<div class="comment-colour-selector">
<button
class="colour-button prevent-zoom"
title="No Colour"
data-colour="none"
:class="{ selected: props.colour === 'none' }"
@click="() => onClickColour('none')"></button>
<button
v-for="(hex, name) in colours"
:key="name"
class="colour-button prevent-zoom"
:data-colour="name"
:title="`Colour ${name}`"
:class="{ selected: props.colour === name }"
:style="{
'--colour': hex,
'--colour-bright': brightColours[name],
}"
@click="() => onClickColour(name)"></button>
</div>
</template>
<style scoped lang="scss">
@import "theme/blue.scss";
.comment-colour-selector {
position: absolute;
z-index: 10000;
display: grid;
grid-template-rows: 1rem 1rem;
grid-template-columns: repeat(5, 1rem);
grid-auto-flow: column;
overflow: hidden;
border-radius: 0.25rem;
.colour-button {
--colour: #{$brand-primary};
--colour-bright: #{$brand-secondary};
background-color: var(--colour);
border-color: var(--colour-bright);
border-width: 0;
border-radius: 0;
padding: 0;
width: 100%;
height: 100%;
display: grid;
place-items: center;
transition: none;
&:hover {
background-color: var(--colour-bright);
}
&:focus,
&:focus-visible {
border-color: var(--colour-bright);
border-width: 2px;
box-shadow: none;
}
&.selected::after {
content: "";
display: block;
width: 50%;
height: 50%;
border-radius: 50%;
background-color: var(--colour-bright);
}
&.selected:hover::after {
background-color: var(--colour);
}
}
}
</style>
@@ -10,14 +10,14 @@ import { computed, onMounted, reactive, ref, watch } from "vue";
import { AxisAlignedBoundingBox, type Rectangle } from "@/components/Workflow/Editor/modules/geometry";
import { useWorkflowStores } from "@/composables/workflowStores";
import type { FrameWorkflowComment, WorkflowComment, WorkflowCommentColour } from "@/stores/workflowEditorCommentStore";
import type { FrameWorkflowComment, WorkflowComment, WorkflowCommentColor } from "@/stores/workflowEditorCommentStore";
import type { Step } from "@/stores/workflowStepStore";
import { brighterColours, darkenedColours } from "./colours";
import { brighterColors, darkenedColors } from "./colors";
import { useResizable } from "./useResizable";
import { selectAllText } from "./utilities";
import ColourSelector from "./ColourSelector.vue";
import ColorSelector from "./ColorSelector.vue";
import DraggablePan from "@/components/Workflow/Editor/DraggablePan.vue";
library.add(faObjectGroup, faTrashAlt, faPalette, faCompressAlt);
@@ -35,7 +35,7 @@ const emit = defineEmits<{
(e: "move", position: [number, number]): void;
(e: "pan-by", position: { x: number; y: number }): void;
(e: "remove"): void;
(e: "set-colour", colour: WorkflowCommentColour): void;
(e: "set-color", color: WorkflowCommentColor): void;
}>();
const resizeContainer = ref<HTMLDivElement>();
@@ -69,7 +69,7 @@ function saveText() {
emit("change", { ...props.comment.data, title: getInnerText() });
}
const showColourSelector = ref(false);
const showColorSelector = ref(false);
const rootElement = ref<HTMLDivElement>();
const { focused } = useFocusWithin(rootElement);
@@ -78,7 +78,7 @@ watch(
() => focused.value,
() => {
if (!focused.value) {
showColourSelector.value = false;
showColorSelector.value = false;
}
}
);
@@ -87,8 +87,8 @@ function onClick() {
editableElement.value?.focus();
}
function onSetColour(colour: WorkflowCommentColour) {
emit("set-colour", colour);
function onSetColor(color: WorkflowCommentColor) {
emit("set-color", color);
}
const { stateStore, stepStore, commentStore } = useWorkflowStores();
@@ -242,9 +242,9 @@ function onFitToContent() {
const cssVariables = computed(() => {
const vars: Record<string, string> = {};
if (props.comment.colour !== "none") {
vars["--primary-colour"] = darkenedColours[props.comment.colour];
vars["--secondary-colour"] = brighterColours[props.comment.colour];
if (props.comment.color !== "none") {
vars["--primary-color"] = darkenedColors[props.comment.color];
vars["--secondary-color"] = brighterColors[props.comment.color];
}
return vars;
@@ -303,9 +303,9 @@ onMounted(() => {
<BButton
class="button prevent-zoom"
variant="outline-primary"
title="Colour"
:pressed="showColourSelector"
@click="() => (showColourSelector = !showColourSelector)">
title="Color"
:pressed="showColorSelector"
@click="() => (showColorSelector = !showColorSelector)">
<FontAwesomeIcon icon="fa-palette" class="prevent-zoom" />
</BButton>
<BButton class="button prevent-zoom" variant="dark" title="Delete comment" @click="() => emit('remove')">
@@ -313,11 +313,11 @@ onMounted(() => {
</BButton>
</BButtonGroup>
<ColourSelector
v-if="showColourSelector"
class="colour-selector"
:colour="props.comment.colour"
@set-colour="onSetColour" />
<ColorSelector
v-if="showColorSelector"
class="color-selector"
:color="props.comment.color"
@set-color="onSetColor" />
</div>
</template>
@@ -338,7 +338,7 @@ onMounted(() => {
resize: both;
}
.colour-selector {
.color-selector {
visibility: visible;
}
@@ -354,10 +354,10 @@ onMounted(() => {
}
.resize-container {
--primary-colour: #{$brand-primary};
--secondary-colour: #{$white};
--primary-color: #{$brand-primary};
--secondary-color: #{$white};
color: var(--primary-colour);
color: var(--primary-color);
width: 100%;
height: 100%;
min-height: 100px;
@@ -366,12 +366,12 @@ onMounted(() => {
overflow: hidden;
border-radius: 0.25rem;
border-color: var(--primary-colour);
border-color: var(--primary-color);
border-style: solid;
border-width: 2px;
.frame-comment-header {
background-color: var(--primary-colour);
background-color: var(--primary-color);
color: $white;
font-size: 1rem;
padding: 0.1rem 0.5rem;
@@ -403,18 +403,18 @@ onMounted(() => {
// coloring the "background" via ::after avoids zooming artifacts on the header
display: flex;
flex-direction: column;
background-color: var(--primary-colour);
background-color: var(--primary-color);
&::after {
content: "";
display: block;
background-color: var(--secondary-colour);
background-color: var(--secondary-color);
flex: 1;
position: relative;
}
}
.colour-selector {
.color-selector {
visibility: hidden;
right: 0;
top: -4.5rem;
@@ -6,7 +6,7 @@ import { useWorkflowStores } from "@/composables/workflowStores";
import type { FreehandWorkflowComment } from "@/stores/workflowEditorCommentStore";
import { vecSubtract } from "../modules/geometry";
import { colours } from "./colours";
import { colors } from "./colors";
const props = defineProps<{
comment: FreehandWorkflowComment;
@@ -34,8 +34,8 @@ const style = computed(() => {
"--thickness": `${props.comment.data.thickness}px`,
} as Record<string, string>;
if (props.comment.colour !== "none") {
style["--colour"] = colours[props.comment.colour];
if (props.comment.color !== "none") {
style["--color"] = colors[props.comment.color];
}
if (toolbarStore.inputCatcherEnabled) {
@@ -72,7 +72,7 @@ function onClick() {
@import "theme/blue.scss";
.freehand-workflow-comment {
--colour: #{$brand-primary};
--color: #{$brand-primary};
--thickness: 5px;
position: absolute;
@@ -88,7 +88,7 @@ function onClick() {
path {
stroke-width: var(--thickness);
stroke: var(--colour);
stroke: var(--color);
}
pointer-events: none;
@@ -10,13 +10,13 @@ import { computed, onMounted, reactive, ref, watch } from "vue";
import { useMarkdown } from "@/composables/markdown";
import { useUid } from "@/composables/utils/uid";
import { useWorkflowStores } from "@/composables/workflowStores";
import type { MarkdownWorkflowComment, WorkflowCommentColour } from "@/stores/workflowEditorCommentStore";
import type { MarkdownWorkflowComment, WorkflowCommentColor } from "@/stores/workflowEditorCommentStore";
import { darkenedColours } from "./colours";
import { darkenedColors } from "./colors";
import { useResizable } from "./useResizable";
import { selectAllText } from "./utilities";
import ColourSelector from "./ColourSelector.vue";
import ColorSelector from "./ColorSelector.vue";
import DraggablePan from "@/components/Workflow/Editor/DraggablePan.vue";
library.add(faTrashAlt, faPalette);
@@ -34,7 +34,7 @@ const emit = defineEmits<{
(e: "move", position: [number, number]): void;
(e: "pan-by", position: { x: number; y: number }): void;
(e: "remove"): void;
(e: "set-colour", colour: WorkflowCommentColour): void;
(e: "set-color", color: WorkflowCommentColor): void;
}>();
const resizeContainer = ref<HTMLDivElement>();
@@ -86,7 +86,7 @@ function onMouseup() {
}
}
const showColourSelector = ref(false);
const showColorSelector = ref(false);
const rootElement = ref<HTMLDivElement>();
const { focused } = useFocusWithin(rootElement);
@@ -95,13 +95,13 @@ watch(
() => focused.value,
() => {
if (!focused.value) {
showColourSelector.value = false;
showColorSelector.value = false;
}
}
);
function onSetColour(colour: WorkflowCommentColour) {
emit("set-colour", colour);
function onSetColor(color: WorkflowCommentColor) {
emit("set-color", color);
}
function onTextChange() {
@@ -115,8 +115,8 @@ function onTextChange() {
const cssVariables = computed(() => {
const vars: Record<string, string> = {};
if (props.comment.colour !== "none") {
vars["--primary-colour"] = darkenedColours[props.comment.colour];
if (props.comment.color !== "none") {
vars["--primary-color"] = darkenedColors[props.comment.color];
}
return vars;
@@ -163,9 +163,9 @@ onMounted(() => {
<BButton
class="button prevent-zoom"
variant="outline-primary"
title="Colour"
:pressed="showColourSelector"
@click="() => (showColourSelector = !showColourSelector)">
title="Color"
:pressed="showColorSelector"
@click="() => (showColorSelector = !showColorSelector)">
<FontAwesomeIcon icon="fa-palette" class="prevent-zoom" />
</BButton>
<BButton class="button prevent-zoom" variant="dark" title="Delete comment" @click="() => emit('remove')">
@@ -173,11 +173,11 @@ onMounted(() => {
</BButton>
</BButtonGroup>
<ColourSelector
v-if="showColourSelector"
class="colour-selector"
:colour="props.comment.colour"
@set-colour="onSetColour" />
<ColorSelector
v-if="showColorSelector"
class="color-selector"
:color="props.comment.color"
@set-color="onSetColor" />
</div>
</template>
@@ -209,7 +209,7 @@ $min-height: 1.5em;
visibility: visible;
}
.colour-selector {
.color-selector {
visibility: visible;
}
@@ -313,7 +313,7 @@ $min-height: 1.5em;
&:deep(blockquote) {
padding-left: 0.5rem;
border-left: 2px solid var(--primary-colour);
border-left: 2px solid var(--primary-color);
margin-bottom: 0.5rem;
p {
@@ -327,13 +327,13 @@ $min-height: 1.5em;
}
.resize-container {
--primary-colour: #{$brand-primary};
--primary-color: #{$brand-primary};
color: var(--primary-colour);
color: var(--primary-color);
background-color: $white;
.markdown-textarea {
color: var(--primary-colour);
color: var(--primary-color);
}
width: 100%;
@@ -344,7 +344,7 @@ $min-height: 1.5em;
overflow: hidden;
border-radius: 0.25rem;
border-color: var(--primary-colour);
border-color: var(--primary-color);
border-style: solid;
border-width: 2px;
@@ -357,7 +357,7 @@ $min-height: 1.5em;
}
}
.colour-selector {
.color-selector {
visibility: hidden;
right: 0;
top: -4.5rem;
@@ -9,13 +9,13 @@ import { sanitize } from "dompurify";
import { computed, onMounted, reactive, ref, watch } from "vue";
import { useWorkflowStores } from "@/composables/workflowStores";
import type { TextWorkflowComment, WorkflowCommentColour } from "@/stores/workflowEditorCommentStore";
import type { TextWorkflowComment, WorkflowCommentColor } from "@/stores/workflowEditorCommentStore";
import { colours } from "./colours";
import { colors } from "./colors";
import { useResizable } from "./useResizable";
import { selectAllText } from "./utilities";
import ColourSelector from "./ColourSelector.vue";
import ColorSelector from "./ColorSelector.vue";
import DraggablePan from "@/components/Workflow/Editor/DraggablePan.vue";
library.add(faTrashAlt, faPalette);
@@ -33,7 +33,7 @@ const emit = defineEmits<{
(e: "move", position: [number, number]): void;
(e: "pan-by", position: { x: number; y: number }): void;
(e: "remove"): void;
(e: "set-colour", colour: WorkflowCommentColour): void;
(e: "set-color", color: WorkflowCommentColor): void;
}>();
const resizeContainer = ref<HTMLDivElement>();
@@ -118,7 +118,7 @@ function onMove(position: { x: number; y: number }) {
emit("move", [position.x, position.y]);
}
const showColourSelector = ref(false);
const showColorSelector = ref(false);
const rootElement = ref<HTMLDivElement>();
const { focused } = useFocusWithin(rootElement);
@@ -127,7 +127,7 @@ watch(
() => focused.value,
() => {
if (!focused.value) {
showColourSelector.value = false;
showColorSelector.value = false;
if (getInnerText() === "") {
emit("remove");
@@ -138,8 +138,8 @@ watch(
}
);
function onSetColour(colour: WorkflowCommentColour) {
emit("set-colour", colour);
function onSetColor(color: WorkflowCommentColor) {
emit("set-color", color);
}
const cssVariables = computed(() => {
@@ -147,8 +147,8 @@ const cssVariables = computed(() => {
"--font-size": `${fontSize.value}rem`,
};
if (props.comment.colour !== "none") {
vars["--font-colour"] = colours[props.comment.colour];
if (props.comment.color !== "none") {
vars["--font-color"] = colors[props.comment.color];
}
return vars;
@@ -222,9 +222,9 @@ onMounted(() => {
<BButton
class="button prevent-zoom"
variant="outline-primary"
title="Colour"
:pressed="showColourSelector"
@click="() => (showColourSelector = !showColourSelector)">
title="Color"
:pressed="showColorSelector"
@click="() => (showColorSelector = !showColorSelector)">
<FontAwesomeIcon icon="fa-palette" class="prevent-zoom" />
</BButton>
<BButton
@@ -246,11 +246,11 @@ onMounted(() => {
</BButton>
</BButtonGroup>
<ColourSelector
v-if="showColourSelector"
class="colour-selector"
:colour="props.comment.colour"
@set-colour="onSetColour" />
<ColorSelector
v-if="showColorSelector"
class="color-selector"
:color="props.comment.color"
@set-color="onSetColor" />
</div>
</template>
@@ -272,7 +272,7 @@ onMounted(() => {
visibility: visible;
}
.colour-selector {
.color-selector {
visibility: visible;
}
@@ -290,9 +290,9 @@ onMounted(() => {
.resize-container {
--font-size: 1rem;
--font-colour: #{$brand-primary};
--font-color: #{$brand-primary};
color: var(--font-colour);
color: var(--font-color);
font-size: var(--font-size);
width: 100%;
@@ -345,7 +345,7 @@ onMounted(() => {
}
}
.colour-selector {
.color-selector {
visibility: hidden;
right: 0.75rem;
top: -4.5rem;
@@ -8,7 +8,7 @@ import WorkflowComment from "./WorkflowComment.vue";
const changeData = jest.fn();
const changeSize = jest.fn();
const changePosition = jest.fn();
const changeColour = jest.fn();
const changeColor = jest.fn();
const deleteComment = jest.fn();
jest.mock("@/composables/workflowStores", () => ({
@@ -17,7 +17,7 @@ jest.mock("@/composables/workflowStores", () => ({
changeData,
changeSize,
changePosition,
changeColour,
changeColor,
deleteComment,
isJustCreated: () => false,
},
@@ -37,7 +37,7 @@ describe("WorkflowComment", () => {
const comment = {
id: 0,
type: "text",
colour: "none",
color: "none",
position: [0, 0],
size: [100, 100],
data: {},
@@ -125,8 +125,8 @@ describe("WorkflowComment", () => {
textComment.vm.$emit("move", [20, 20]);
expect(changePosition).toBeCalledWith(123, [20, 20]);
textComment.vm.$emit("set-colour", "pink");
expect(changeColour).toBeCalledWith(123, "pink");
textComment.vm.$emit("set-color", "pink");
expect(changeColor).toBeCalledWith(123, "pink");
textComment.vm.$emit("remove");
expect(deleteComment).toBeCalledWith(123);
@@ -3,7 +3,7 @@ import type { UseElementBoundingReturn } from "@vueuse/core";
import { computed } from "vue";
import { useWorkflowStores } from "@/composables/workflowStores";
import type { WorkflowComment, WorkflowCommentColour } from "@/stores/workflowEditorCommentStore";
import type { WorkflowComment, WorkflowCommentColor } from "@/stores/workflowEditorCommentStore";
import FrameComment from "./FrameComment.vue";
import FreehandComment from "./FreehandComment.vue";
@@ -50,8 +50,8 @@ function onRemove() {
commentStore.deleteComment(props.comment.id);
}
function onSetColour(colour: WorkflowCommentColour) {
commentStore.changeColour(props.comment.id, colour);
function onSetColor(color: WorkflowCommentColor) {
commentStore.changeColor(props.comment.id, color);
}
</script>
@@ -68,7 +68,7 @@ function onSetColour(colour: WorkflowCommentColour) {
@move="onMove"
@pan-by="onPan"
@remove="onRemove"
@set-colour="onSetColour" />
@set-color="onSetColor" />
<MarkdownComment
v-else-if="props.comment.type === 'markdown'"
:comment="props.comment"
@@ -80,7 +80,7 @@ function onSetColour(colour: WorkflowCommentColour) {
@move="onMove"
@pan-by="onPan"
@remove="onRemove"
@set-colour="onSetColour" />
@set-color="onSetColor" />
<FrameComment
v-else-if="props.comment.type === 'frame'"
:comment="props.comment"
@@ -92,7 +92,7 @@ function onSetColour(colour: WorkflowCommentColour) {
@move="onMove"
@pan-by="onPan"
@remove="onRemove"
@set-colour="onSetColour" />
@set-color="onSetColor" />
<FreehandComment v-else-if="props.comment.type === 'freehand'" :comment="props.comment" @remove="onRemove" />
</div>
</template>
@@ -1,6 +1,6 @@
import { Hsluv } from "hsluv";
export const colours = {
export const colors = {
black: "#000",
blue: "#004cec",
turquoise: "#00bbd9",
@@ -12,39 +12,39 @@ export const colours = {
pink: "#fb00a6",
} as const;
export type Colour = keyof typeof colours;
export type HexColour = `#${string}`;
export type Color = keyof typeof colors;
export type HexColor = `#${string}`;
export const brightColours = (() => {
export const brightColors = (() => {
const brighter: Record<string, string> = {};
const converter = new Hsluv();
Object.entries(colours).forEach(([name, colour]) => {
converter.hex = colour;
Object.entries(colors).forEach(([name, color]) => {
converter.hex = color;
converter.hexToHsluv();
converter.hsluv_l += (100 - converter.hsluv_l) * 0.5;
converter.hsluvToHex();
brighter[name] = converter.hex;
});
return brighter as Record<Colour, HexColour>;
return brighter as Record<Color, HexColor>;
})();
export const brighterColours = (() => {
export const brighterColors = (() => {
const brighter: Record<string, string> = {};
const converter = new Hsluv();
Object.entries(colours).forEach(([name, colour]) => {
converter.hex = colour;
Object.entries(colors).forEach(([name, color]) => {
converter.hex = color;
converter.hexToHsluv();
converter.hsluv_l += (100 - converter.hsluv_l) * 0.95;
converter.hsluvToHex();
brighter[name] = converter.hex;
});
return brighter as Record<Colour, HexColour>;
return brighter as Record<Color, HexColor>;
})();
export const darkenedColours = {
...colours,
export const darkenedColors = {
...colors,
turquoise: "#00a6c0" as const,
lime: "#5eae00" as const,
yellow: "#e9ad00" as const,
@@ -14,7 +14,7 @@ import { match } from "@/utils/utils";
import { useToolLogic } from "./useToolLogic";
import ColourSelector from "@/components/Workflow/Editor/Comments/ColourSelector.vue";
import ColorSelector from "@/components/Workflow/Editor/Comments/ColorSelector.vue";
library.add(faMagnet, faMousePointer, faObjectGroup, faMarkdown, faPen, faEraser);
@@ -226,10 +226,10 @@ whenever(ctrl_7!, () => (toolbarStore.currentTool = "freehandEraser"));
</div>
<div v-if="!['pointer', 'freehandEraser'].includes(toolbarStore.currentTool)" class="option buttons">
<ColourSelector
:colour="commentOptions.colour"
class="colour-selector"
@set-colour="(colour) => (commentOptions.colour = colour)" />
<ColorSelector
:color="commentOptions.color"
class="color-selector"
@set-color="(color) => (commentOptions.color = color)" />
</div>
<div v-if="toolbarStore.currentTool === 'textComment'" class="option small">
@@ -390,7 +390,7 @@ whenever(ctrl_7!, () => (toolbarStore.currentTool = "freehandEraser"));
justify-content: space-between;
}
.colour-selector {
.color-selector {
position: relative;
}
@@ -37,7 +37,7 @@ export function useToolLogic(toolbarStore: WorkflowEditorToolbarStore, commentSt
id: commentStore.highestCommentId + 1,
position: start,
size: [0, 0] as [number, number],
colour: commentOptions.colour,
color: commentOptions.color,
};
comment = match(toolbarStore.currentTool, {
@@ -1,6 +1,6 @@
import { curveCatmullRom, line } from "d3";
import * as commentColours from "@/components/Workflow/Editor/Comments/colours";
import * as commentColors from "@/components/Workflow/Editor/Comments/colors";
import type {
FrameWorkflowComment,
FreehandWorkflowComment,
@@ -14,21 +14,21 @@ export function drawBoxComments(
ctx: CanvasRenderingContext2D,
comments: FrameWorkflowComment[] | TextWorkflowComment[] | MarkdownWorkflowComment[],
lineWidth: number,
defaultColour: string,
colourFill = false
defaultColor: string,
colorFill = false
) {
ctx.lineWidth = lineWidth;
if (colourFill) {
if (colorFill) {
comments.forEach((comment) => {
ctx.beginPath();
if (comment.colour !== "none") {
ctx.fillStyle = commentColours.brighterColours[comment.colour];
ctx.strokeStyle = commentColours.colours[comment.colour];
if (comment.color !== "none") {
ctx.fillStyle = commentColors.brighterColors[comment.color];
ctx.strokeStyle = commentColors.colors[comment.color];
} else {
ctx.fillStyle = "rgba(0, 0, 0, 0)";
ctx.strokeStyle = defaultColour;
ctx.strokeStyle = defaultColor;
}
ctx.rect(comment.position[0], comment.position[1], comment.size[0], comment.size[1]);
@@ -39,10 +39,10 @@ export function drawBoxComments(
comments.forEach((comment) => {
ctx.beginPath();
if (comment.colour !== "none") {
ctx.strokeStyle = commentColours.colours[comment.colour];
if (comment.color !== "none") {
ctx.strokeStyle = commentColors.colors[comment.color];
} else {
ctx.strokeStyle = defaultColour;
ctx.strokeStyle = defaultColor;
}
ctx.rect(comment.position[0], comment.position[1], comment.size[0], comment.size[1]);
@@ -55,11 +55,11 @@ export function drawBoxComments(
export function drawSteps(
ctx: CanvasRenderingContext2D,
steps: Step[],
colour: string,
color: string,
stateStore: ReturnType<typeof useWorkflowStateStore>
) {
ctx.beginPath();
ctx.fillStyle = colour;
ctx.fillStyle = color;
steps.forEach((step) => {
const rect = stateStore.stepPosition[step.id];
@@ -73,15 +73,15 @@ export function drawSteps(
export function drawFreehandComments(
ctx: CanvasRenderingContext2D,
comments: FreehandWorkflowComment[],
defaultColour: string
defaultColor: string
) {
const catmullRom = line().curve(curveCatmullRom).context(ctx);
comments.forEach((comment) => {
if (comment.colour === "none") {
ctx.strokeStyle = defaultColour;
if (comment.color === "none") {
ctx.strokeStyle = defaultColor;
} else {
ctx.strokeStyle = commentColours.colours[comment.colour];
ctx.strokeStyle = commentColors.colors[comment.color];
}
ctx.lineWidth = comment.data.thickness;
@@ -10,7 +10,7 @@ import {
const freehandComment: FreehandWorkflowComment = {
type: "freehand",
colour: "none",
color: "none",
data: {
thickness: 10,
line: [[100, 100]],
@@ -22,7 +22,7 @@ const freehandComment: FreehandWorkflowComment = {
const textComment: TextWorkflowComment = {
type: "text",
colour: "none",
color: "none",
data: {
size: 1,
text: "Hello World",
@@ -34,7 +34,7 @@ const textComment: TextWorkflowComment = {
const markdownComment: MarkdownWorkflowComment = {
type: "markdown",
colour: "none",
color: "none",
data: {
text: "# Hello World",
},
@@ -45,7 +45,7 @@ const markdownComment: MarkdownWorkflowComment = {
const frameComment: FrameWorkflowComment = {
type: "frame",
colour: "none",
color: "none",
data: {
title: "My Frame",
},
@@ -56,7 +56,7 @@ const frameComment: FrameWorkflowComment = {
const frameCommentTwo: FrameWorkflowComment = {
type: "frame",
colour: "none",
color: "none",
data: {
title: "My Frame",
},
@@ -143,13 +143,13 @@ describe("workflowEditorCommentStore", () => {
it("does not mutate input data", () => {
const commentStore = useWorkflowCommentStore("mock-id");
const comment: TextWorkflowComment = { ...textComment, id: 0, colour: "pink" };
const comment: TextWorkflowComment = { ...textComment, id: 0, color: "pink" };
commentStore.addComments([comment]);
commentStore.changeColour(0, "blue");
commentStore.changeColor(0, "blue");
expect(commentStore.comments[0]?.colour).toBe("blue");
expect(comment.colour).toBe("pink");
expect(commentStore.comments[0]?.color).toBe("blue");
expect(comment.color).toBe("pink");
});
it("implements reset", () => {
@@ -1,7 +1,7 @@
import { defineStore } from "pinia";
import { computed, del, ref, set } from "vue";
import type { Colour } from "@/components/Workflow/Editor/Comments/colours";
import type { Color } from "@/components/Workflow/Editor/Comments/colors";
import {
AxisAlignedBoundingBox,
type Rectangle,
@@ -18,12 +18,12 @@ import { hasKeys, match } from "@/utils/utils";
import { useWorkflowStateStore } from "./workflowEditorStateStore";
import { Step, useWorkflowStepStore } from "./workflowStepStore";
export type WorkflowCommentColour = Colour | "none";
export type WorkflowCommentColor = Color | "none";
export interface BaseWorkflowComment {
id: number;
type: string;
colour: WorkflowCommentColour;
color: WorkflowCommentColor;
position: [number, number];
size: [number, number];
data: unknown;
@@ -139,9 +139,9 @@ export const useWorkflowCommentStore = (workflowId: string) => {
set(comment, "data", data);
}
function changeColour(id: number, colour: WorkflowCommentColour) {
function changeColor(id: number, color: WorkflowCommentColor) {
const comment = getComment.value(id);
set(comment, "colour", colour);
set(comment, "color", color);
}
function addPoint(id: number, point: [number, number]) {
@@ -294,7 +294,7 @@ export const useWorkflowCommentStore = (workflowId: string) => {
changePosition,
changeSize,
changeData,
changeColour,
changeColor,
addPoint,
deleteComment,
createComment,
@@ -4,7 +4,7 @@ import { computed, onScopeDispose, reactive, ref, watch } from "vue";
import { useUserLocalStorage } from "@/composables/userLocalStorage";
import { WorkflowCommentColour } from "./workflowEditorCommentStore";
import { WorkflowCommentColor } from "./workflowEditorCommentStore";
export type CommentTool = "textComment" | "markdownComment" | "frameComment" | "freehandComment" | "freehandEraser";
export type EditorTool = "pointer" | CommentTool;
@@ -38,7 +38,7 @@ export const useWorkflowEditorToolbarStore = (workflowId: string) => {
const commentOptions = reactive({
bold: false,
italic: false,
colour: "none" as WorkflowCommentColour,
color: "none" as WorkflowCommentColor,
textSize: 2,
lineThickness: 5,
smoothing: 2,
+1 -1
View File
@@ -690,7 +690,7 @@ workflow_editor:
snapping_distance: "[data-option='snapping-distance']"
toggle_bold: "[data-option='toggle-bold']"
toggle_italic: "[data-option='toggle-italic']"
colour: ".colour-selector [data-colour='${colour}']"
color: ".color-selector [data-color='${color}']"
font_size: "[data-option='font-size']"
line_thickness: "[data-option='line-thickness']"
smoothing: "[data-option='smoothing']"
+3 -3
View File
@@ -7987,7 +7987,7 @@ class WorkflowComment(Base, RepresentById):
position = Column(MutableJSONType)
size = Column(JSONType)
type = Column(String(16))
colour = Column(String(16))
color = Column(String(16))
data = Column(JSONType)
parent_comment_id = Column(Integer, ForeignKey("workflow_comment.id"), nullable=True)
@@ -8022,7 +8022,7 @@ class WorkflowComment(Base, RepresentById):
"position": self.position,
"size": self.size,
"type": self.type,
"colour": self.colour,
"color": self.color,
"data": self.data,
}
@@ -8044,7 +8044,7 @@ class WorkflowComment(Base, RepresentById):
comment.type = dict.get("type", "text")
comment.position = dict.get("position", None)
comment.size = dict.get("size", None)
comment.colour = dict.get("colour", "none")
comment.color = dict.get("color", "none")
comment.data = dict.get("data", None)
return comment
@@ -39,7 +39,7 @@ def upgrade():
sa.Column("position", MutableJSONType),
sa.Column("size", JSONType),
sa.Column("type", sa.String(16)),
sa.Column("colour", sa.String(16)),
sa.Column("color", sa.String(16)),
sa.Column("data", JSONType),
sa.Column(PARENT_COMMENT_COLUMN_NAME, sa.Integer, sa.ForeignKey("workflow_comment.id"), nullable=True),
)
+2 -2
View File
@@ -14,8 +14,8 @@ from typing_extensions import Literal
class BaseComment(BaseModel):
id: int = Field(..., description="Unique identifier for this comment. Determined by the comments order")
colour: Literal["none", "black", "blue", "turquoise", "green", "lime", "orange", "yellow", "red", "pink"] = Field(
..., description="Colour this comment is displayed as. The exact colour hex is determined by the client"
color: Literal["none", "black", "blue", "turquoise", "green", "lime", "orange", "yellow", "red", "pink"] = Field(
..., description="Color this comment is displayed as. The exact color hex is determined by the client"
)
position: Tuple[float, float] = Field(..., description="[x, y] position of this comment in the Workflow")
size: Tuple[float, float] = Field(..., description="[width, height] size of this comment")