Skip to content

Commit

Permalink
feat: update config values with a generic utils function
Browse files Browse the repository at this point in the history
  • Loading branch information
ramenhog committed Nov 7, 2024
1 parent 8f09539 commit a5e19e2
Show file tree
Hide file tree
Showing 10 changed files with 160 additions and 157 deletions.
16 changes: 14 additions & 2 deletions demo/ts/components/theme-builder/accordion.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,20 @@ import React from "react";
import clsx from "clsx";
import { FaChevronDown } from "react-icons/fa";

const Accordion = ({ id, title, children }) => {
const [isOpen, setIsOpen] = React.useState(false);
type AccordionProps = {
id: string;
title: string;
children: React.ReactNode;
defaultOpen?: boolean;
};

const Accordion = ({
id,
title,
children,
defaultOpen = false,
}: AccordionProps) => {
const [isOpen, setIsOpen] = React.useState(defaultOpen);

const toggleAccordion = () => {
setIsOpen(!isOpen);
Expand Down
10 changes: 5 additions & 5 deletions demo/ts/components/theme-builder/color-picker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ type ColorPickerProps = {
label?: string;
color: string;
id: string;
onColorChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
onColorChange: (color: string) => void;
showColorName?: boolean;
};

Expand All @@ -21,7 +21,7 @@ const ColorPicker = ({

const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
if (onColorChange) {
onColorChange(event);
onColorChange(event.target.value);
}
};

Expand All @@ -33,7 +33,7 @@ const ColorPicker = ({
</label>
)}
<div
className={clsx("relative inline-flex rounded-full group", {
className={clsx("relative inline-flex rounded-full group/swatch", {
"border-2 border-gray-200 p-0.5 cursor-pointer justify-between bg-gray-100":
showColorName,
})}
Expand All @@ -55,7 +55,7 @@ const ColorPicker = ({
/>
{!showColorName && (
<div
className={`absolute top-0 left-0 w-full h-full text-white flex justify-center items-center text-xl rounded-full opacity-0 group-hover:opacity-100 ${
className={`absolute top-0 left-0 w-full h-full text-white flex justify-center items-center text-xl rounded-full opacity-0 group-hover/swatch:opacity-100 ${
isPickerOpen ? "opacity-100" : ""
}`}
>
Expand All @@ -82,7 +82,7 @@ const ColorPicker = ({
)}
<input
id={id}
className={`absolute top-0 left-0 w-full h-full cursor-pointer opacity-0 z-10 group-hover:border-currentColor ${
className={`absolute top-0 left-0 w-full h-full cursor-pointer opacity-0 z-10 group-hover/swatch:border-currentColor ${
isPickerOpen ? "border-currentColor" : ""
}`}
type="color"
Expand Down
9 changes: 5 additions & 4 deletions demo/ts/components/theme-builder/color-scale-options.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Select from "./select";
import ColorPicker from "./color-picker";

export type ColorChangeArgs = {
event: React.ChangeEvent<HTMLInputElement>;
newColor: string;
index: number;
colorScale: string;
};
Expand All @@ -13,7 +13,7 @@ type ColorScaleOptionsProps = {
palette?: VictoryThemeDefinition["palette"];
activeColorScale?: ColorScalePropType;
onColorChange: (args: ColorChangeArgs) => void;
onColorScaleChange: (event: React.ChangeEvent<HTMLSelectElement>) => void;
onColorScaleChange: (colorScale: string) => void;
};

const colorScales = [
Expand Down Expand Up @@ -57,16 +57,17 @@ const ColorScaleOptions = ({
onChange={onColorScaleChange}
options={colorScales}
label="Color Scale"
className="mb-5"
/>
<div className="flex flex-wrap gap-3 mb-5">
{palette?.[activeColorScale as string]?.map((color, i) => (
<ColorPicker
key={i}
color={color}
id={`color-${i}`}
onColorChange={(event) =>
onColorChange={(newColor) =>
onColorChange({
event,
newColor,
index: i,
colorScale: activeColorScale as string,
})
Expand Down
60 changes: 45 additions & 15 deletions demo/ts/components/theme-builder/config-mapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,68 @@ import Accordion from "./accordion";
import Select from "./select";
import Slider from "./slider";
import ColorPicker from "./color-picker";
import ColorScaleOptions from "./color-scale-options";
import { getConfigValue } from "./utils";

const ConfigMapper = ({
themeConfig,
activeColorScale,
updateThemeConfig,
handleColorScaleChange,
handleLabelConfigChange,
}) => {
const handleColorChange = ({ newColor, index, colorScale }) => {
const updatedColors = themeConfig?.palette?.[colorScale]?.map((color, i) =>
i === index ? newColor : color,
);
updateThemeConfig(`palette.${colorScale}`, updatedColors);
};

return (
<>
{optionsConfig.map((section) => (
<Accordion key={section.title} title={section.title} id={section.title}>
{optionsConfig.map((section, index) => (
<Accordion
key={section.title}
title={section.title}
id={section.title}
defaultOpen={index === 0}
>
{section.fields.map((field) => {
if (field.type === "colorScale") {
return (
<Select
<ColorScaleOptions
key={field.label}
id="color-scale-select"
value={activeColorScale}
onChange={handleColorScaleChange}
options={field.options}
label={field.label}
activeColorScale={activeColorScale}
palette={themeConfig?.palette}
onColorChange={handleColorChange}
onColorScaleChange={handleColorScaleChange}
/>
);
}
const configValue = getConfigValue(themeConfig, field.path);
if (field.type === "slider") {
return (
<Slider
id={field.label}
key={field.label}
label={field.label}
defaultValue={field.default}
value={configValue as number}
unit={field.unit}
onChange={(value) =>
handleLabelConfigChange({ [field.label]: value })
onChange={(newValue) =>
updateThemeConfig(field.path, newValue)
}
/>
);
}
if (field.type === "select") {
return (
<Select
id={field.label}
key={field.label}
label={field.label}
value={configValue as string}
options={field.options}
onChange={(newValue) =>
updateThemeConfig(field.path, newValue)
}
/>
);
Expand All @@ -47,10 +76,11 @@ const ConfigMapper = ({
id={field.label}
key={field.label}
label={field.label}
color={field.default}
onColorChange={(color) =>
handleLabelConfigChange({ [field.label]: color })
color={configValue as string}
onColorChange={(newColor) =>
updateThemeConfig(field.path, newColor)
}
showColorName
/>
);
}
Expand Down
77 changes: 16 additions & 61 deletions demo/ts/components/theme-builder/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import React from "react";
import "./tailwind.css";

import {
ColorScalePropType,
LabelProps,
VictoryTheme,
VictoryThemeDefinition,
} from "victory-core";
Expand All @@ -10,14 +11,11 @@ import { VictoryAxis } from "victory-axis";
import { VictoryStack } from "victory-stack";
import { VictoryBar } from "victory-bar";
import { VictoryArea } from "victory-area";
import ColorScaleOptions, { ColorChangeArgs } from "./color-scale-options";
import Select from "./select";
import ConfigPreview from "./config-preview";
import Button from "./button";

import "./tailwind.css";
import LabelOptions from "./label-options";
import ConfigMapper from "./config-mapper";
import { setNestedConfigValue } from "./utils";

export type ThemeOption = {
name: string;
Expand Down Expand Up @@ -84,50 +82,24 @@ const ThemeBuilder = () => {
const [showThemeConfigPreview, setShowThemeConfigPreview] =
React.useState(false);

const handleThemeSelect = (event: React.ChangeEvent<HTMLSelectElement>) => {
const themeName = event.target.value;
const handleThemeSelect = (themeName: string) => {
const theme = themes.find((t) => t.name === themeName);
setBaseTheme(theme);
setCustomThemeConfig({ ...theme?.config });
};

const handleLabelConfigChange = (newLabelConfig: Partial<LabelProps>) => {
if (customThemeConfig) {
const updatedConfig = {
...customThemeConfig,
axis: {
...customThemeConfig.axis,
style: {
...customThemeConfig.axis?.style,
axisLabel: {
...customThemeConfig.axis?.style?.axisLabel,
...newLabelConfig,
},
},
},
};
setCustomThemeConfig(updatedConfig as VictoryThemeDefinition);
}
};

const handleColorChange = ({ event, index, colorScale }: ColorChangeArgs) => {
const newColor = event.target.value;
const updatedConfig = {
...customThemeConfig,
palette: {
...customThemeConfig?.palette,
[colorScale]: customThemeConfig?.palette?.[colorScale]?.map(
(color, i) => (i === index ? newColor : color),
),
},
};
const updateCustomThemeConfig = (path: string, newValue: unknown) => {
if (!customThemeConfig) return;
const updatedConfig = setNestedConfigValue(
customThemeConfig,
path,
newValue,
);
setCustomThemeConfig(updatedConfig);
};

const handleColorScaleChange = (
event: React.ChangeEvent<HTMLSelectElement>,
) => {
setActiveColorScale(event.target.value as ColorScalePropType);
const handleColorScaleChange = (colorScale: string) => {
setActiveColorScale(colorScale as ColorScalePropType);
};

const handleThemeConfigPreviewOpen = () => {
Expand Down Expand Up @@ -155,29 +127,12 @@ const ThemeBuilder = () => {
/>
{customThemeConfig && (
<section>
<h2 className="text-lg font-bold mb-4">Customization Options</h2>
<h2 className="text-lg font-bold my-4">Customization Options</h2>
<ConfigMapper
themeConfig={customThemeConfig}
activeColorScale={activeColorScale}
handleColorScaleChange={handleColorScaleChange}
handleLabelConfigChange={handleLabelConfigChange}
/>
</section>
)}
{false && (
<section>
<h2 className="text-lg font-bold mb-4">Customization Options</h2>
<h3 className="text-lg font-bold mb-4">Color Options</h3>
<ColorScaleOptions
activeColorScale={activeColorScale}
palette={customThemeConfig?.palette}
onColorChange={handleColorChange}
onColorScaleChange={handleColorScaleChange}
/>
<LabelOptions
labelConfig={
customThemeConfig?.axis?.style?.axisLabel as LabelProps
}
onLabelConfigChange={handleLabelConfigChange}
updateThemeConfig={updateCustomThemeConfig}
/>
</section>
)}
Expand Down
49 changes: 0 additions & 49 deletions demo/ts/components/theme-builder/label-options.tsx

This file was deleted.

Loading

0 comments on commit a5e19e2

Please sign in to comment.