2026-02-21 09:41:46 +01:00
|
|
|
import { useState, useRef, useEffect } from 'react'
|
|
|
|
|
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from '@/components/ui/dialog'
|
|
|
|
|
import { Button } from '@/components/ui/button'
|
|
|
|
|
import { Input } from '@/components/ui/input'
|
|
|
|
|
|
|
|
|
|
interface CreateTypeDialogProps {
|
|
|
|
|
open: boolean
|
|
|
|
|
onClose: () => void
|
|
|
|
|
onCreate: (name: string) => void
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function CreateTypeDialog({ open, onClose, onCreate }: CreateTypeDialogProps) {
|
|
|
|
|
const [name, setName] = useState('')
|
|
|
|
|
const inputRef = useRef<HTMLInputElement>(null)
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (open) {
|
fix: resolve React hooks/compiler ESLint errors
- Wrap ref assignments in useEffect to fix refs-during-render in
useTabManagement, useKeyboardNavigation, and Editor
- Rewrite useAppKeyboard to define keyMap inside useEffect, eliminating
ref access during render
- Add eslint-disable for react-hooks/set-state-in-effect on legitimate
dialog reset patterns (CommitDialog, CreateNoteDialog, CreateTypeDialog,
QuickOpenPalette, AIChatPanel, useVaultLoader)
- Add eslint-disable for react-hooks/static-components on icon lookups
(NoteItem, NoteList PinnedCard) — stateless icon components from a
static map
- Add eslint-disable for react-hooks/purity on Date.now() in
NoteItem TrashDateLine — intentionally memoized on trashedAt
- Remove unused `model` param from buildSystemPrompt (ai-chat.ts) and
update callers
- Fix exhaustive-deps: suppress vault object dep in App.tsx git history
effect (vault object is unstable, loadGitHistory is the real dep)
- Remove unused `modifiedFiles` from useNoteListData params and caller
- Add missing `ref` to Sidebar useOutsideClick deps
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 14:06:51 +01:00
|
|
|
setName('') // eslint-disable-line react-hooks/set-state-in-effect -- reset on dialog open
|
2026-02-21 09:41:46 +01:00
|
|
|
setTimeout(() => inputRef.current?.focus(), 50)
|
|
|
|
|
}
|
|
|
|
|
}, [open])
|
|
|
|
|
|
|
|
|
|
const handleSubmit = (e: React.FormEvent) => {
|
|
|
|
|
e.preventDefault()
|
|
|
|
|
const trimmed = name.trim()
|
|
|
|
|
if (!trimmed) return
|
|
|
|
|
onCreate(trimmed)
|
|
|
|
|
onClose()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<Dialog open={open} onOpenChange={(isOpen) => { if (!isOpen) onClose() }}>
|
|
|
|
|
<DialogContent showCloseButton={false} className="sm:max-w-[380px]">
|
|
|
|
|
<DialogHeader>
|
|
|
|
|
<DialogTitle>Create New Type</DialogTitle>
|
|
|
|
|
</DialogHeader>
|
|
|
|
|
<form onSubmit={handleSubmit} className="space-y-4">
|
|
|
|
|
<div className="space-y-1.5">
|
|
|
|
|
<label className="text-xs font-medium uppercase tracking-wide text-muted-foreground">
|
|
|
|
|
Type Name
|
|
|
|
|
</label>
|
|
|
|
|
<Input
|
|
|
|
|
ref={inputRef}
|
|
|
|
|
placeholder="e.g. Recipe, Book, Habit..."
|
|
|
|
|
value={name}
|
|
|
|
|
onChange={(e) => setName(e.target.value)}
|
|
|
|
|
/>
|
|
|
|
|
<p className="text-xs text-muted-foreground">
|
|
|
|
|
Creates a type document. Its properties become defaults for new docs of this type.
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
<DialogFooter>
|
|
|
|
|
<Button type="button" variant="outline" onClick={onClose}>
|
|
|
|
|
Cancel
|
|
|
|
|
</Button>
|
|
|
|
|
<Button type="submit" disabled={!name.trim()}>
|
|
|
|
|
Create
|
|
|
|
|
</Button>
|
|
|
|
|
</DialogFooter>
|
|
|
|
|
</form>
|
|
|
|
|
</DialogContent>
|
|
|
|
|
</Dialog>
|
|
|
|
|
)
|
|
|
|
|
}
|