Skip to content

Commit

Permalink
feat(core): added delete and edit functions on color slices
Browse files Browse the repository at this point in the history
implemented functions to delete and to edit a color value

wip #15
  • Loading branch information
gabrieleAngius committed Jun 15, 2023
1 parent 4ddb81d commit 68e2484
Show file tree
Hide file tree
Showing 7 changed files with 528 additions and 13 deletions.
2 changes: 1 addition & 1 deletion test-environment/getFigmaMock.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ module.exports.getFigmaMock = (jestFn) => {
getLocalPaintStyles: jestFn(() => []),
getLocalTextStyles: jestFn(() => []),
getLocalEffectStyles: jestFn(() => []),
getStyleById: jestFn(() => []),
getStyleById: jestFn(() => {}),
loadFontAsync: jestFn(() => Promise.resolve()),
createTextStyle: jestFn(() => ({ id: randomId() })),
createPaintStyle: jestFn(() => ({ id: randomId() })),
Expand Down
45 changes: 37 additions & 8 deletions widget-src/components/Colors/ColorSlice.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { ColorSliceItem, Store } from "../../types";
import { DeleteButton } from "../Buttons/DeleteButton";
import { getHexAndOpacity } from "../../utils/getHexAndOpacity";
import { ColorValue } from "./ColorValue";
import { deleteColor } from "./deleteColor";
import { editColor } from "./editColor";

const { widget } = figma;
const { Frame, Ellipse, Input, AutoLayout, Text } = widget;
Expand All @@ -16,6 +18,7 @@ export const ColorSlice = ({ isHex, colorsMap, ...slice }: Props) => {
const { hex, opacityPercent } = getHexAndOpacity(slice.rgba);
const { color, opacity } = rgbaToFigmaColor(slice.rgba);
const fill = { ...color, a: opacity };

return (
<AutoLayout
name="Color Slice"
Expand All @@ -30,7 +33,7 @@ export const ColorSlice = ({ isHex, colorsMap, ...slice }: Props) => {
<Frame name="Frame3" overflow="visible" width={41} height={41}>
<Ellipse width={41} height={41} fill={fill} />
</Frame>
<DeleteButton onClick={() => {}} />
<DeleteButton onClick={() => deleteColor(slice, colorsMap)} />
</Frame>
<AutoLayout direction="vertical" spacing={2}>
<Input
Expand All @@ -44,7 +47,9 @@ export const ColorSlice = ({ isHex, colorsMap, ...slice }: Props) => {
width={90}
inputBehavior="truncate"
inputFrameProps={{ direction: "horizontal" }}
onTextEditEnd={() => {}}
onTextEditEnd={(event) =>
editColor({ valueToEdit: "name", event, colorsMap, slice })
}
/>
{isHex ? (
<AutoLayout
Expand Down Expand Up @@ -74,7 +79,9 @@ export const ColorSlice = ({ isHex, colorsMap, ...slice }: Props) => {
fontWeight={500}
strokeWidth={0.632}
value={hex}
onTextEditEnd={() => {}}
onTextEditEnd={(event) =>
editColor({ valueToEdit: "hex", event, colorsMap, slice })
}
/>
</Frame>
<AutoLayout width="fill-parent" height={20}>
Expand All @@ -97,7 +104,9 @@ export const ColorSlice = ({ isHex, colorsMap, ...slice }: Props) => {
fontWeight={500}
strokeWidth={0.632}
value={opacityPercent}
onTextEditEnd={() => {}}
onTextEditEnd={(event) =>
editColor({ valueToEdit: "opacity", event, colorsMap, slice })
}
/>
<Text
name="opacity"
Expand All @@ -113,10 +122,30 @@ export const ColorSlice = ({ isHex, colorsMap, ...slice }: Props) => {
</AutoLayout>
) : (
<AutoLayout direction="vertical" width={50} height={50} spacing={2}>
<ColorValue label="R" value={slice.rgba.r} />
<ColorValue label="G" value={slice.rgba.g} />
<ColorValue label="B" value={slice.rgba.b} />
<ColorValue label="A" value={slice.rgba.a} />
<ColorValue
rgbaKey="r"
value={slice.rgba.r}
colorsMap={colorsMap}
slice={slice}
/>
<ColorValue
rgbaKey="g"
value={slice.rgba.g}
colorsMap={colorsMap}
slice={slice}
/>
<ColorValue
rgbaKey="b"
value={slice.rgba.b}
colorsMap={colorsMap}
slice={slice}
/>
<ColorValue
rgbaKey="a"
value={slice.rgba.a}
colorsMap={colorsMap}
slice={slice}
/>
</AutoLayout>
)}
</AutoLayout>
Expand Down
15 changes: 11 additions & 4 deletions widget-src/components/Colors/ColorValue.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import { ColorSliceItem } from "../../types";
import { editColor } from "./editColor";

const { widget } = figma;
const { Frame, Input, Text } = widget;

type Props = {
value: number;
label: string;
rgbaKey: keyof RGBA;
colorsMap: SyncedMap<ColorSliceItem>;
slice: ColorSliceItem;
};

export const ColorValue = ({ value, label }: Props) => {
export const ColorValue = ({ value, rgbaKey, colorsMap, slice }: Props) => {
return (
<Frame width="fill-parent" height="fill-parent">
<Text
Expand All @@ -16,7 +21,7 @@ export const ColorValue = ({ value, label }: Props) => {
fontSize={10}
fontWeight={500}
>
{label}
{rgbaKey.toUpperCase()}
</Text>
<Input
x={10}
Expand All @@ -28,7 +33,9 @@ export const ColorValue = ({ value, label }: Props) => {
fontWeight={500}
strokeWidth={0.632}
value={`${value}`}
onTextEditEnd={() => {}}
onTextEditEnd={(event) =>
editColor({ valueToEdit: "rgba", rgbaKey, event, colorsMap, slice })
}
/>
</Frame>
);
Expand Down
49 changes: 49 additions & 0 deletions widget-src/components/Colors/deleteColor.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { mockSyncedMap } from "../../test-utils/mockSyncedMap";
import { ColorSliceItem } from "../../types";
import { deleteColor } from "./deleteColor";

describe("deleteColor", () => {
it("should delete the color if there are at least 2 items", () => {
const mockRemove = jest.fn();
jest
.spyOn(figma, "getStyleById")
.mockReturnValue({ remove: mockRemove } as any);
const slice1: ColorSliceItem = {
id: "id-1",
name: "primary",
rgba: { r: 1, g: 1, b: 1, a: 1 },
libStyleId: "lib-id-1",
};
const slice2: ColorSliceItem = {
id: "id-2",
name: "secondary",
rgba: { r: 1, g: 1, b: 1, a: 1 },
libStyleId: "lib-id-2",
};
const colorsMap = mockSyncedMap<ColorSliceItem>({
[slice1.id]: slice1,
[slice2.id]: slice2,
});
deleteColor(slice1, colorsMap);

expect(figma.notify).not.toBeCalled();
expect(colorsMap.delete).toBeCalledTimes(1);
expect(colorsMap.delete).toBeCalledWith(slice1.id);
});
it("should not delete the color if there's one value or less and call notify", () => {
const slice: ColorSliceItem = {
id: "id-1",
name: "primary",
rgba: { r: 1, g: 1, b: 1, a: 1 },
libStyleId: "lib-id",
};
const colorsMap = mockSyncedMap<ColorSliceItem>({ [slice.id]: slice });
deleteColor(slice, colorsMap);

expect(figma.notify).toBeCalledTimes(1);
expect(figma.notify).toBeCalledWith(
expect.any(String),
expect.objectContaining({ error: true })
);
});
});
21 changes: 21 additions & 0 deletions widget-src/components/Colors/deleteColor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { ColorSliceItem } from "../../types";
import { syncColorLib } from "../../utils/syncColorLib";

export const deleteColor = (
slice: ColorSliceItem,
colorsMap: SyncedMap<ColorSliceItem>
) => {
if (colorsMap.size < 2) {
figma.notify("Impossible to remove all slices. Please keep at least one", {
error: true,
timeout: 3000,
});
return;
}
colorsMap.delete(slice.id);
const colorStyle = figma.getStyleById(slice.libStyleId);
if (colorStyle) {
colorStyle.remove();
}
syncColorLib(colorsMap);
};
Loading

0 comments on commit 68e2484

Please sign in to comment.