├── .npmrc ├── src ├── store │ ├── slices │ │ ├── auth │ │ │ └── index.ts │ │ ├── fonts │ │ │ ├── selectors.ts │ │ │ ├── reducer.ts │ │ │ └── actions.ts │ │ ├── design-editor │ │ │ ├── selectors.ts │ │ │ ├── actions.ts │ │ │ └── reducer.ts │ │ ├── resources │ │ │ ├── selectors.ts │ │ │ ├── reducer.ts │ │ │ └── actions.ts │ │ └── uploads │ │ │ ├── selectors.ts │ │ │ ├── reducer.ts │ │ │ └── actions.ts │ ├── store.ts │ └── rootReducer.ts ├── vite-env.d.ts ├── components │ ├── Loading │ │ ├── index.ts │ │ └── Loading.tsx │ ├── Dropzone │ │ ├── index.ts │ │ └── DropZone.tsx │ ├── Scrollable │ │ ├── index.ts │ │ └── Scrollable.tsx │ ├── Icons │ │ ├── Add.tsx │ │ ├── Pause.tsx │ │ ├── Italic.tsx │ │ ├── TextAlignLeft.tsx │ │ ├── Undo.tsx │ │ ├── TextAlignJustify.tsx │ │ ├── Redo.tsx │ │ ├── PlaySolid.tsx │ │ ├── Templates.tsx │ │ ├── TextAlignRight.tsx │ │ ├── Compress.tsx │ │ ├── Elements.tsx │ │ ├── TextAlignCenter.tsx │ │ ├── Expand.tsx │ │ ├── Video.tsx │ │ ├── Graphics.tsx │ │ ├── TimePast.tsx │ │ ├── Search.tsx │ │ ├── TextColor.tsx │ │ ├── VerticalLine.tsx │ │ ├── Uploads.tsx │ │ ├── ArrowDownOutline.tsx │ │ ├── Play.tsx │ │ ├── Underline.tsx │ │ ├── Background.tsx │ │ ├── Images.tsx │ │ ├── Underline copy.tsx │ │ ├── Duplicate.tsx │ │ ├── Text.tsx │ │ ├── Spacing.tsx │ │ ├── Refresh.tsx │ │ ├── CopyStyle.tsx │ │ ├── Layers.tsx │ │ ├── Pixabay.tsx │ │ ├── Delete.tsx │ │ ├── Presentation.tsx │ │ ├── RemoveCircleOutline.tsx │ │ ├── AngleDoubleLeft.tsx │ │ ├── Bold.tsx │ │ ├── Download.tsx │ │ ├── FlipHorizontal.tsx │ │ ├── Locked.tsx │ │ ├── ArrowBackOutline.tsx │ │ ├── FlipVertical.tsx │ │ ├── SendToBack.tsx │ │ ├── SwapHorizontal.tsx │ │ ├── Spacing copy.tsx │ │ ├── Unlocked.tsx │ │ ├── AddCircleOutline.tsx │ │ ├── BringToFront.tsx │ │ ├── LetterCase.tsx │ │ ├── Logo.tsx │ │ ├── AlignLeft.tsx │ │ ├── AlignTop.tsx │ │ ├── AlignRight.tsx │ │ ├── AlignBottom.tsx │ │ ├── AlignCenter.tsx │ │ ├── AlignMiddle.tsx │ │ ├── Paste.tsx │ │ ├── Eye.tsx │ │ ├── InformationCircleOutline.tsx │ │ ├── Opacity..tsx │ │ ├── CloudCheck.tsx │ │ ├── index.ts │ │ ├── EyeCrossed.tsx │ │ ├── Customize.tsx │ │ └── Github.tsx │ └── Resizable │ │ └── resizer.tsx ├── views │ ├── Dashboard │ │ ├── index.ts │ │ └── Dashboard.tsx │ └── DesignEditor │ │ ├── components │ │ ├── Preview │ │ │ ├── index.ts │ │ │ ├── Graphic.tsx │ │ │ ├── Preview.tsx │ │ │ ├── Presentation.tsx │ │ │ └── Video.tsx │ │ ├── Footer │ │ │ ├── Graphic │ │ │ │ ├── index.ts │ │ │ │ ├── Graphic.tsx │ │ │ │ └── SceneItem.tsx │ │ │ ├── Video │ │ │ │ ├── index.ts │ │ │ │ ├── Video.tsx │ │ │ │ ├── TimelineControl.tsx │ │ │ │ ├── Common.tsx │ │ │ │ └── TimeMarker.tsx │ │ │ ├── index.ts │ │ │ ├── Presentation │ │ │ │ ├── index.ts │ │ │ │ ├── Presentation.tsx │ │ │ │ └── SceneItem.tsx │ │ │ └── Footer.tsx │ │ ├── Canvas │ │ │ ├── index.ts │ │ │ └── Canvas.tsx │ │ ├── Navbar │ │ │ └── index.ts │ │ ├── Panels │ │ │ ├── index.ts │ │ │ ├── Panels.tsx │ │ │ ├── panelItems │ │ │ │ ├── index.ts │ │ │ │ ├── CanvasFill.tsx │ │ │ │ ├── PathFill.tsx │ │ │ │ ├── TextFill.tsx │ │ │ │ └── Elements.tsx │ │ │ ├── PanelItem.tsx │ │ │ └── PanelsList.tsx │ │ ├── Toolbox │ │ │ ├── index.ts │ │ │ ├── Items.tsx │ │ │ ├── Multiple.tsx │ │ │ ├── Image.tsx │ │ │ ├── Locked.tsx │ │ │ ├── Canvas.tsx │ │ │ ├── Toolbox.tsx │ │ │ ├── Path.tsx │ │ │ ├── Shared │ │ │ │ ├── Flip.tsx │ │ │ │ └── Opacity.tsx │ │ │ └── Vector.tsx │ │ ├── Playback │ │ │ └── index.ts │ │ ├── ContextMenu │ │ │ └── index.ts │ │ └── EditorContainer │ │ │ └── index.tsx │ │ ├── index.ts │ │ ├── utils │ │ ├── scenes.ts │ │ └── text.ts │ │ ├── VideoEditor.tsx │ │ ├── PresentationEditor.tsx │ │ ├── GraphicEditor.tsx │ │ ├── DesignEditor.tsx │ │ └── SelectEditor.tsx ├── translations │ ├── en │ │ ├── common.json │ │ └── editor.json │ ├── es │ │ ├── common.json │ │ └── editor.json │ └── index.ts ├── interfaces │ ├── common.ts │ ├── DesignEditor.ts │ └── editor.ts ├── env.d.ts ├── hooks │ ├── useIsMobile.ts │ ├── useEditorType.tsx │ ├── useDesignEditorScenes.tsx │ ├── useIsSidebarOpen.tsx │ ├── useSetIsSidebarOpen.tsx │ ├── useContextMenuSceneRequest.ts │ ├── useContextMenuTimelineRequest.ts │ ├── useAppContext.tsx │ ├── useDesignEditorContext.ts │ └── useOnClickOutside.tsx ├── utils │ ├── data.ts │ ├── unique.ts │ ├── get-selection-type.ts │ ├── object-options.ts │ ├── fonts.ts │ └── video.ts ├── main.tsx ├── Router.tsx ├── constants │ ├── contants.ts │ ├── app-options.ts │ ├── design-editor.ts │ ├── fonts.ts │ └── format-sizes.ts ├── services │ ├── pexels.ts │ └── pixabay.ts ├── styles │ └── styles.css ├── Provider.tsx ├── contexts │ └── AppContext.tsx ├── Pages.tsx └── Container.tsx ├── .env.sample ├── .prettierrc ├── tsconfig.node.json ├── vite.config.ts ├── Dockerfile ├── .gitignore ├── nginx └── templates │ └── default.conf.template ├── index.html ├── tsconfig.json ├── README.md ├── LICENSE └── package.json /.npmrc: -------------------------------------------------------------------------------- 1 | strict-peer-dependencies=false -------------------------------------------------------------------------------- /src/store/slices/auth/index.ts: -------------------------------------------------------------------------------- 1 | export default {}; 2 | -------------------------------------------------------------------------------- /.env.sample: -------------------------------------------------------------------------------- 1 | VITE_APP_PIXABAY_KEY="" 2 | VITE_APP_PEXELS_KEY="" -------------------------------------------------------------------------------- /src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 120, 3 | "semi": false 4 | } 5 | -------------------------------------------------------------------------------- /src/components/Loading/index.ts: -------------------------------------------------------------------------------- 1 | import Loading from "./Loading"; 2 | 3 | export default Loading -------------------------------------------------------------------------------- /src/views/Dashboard/index.ts: -------------------------------------------------------------------------------- 1 | import Dashboard from "./Dashboard" 2 | export default Dashboard 3 | -------------------------------------------------------------------------------- /src/components/Dropzone/index.ts: -------------------------------------------------------------------------------- 1 | import DropZone from './DropZone' 2 | 3 | export default DropZone 4 | -------------------------------------------------------------------------------- /src/views/DesignEditor/components/Preview/index.ts: -------------------------------------------------------------------------------- 1 | export { default as default } from "./Preview" 2 | -------------------------------------------------------------------------------- /src/components/Scrollable/index.ts: -------------------------------------------------------------------------------- 1 | import Scrollable from "./Scrollable" 2 | export default Scrollable 3 | -------------------------------------------------------------------------------- /src/views/DesignEditor/components/Footer/Graphic/index.ts: -------------------------------------------------------------------------------- 1 | export { default as default } from "./Graphic" 2 | -------------------------------------------------------------------------------- /src/views/DesignEditor/components/Canvas/index.ts: -------------------------------------------------------------------------------- 1 | import Canvas from "./Canvas" 2 | export default Canvas 3 | -------------------------------------------------------------------------------- /src/views/DesignEditor/components/Footer/Video/index.ts: -------------------------------------------------------------------------------- 1 | import Video from "./Video" 2 | export default Video 3 | -------------------------------------------------------------------------------- /src/views/DesignEditor/components/Footer/index.ts: -------------------------------------------------------------------------------- 1 | import Footer from "./Footer" 2 | export default Footer 3 | -------------------------------------------------------------------------------- /src/views/DesignEditor/components/Navbar/index.ts: -------------------------------------------------------------------------------- 1 | import Navbar from "./Navbar" 2 | export default Navbar 3 | -------------------------------------------------------------------------------- /src/views/DesignEditor/components/Panels/index.ts: -------------------------------------------------------------------------------- 1 | import Panels from "./Panels" 2 | export default Panels 3 | -------------------------------------------------------------------------------- /src/views/DesignEditor/components/Toolbox/index.ts: -------------------------------------------------------------------------------- 1 | import Toolbox from "./Toolbox" 2 | export default Toolbox 3 | -------------------------------------------------------------------------------- /src/views/DesignEditor/index.ts: -------------------------------------------------------------------------------- 1 | import DesignEditor from "./DesignEditor" 2 | export default DesignEditor 3 | -------------------------------------------------------------------------------- /src/translations/en/common.json: -------------------------------------------------------------------------------- 1 | { 2 | "welcome": { 3 | "title": "Welcome to {{framework}}" 4 | } 5 | } -------------------------------------------------------------------------------- /src/views/DesignEditor/components/Footer/Presentation/index.ts: -------------------------------------------------------------------------------- 1 | export { default as default } from "./Presentation" 2 | -------------------------------------------------------------------------------- /src/views/DesignEditor/components/Playback/index.ts: -------------------------------------------------------------------------------- 1 | import Playback from "./Playback" 2 | export default Playback 3 | -------------------------------------------------------------------------------- /src/translations/es/common.json: -------------------------------------------------------------------------------- 1 | { 2 | "welcome": { 3 | "title": "Willkommen bei {{framework}}" 4 | } 5 | } -------------------------------------------------------------------------------- /src/views/DesignEditor/components/ContextMenu/index.ts: -------------------------------------------------------------------------------- 1 | import ContextMenu from './ContextMenu' 2 | export default ContextMenu 3 | -------------------------------------------------------------------------------- /src/views/Dashboard/Dashboard.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | 3 | const Dashboard = () => { 4 | return
5 | } 6 | 7 | export default Dashboard 8 | -------------------------------------------------------------------------------- /src/store/slices/fonts/selectors.ts: -------------------------------------------------------------------------------- 1 | import { RootState } from "~/store/rootReducer"; 2 | 3 | export const selectFonts = (state: RootState) => state.fonts.fonts; 4 | -------------------------------------------------------------------------------- /src/store/slices/design-editor/selectors.ts: -------------------------------------------------------------------------------- 1 | import { RootState } from "~/store/rootReducer" 2 | 3 | export const selectPages = (state: RootState) => state.designEditor.pages 4 | -------------------------------------------------------------------------------- /src/interfaces/common.ts: -------------------------------------------------------------------------------- 1 | export interface Page { 2 | id: string 3 | name: string 4 | } 5 | 6 | export interface FontItem { 7 | name: string 8 | url: string 9 | } 10 | -------------------------------------------------------------------------------- /src/store/slices/resources/selectors.ts: -------------------------------------------------------------------------------- 1 | import { RootState } from "~/store/rootReducer" 2 | 3 | export const selectPixabayResources = (state: RootState) => state.resources.pixabay 4 | -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "esnext", 5 | "moduleResolution": "node" 6 | }, 7 | "include": ["vite.config.ts"] 8 | } 9 | -------------------------------------------------------------------------------- /src/store/slices/uploads/selectors.ts: -------------------------------------------------------------------------------- 1 | import { RootState } from "~/store/rootReducer" 2 | 3 | export const selectUploads = (state: RootState) => state.uploads.uploads 4 | export const selectUploading = (state: RootState) => state.uploads.uploading 5 | -------------------------------------------------------------------------------- /src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | interface ImportMetaEnv { 4 | readonly VITE_APP_PIXABAY_KEY: string 5 | readonly VITE_APP_PEXELS_KEY: string 6 | } 7 | 8 | interface ImportMeta { 9 | readonly env: ImportMetaEnv 10 | } 11 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite" 2 | import react from "@vitejs/plugin-react" 3 | import tsconfigPaths from "vite-tsconfig-paths" 4 | 5 | // https://vitejs.dev/config/ 6 | export default defineConfig({ 7 | plugins: [react(), tsconfigPaths()], 8 | }) 9 | -------------------------------------------------------------------------------- /src/hooks/useIsMobile.ts: -------------------------------------------------------------------------------- 1 | import { AppContext } from "~/contexts/AppContext" 2 | import { useContext } from "react" 3 | 4 | const useIsMobile = () => { 5 | const { isMobile } = useContext(AppContext) 6 | return isMobile 7 | } 8 | 9 | export default useIsMobile 10 | -------------------------------------------------------------------------------- /src/utils/data.ts: -------------------------------------------------------------------------------- 1 | export const toBase64 = (file: File) => 2 | new Promise((resolve, reject) => { 3 | const reader = new FileReader() 4 | reader.readAsDataURL(file) 5 | reader.onload = () => resolve(reader.result) 6 | reader.onerror = (error) => reject(error) 7 | }) 8 | -------------------------------------------------------------------------------- /src/hooks/useEditorType.tsx: -------------------------------------------------------------------------------- 1 | import { useContext } from "react" 2 | import { DesignEditorContext } from "~/contexts/DesignEditor" 3 | 4 | const useEditorType = () => { 5 | const { editorType } = useContext(DesignEditorContext) 6 | return editorType 7 | } 8 | 9 | export default useEditorType 10 | -------------------------------------------------------------------------------- /src/views/DesignEditor/components/Panels/Panels.tsx: -------------------------------------------------------------------------------- 1 | import PanelItem from "./PanelItem" 2 | import PanelsList from "./PanelsList" 3 | 4 | const Panels = () => { 5 | return ( 6 | <> 7 | 8 | 9 | 10 | ) 11 | } 12 | 13 | export default Panels 14 | -------------------------------------------------------------------------------- /src/store/slices/design-editor/actions.ts: -------------------------------------------------------------------------------- 1 | import { Page } from "~/interfaces/common"; 2 | import { createAction } from "@reduxjs/toolkit"; 3 | 4 | export const addPage = createAction("designEditor/addPage"); 5 | export const removePage = createAction>( 6 | "designEditor/removePage" 7 | ); 8 | -------------------------------------------------------------------------------- /src/hooks/useDesignEditorScenes.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { DesignEditorContext } from "~/contexts/DesignEditor" 3 | 4 | const useDesignEditorScenes = () => { 5 | const { scenes } = React.useContext(DesignEditorContext) 6 | return scenes 7 | } 8 | 9 | export default useDesignEditorScenes 10 | -------------------------------------------------------------------------------- /src/hooks/useIsSidebarOpen.tsx: -------------------------------------------------------------------------------- 1 | import { useContext } from "react" 2 | import { DesignEditorContext } from "~/contexts/DesignEditor" 3 | 4 | const useIsSidebarOpen = () => { 5 | const { isSidebarOpen } = useContext(DesignEditorContext) 6 | return isSidebarOpen 7 | } 8 | 9 | export default useIsSidebarOpen 10 | -------------------------------------------------------------------------------- /src/hooks/useSetIsSidebarOpen.tsx: -------------------------------------------------------------------------------- 1 | import { useContext } from "react" 2 | import { DesignEditorContext } from "~/contexts/DesignEditor" 3 | 4 | const useSetIsSidebarOpen = () => { 5 | const { setIsSidebarOpen } = useContext(DesignEditorContext) 6 | return setIsSidebarOpen 7 | } 8 | 9 | export default useSetIsSidebarOpen 10 | -------------------------------------------------------------------------------- /src/components/Icons/Add.tsx: -------------------------------------------------------------------------------- 1 | function Add({ size }: { size: number }) { 2 | return ( 3 | 4 | 5 | 6 | ) 7 | } 8 | 9 | export default Add 10 | -------------------------------------------------------------------------------- /src/hooks/useContextMenuSceneRequest.ts: -------------------------------------------------------------------------------- 1 | import { useContext } from "react" 2 | import { DesignEditorContext } from "~/contexts/DesignEditor" 3 | 4 | const useContextMenuSceneRequest = () => { 5 | const { contextMenuSceneRequest } = useContext(DesignEditorContext) 6 | return contextMenuSceneRequest 7 | } 8 | 9 | export default useContextMenuSceneRequest 10 | -------------------------------------------------------------------------------- /src/components/Icons/Pause.tsx: -------------------------------------------------------------------------------- 1 | function Pause({ size }: { size: number }) { 2 | return ( 3 | 4 | 5 | 6 | 7 | ) 8 | } 9 | 10 | export default Pause 11 | -------------------------------------------------------------------------------- /src/views/DesignEditor/components/Footer/Video/Video.tsx: -------------------------------------------------------------------------------- 1 | import Timeline from "./Timeline" 2 | import Common from "./Common" 3 | import { Block } from "baseui/block" 4 | 5 | const Video = () => { 6 | return ( 7 | 8 | 9 | 10 | 11 | ) 12 | } 13 | 14 | export default Video -------------------------------------------------------------------------------- /src/hooks/useContextMenuTimelineRequest.ts: -------------------------------------------------------------------------------- 1 | import { useContext } from "react" 2 | import { DesignEditorContext } from "~/contexts/DesignEditor" 3 | 4 | const useContextMenuTimelineRequest = () => { 5 | const { contextMenuTimelineRequest } = useContext(DesignEditorContext) 6 | return contextMenuTimelineRequest 7 | } 8 | 9 | export default useContextMenuTimelineRequest 10 | -------------------------------------------------------------------------------- /src/main.tsx: -------------------------------------------------------------------------------- 1 | import ReactDOM from "react-dom/client" 2 | import Provider from "./Provider" 3 | import Router from "./Router" 4 | import Container from "./Container" 5 | import "./styles/styles.css" 6 | 7 | ReactDOM.createRoot(document.getElementById("root")!).render( 8 | 9 | 10 | 11 | 12 | 13 | ) 14 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # base image 2 | FROM node:18-alpine as build 3 | 4 | # set working directory 5 | WORKDIR /app 6 | 7 | ADD . . 8 | 9 | RUN npm i -g pnpm 10 | RUN pnpm i 11 | 12 | RUN pnpm build 13 | 14 | FROM nginx:1.19-alpine 15 | 16 | COPY nginx/templates /etc/nginx/templates/ 17 | 18 | COPY --from=build /app/dist /usr/share/nginx/html 19 | 20 | CMD ["nginx", "-g", "daemon off;"] -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | .vercel 26 | build 27 | dist 28 | .env -------------------------------------------------------------------------------- /nginx/templates/default.conf.template: -------------------------------------------------------------------------------- 1 | server { 2 | listen ${PORT}; 3 | # listen [::]:${PORT}; 4 | location / { 5 | root /usr/share/nginx/html; 6 | index index.html index.htm; 7 | try_files $uri $uri/ /index.html; 8 | } 9 | error_page 500 502 503 504 /50x.html; 10 | location = /50x.html { 11 | root /usr/share/nginx/html; 12 | } 13 | } -------------------------------------------------------------------------------- /src/components/Icons/Italic.tsx: -------------------------------------------------------------------------------- 1 | function Italic({ size }: { size: number }) { 2 | return ( 3 | 4 | 8 | 9 | ) 10 | } 11 | 12 | export default Italic 13 | -------------------------------------------------------------------------------- /src/views/DesignEditor/components/Toolbox/Items.tsx: -------------------------------------------------------------------------------- 1 | import Text from "./Text" 2 | import Path from "./Path" 3 | import Image from "./Image" 4 | import Vector from "./Vector" 5 | import Locked from "./Locked" 6 | import Multiple from "./Multiple" 7 | import Canvas from "./Canvas" 8 | 9 | export default { 10 | StaticText: Text, 11 | StaticPath: Path, 12 | StaticImage: Image, 13 | StaticVector: Vector, 14 | Locked, 15 | Multiple, 16 | Canvas, 17 | } 18 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/Router.tsx: -------------------------------------------------------------------------------- 1 | import { BrowserRouter, Routes, Route } from "react-router-dom" 2 | import DesignEditor from "~/views/DesignEditor" 3 | import Dashboard from "~/views/Dashboard" 4 | 5 | const Router = () => { 6 | return ( 7 | 8 | 9 | } /> 10 | } /> 11 | 12 | 13 | ) 14 | } 15 | 16 | export default Router 17 | -------------------------------------------------------------------------------- /src/constants/contants.ts: -------------------------------------------------------------------------------- 1 | import { TextOptions } from "~/interfaces/editor" 2 | 3 | export const propertiesToInclude = ["id", "selectable"] 4 | 5 | export const defaultTextOptions: TextOptions = { 6 | underline: false, 7 | textAlign: "left", 8 | charSpacing: 0, 9 | fill: "#000000", 10 | fontFamily: "Open Sans", 11 | fontSize: 12, 12 | lineHeight: 12, 13 | isGroup: false, 14 | isMultiple: false, 15 | styles: [], 16 | font: {}, 17 | activeStyle: {}, 18 | } 19 | -------------------------------------------------------------------------------- /src/utils/unique.ts: -------------------------------------------------------------------------------- 1 | import { customAlphabet } from "nanoid" 2 | 3 | const nanoid = customAlphabet("_0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", 10) 4 | 5 | export const uniqueId = () => { 6 | return nanoid() 7 | } 8 | 9 | export const uniqueFilename = (name: string) => { 10 | const nameArray = name.split(".") 11 | const extension = nameArray[nameArray.length - 1] 12 | const uniqueName = [uniqueId(), extension].join(".") 13 | return uniqueName 14 | } 15 | -------------------------------------------------------------------------------- /src/translations/en/editor.json: -------------------------------------------------------------------------------- 1 | { 2 | "panels": { 3 | "panelsList": { 4 | "templates": "Templates", 5 | "customize": "Customize", 6 | "elements": "Elements", 7 | "images": "Images", 8 | "videos": "Videos", 9 | "uploads": "Uploads", 10 | "text": "Text", 11 | "graphics": "Graphics", 12 | "pixabay": "Pixabay", 13 | "layers": "Layers" 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /src/views/DesignEditor/components/Footer/Footer.tsx: -------------------------------------------------------------------------------- 1 | import Graphic from "./Graphic" 2 | import Presentation from "./Presentation" 3 | import Video from "./Video" 4 | import useEditorType from "~/hooks/useEditorType" 5 | 6 | const Footer = () => { 7 | const editorType = useEditorType() 8 | 9 | return { 10 | NONE: <>, 11 | PRESENTATION: , 12 | VIDEO:
72 | } 73 | accessibilityType="tooltip" 74 | > 75 |
76 |
88 |
89 | 90 | ) 91 | })} 92 | 93 | 94 | 95 | 96 | 97 | 98 | ) 99 | } 100 | 101 | export default Vector 102 | -------------------------------------------------------------------------------- /src/views/DesignEditor/components/Toolbox/Shared/Opacity.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { Block } from "baseui/block" 3 | import { Input } from "baseui/input" 4 | import { Slider } from "baseui/slider" 5 | import { ILayer } from "@layerhub-io/types" 6 | import { StatefulPopover, PLACEMENT } from "baseui/popover" 7 | import { useActiveObject, useEditor } from "@layerhub-io/react" 8 | import { Button, SIZE, KIND } from "baseui/button" 9 | import OpacityIcon from "~/components/Icons/Opacity." 10 | 11 | const Opacity = () => { 12 | const editor = useEditor() 13 | const [state, setState] = React.useState({ opacity: 1 }) 14 | const activeObject = useActiveObject() as Required 15 | 16 | React.useEffect(() => { 17 | if (activeObject) { 18 | setState({ opacity: activeObject.opacity * 100 }) 19 | } 20 | }, [activeObject]) 21 | 22 | const onChange = React.useCallback( 23 | (value: number) => { 24 | setState({ opacity: value }) 25 | editor.objects.update({ opacity: value / 100 }) 26 | }, 27 | [editor] 28 | ) 29 | 30 | return ( 31 | ( 34 | 35 | 36 | Opacity 37 | 38 | {}} 63 | value={Math.round(state.opacity)} 64 | /> 65 | 66 | 67 | 68 | 69 | null, 72 | ThumbValue: () => null, 73 | TickBar: () => null, 74 | Track: { 75 | style: { 76 | paddingRight: 0, 77 | paddingLeft: 0, 78 | }, 79 | }, 80 | Thumb: { 81 | style: { 82 | height: "12px", 83 | width: "12px", 84 | }, 85 | }, 86 | }} 87 | min={0} 88 | max={100} 89 | marks={false} 90 | value={[state.opacity]} 91 | // @ts-ignore 92 | onChange={({ value }) => onChange(value)} 93 | /> 94 | 95 | 96 | )} 97 | > 98 | 101 | 102 | ) 103 | } 104 | 105 | export default Opacity 106 | --------------------------------------------------------------------------------