Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: use radio group in Data source manage #680

Merged
merged 20 commits into from
Sep 14, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export const Default: Story = (args: Props) => {
};

Default.args = {
inactive: false,
label: "test",
selected: false,
value: "test",
key: "test",
};
46 changes: 19 additions & 27 deletions web/src/beta/components/RadioGroup/RadioBox/index.tsx
KaWaite marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -1,50 +1,45 @@
import { useCallback, useState } from "react";
import { useCallback } from "react";

import { fonts, styled } from "@reearth/services/theme";

export type Props = {
inactive?: boolean;
selected?: boolean;
value: string;
key: string;
onClick?: (value: string) => void;
label?: string;
};

const RadioBox: React.FC<Props> = ({ inactive, selected, value, onClick }: Props) => {
const [isChecked, setIsChecked] = useState(selected ?? false);

const handleRadioClick = useCallback(() => {
setIsChecked(!isChecked);
if (onClick) onClick(value);
}, [isChecked, onClick, value]);
const RadioBox: React.FC<Props> = ({ selected, key, label, onClick }: Props) => {
const handleRadioClick = useCallback(
(value: string) => {
onClick?.(value);
},
[onClick],
);

return (
<Radio selected={isChecked} inactive={inactive}>
<RadioInput type="radio" value={inactive ? undefined : value} onClick={handleRadioClick} />
<RadioButton selected={isChecked} inactive={inactive}>
{isChecked && <Checkmark selected={isChecked} inactive={inactive} />}
<Radio>
<RadioInput type="radio" value={key} onClick={() => handleRadioClick(key)} />
<RadioButton selected={selected}>
{selected && <RadioIndicator selected={selected} />}
</RadioButton>
<RadioText>{value}</RadioText>
<RadioText>{label}</RadioText>
</Radio>
);
};
export default RadioBox;

const Checkmark = styled.div<{
inactive?: boolean;
const RadioIndicator = styled.div<{
selected?: boolean;
}>`
width: 10px;
height: 10px;
border-radius: 50%;
background-color: white;
background-color: ${({ selected, inactive, theme }) =>
selected ? theme.select.main : inactive ? theme.content.weaker : theme.content.main};
background-color: ${({ selected, theme }) => (selected ? theme.select.main : theme.content.main)};
`;

const Radio = styled.label<{
inactive?: boolean;
selected?: boolean;
}>`
const Radio = styled.label`
display: flex;
align-items: center;
min-width: 30px;
Expand All @@ -66,15 +61,12 @@ const RadioInput = styled.input`
`;

const RadioButton = styled.span<{
inactive?: boolean;
selected?: boolean;
}>`
width: 16px;
height: 16px;
border-radius: 50%;
border: 2px solid
${({ selected, inactive, theme }) =>
selected ? theme.select.main : inactive ? theme.content.weaker : theme.content.main};
border: 2px solid ${({ selected, theme }) => (selected ? theme.select.main : theme.content.main)};
margin-right: 4px;
display: flex;
justify-content: center;
Expand Down
4 changes: 2 additions & 2 deletions web/src/beta/components/RadioGroup/index.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ export default meta;
type Story = StoryObj<typeof RadioGroup>;

const options = [
{ key: "option1", value: "Option 1", selected: false },
{ key: "option2", value: "Option 2", selected: false },
{ label: "option1", keyValue: "Option 1" },
{ label: "option2", keyValue: "Option 2" },
];

export const VerticalRadioGroup: Story = (args: Props) => {
Expand Down
41 changes: 20 additions & 21 deletions web/src/beta/components/RadioGroup/index.tsx
Original file line number Diff line number Diff line change
@@ -1,53 +1,52 @@
import { memo, useCallback, useState } from "react";
import { memo, useCallback } from "react";

import RadioBox from "@reearth/beta/components/RadioGroup/RadioBox";
import { styled } from "@reearth/services/theme";

export type Option = {
key: string;
KaWaite marked this conversation as resolved.
Show resolved Hide resolved
value: string;
selected: boolean;
label?: string;
keyValue: string;
};

export type RadioGroupProps = {
options: Option[];
layout?: "vertical" | "horizontal";
selectedValue?: string;
onChange?: (value: string) => void;
};

const RadioGroup: React.FC<RadioGroupProps> = ({ options, layout, onChange }) => {
const [currentOptions, updateOptions] = useState<Option[]>(options);
const [key, setKey] = useState(0);

const RadioGroup: React.FC<RadioGroupProps> = ({
options,
layout = "horizontal",
selectedValue,
onChange,
}) => {
const handleRadioChange = useCallback(
(value: string) => {
updateOptions(
currentOptions.map(option => ({
...option,
selected: !option.selected && option.value === value,
})),
);
setKey(prevKey => prevKey + 1);
if (value === selectedValue) return;
onChange?.(value);
},
[currentOptions, onChange],
[onChange, selectedValue],
);

return (
<RadioGroupContainer layout={layout}>
{currentOptions.map(option => (
{options.map(option => (
<RadioBox
key={`${option.key}-${key}`}
value={option.value}
selected={option.selected}
onClick={() => handleRadioChange(option.value)}
key={option.keyValue}
selected={option.keyValue === selectedValue}
label={option.label}
onClick={() => handleRadioChange(option.keyValue)}
/>
))}
</RadioGroupContainer>
);
};

export default memo(RadioGroup);

const RadioGroupContainer = styled.div<{ layout?: "vertical" | "horizontal" }>`
display: flex;
flex-direction: ${({ layout }) => (layout === "vertical" ? "column" : "row")};
gap: 12px;
`;
34 changes: 15 additions & 19 deletions web/src/beta/features/Editor/DataSourceManager/Asset/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React from "react";
import React, { useMemo } from "react";

import Button from "@reearth/beta/components/Button";
import SelectField from "@reearth/beta/components/fields/SelectField";
import RadioGroup from "@reearth/beta/components/RadioGroup";
import Toggle from "@reearth/beta/components/Toggle";
import generateRandomString from "@reearth/beta/utils/generate-random-string";
import RadioButton from "@reearth/classic/components/atoms/RadioButton";
import { useT } from "@reearth/services/i18n";

import { DataProps } from "..";
Expand All @@ -14,7 +14,6 @@ import {
InputGroup,
Input,
SourceTypeWrapper,
RadioButtonLabel,
SubmitWrapper,
TextArea,
} from "../utils";
Expand All @@ -24,6 +23,7 @@ const SelectDataType: React.FC<{ fileFormat: string; setFileFormat: (k: string)
setFileFormat,
}) => {
const t = useT();

return (
<SelectField
value={fileFormat}
Expand All @@ -41,6 +41,13 @@ const Asset: React.FC<DataProps> = ({ sceneId, onSubmit, onClose }) => {
const [fileFormat, setFileFormat] = React.useState("GeoJSON");
const [value, setValue] = React.useState("");
const [prioritizePerformance, setPrioritizePerformance] = React.useState(false);
const DataSourceOptions = useMemo(
() => [
{ label: t("From URL"), keyValue: "url" },
{ label: t("From Value"), keyValue: "value" },
],
[t],
);

const handleSubmit = () => {
onSubmit({
Expand Down Expand Up @@ -78,22 +85,11 @@ const Asset: React.FC<DataProps> = ({ sceneId, onSubmit, onClose }) => {
label={t("Source Type")}
description={t("Select the type of data source you want to add.")}>
<SourceTypeWrapper>
<RadioButtonLabel>
<RadioButton
value="url"
checked={sourceType == "url"}
handleChange={c => c && setSourceType("url")}
/>
{t("From URL")}
</RadioButtonLabel>
<RadioButtonLabel>
<RadioButton
value="value"
checked={sourceType == "value"}
handleChange={c => c && setSourceType("value")}
/>
{t("From Value")}
</RadioButtonLabel>
<RadioGroup
options={DataSourceOptions}
selectedValue={sourceType}
onChange={setSourceType}
/>
</SourceTypeWrapper>
</InputGroup>
{sourceType == "url" && (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import React from "react";

import Button from "@reearth/beta/components/Button";
import RadioGroup from "@reearth/beta/components/RadioGroup";
import Text from "@reearth/beta/components/Text";
import generateRandomString from "@reearth/beta/utils/generate-random-string";
import RadioButton from "@reearth/classic/components/atoms/RadioButton";
import { useT } from "@reearth/services/i18n";

import { DataProps } from "..";
import {
Expand All @@ -13,10 +14,11 @@ import {
Input,
SourceTypeWrapper,
SubmitWrapper,
RadioButtonLabel,
} from "../utils";

const DelimitedText: React.FC<DataProps> = ({ sceneId, onSubmit, onClose }) => {
const t = useT();

const [sourceType, setSourceType] = React.useState("url"); // ["url", "local", "value"]
const [value, setValue] = React.useState("");
const [lat, setLat] = React.useState("");
Expand Down Expand Up @@ -61,14 +63,11 @@ const DelimitedText: React.FC<DataProps> = ({ sceneId, onSubmit, onClose }) => {
label="Source Type"
description="Select the type of data source you want to add.">
<SourceTypeWrapper>
<RadioButtonLabel>
<RadioButton
value="url"
checked={sourceType == "url"}
handleChange={c => c && setSourceType("url")}
/>
From URL
</RadioButtonLabel>
<RadioGroup
options={[{ label: t("From URL"), keyValue: "url" }]}
selectedValue={sourceType}
onChange={setSourceType}
/>
</SourceTypeWrapper>
</InputGroup>
<InputGroup label="Resource URL" description="URL of the data source you want to add.">
Expand Down
Loading