diff --git a/src/client/components/Dashboard.tsx b/src/client/components/Dashboard.tsx
index 72349f7..63d9aaf 100644
--- a/src/client/components/Dashboard.tsx
+++ b/src/client/components/Dashboard.tsx
@@ -14,7 +14,6 @@ import {
import { AppDetail } from './AppDetail'
import { AppSelector } from './AppSelector'
import { DashboardLanding } from './DashboardLanding'
-import { Modal } from './modal'
import { SettingsPage } from './SettingsPage'
import { Sidebar } from './Sidebar'
@@ -55,7 +54,6 @@ export function Dashboard({ render }: { render: () => void }) {
{!isNarrow && }
-
)
}
diff --git a/src/client/components/modal.tsx b/src/client/components/modal.tsx
index d513285..fb5c833 100644
--- a/src/client/components/modal.tsx
+++ b/src/client/components/modal.tsx
@@ -1,19 +1,21 @@
import type { Child } from 'hono/jsx'
+import { render } from 'hono/jsx/dom'
import { define } from '@because/forge'
import { theme } from '../themes'
let modalTitle: string | null = null
let modalContent: (() => Child) | null = null
-let renderFn: (() => void) | null = null
-export const initModal = (render: () => void) => {
- renderFn = render
+const root = document.getElementById('modal')!
+
+const renderModal = () => {
+ render(, root)
}
export const openModal = (title: string, content: () => Child) => {
modalTitle = title
modalContent = content
- renderFn?.()
+ renderModal()
requestAnimationFrame(() => {
document.querySelector('[data-modal-body] input')?.focus()
})
@@ -22,12 +24,10 @@ export const openModal = (title: string, content: () => Child) => {
export const closeModal = () => {
modalTitle = null
modalContent = null
- renderFn?.()
+ renderModal()
}
-export const rerenderModal = () => {
- renderFn?.()
-}
+export { renderModal }
// ESC key handler
document.addEventListener('keydown', (e) => {
diff --git a/src/client/index.tsx b/src/client/index.tsx
index a8bec33..a4460a7 100644
--- a/src/client/index.tsx
+++ b/src/client/index.tsx
@@ -1,6 +1,5 @@
import { render as renderApp } from 'hono/jsx/dom'
import { Dashboard } from './components'
-import { initModal } from './components/modal'
import { initRouter, navigate } from './router'
import { apps, dashboardTab, getSelectedTab, selectedApp, setApps, setIsNarrow } from './state'
import { initToolIframes, updateToolIframes } from './tool-iframes'
@@ -21,7 +20,6 @@ const render = () => {
}
// Initialize render functions
-initModal(render)
initUpdate(render)
initToolIframes()
diff --git a/src/client/modals/DeleteApp.tsx b/src/client/modals/DeleteApp.tsx
index d07de9f..218b6c7 100644
--- a/src/client/modals/DeleteApp.tsx
+++ b/src/client/modals/DeleteApp.tsx
@@ -1,5 +1,5 @@
import type { App } from '../../shared/types'
-import { closeModal, openModal, rerenderModal } from '../components/modal'
+import { closeModal, openModal, renderModal } from '../components/modal'
import { navigate } from '../router'
import { selectedApp } from '../state'
import { Button, Form, FormActions, FormError, FormField, FormInput, FormLabel } from '../styles'
@@ -17,13 +17,13 @@ async function deleteApp(input: HTMLInputElement) {
if (value !== expected) {
deleteAppError = `Type "${expected}" to confirm`
- rerenderModal()
+ renderModal()
return
}
deleteAppDeleting = true
deleteAppError = ''
- rerenderModal()
+ renderModal()
try {
const res = await fetch(`/api/sync/apps/${deleteAppTarget.name}`, {
@@ -41,7 +41,7 @@ async function deleteApp(input: HTMLInputElement) {
} catch (err) {
deleteAppError = err instanceof Error ? err.message : 'Failed to delete app'
deleteAppDeleting = false
- rerenderModal()
+ renderModal()
}
}
diff --git a/src/client/modals/NewApp.tsx b/src/client/modals/NewApp.tsx
index 94f51d5..e48e654 100644
--- a/src/client/modals/NewApp.tsx
+++ b/src/client/modals/NewApp.tsx
@@ -1,4 +1,4 @@
-import { closeModal, openModal, rerenderModal } from '../components/modal'
+import { closeModal, openModal, renderModal } from '../components/modal'
import { navigate } from '../router'
import { apps } from '../state'
import { Button, Form, FormActions, FormCheckbox, FormCheckboxField, FormCheckboxLabel, FormError, FormField, FormInput, FormLabel, FormSelect } from '../styles'
@@ -16,25 +16,25 @@ async function createNewApp() {
if (!name) {
newAppError = 'App name is required'
- rerenderModal()
+ renderModal()
return
}
if (!/^[a-z][a-z0-9-]*$/.test(name)) {
newAppError = 'Name must start with a letter and contain only lowercase letters, numbers, and hyphens'
- rerenderModal()
+ renderModal()
return
}
if (apps.some(a => a.name === name)) {
newAppError = 'An app with this name already exists'
- rerenderModal()
+ renderModal()
return
}
newAppCreating = true
newAppError = ''
- rerenderModal()
+ renderModal()
try {
const res = await fetch('/api/apps', {
@@ -55,7 +55,7 @@ async function createNewApp() {
} catch (err) {
newAppError = err instanceof Error ? err.message : 'Failed to create app'
newAppCreating = false
- rerenderModal()
+ renderModal()
}
}
@@ -105,7 +105,7 @@ export function openNewAppModal() {
checked={newAppTool}
onChange={(e: Event) => {
newAppTool = (e.target as HTMLInputElement).checked
- rerenderModal()
+ renderModal()
}}
/>
Tool
diff --git a/src/client/modals/RenameApp.tsx b/src/client/modals/RenameApp.tsx
index 53c0101..3e8c2ca 100644
--- a/src/client/modals/RenameApp.tsx
+++ b/src/client/modals/RenameApp.tsx
@@ -1,5 +1,5 @@
import type { App } from '../../shared/types'
-import { closeModal, openModal, rerenderModal } from '../components/modal'
+import { closeModal, openModal, renderModal } from '../components/modal'
import { navigate } from '../router'
import { apps } from '../state'
import { Button, Form, FormActions, FormError, FormField, FormInput, FormLabel } from '../styles'
@@ -15,13 +15,13 @@ async function doRenameApp(input: HTMLInputElement) {
if (!newName) {
renameAppError = 'App name is required'
- rerenderModal()
+ renderModal()
return
}
if (!/^[a-z][a-z0-9-]*$/.test(newName)) {
renameAppError = 'Name must start with a letter and contain only lowercase letters, numbers, and hyphens'
- rerenderModal()
+ renderModal()
return
}
@@ -32,13 +32,13 @@ async function doRenameApp(input: HTMLInputElement) {
if (apps.some(a => a.name === newName)) {
renameAppError = 'An app with this name already exists'
- rerenderModal()
+ renderModal()
return
}
renameAppRenaming = true
renameAppError = ''
- rerenderModal()
+ renderModal()
try {
const res = await fetch(`/api/apps/${renameAppTarget.name}/rename`, {
@@ -65,7 +65,7 @@ async function doRenameApp(input: HTMLInputElement) {
} catch (err) {
renameAppError = err instanceof Error ? err.message : 'Failed to rename app'
renameAppRenaming = false
- rerenderModal()
+ renderModal()
}
}
diff --git a/src/server/shell.tsx b/src/server/shell.tsx
index daf3879..afebae8 100644
--- a/src/server/shell.tsx
+++ b/src/server/shell.tsx
@@ -9,6 +9,7 @@ export const Shell = () => (
+