diff --git a/web/src/beta/components/RadioGroup/RadioBox/index.stories.tsx b/web/src/beta/components/RadioGroup/RadioBox/index.stories.tsx index f6bbbff586..8cb3253a1b 100644 --- a/web/src/beta/components/RadioGroup/RadioBox/index.stories.tsx +++ b/web/src/beta/components/RadioGroup/RadioBox/index.stories.tsx @@ -29,7 +29,7 @@ export const Default: Story = (args: Props) => { }; Default.args = { - inactive: false, + label: "test", selected: false, - value: "test", + key: "test", }; diff --git a/web/src/beta/components/RadioGroup/RadioBox/index.tsx b/web/src/beta/components/RadioGroup/RadioBox/index.tsx index ae2e9b728e..105edcc756 100644 --- a/web/src/beta/components/RadioGroup/RadioBox/index.tsx +++ b/web/src/beta/components/RadioGroup/RadioBox/index.tsx @@ -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 = ({ 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 = ({ selected, key, label, onClick }: Props) => { + const handleRadioClick = useCallback( + (value: string) => { + onClick?.(value); + }, + [onClick], + ); return ( - - - - {isChecked && } + + handleRadioClick(key)} /> + + {selected && } - {value} + {label} ); }; 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; @@ -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; diff --git a/web/src/beta/components/RadioGroup/index.stories.tsx b/web/src/beta/components/RadioGroup/index.stories.tsx index 6eb1d9d6e1..52bc11330f 100644 --- a/web/src/beta/components/RadioGroup/index.stories.tsx +++ b/web/src/beta/components/RadioGroup/index.stories.tsx @@ -15,8 +15,8 @@ export default meta; type Story = StoryObj; 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) => { diff --git a/web/src/beta/components/RadioGroup/index.tsx b/web/src/beta/components/RadioGroup/index.tsx index d673bdce85..5a0582b149 100644 --- a/web/src/beta/components/RadioGroup/index.tsx +++ b/web/src/beta/components/RadioGroup/index.tsx @@ -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; - 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 = ({ options, layout, onChange }) => { - const [currentOptions, updateOptions] = useState(options); - const [key, setKey] = useState(0); - +const RadioGroup: React.FC = ({ + 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 ( - {currentOptions.map(option => ( + {options.map(option => ( handleRadioChange(option.value)} + key={option.keyValue} + selected={option.keyValue === selectedValue} + label={option.label} + onClick={() => handleRadioChange(option.keyValue)} /> ))} ); }; + export default memo(RadioGroup); const RadioGroupContainer = styled.div<{ layout?: "vertical" | "horizontal" }>` display: flex; flex-direction: ${({ layout }) => (layout === "vertical" ? "column" : "row")}; + gap: 12px; `; diff --git a/web/src/beta/features/Editor/DataSourceManager/Asset/index.tsx b/web/src/beta/features/Editor/DataSourceManager/Asset/index.tsx index 5f85167503..f48f393458 100644 --- a/web/src/beta/features/Editor/DataSourceManager/Asset/index.tsx +++ b/web/src/beta/features/Editor/DataSourceManager/Asset/index.tsx @@ -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 ".."; @@ -14,7 +14,6 @@ import { InputGroup, Input, SourceTypeWrapper, - RadioButtonLabel, SubmitWrapper, TextArea, } from "../utils"; @@ -24,6 +23,7 @@ const SelectDataType: React.FC<{ fileFormat: string; setFileFormat: (k: string) setFileFormat, }) => { const t = useT(); + return ( = ({ 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({ @@ -78,22 +85,11 @@ const Asset: React.FC = ({ sceneId, onSubmit, onClose }) => { label={t("Source Type")} description={t("Select the type of data source you want to add.")}> - - c && setSourceType("url")} - /> - {t("From URL")} - - - c && setSourceType("value")} - /> - {t("From Value")} - + {sourceType == "url" && ( diff --git a/web/src/beta/features/Editor/DataSourceManager/DelimitedText/index.tsx b/web/src/beta/features/Editor/DataSourceManager/DelimitedText/index.tsx index 3bf0b38957..c9436ac78c 100644 --- a/web/src/beta/features/Editor/DataSourceManager/DelimitedText/index.tsx +++ b/web/src/beta/features/Editor/DataSourceManager/DelimitedText/index.tsx @@ -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 { @@ -13,10 +14,11 @@ import { Input, SourceTypeWrapper, SubmitWrapper, - RadioButtonLabel, } from "../utils"; const DelimitedText: React.FC = ({ 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(""); @@ -61,14 +63,11 @@ const DelimitedText: React.FC = ({ sceneId, onSubmit, onClose }) => { label="Source Type" description="Select the type of data source you want to add."> - - c && setSourceType("url")} - /> - From URL - +