diff --git a/web/codegen.ts b/web/codegen.ts index 3d875a038e..a4541974b2 100644 --- a/web/codegen.ts +++ b/web/codegen.ts @@ -25,6 +25,7 @@ const config: CodegenConfig = { URL: "string", Lang: "string", TranslatedString: "{ [lang in string]?: string } | null", + JSON: "any", }, }, }, diff --git a/web/src/beta/components/Icon/Icons/addLayer.svg b/web/src/beta/components/Icon/Icons/addLayer.svg new file mode 100644 index 0000000000..dbbb40315a --- /dev/null +++ b/web/src/beta/components/Icon/Icons/addLayer.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/web/src/beta/components/Icon/icons.ts b/web/src/beta/components/Icon/icons.ts index ecaa0f000b..cc17776933 100644 --- a/web/src/beta/components/Icon/icons.ts +++ b/web/src/beta/components/Icon/icons.ts @@ -38,6 +38,7 @@ import Bin from "./Icons/bin.svg"; import Install from "./Icons/install.svg"; import UploadSimple from "./Icons/uploadSimple.svg"; import Search from "./Icons/search.svg"; +import AddLayerIcon from "./Icons/addLayer.svg"; // MSIC import CheckCircle from "./Icons/checkCircle.svg"; @@ -107,6 +108,7 @@ import PublicGitHubRepo from "./Icons/publicGitHubRepo.svg"; import Marketplace from "./Icons/marketplace.svg"; export default { + addLayer: AddLayerIcon, file: File, dl: InfoTable, infobox: Infobox, diff --git a/web/src/beta/components/Modal/index.tsx b/web/src/beta/components/Modal/index.tsx index 38d7fe32a3..4cdb5361b9 100644 --- a/web/src/beta/components/Modal/index.tsx +++ b/web/src/beta/components/Modal/index.tsx @@ -23,6 +23,7 @@ type Props = { children?: ReactNode; isVisible?: boolean; onClose?: () => void; + onTabChange?: (tabId: string) => void; sidebarTabs?: SidebarTab[]; }; @@ -35,6 +36,7 @@ const Modal: React.FC = ({ children, isVisible, onClose, + onTabChange, sidebarTabs, }) => { const [TabsFields, setTabsFields] = useState[]>([]); @@ -56,8 +58,9 @@ const Modal: React.FC = ({ const handleTabChange = useCallback( (tabId: string) => { handleActivate(tabId); + onTabChange?.(tabId); }, - [handleActivate], + [handleActivate, onTabChange], ); return ( @@ -79,11 +82,13 @@ const Modal: React.FC = ({ )} {tabs.length > 0 && {tabs.find(tab => tab.active === true)?.content}} - {children} - - {tabs.find(tab => tab.active === true)?.tabButton1 ?? button1} - {tabs.find(tab => tab.active === true)?.tabButton2 ?? button2} - + {children && {children}} + {button1 || button2 ? ( + + {tabs.find(tab => tab.active === true)?.tabButton1 ?? button1} + {tabs.find(tab => tab.active === true)?.tabButton2 ?? button2} + + ) : null} @@ -99,6 +104,7 @@ const NavBarWrapper = styled.div` flex-direction: column; padding: 16px; gap: 10px; + background: ${({ theme }) => theme.bg[0]}; border-right: 1px solid ${({ theme }) => theme.bg[3]}; `; @@ -107,13 +113,14 @@ const Tab = styled.button<{ isSelected?: boolean }>` padding: 4px 8px; border-radius: 4px; background: ${({ isSelected, theme }) => (isSelected ? theme.bg[2] : "transparent")}; - color: ${({ isSelected, theme }) => (isSelected ? theme.content.main : theme.bg[2])}; + color: ${({ isSelected, theme }) => (isSelected ? theme.content.main : theme.content.weak)}; `; const ContentWrapper = styled.div` display: flex; flex-direction: column; flex: 1; + background: ${({ theme }) => theme.bg[0]}; `; const Content = styled.div` diff --git a/web/src/beta/features/Editor/DataSourceManager/Asset/index.tsx b/web/src/beta/features/Editor/DataSourceManager/Asset/index.tsx new file mode 100644 index 0000000000..95af66785d --- /dev/null +++ b/web/src/beta/features/Editor/DataSourceManager/Asset/index.tsx @@ -0,0 +1,153 @@ +import React from "react"; + +import Button from "@reearth/beta/components/Button"; +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 Select from "@reearth/classic/components/atoms/Select"; +import { Option } from "@reearth/classic/components/atoms/SelectOption"; + +import { DataProps } from ".."; +import { + ColJustiftBetween, + AssetWrapper, + InputGroup, + Input, + SourceTypeWrapper, + RadioButtonLabel, + SubmitWrapper, + TextArea, +} from "../utils"; + +const Asset: React.FC = ({ sceneId, onSubmit, onClose }) => { + const [sourceType, setSourceType] = React.useState("url"); // ["url", "local", "value"] + const [fileFormat, setFileFormat] = React.useState("GeoJSON"); + const [value, setValue] = React.useState(""); + const [prioritizePerformance, setPrioritizePerformance] = React.useState(false); + + const handleSubmit = () => { + onSubmit({ + layerType: "simple", + sceneId, + title: generateRandomString(5), + visible: true, + config: { + data: { + url: sourceType === "url" && value !== "" ? value : null, + type: fileFormat.toLowerCase(), + value: sourceType === "value" && value !== "" ? value : null, + }, + resource: { + clampToGround: true, + }, + marker: { + heightReference: "clamp", + }, + polygon: { + heightReference: "clamp", + }, + polyline: { + clampToGround: true, + }, + }, + }); + onClose(); + }; + + return ( + + + + + + c && setSourceType("url")} + /> + From URL + + + c && setSourceType("value")} + /> + From Value + + + + {sourceType == "url" && ( + <> + + + + + setValue(e.target.value)} + /> + + {fileFormat === "GeoJSON" && ( + + setPrioritizePerformance(v)} + /> + + )} + + )} + {sourceType == "value" && ( + <> + + + + +