feat: zigzag fill easter egg (#6439)
This commit is contained in:
parent
ec215362a1
commit
e4d8ba226f
@ -1,4 +1,5 @@
|
||||
import { AppState } from "../../src/types";
|
||||
import { trackEvent } from "../analytics";
|
||||
import { ButtonIconSelect } from "../components/ButtonIconSelect";
|
||||
import { ColorPicker } from "../components/ColorPicker";
|
||||
import { IconPicker } from "../components/IconPicker";
|
||||
@ -37,6 +38,7 @@ import {
|
||||
TextAlignLeftIcon,
|
||||
TextAlignCenterIcon,
|
||||
TextAlignRightIcon,
|
||||
FillZigZagIcon,
|
||||
} from "../components/icons";
|
||||
import {
|
||||
DEFAULT_FONT_FAMILY,
|
||||
@ -294,7 +296,12 @@ export const actionChangeBackgroundColor = register({
|
||||
export const actionChangeFillStyle = register({
|
||||
name: "changeFillStyle",
|
||||
trackEvent: false,
|
||||
perform: (elements, appState, value) => {
|
||||
perform: (elements, appState, value, app) => {
|
||||
trackEvent(
|
||||
"element",
|
||||
"changeFillStyle",
|
||||
`${value} (${app.device.isMobile ? "mobile" : "desktop"})`,
|
||||
);
|
||||
return {
|
||||
elements: changeProperty(elements, appState, (el) =>
|
||||
newElementWith(el, {
|
||||
@ -305,15 +312,23 @@ export const actionChangeFillStyle = register({
|
||||
commitToHistory: true,
|
||||
};
|
||||
},
|
||||
PanelComponent: ({ elements, appState, updateData }) => (
|
||||
PanelComponent: ({ elements, appState, updateData }) => {
|
||||
const selectedElements = getSelectedElements(elements, appState);
|
||||
const allElementsZigZag = selectedElements.every(
|
||||
(el) => el.fillStyle === "zigzag",
|
||||
);
|
||||
|
||||
return (
|
||||
<fieldset>
|
||||
<legend>{t("labels.fill")}</legend>
|
||||
<ButtonIconSelect
|
||||
type="button"
|
||||
options={[
|
||||
{
|
||||
value: "hachure",
|
||||
text: t("labels.hachure"),
|
||||
icon: FillHachureIcon,
|
||||
icon: allElementsZigZag ? FillZigZagIcon : FillHachureIcon,
|
||||
active: allElementsZigZag ? true : undefined,
|
||||
},
|
||||
{
|
||||
value: "cross-hatch",
|
||||
@ -326,19 +341,26 @@ export const actionChangeFillStyle = register({
|
||||
icon: FillSolidIcon,
|
||||
},
|
||||
]}
|
||||
group="fill"
|
||||
value={getFormValue(
|
||||
elements,
|
||||
appState,
|
||||
(element) => element.fillStyle,
|
||||
appState.currentItemFillStyle,
|
||||
)}
|
||||
onChange={(value) => {
|
||||
updateData(value);
|
||||
onClick={(value, event) => {
|
||||
const nextValue =
|
||||
event.altKey &&
|
||||
value === "hachure" &&
|
||||
selectedElements.every((el) => el.fillStyle === "hachure")
|
||||
? "zigzag"
|
||||
: value;
|
||||
|
||||
updateData(nextValue);
|
||||
}}
|
||||
/>
|
||||
</fieldset>
|
||||
),
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
export const actionChangeStrokeWidth = register({
|
||||
|
@ -1,33 +1,59 @@
|
||||
import clsx from "clsx";
|
||||
|
||||
// TODO: It might be "clever" to add option.icon to the existing component <ButtonSelect />
|
||||
export const ButtonIconSelect = <T extends Object>({
|
||||
options,
|
||||
value,
|
||||
onChange,
|
||||
group,
|
||||
}: {
|
||||
options: { value: T; text: string; icon: JSX.Element; testId?: string }[];
|
||||
export const ButtonIconSelect = <T extends Object>(
|
||||
props: {
|
||||
options: {
|
||||
value: T;
|
||||
text: string;
|
||||
icon: JSX.Element;
|
||||
testId?: string;
|
||||
/** if not supplied, defaults to value identity check */
|
||||
active?: boolean;
|
||||
}[];
|
||||
value: T | null;
|
||||
onChange: (value: T) => void;
|
||||
group: string;
|
||||
}) => (
|
||||
type?: "radio" | "button";
|
||||
} & (
|
||||
| { type?: "radio"; group: string; onChange: (value: T) => void }
|
||||
| {
|
||||
type: "button";
|
||||
onClick: (
|
||||
value: T,
|
||||
event: React.MouseEvent<HTMLButtonElement, MouseEvent>,
|
||||
) => void;
|
||||
}
|
||||
),
|
||||
) => (
|
||||
<div className="buttonList buttonListIcon">
|
||||
{options.map((option) => (
|
||||
{props.options.map((option) =>
|
||||
props.type === "button" ? (
|
||||
<button
|
||||
key={option.text}
|
||||
onClick={(event) => props.onClick(option.value, event)}
|
||||
className={clsx({
|
||||
active: option.active ?? props.value === option.value,
|
||||
})}
|
||||
data-testid={option.testId}
|
||||
title={option.text}
|
||||
>
|
||||
{option.icon}
|
||||
</button>
|
||||
) : (
|
||||
<label
|
||||
key={option.text}
|
||||
className={clsx({ active: value === option.value })}
|
||||
className={clsx({ active: props.value === option.value })}
|
||||
title={option.text}
|
||||
>
|
||||
<input
|
||||
type="radio"
|
||||
name={group}
|
||||
onChange={() => onChange(option.value)}
|
||||
checked={value === option.value}
|
||||
name={props.group}
|
||||
onChange={() => props.onChange(option.value)}
|
||||
checked={props.value === option.value}
|
||||
data-testid={option.testId}
|
||||
/>
|
||||
{option.icon}
|
||||
</label>
|
||||
))}
|
||||
),
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
@ -1008,6 +1008,13 @@ export const UngroupIcon = React.memo(({ theme }: { theme: Theme }) =>
|
||||
),
|
||||
);
|
||||
|
||||
export const FillZigZagIcon = createIcon(
|
||||
<g strokeWidth={1.25}>
|
||||
<path d="M5.879 2.625h8.242a3.27 3.27 0 0 1 3.254 3.254v8.242a3.27 3.27 0 0 1-3.254 3.254H5.88a3.27 3.27 0 0 1-3.254-3.254V5.88A3.27 3.27 0 0 1 5.88 2.626l-.001-.001ZM4.518 16.118l7.608-12.83m.198 13.934 5.051-9.897M2.778 9.675l9.348-6.387m-7.608 12.83 12.857-8.793" />
|
||||
</g>,
|
||||
modifiedTablerIconProps,
|
||||
);
|
||||
|
||||
export const FillHachureIcon = createIcon(
|
||||
<>
|
||||
<path
|
||||
|
@ -155,6 +155,9 @@
|
||||
margin: 1px;
|
||||
}
|
||||
|
||||
.welcome-screen-menu-item:focus-visible,
|
||||
.dropdown-menu-item:focus-visible,
|
||||
button:focus-visible,
|
||||
.buttonList label:focus-within,
|
||||
input:focus-visible {
|
||||
outline: transparent;
|
||||
|
@ -9,7 +9,7 @@ import {
|
||||
import { MarkNonNullable, ValueOf } from "../utility-types";
|
||||
|
||||
export type ChartType = "bar" | "line";
|
||||
export type FillStyle = "hachure" | "cross-hatch" | "solid";
|
||||
export type FillStyle = "hachure" | "cross-hatch" | "solid" | "zigzag";
|
||||
export type FontFamilyKeys = keyof typeof FONT_FAMILY;
|
||||
export type FontFamilyValues = typeof FONT_FAMILY[FontFamilyKeys];
|
||||
export type Theme = typeof THEME[keyof typeof THEME];
|
||||
|
Loading…
x
Reference in New Issue
Block a user