a tool for shared writing and social publishing
at feature/reader 116 lines 3.4 kB view raw
1"use client"; 2 3import { createNewLeaflet } from "actions/createNewLeaflet"; 4import { createNewLeafletFromTemplate } from "actions/createNewLeafletFromTemplate"; 5import { ActionButton } from "components/ActionBar/ActionButton"; 6import { AddTiny } from "components/Icons/AddTiny"; 7import { BlockCanvasPageSmall } from "components/Icons/BlockCanvasPageSmall"; 8import { BlockDocPageSmall } from "components/Icons/BlockDocPageSmall"; 9import { TemplateSmall } from "components/Icons/TemplateSmall"; 10import { Menu, MenuItem } from "components/Layout"; 11import { useIsMobile } from "src/hooks/isMobile"; 12import { create } from "zustand"; 13import { combine, createJSONStorage, persist } from "zustand/middleware"; 14 15export const useTemplateState = create( 16 persist( 17 combine( 18 { 19 templates: [] as { id: string; name: string }[], 20 }, 21 (set) => ({ 22 removeTemplate: (template: { id: string }) => 23 set((state) => { 24 return { 25 templates: state.templates.filter((t) => t.id !== template.id), 26 }; 27 }), 28 addTemplate: (template: { id: string; name: string }) => 29 set((state) => { 30 if (state.templates.find((t) => t.id === template.id)) return state; 31 return { templates: [...state.templates, template] }; 32 }), 33 }), 34 ), 35 { 36 name: "home-templates", 37 storage: createJSONStorage(() => localStorage), 38 }, 39 ), 40); 41export const CreateNewLeafletButton = (props: {}) => { 42 let isMobile = useIsMobile(); 43 let templates = useTemplateState((s) => s.templates); 44 let openNewLeaflet = (id: string) => { 45 if (isMobile) { 46 window.location.href = `/${id}?focusFirstBlock`; 47 } else { 48 window.open(`/${id}?focusFirstBlock`, "_blank"); 49 } 50 }; 51 return ( 52 <Menu 53 asChild 54 trigger={ 55 <ActionButton 56 id="new-leaflet-button" 57 primary 58 icon=<AddTiny className="m-1 shrink-0" /> 59 label="New" 60 /> 61 } 62 > 63 <MenuItem 64 onSelect={async () => { 65 let id = await createNewLeaflet({ 66 pageType: "doc", 67 redirectUser: false, 68 }); 69 openNewLeaflet(id); 70 }} 71 > 72 <BlockDocPageSmall />{" "} 73 <div className="flex flex-col"> 74 <div>New Doc</div> 75 <div className="text-tertiary text-sm font-normal"> 76 A good ol&apos; text document 77 </div> 78 </div> 79 </MenuItem> 80 <MenuItem 81 onSelect={async () => { 82 let id = await createNewLeaflet({ 83 pageType: "canvas", 84 redirectUser: false, 85 }); 86 openNewLeaflet(id); 87 }} 88 > 89 <BlockCanvasPageSmall /> 90 <div className="flex flex-col"> 91 New Canvas 92 <div className="text-tertiary text-sm font-normal"> 93 A digital whiteboard 94 </div> 95 </div> 96 </MenuItem> 97 {templates.length > 0 && ( 98 <hr className="border-border-light mx-2 mb-0.5" /> 99 )} 100 {templates.map((t) => { 101 return ( 102 <MenuItem 103 key={t.id} 104 onSelect={async () => { 105 let id = await createNewLeafletFromTemplate(t.id, false); 106 if (!id.error) openNewLeaflet(id.id); 107 }} 108 > 109 <TemplateSmall /> 110 New {t.name} 111 </MenuItem> 112 ); 113 })} 114 </Menu> 115 ); 116};