mirror of
https://github.com/penxio/penx.git
synced 2026-05-12 03:03:12 -04:00
feat: add fallback
This commit is contained in:
11
package.json
11
package.json
@@ -40,6 +40,8 @@
|
||||
"@floating-ui/react": "^0.25.4",
|
||||
"@glideapps/glide-data-grid": "^6.0.3",
|
||||
"@hookform/resolvers": "^3.10.0",
|
||||
"@ionic/react": "^8.5.7",
|
||||
"@ionic/react-router": "^8.5.7",
|
||||
"@lingui/core": "5.3.1",
|
||||
"@lingui/macro": "^5.3.1",
|
||||
"@lingui/react": "5.3.1",
|
||||
@@ -73,12 +75,12 @@
|
||||
"@radix-ui/react-toolbar": "^1.1.2",
|
||||
"@radix-ui/react-tooltip": "^1.1.8",
|
||||
"@tanstack/react-query": "^5.74.3",
|
||||
"@tauri-apps/plugin-http": "^2.2.0",
|
||||
"@tauri-apps/plugin-fs": "2.2.1",
|
||||
"@tauri-apps/api": "2.5.0",
|
||||
"@tauri-apps/plugin-dialog": "2.2.1",
|
||||
"@tauri-apps/plugin-fs": "2.2.1",
|
||||
"@tauri-apps/plugin-http": "^2.2.0",
|
||||
"@tauri-apps/plugin-opener": "^2",
|
||||
"@tauri-apps/plugin-process": "^2.2.1",
|
||||
"@tauri-apps/plugin-dialog": "2.2.1",
|
||||
"@tauri-apps/plugin-updater": "^2.7.1",
|
||||
"@trpc/client": "11.1.2",
|
||||
"@trpc/next": "11.1.2",
|
||||
@@ -135,8 +137,6 @@
|
||||
"@uiw/react-color": "^2.4.5",
|
||||
"@uploadthing/react": "7.1.0",
|
||||
"@vercel/functions": "^2.0.0",
|
||||
"@ionic/react": "^8.5.7",
|
||||
"@ionic/react-router": "^8.5.7",
|
||||
"ai": "^4.1.24",
|
||||
"array-move": "^4.0.0",
|
||||
"axios": "^1.7.9",
|
||||
@@ -228,6 +228,7 @@
|
||||
"react-dnd": "^16.0.1",
|
||||
"react-dnd-html5-backend": "^16.0.1",
|
||||
"react-dom": "^19.0.0",
|
||||
"react-error-boundary": "^6.0.0",
|
||||
"react-fast-compare": "^3.2.2",
|
||||
"react-grid-layout": "^1.5.1",
|
||||
"react-hook-form": "^7.54.2",
|
||||
|
||||
12
packages/components/Fallback/Fallback.tsx
Normal file
12
packages/components/Fallback/Fallback.tsx
Normal file
@@ -0,0 +1,12 @@
|
||||
import { ReloadAppBtn } from './ReloadAppBtn'
|
||||
|
||||
export const Fallback = () => {
|
||||
return (
|
||||
<div className='h-[80vh] flex flex-col items-center justify-center gap-1' >
|
||||
<div className='text-lg text-foreground/60'>
|
||||
⚠️Something went wrong
|
||||
</div>
|
||||
<ReloadAppBtn />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
9
packages/components/Fallback/ReloadAppBtn.tsx
Normal file
9
packages/components/Fallback/ReloadAppBtn.tsx
Normal file
@@ -0,0 +1,9 @@
|
||||
import { Button } from '@penx/uikit/ui/button'
|
||||
|
||||
export const ReloadAppBtn = () => {
|
||||
async function reloadApp() {
|
||||
window.location.reload()
|
||||
}
|
||||
|
||||
return <Button onClick={() => reloadApp()}>Reload App</Button>
|
||||
}
|
||||
@@ -1,41 +1,35 @@
|
||||
'use client'
|
||||
|
||||
import { ReactNode, useEffect, useRef } from 'react'
|
||||
import { nextTick } from 'process'
|
||||
import { Shape, ShapeStream } from '@electric-sql/client'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { editorDefaultValue } from '@penx/constants'
|
||||
import { useCreations } from '@penx/hooks/useCreations'
|
||||
import { useSiteTags } from '@penx/hooks/useSiteTags'
|
||||
import { useSession } from '@penx/session'
|
||||
import { Button } from '@penx/uikit/button'
|
||||
import { ErrorBoundary } from 'react-error-boundary'
|
||||
import {
|
||||
SidebarInset,
|
||||
SidebarProvider,
|
||||
SidebarTrigger,
|
||||
} from '@penx/uikit/sidebar'
|
||||
import { uniqueId } from '@penx/unique-id'
|
||||
import { Fallback } from '../../Fallback/Fallback'
|
||||
import { AppSidebar } from '../Sidebar/app-sidebar'
|
||||
import { PanelList } from './PanelList'
|
||||
|
||||
export function PanelLayout({ children }: { children: ReactNode }) {
|
||||
// useSiteTags()
|
||||
return (
|
||||
<SidebarProvider className="">
|
||||
<AppSidebar className="z-3" />
|
||||
<SidebarInset className="z-2 relative">
|
||||
<PanelList />
|
||||
</SidebarInset>
|
||||
<ErrorBoundary fallback={<Fallback></Fallback>}>
|
||||
<SidebarProvider className="">
|
||||
<AppSidebar className="z-3" />
|
||||
<SidebarInset className="z-2 relative">
|
||||
<PanelList />
|
||||
</SidebarInset>
|
||||
|
||||
<div
|
||||
className="z-1 fixed left-[10%] top-[0px] h-[80vh] w-[100vw] opacity-30 dark:opacity-0"
|
||||
style={{
|
||||
filter: 'blur(150px) saturate(150%)',
|
||||
transform: 'translateZ(0)',
|
||||
backgroundImage:
|
||||
'radial-gradient(at 27% 37%, #3a8bfd 0, transparent 50%), radial-gradient(at 97% 21%, #9772fe 0, transparent 50%), radial-gradient(at 52% 99%, #fd3a4e 0, transparent 50%), radial-gradient(at 10% 29%, #5afc7d 0, transparent 50%), radial-gradient(at 97% 96%, #e4c795 0, transparent 50%), radial-gradient(at 33% 50%, #8ca8e8 0, transparent 50%), radial-gradient(at 79% 53%, #eea5ba 0, transparent 50%)',
|
||||
}}
|
||||
></div>
|
||||
</SidebarProvider>
|
||||
<div
|
||||
className="z-1 fixed left-[10%] top-[0px] h-[80vh] w-[100vw] opacity-30 dark:opacity-0"
|
||||
style={{
|
||||
filter: 'blur(150px) saturate(150%)',
|
||||
transform: 'translateZ(0)',
|
||||
backgroundImage:
|
||||
'radial-gradient(at 27% 37%, #3a8bfd 0, transparent 50%), radial-gradient(at 97% 21%, #9772fe 0, transparent 50%), radial-gradient(at 52% 99%, #fd3a4e 0, transparent 50%), radial-gradient(at 10% 29%, #5afc7d 0, transparent 50%), radial-gradient(at 97% 96%, #e4c795 0, transparent 50%), radial-gradient(at 33% 50%, #8ca8e8 0, transparent 50%), radial-gradient(at 79% 53%, #eea5ba 0, transparent 50%)',
|
||||
}}
|
||||
></div>
|
||||
</SidebarProvider>
|
||||
</ErrorBoundary>
|
||||
)
|
||||
}
|
||||
|
||||
51
packages/components/src/area-widgets/AllCreationCard.tsx
Normal file
51
packages/components/src/area-widgets/AllCreationCard.tsx
Normal file
@@ -0,0 +1,51 @@
|
||||
'use client'
|
||||
|
||||
import React, { ReactNode } from 'react'
|
||||
import { XIcon } from 'lucide-react'
|
||||
import { AnimatePresence, motion } from 'motion/react'
|
||||
import { Widget } from '@penx/types'
|
||||
import { Button } from '@penx/uikit/button'
|
||||
import { IsAllProvider } from './IsAllContext'
|
||||
import { WidgetRender } from './WidgetRender'
|
||||
|
||||
interface Props {
|
||||
name: ReactNode
|
||||
visible: boolean
|
||||
setVisible: any
|
||||
widget: Widget
|
||||
}
|
||||
|
||||
export function AllCreationCard({ name, visible, setVisible, widget }: Props) {
|
||||
return (
|
||||
<AnimatePresence initial={false}>
|
||||
{visible && (
|
||||
<motion.div
|
||||
initial={{ left: -240 }}
|
||||
animate={{ left: 8 }}
|
||||
exit={{ left: -240 }}
|
||||
className="bg-background fixed bottom-2 left-[8px] top-2 z-50 flex w-[240px] flex-col rounded-md shadow-lg"
|
||||
>
|
||||
<div className="flex items-center justify-between gap-1 px-3 py-2">
|
||||
<div className="select-none text-sm font-semibold">{name}</div>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="size-6 rounded-md"
|
||||
onClick={() => {
|
||||
setVisible(false)
|
||||
}}
|
||||
>
|
||||
<XIcon size={16} className="text-foreground/60"></XIcon>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="flex-1 overflow-auto">
|
||||
<IsAllProvider isAll>
|
||||
<WidgetRender widget={widget} />
|
||||
</IsAllProvider>
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
)
|
||||
}
|
||||
@@ -18,6 +18,7 @@ import { WidgetIcon } from '@penx/widgets/WidgetIcon'
|
||||
import { WidgetName } from '@penx/widgets/WidgetName'
|
||||
import { QuickInput } from '../QuickInput'
|
||||
import { AddCreationButton } from './AddCreationButton'
|
||||
import { AllCreationCard } from './AllCreationCard'
|
||||
import { IsAllProvider } from './IsAllContext'
|
||||
import { TitleContextMenu } from './TitleContextMenu'
|
||||
import { ToggleButton } from './ToggleButton'
|
||||
@@ -95,7 +96,7 @@ export const WidgetItem = forwardRef<HTMLDivElement, Props>(
|
||||
return
|
||||
}
|
||||
|
||||
store.panels.openWidgetPanel(widget)
|
||||
// store.panels.openWidgetPanel(widget)
|
||||
setVisible(!visible)
|
||||
}}
|
||||
>
|
||||
@@ -163,6 +164,15 @@ export const WidgetItem = forwardRef<HTMLDivElement, Props>(
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
|
||||
{!isMobileApp && (
|
||||
<AllCreationCard
|
||||
name={<WidgetName widget={widget} molds={molds} />}
|
||||
visible={visible}
|
||||
setVisible={setVisible}
|
||||
widget={widget}
|
||||
/>
|
||||
)}
|
||||
|
||||
{isMobileApp && (
|
||||
<Drawer.Root open={visible} onOpenChange={setVisible}>
|
||||
<Drawer.Portal>
|
||||
|
||||
13
pnpm-lock.yaml
generated
13
pnpm-lock.yaml
generated
@@ -653,6 +653,9 @@ importers:
|
||||
react-dom:
|
||||
specifier: ^19.0.0
|
||||
version: 19.0.0(react@19.0.0)
|
||||
react-error-boundary:
|
||||
specifier: ^6.0.0
|
||||
version: 6.0.0(react@19.0.0)
|
||||
react-fast-compare:
|
||||
specifier: ^3.2.2
|
||||
version: 3.2.2
|
||||
@@ -12114,6 +12117,11 @@ packages:
|
||||
resolution: {integrity: sha512-OeR2jAxdoqUMHIn/nS9fgreI5hSpgGoL5ezdal4+oO7YSSgJR8ga+PkYGJrSrJ9MKlPcQjMQXnketrD7WNmNsg==}
|
||||
engines: {node: '>= 6'}
|
||||
|
||||
react-error-boundary@6.0.0:
|
||||
resolution: {integrity: sha512-gdlJjD7NWr0IfkPlaREN2d9uUZUlksrfOx7SX62VRerwXbMY6ftGCIZua1VG1aXFNOimhISsTq+Owp725b9SiA==}
|
||||
peerDependencies:
|
||||
react: '>=16.13.1'
|
||||
|
||||
react-fast-compare@3.2.2:
|
||||
resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==}
|
||||
|
||||
@@ -25545,6 +25553,11 @@ snapshots:
|
||||
dependencies:
|
||||
prop-types: 15.8.1
|
||||
|
||||
react-error-boundary@6.0.0(react@19.0.0):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.1
|
||||
react: 19.0.0
|
||||
|
||||
react-fast-compare@3.2.2: {}
|
||||
|
||||
react-from-dom@0.7.5(react@19.0.0):
|
||||
|
||||
Reference in New Issue
Block a user