Procházet zdrojové kódy

add extension to modal

dogukanuhn před 2 roky
rodič
revize
34dd9e7ccd

+ 70 - 0
src/components/FileInput/index.tsx

@@ -0,0 +1,70 @@
+import React from "react";
+import styled from "styled-components";
+
+const StyledInputWrapper = styled.div`
+  background: ${({ theme }) => theme.BACKGROUND_TERTIARY};
+  width: 100%;
+  border-radius: 4px;
+`;
+
+const StyledForm = styled.div`
+  display: flex;
+  
+  flex: 1;
+`;
+
+const StyledInput = styled.input`
+  background: ${({ theme }) => theme.BACKGROUND_TERTIARY};
+  color: ${({ theme }) => theme.INTERACTIVE_NORMAL};
+  outline: none;
+  border: none;
+  border-radius: 4px;
+  line-height: 32px;
+  padding: 10px;
+  width: 100%;
+  height: 40px;
+`;
+
+const StyledButton = styled.button`
+  display: flex;
+  align-items: center;
+  background: none;
+  color: ${({ theme }) => theme.INTERACTIVE_NORMAL};
+  padding: 0 10px;
+  min-height: unset;
+
+  &:hover {
+    box-shadow: none;
+  }
+  
+  &.active {
+    background: ${({ theme }) => theme.PRIMARY};;
+  }
+`;
+
+export interface ModalProps {
+    value:string | number | readonly string[] | undefined,
+    extensions:string[]
+    setExtension: Function,
+    onChange: React.ChangeEventHandler<HTMLInputElement> | undefined,
+}
+export const FileInput: React.FC<ModalProps> = (props) => {
+
+    const {setExtension, onChange,extensions,value } = props
+  return (
+    <StyledInputWrapper>
+      <StyledForm>
+        <StyledInput
+          type="text"
+          onChange={onChange}
+          value={value}
+          placeholder="File Name"
+        />
+          {extensions.map((ext,key)=> (<StyledButton key={key} aria-label="search" onClick={()=> setExtension(key)}>
+              {ext}
+          </StyledButton>))}
+
+      </StyledForm>
+    </StyledInputWrapper>
+  );
+};

+ 15 - 6
src/containers/Modals/DownloadModal/index.tsx

@@ -1,11 +1,11 @@
 import React from "react";
-import { toBlob, toPng } from "html-to-image";
+import { toBlob, toPng,toSvg } from "html-to-image";
 import { TwitterPicker } from "react-color";
 import { TwitterPickerStylesProps } from "react-color/lib/components/twitter/Twitter";
 import toast from "react-hot-toast";
 import { FiCopy, FiDownload } from "react-icons/fi";
 import { Button } from "src/components/Button";
-import { Input } from "src/components/Input";
+import { FileInput } from "src/components/FileInput";
 import { Modal, ModalProps } from "src/components/Modal";
 import useConfig from "src/hooks/store/useConfig";
 import styled from "styled-components";
@@ -92,8 +92,14 @@ const StyledColorIndicator = styled.div<{ color: string }>`
   border-color: rgba(0, 0, 0, 0.1);
 `;
 
+enum Extensions {
+  svg,
+  png
+}
 export const DownloadModal: React.FC<ModalProps> = ({ visible, setVisible }) => {
   const setConfig = useConfig(state => state.setConfig);
+
+  const [extension, setExtension] = React.useState(Extensions.svg)
   const [fileDetails, setFileDetails] = React.useState({
     filename: "jsoncrack.com",
     backgroundColor: "transparent",
@@ -137,12 +143,14 @@ export const DownloadModal: React.FC<ModalProps> = ({ visible, setVisible }) =>
 
       const imageElement = document.querySelector("svg[id*='ref']") as HTMLElement;
 
-      const dataURI = await toPng(imageElement, {
+      let exportImage = extension === Extensions.svg ? toSvg : toPng
+
+      const dataURI = await exportImage(imageElement, {
         quality: fileDetails.quality,
         backgroundColor: fileDetails.backgroundColor,
       });
 
-      downloadURI(dataURI, `${fileDetails.filename}.png`);
+      downloadURI(dataURI, `${fileDetails.filename}.${Extensions[extension]}`);
     } catch (error) {
       toast.error("Failed to download image!");
     } finally {
@@ -162,10 +170,11 @@ export const DownloadModal: React.FC<ModalProps> = ({ visible, setVisible }) =>
         <StyledContainer>
           File Name
           <StyledColorWrapper>
-            <Input
-              placeholder="File Name"
+            <FileInput
               value={fileDetails.filename}
               onChange={e => updateDetails("filename", e.target.value)}
+              setExtension={(ext:number)=> setExtension(ext)}
+              extensions={Object.keys(Extensions).filter((v) => isNaN(Number(v)))}
             />
           </StyledColorWrapper>
         </StyledContainer>

+ 3 - 0
src/hooks/store/useConfig.tsx

@@ -7,6 +7,7 @@ interface ConfigActions {
   setJson: (json: string) => void;
   setConfig: (key: keyof Config, value: unknown) => void;
   getJson: () => string;
+  setExtension: () => (extension: number) => void;
   zoomIn: () => void;
   zoomOut: () => void;
   centerView: () => void;
@@ -18,6 +19,7 @@ const initialStates = {
   layout: "RIGHT" as CanvasDirection,
   expand: true,
   hideEditor: false,
+  extension: 0,
   performanceMode: true,
   disableLoading: false,
   zoomPanPinch: undefined as ReactZoomPanPinchRef | undefined,
@@ -29,6 +31,7 @@ const useConfig = create<Config & ConfigActions>()((set, get) => ({
   ...initialStates,
   getJson: () => get().json,
   setJson: (json: string) => set({ json }),
+  setExtension: (extension: number) => set({ extension }),
   zoomIn: () => {
     const zoomPanPinch = get().zoomPanPinch;
     if (zoomPanPinch) {