quoin-editor 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +83 -5
- package/dist/index.cjs +107 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +80 -4
- package/dist/index.d.ts +80 -4
- package/dist/index.js +94 -18
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +40 -11
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/canvas/BlockCanvas.tsx","../src/context.tsx","../src/registry.ts","../src/blocks/core.ts","../src/blocks/MarkdownBlockEditor.tsx","../src/upload/FilePickerButton.tsx","../src/ui/button.tsx","../src/ui/cn.ts","../src/ui/touch-target.ts","../src/markdown/edit.ts","../src/markdown/line-at.ts","../src/markdown/insert-command.ts","../src/markdown/shortcut-label.ts","../src/ui/dialog.tsx","../src/markdown/ShortcutsReference.tsx","../src/markdown/SlashPalette.tsx","../src/markdown/commands.ts","../src/ui/command.tsx","../src/ui/popover.tsx","../src/markdown/useMarkdownKeymap.ts","../src/markdown/list-continuation.ts","../src/markdown/indent-list.ts","../src/markdown/line-toggles.ts","../src/markdown/slash-trigger.ts","../src/markdown/wrap-selection.ts","../src/markdown/useSlashPalette.ts","../src/markdown/caret-coordinates.ts","../src/hooks/useAutoGrow.ts","../src/blocks/str.ts","../src/ui/select.tsx","../src/ui/textarea.tsx","../src/blocks/CalloutBlockEditor.tsx","../src/ui/input.tsx","../src/blocks/CodeBlockEditor.tsx","../src/blocks/ImageBlockEditor.tsx","../src/upload/UploadField.tsx","../src/blocks/intrinsic-size.ts","../src/blocks/FileBlockEditor.tsx","../src/blocks/previews.tsx","../src/hooks/useBlockList.ts","../src/hooks/new-block-id.ts","../src/canvas/announcements.ts","../src/canvas/BlockActionsMenu.tsx","../src/ui/dropdown-menu.tsx","../src/canvas/BlockCard.tsx","../src/canvas/BlockEditor.tsx","../src/canvas/source-offset.ts","../src/canvas/BlockInserter.tsx","../src/canvas/DocumentStarter.tsx","../src/canvas/reorder-indices.ts","../src/canvas/same-blocks.ts","../src/canvas/SortableBlock.tsx","../src/hooks/useAutosave.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport {\n DndContext,\n KeyboardSensor,\n PointerSensor,\n closestCenter,\n useSensor,\n useSensors,\n type DragEndEvent,\n} from '@dnd-kit/core';\nimport { restrictToVerticalAxis } from '@dnd-kit/modifiers';\nimport { SortableContext, sortableKeyboardCoordinates, verticalListSortingStrategy } from '@dnd-kit/sortable';\nimport { QuoinProvider } from '../context';\nimport { blockByType, type AnyBlockDefinition } from '../registry';\nimport { coreBlocks } from '../blocks/core';\nimport type { QuoinBlock, UploadFn } from '../types';\nimport { useBlockList } from '../hooks/useBlockList';\nimport { cn } from '../ui/cn';\nimport { buildAnnouncements } from './announcements';\nimport { BlockActionsMenu } from './BlockActionsMenu';\nimport { BlockCard } from './BlockCard';\nimport { BlockInserter } from './BlockInserter';\nimport { DocumentStarter } from './DocumentStarter';\nimport { reorderIndices } from './reorder-indices';\nimport { sameBlocks } from './same-blocks';\nimport { SortableBlock } from './SortableBlock';\n\n/** Props for `BlockCanvas`; `blocks` and `onChange` are the whole document contract. */\nexport type BlockCanvasProps = {\n /**\n * The document. Update it synchronously from `onChange`, as with a controlled `<input value onChange>`:\n * a host that applies edits late (a debounce, a transition, an async store) will see typing revert,\n * and should treat the canvas as uncontrolled by passing the initial document and ignoring later echoes.\n * A new array that differs from the last one you supplied replaces what the canvas shows, which is how a host\n * loads, undoes or merges. An array structurally equal to the last one you supplied is ignored, so a \"discard\n * changes\" button that hands back the original document does nothing; remount the canvas with a React `key` to\n * force a reset. The comparison is shallow over each block's `data`: a host whose block `data` holds nested\n * objects rebuilt on every render, and which does not echo `onChange` back, can still lose an edit. The core\n * block types all have flat data, so this only affects custom blocks.\n */\n blocks: QuoinBlock[];\n onChange: (blocks: QuoinBlock[]) => void;\n /** Defaults to the five core block types. Pass `[...coreBlocks, yours]` to extend them. */\n blockTypes?: AnyBlockDefinition[];\n upload?: UploadFn;\n resolveAssetUrl?: (storageKey: string) => string;\n onError?: (error: Error) => void;\n /** Renders the document with no inserters, menus, drag handles or editors. */\n readOnly?: boolean;\n /** Added to the root element's own classes rather than replacing them. */\n className?: string;\n id?: string;\n /** Names the document for assistive technology; the root then becomes a labelled group. */\n 'aria-label'?: string;\n};\n\ntype Selection = { start: number; end: number };\n\nfunction Canvas({\n blocks,\n onChange,\n blockTypes,\n readOnly,\n className,\n id,\n 'aria-label': ariaLabel,\n}: Pick<BlockCanvasProps, 'blocks' | 'onChange' | 'readOnly' | 'className' | 'id' | 'aria-label'> & {\n blockTypes: AnyBlockDefinition[];\n}) {\n const list = useBlockList(blocks);\n const { insertAt, update, remove, move, reorder, reset } = list;\n const sensors = useSensors(\n useSensor(PointerSensor, { activationConstraint: { distance: 4 } }),\n useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates }),\n );\n const dndId = React.useId();\n const [newBlockId, setNewBlockId] = React.useState<string | null>(null);\n const [seedSelection, setSeedSelection] = React.useState<Selection | null>(null);\n const listRef = React.useRef<HTMLDivElement>(null);\n const pendingDeleteIndexRef = React.useRef<number | null>(null);\n const announcements = React.useMemo(\n () => buildAnnouncements(list.blocks, blockTypes),\n [list.blocks, blockTypes],\n );\n\n // The reducer reads `blocks` once, so the two effects below carry the document\n // across the boundary in both directions. An array this canvas emitted is\n // recognised when the host hands it back and is not reset; an array the host\n // supplies is foreign and is. Seeding the refs with the first `blocks` keeps\n // mounting from reporting a change nobody made.\n const lastEmitted = React.useRef<QuoinBlock[]>(blocks);\n const lastSupplied = React.useRef<QuoinBlock[]>(blocks);\n\n React.useEffect(() => {\n if (list.blocks === lastEmitted.current) return;\n lastEmitted.current = list.blocks;\n onChange(list.blocks);\n }, [list.blocks, onChange]);\n\n React.useEffect(() => {\n const previous = lastSupplied.current;\n lastSupplied.current = blocks;\n if (blocks === lastEmitted.current) return;\n // A host that builds a fresh array on every render, without echoing edits, would\n // otherwise wipe them on any unrelated re-render. An undo replays a different array.\n if (sameBlocks(blocks, previous) || sameBlocks(blocks, list.blocks)) return;\n lastEmitted.current = blocks;\n reset(blocks);\n }, [blocks, reset]);\n\n const insertPlain = React.useCallback(\n (index: number, type: string, data?: Record<string, unknown>) => {\n setSeedSelection(null);\n const seed = data ?? blockByType(blockTypes, type)?.initialData?.() ?? {};\n setNewBlockId(insertAt(index, type, seed));\n },\n [insertAt, blockTypes],\n );\n\n function handleDelete(index: number, id: string) {\n pendingDeleteIndexRef.current = index;\n remove(id);\n }\n\n React.useEffect(() => {\n const index = pendingDeleteIndexRef.current;\n pendingDeleteIndexRef.current = null;\n if (index === null || !listRef.current) return;\n const landingIndex = Math.min(index, list.blocks.length - 1);\n const card =\n landingIndex >= 0 ? listRef.current.querySelector<HTMLElement>(`[data-block-index=\"${landingIndex}\"]`) : null;\n (card?.querySelector<HTMLElement>('button') ?? listRef.current.querySelector<HTMLElement>('button'))?.focus();\n }, [list.blocks]);\n\n function handleDragEnd(event: DragEndEvent) {\n const { active, over } = event;\n const result = reorderIndices(\n list.blocks.map((b) => b.id),\n String(active.id),\n over ? String(over.id) : null,\n );\n if (result) reorder(result.from, result.to);\n }\n\n const rootProps = {\n ref: listRef,\n id,\n className: cn('quoin flex flex-col', className),\n role: ariaLabel ? 'group' : undefined,\n 'aria-label': ariaLabel,\n };\n\n if (readOnly) {\n return (\n <div {...rootProps}>\n <ul className=\"flex flex-col\">\n {list.blocks.map((b, i) => (\n <li key={b.id}>\n <div data-block-index={i} className=\"rounded-lg px-2 py-1\">\n <BlockCard block={b} index={i} editingByDefault={false} readOnly onUpdate={update} />\n </div>\n </li>\n ))}\n </ul>\n </div>\n );\n }\n\n return (\n <div {...rootProps}>\n <BlockInserter index={0} onInsert={insertPlain} label=\"Insert a block at the start\" />\n <DndContext\n id={dndId}\n sensors={sensors}\n collisionDetection={closestCenter}\n modifiers={[restrictToVerticalAxis]}\n accessibility={{ announcements }}\n onDragEnd={handleDragEnd}\n >\n <SortableContext items={list.blocks.map((b) => b.id)} strategy={verticalListSortingStrategy}>\n <ul className=\"flex flex-col\">\n {list.blocks.map((b, i) => (\n <li key={b.id}>\n <SortableBlock\n id={b.id}\n index={i}\n actions={\n <BlockActionsMenu\n index={i}\n count={list.blocks.length}\n label={blockByType(blockTypes, b.type)?.label ?? b.type}\n onMove={move}\n onDelete={() => handleDelete(i, b.id)}\n />\n }\n >\n <BlockCard\n block={b}\n index={i}\n editingByDefault={b.id === newBlockId}\n initialSelection={b.id === newBlockId ? seedSelection : null}\n onUpdate={update}\n onInsertBlock={insertPlain}\n />\n </SortableBlock>\n <BlockInserter\n index={i + 1}\n onInsert={insertPlain}\n label={`Insert a block after block ${i + 1}`}\n />\n </li>\n ))}\n </ul>\n </SortableContext>\n </DndContext>\n <DocumentStarter\n autoFocus={list.blocks.length === 0}\n onStart={(markdown, selection) => {\n setSeedSelection(selection ?? null);\n setNewBlockId(insertAt(list.blocks.length, 'MARKDOWN', { markdown }));\n }}\n onInsertBlock={(type) => insertPlain(list.blocks.length, type)}\n />\n </div>\n );\n}\n\n/** The editor: renders `blocks`, reports every edit through `onChange`, and accepts a new `blocks` array from outside at any time. */\nexport function BlockCanvas({\n blocks,\n onChange,\n blockTypes = coreBlocks,\n upload,\n resolveAssetUrl,\n onError,\n readOnly = false,\n className,\n id,\n 'aria-label': ariaLabel,\n}: BlockCanvasProps) {\n const config = React.useMemo(\n () => ({ blockTypes, upload, resolveAssetUrl, onError }),\n [blockTypes, upload, resolveAssetUrl, onError],\n );\n return (\n <QuoinProvider value={config}>\n <Canvas\n blocks={blocks}\n onChange={onChange}\n blockTypes={blockTypes}\n readOnly={readOnly}\n className={className}\n id={id}\n aria-label={ariaLabel}\n />\n </QuoinProvider>\n );\n}\n","'use client';\n\nimport * as React from 'react';\nimport type { AnyBlockDefinition } from './registry';\nimport type { UploadFn } from './types';\n\n/** The resolved canvas configuration every block editor reads through `useQuoin`. */\nexport type QuoinConfig = {\n blockTypes: AnyBlockDefinition[];\n /** Absent when the host has not wired uploads; upload fields then render disabled. */\n upload?: UploadFn;\n resolveAssetUrl: (storageKey: string) => string;\n onError: (error: Error) => void;\n};\n\n/** What a host passes to `QuoinProvider`: only the block types are required. */\nexport type QuoinConfigInput = Partial<QuoinConfig> & {\n blockTypes: AnyBlockDefinition[];\n};\n\nconst QuoinContext = React.createContext<QuoinConfig | null>(null);\n\n/** Supplies the block registry and the host couplings (upload, asset URLs, error reporting) to every block below it. */\nexport function QuoinProvider({\n value,\n children,\n}: {\n value: QuoinConfigInput;\n children: React.ReactNode;\n}) {\n const { blockTypes, upload, resolveAssetUrl, onError } = value;\n const config = React.useMemo<QuoinConfig>(\n () => ({\n blockTypes,\n upload,\n // Identity default: an empty key resolves to an empty string, which stays falsy\n // wherever a resolved URL is tested for \"no asset chosen yet\".\n resolveAssetUrl: resolveAssetUrl ?? ((key: string) => key),\n onError: onError ?? ((error: Error) => console.error(error)),\n }),\n [blockTypes, upload, resolveAssetUrl, onError],\n );\n return <QuoinContext.Provider value={config}>{children}</QuoinContext.Provider>;\n}\n\n/** Reads the canvas configuration. Throws outside a QuoinProvider rather than returning a silent default. */\nexport function useQuoin(): QuoinConfig {\n const config = React.useContext(QuoinContext);\n if (!config) throw new Error('useQuoin must be used inside a QuoinProvider.');\n return config;\n}\n","import type { ComponentType } from 'react';\nimport type { LucideIcon } from 'lucide-react';\nimport type { BlockEditorProps, BlockPreviewProps } from './types';\n\n/** Describes one block type: how to label it, how to draw it at rest, how to edit it. */\nexport type BlockDefinition<D extends object = Record<string, unknown>> = {\n type: string;\n label: string;\n icon: LucideIcon;\n editor: ComponentType<BlockEditorProps<D>>;\n /**\n * What the block shows when it is not being edited. Optional so a host can register an\n * edit-only block type, and overridable so a host can supply rich rendering (a full\n * markdown pipeline, a chart) without Quoin depending on one.\n */\n preview?: ComponentType<BlockPreviewProps<D>>;\n /**\n * Called when a new block of this type is inserted, to seed its data.\n * `NoInfer` keeps `D` inferred from `editor` and `preview` alone, so the seed is checked\n * against the editor's data type instead of widening it.\n */\n initialData?: () => NoInfer<D>;\n /** Whether the block is offered in the slash palette and inserter; defaults to true. */\n inSlashPalette?: boolean;\n /**\n * Renders this block's editor permanently instead of a preview you click to edit.\n * Also supply a `preview`: a read-only canvas draws the preview rather than the editor,\n * so without one the block's content is invisible there.\n */\n alwaysEditing?: boolean;\n};\n\n/** A definition with its data type erased, so definitions of different shapes compose in one array. */\nexport type AnyBlockDefinition = BlockDefinition<Record<string, unknown>>;\n\n/**\n * Types `data` inside your editor component, then erases the generic on the way out.\n * The erasure is deliberate: `D` appears in both covariant and contravariant positions\n * on `editor`, so without it an array of differently-shaped definitions will not typecheck.\n * `initialData` is checked against the editor's data type. That relies on `NoInfer`, so\n * TypeScript 5.4 or later is required.\n */\nexport function defineBlock<D extends object>(definition: BlockDefinition<D>): AnyBlockDefinition {\n return definition as unknown as AnyBlockDefinition;\n}\n\n/** The definition for a type, or undefined; the last registration of a type wins, so a host can override a core block. */\nexport function blockByType(\n definitions: AnyBlockDefinition[],\n type: string,\n): AnyBlockDefinition | undefined {\n for (let i = definitions.length - 1; i >= 0; i -= 1) {\n if (definitions[i].type === type) return definitions[i];\n }\n return undefined;\n}\n\n/** The definitions offered in the slash palette, in registration order, one per type, with the last registration of a type winning. */\nexport function paletteBlocks(definitions: AnyBlockDefinition[]): AnyBlockDefinition[] {\n const seen = new Set<string>();\n const out: AnyBlockDefinition[] = [];\n for (let i = definitions.length - 1; i >= 0; i -= 1) {\n const d = definitions[i];\n if (seen.has(d.type)) continue;\n // Claim the type BEFORE honouring the opt-out, so a hidden override suppresses the\n // definition it replaces instead of letting the earlier one reappear. Without this,\n // the palette can offer a block that `blockByType` resolves to a different definition.\n seen.add(d.type);\n if (d.inSlashPalette === false) continue;\n out.push(d);\n }\n return out.reverse();\n}\n","import { Code, FileText, MessageSquare, Image, Paperclip } from 'lucide-react';\nimport { defineBlock, type AnyBlockDefinition } from '../registry';\nimport { MarkdownBlockEditor } from './MarkdownBlockEditor';\nimport { CalloutBlockEditor } from './CalloutBlockEditor';\nimport { CodeBlockEditor } from './CodeBlockEditor';\nimport { ImageBlockEditor } from './ImageBlockEditor';\nimport { FileBlockEditor } from './FileBlockEditor';\nimport {\n MarkdownPreview,\n CalloutPreview,\n CodePreview,\n ImagePreview,\n FilePreview,\n} from './previews';\n\n/** The block types Quoin ships with. Spread them alongside your own definitions. */\nexport const coreBlocks: AnyBlockDefinition[] = [\n defineBlock({\n type: 'MARKDOWN',\n label: 'Markdown',\n icon: FileText,\n editor: MarkdownBlockEditor,\n preview: MarkdownPreview,\n initialData: () => ({ markdown: '' }),\n }),\n defineBlock({\n type: 'CALLOUT',\n label: 'Callout',\n icon: MessageSquare,\n editor: CalloutBlockEditor,\n preview: CalloutPreview,\n initialData: () => ({ tone: 'info', body: '' }),\n }),\n defineBlock({\n type: 'CODE',\n label: 'Code',\n icon: Code,\n editor: CodeBlockEditor,\n preview: CodePreview,\n initialData: () => ({ language: '', code: '' }),\n }),\n defineBlock({\n type: 'IMAGE',\n label: 'Image',\n icon: Image,\n editor: ImageBlockEditor,\n preview: ImagePreview,\n initialData: () => ({ storageKey: '', alt: '' }),\n }),\n defineBlock({\n type: 'FILE',\n label: 'File',\n icon: Paperclip,\n editor: FileBlockEditor,\n preview: FilePreview,\n initialData: () => ({ storageKey: '', filename: '' }),\n }),\n];\n","'use client';\n\nimport * as React from 'react';\nimport { useQuoin } from '../context';\nimport { FilePickerButton } from '../upload/FilePickerButton';\nimport { applyEdit } from '../markdown/edit';\nimport { insertCommand } from '../markdown/insert-command';\nimport { ShortcutsReference } from '../markdown/ShortcutsReference';\nimport { SlashPalette } from '../markdown/SlashPalette';\nimport { useMarkdownKeymap } from '../markdown/useMarkdownKeymap';\nimport { useSlashPalette } from '../markdown/useSlashPalette';\nimport type { TextCommand } from '../markdown/commands';\nimport { useAutoGrow } from '../hooks/useAutoGrow';\nimport type { BlockEditorProps } from '../types';\nimport { str } from './str';\n\nconst BOX = [\n '-mx-2 min-h-7 w-[calc(100%+1rem)] resize-none rounded-md border-0 bg-transparent px-2 py-0',\n 'text-base leading-7 outline-none placeholder:text-muted-foreground',\n 'transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:ring-ring/50',\n].join(' ');\n\nexport function MarkdownBlockEditor({ data, onChange, onInsertBlock, onDone }: BlockEditorProps) {\n const { onError } = useQuoin();\n const markdown = str(data.markdown);\n const ref = useAutoGrow<HTMLTextAreaElement>(markdown);\n const palette = useSlashPalette(ref);\n const [shortcutsOpen, setShortcutsOpen] = React.useState(false);\n\n const set = (patch: Record<string, unknown>) => onChange({ ...data, ...patch });\n const commit = (next: string) => onChange({ ...data, markdown: next });\n\n const keymap = useMarkdownKeymap({ commit, onOpenPalette: palette.openAtCaret });\n\n function reopenBox(): HTMLTextAreaElement | null {\n const el = ref.current;\n el?.focus({ preventScroll: true });\n return el ?? null;\n }\n\n function runTextCommand(command: TextCommand) {\n palette.setOpen(false);\n const el = reopenBox();\n if (!el) return;\n applyEdit(el, insertCommand(command, el.value, palette.offsetRef.current), commit);\n }\n\n function writeLiteralSlash() {\n palette.setOpen(false);\n const el = reopenBox();\n if (!el) return;\n const at = palette.offsetRef.current;\n applyEdit(\n el,\n { value: `${el.value.slice(0, at)}/${el.value.slice(at)}`, selectionStart: at + 1, selectionEnd: at + 1 },\n commit,\n );\n }\n\n function readMarkdownFile(file: File) {\n const reader = new FileReader();\n reader.onload = () => {\n const text = typeof reader.result === 'string' ? reader.result : '';\n if (text.trim() === '') {\n onError(new Error(`${file.name} is empty.`));\n return;\n }\n set({ markdown: text });\n onDone?.();\n };\n reader.onerror = () => onError(new Error(`Could not read ${file.name}.`));\n reader.readAsText(file);\n }\n\n return (\n <div className=\"relative flex flex-col gap-3\">\n <textarea\n ref={ref}\n aria-label=\"Markdown\"\n value={markdown}\n rows={1}\n placeholder=\"Write, or press / for commands\"\n onChange={(e) => set({ markdown: e.target.value })}\n onKeyDown={keymap.onKeyDown}\n onPaste={keymap.onPaste}\n className={BOX}\n />\n <SlashPalette\n open={palette.open}\n caret={palette.caret}\n onOpenChange={palette.setOpen}\n onTextCommand={runTextCommand}\n onBlockCommand={(type) => {\n palette.setOpen(false);\n onInsertBlock?.(type);\n }}\n onShortcuts={() => {\n palette.setOpen(false);\n setShortcutsOpen(true);\n }}\n onDismiss={writeLiteralSlash}\n />\n <ShortcutsReference open={shortcutsOpen} onOpenChange={setShortcutsOpen} />\n {markdown.trim() === '' && (\n <FilePickerButton\n label=\"Upload .md\"\n accept=\".md,text/markdown,text/plain\"\n onPick={readMarkdownFile}\n />\n )}\n </div>\n );\n}\n","'use client';\n\nimport { Upload } from 'lucide-react';\nimport { Button } from '../ui/button';\n\n/** The input itself stays focusable and labelled, laid transparently over the\n * button, so the keyboard and the pointer both land on the real control. The\n * wrapper paints the focus ring the invisible input cannot show. */\nexport function FilePickerButton({\n label,\n accept,\n disabled,\n onPick,\n}: {\n label: string;\n accept?: string;\n disabled?: boolean;\n onPick: (file: File) => void;\n}) {\n return (\n <span className=\"relative inline-flex rounded-md has-[:focus-visible]:ring-[3px] has-[:focus-visible]:ring-ring/50\">\n <Button asChild variant=\"outline\" size=\"sm\">\n <span aria-hidden=\"true\" className={disabled ? 'pointer-events-none opacity-50' : undefined}>\n <Upload aria-hidden=\"true\" />\n {label}\n </span>\n </Button>\n <input\n type=\"file\"\n accept={accept}\n aria-label={label}\n disabled={disabled}\n className=\"absolute inset-0 cursor-pointer opacity-0 disabled:cursor-not-allowed\"\n onChange={(e) => {\n const file = e.target.files?.[0];\n // Clear so picking the same file again still fires `change`, which is what makes retry after a failed upload work.\n e.target.value = '';\n if (file) onPick(file);\n }}\n />\n </span>\n );\n}\n","import * as React from \"react\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { cn } from \"./cn\";\nimport { SQUARE_TAP_TARGET_FLOOR, TAP_TARGET_FLOOR } from \"./touch-target\";\n\n/** Class variants for the button primitive, reusable on other elements. */\nconst buttonVariants = cva(\n \"inline-flex cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-[color,background-color,border-color,box-shadow,opacity] disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 shrink-0 outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50\",\n {\n variants: {\n variant: {\n default:\n \"bg-primary text-primary-foreground shadow-xs hover:bg-primary/90\",\n destructive:\n \"bg-destructive text-white shadow-xs hover:bg-destructive/90 dark:bg-destructive/60 dark:hover:bg-destructive/75\",\n outline:\n \"border border-input bg-transparent shadow-xs hover:bg-accent hover:text-accent-foreground\",\n secondary:\n \"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80\",\n ghost: \"hover:bg-accent hover:text-accent-foreground\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: `h-9 px-4 py-2 has-[>svg]:px-3 ${TAP_TARGET_FLOOR}`,\n xs: `h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3 ${TAP_TARGET_FLOOR}`,\n sm: `h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5 ${TAP_TARGET_FLOOR}`,\n lg: `h-10 rounded-md px-6 has-[>svg]:px-4 ${TAP_TARGET_FLOOR}`,\n icon: `size-9 ${SQUARE_TAP_TARGET_FLOOR}`,\n \"icon-xs\": `size-6 rounded-md [&_svg:not([class*='size-'])]:size-3 ${SQUARE_TAP_TARGET_FLOOR}`,\n \"icon-sm\": `size-8 ${SQUARE_TAP_TARGET_FLOOR}`,\n \"icon-lg\": `size-10 ${SQUARE_TAP_TARGET_FLOOR}`,\n },\n },\n defaultVariants: { variant: \"default\", size: \"default\" },\n },\n);\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & { asChild?: boolean }) {\n const Comp = asChild ? Slot : \"button\";\n return (\n <Comp\n data-slot=\"button\"\n data-variant={variant}\n data-size={size}\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n );\n}\n\nexport { Button, buttonVariants };\n","import { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\n/** Merges class names, with later Tailwind utilities overriding earlier conflicting ones. */\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","/** 44px is the platform minimum for a finger. It is applied as a floor rather than\n * a height so a control keeps its own pointer-precise size, and only where the\n * primary pointer is coarse so mouse-driven layouts keep their density. */\nexport const TAP_TARGET_FLOOR = 'pointer-coarse:min-h-11';\n\n/** The pointer-coarse sizing floor on both axes, for square icon controls. */\nexport const SQUARE_TAP_TARGET_FLOOR = `${TAP_TARGET_FLOOR} pointer-coarse:min-w-11`;\n\n/** For an icon control pinned to a corner, where growing the box would drag the icon\n * inward. The target is a centred, transparent pseudo-element instead, so the hit\n * area reaches 44px while the icon keeps its own size and position. Requires the\n * control to be positioned, which a pinned one already is. */\nexport const ICON_TAP_TARGET_FLOOR = [\n \"pointer-coarse:before:absolute pointer-coarse:before:top-1/2 pointer-coarse:before:left-1/2\",\n 'pointer-coarse:before:size-11 pointer-coarse:before:-translate-x-1/2 pointer-coarse:before:-translate-y-1/2',\n \"pointer-coarse:before:content-['']\",\n].join(' ');\n","/** A text transform result: the next value and where the selection should land. */\nexport type Edit = { value: string; selectionStart: number; selectionEnd: number };\n\nfunction changedSpan(before: string, after: string) {\n let start = 0;\n const shortest = Math.min(before.length, after.length);\n while (start < shortest && before[start] === after[start]) start += 1;\n\n let endBefore = before.length;\n let endAfter = after.length;\n while (endBefore > start && endAfter > start && before[endBefore - 1] === after[endAfter - 1]) {\n endBefore -= 1;\n endAfter -= 1;\n }\n\n return { start, endBefore, replacement: after.slice(start, endAfter) };\n}\n\n// Writing through execCommand keeps the transform as one entry on the browser's\n// own undo stack. Either path commits el.value rather than the edit's intended\n// value: a browser is trusted to write what it was asked, and if it ever\n// wrote something else, committing our own intent instead would silently\n// diverge React's state from the DOM.\nfunction writeNatively(el: HTMLTextAreaElement, replacement: string): boolean {\n if (typeof document.execCommand !== 'function') return false;\n try {\n return replacement === ''\n ? document.execCommand('delete')\n : document.execCommand('insertText', false, replacement);\n } catch {\n return false;\n }\n}\n\n/** Applies an edit to a textarea through the native undo stack when the browser allows it, so Ctrl+Z still works. */\nexport function applyEdit(\n el: HTMLTextAreaElement,\n edit: Edit,\n commit: (value: string) => void,\n): void {\n if (el.value !== edit.value) {\n const { start, endBefore, replacement } = changedSpan(el.value, edit.value);\n el.setSelectionRange(start, endBefore);\n if (!writeNatively(el, replacement)) {\n el.value = edit.value;\n }\n commit(el.value);\n }\n el.setSelectionRange(edit.selectionStart, edit.selectionEnd);\n}\n","const FENCE = /^ {0,3}(```|~~~)/;\n\nexport type Line = { start: number; end: number; text: string };\n\n/** The line containing the offset, with its start and end offsets and its text (no trailing newline). */\nexport function lineAt(value: string, offset: number): Line {\n const start = value.lastIndexOf('\\n', offset - 1) + 1;\n const next = value.indexOf('\\n', offset);\n const end = next === -1 ? value.length : next;\n return { start, end, text: value.slice(start, end) };\n}\n\nexport function isFenceDelimiter(text: string): boolean {\n return FENCE.test(text);\n}\n\nexport function insideFence(value: string, offset: number): boolean {\n const lines = value.slice(0, offset).split('\\n');\n if (isFenceDelimiter(lines[lines.length - 1])) return true;\n\n let open = false;\n for (let i = 0; i < lines.length - 1; i += 1) {\n if (isFenceDelimiter(lines[i])) open = !open;\n }\n return open;\n}\n","import type { Edit } from './edit';\nimport { lineAt } from './line-at';\n\n/** The fields `insertCommand` needs. `TextCommand` satisfies this structurally. */\nexport type InsertableCommand = {\n insert: string;\n caretOffset: number;\n selectLength?: number;\n separate: boolean;\n};\n\n/** Inserts a command's markdown at the caret, starting a new line (or a blank line if it asks) when the caret is mid-line. */\nexport function insertCommand(command: InsertableCommand, value: string, caret: number): Edit {\n const line = lineAt(value, caret);\n const before = value.slice(line.start, caret).replace(/[ \\t]+$/, '');\n const cut = line.start + before.length;\n const prefix = before.trim() === '' ? '' : command.separate ? '\\n\\n' : '\\n';\n const at = cut + prefix.length + command.caretOffset;\n\n return {\n value: value.slice(0, cut) + prefix + command.insert + value.slice(caret),\n selectionStart: at,\n selectionEnd: at + (command.selectLength ?? 0),\n };\n}\n","const MAC_LABEL: Record<string, string> = { mod: '⌘', alt: '⌥', shift: '⇧' };\nconst OTHER_LABEL: Record<string, string> = { mod: 'Ctrl', alt: 'Alt', shift: 'Shift' };\n\nfunction onMac(): boolean {\n if (typeof navigator === 'undefined') return false;\n return /Mac|iPhone|iPad/.test(navigator.userAgent);\n}\n\n/** Renders a \"mod+shift+b\" style hint as the platform's own label, such as ⌘⇧B on a Mac and Ctrl+Shift+B elsewhere. */\nexport function formatShortcut(hint: string): string {\n const mac = onMac();\n const labels = mac ? MAC_LABEL : OTHER_LABEL;\n const parts = hint.split('+').map((part) => labels[part] ?? part.toUpperCase());\n return parts.join(mac ? '' : '+');\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport * as DialogPrimitive from \"@radix-ui/react-dialog\";\nimport { XIcon } from \"lucide-react\";\nimport { cn } from \"./cn\";\nimport { ICON_TAP_TARGET_FLOOR } from \"./touch-target\";\n\nfunction Dialog(props: React.ComponentProps<typeof DialogPrimitive.Root>) {\n return <DialogPrimitive.Root data-slot=\"dialog\" {...props} />;\n}\n\nfunction DialogTrigger(\n props: React.ComponentProps<typeof DialogPrimitive.Trigger>,\n) {\n return <DialogPrimitive.Trigger data-slot=\"dialog-trigger\" {...props} />;\n}\n\nfunction DialogPortal(\n props: React.ComponentProps<typeof DialogPrimitive.Portal>,\n) {\n return <DialogPrimitive.Portal data-slot=\"dialog-portal\" {...props} />;\n}\n\nfunction DialogClose(\n props: React.ComponentProps<typeof DialogPrimitive.Close>,\n) {\n return <DialogPrimitive.Close data-slot=\"dialog-close\" {...props} />;\n}\n\nfunction DialogOverlay({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Overlay>) {\n return (\n <DialogPrimitive.Overlay\n data-slot=\"dialog-overlay\"\n className={cn(\n \"quoin fixed inset-0 z-50 bg-black/50 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction DialogContent({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Content>) {\n return (\n <DialogPortal>\n <DialogOverlay />\n <DialogPrimitive.Content\n data-slot=\"dialog-content\"\n className={cn(\n \"quoin bg-popover fixed top-[50%] left-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n className,\n )}\n {...props}\n >\n {children}\n <DialogPrimitive.Close\n className={cn(\n \"ring-offset-background focus:ring-ring absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-none\",\n ICON_TAP_TARGET_FLOOR,\n )}\n >\n <XIcon />\n <span className=\"sr-only\">Close</span>\n </DialogPrimitive.Close>\n </DialogPrimitive.Content>\n </DialogPortal>\n );\n}\n\nfunction DialogHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"dialog-header\"\n className={cn(\"flex flex-col gap-2 text-center sm:text-left\", className)}\n {...props}\n />\n );\n}\n\nfunction DialogFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"dialog-footer\"\n className={cn(\n \"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction DialogTitle({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Title>) {\n return (\n <DialogPrimitive.Title\n data-slot=\"dialog-title\"\n className={cn(\"text-lg leading-none font-semibold\", className)}\n {...props}\n />\n );\n}\n\nfunction DialogDescription({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Description>) {\n return (\n <DialogPrimitive.Description\n data-slot=\"dialog-description\"\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n );\n}\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n};\n","'use client';\n\nimport { formatShortcut } from './shortcut-label';\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n} from '../ui/dialog';\n\nconst ROWS: Array<{ label: string; keys: string }> = [\n { label: 'Open the command palette', keys: '/' },\n { label: 'Bold', keys: formatShortcut('mod+b') },\n { label: 'Italic', keys: formatShortcut('mod+i') },\n { label: 'Inline code', keys: formatShortcut('mod+e') },\n { label: 'Link', keys: formatShortcut('mod+k') },\n { label: 'Heading', keys: formatShortcut('mod+alt+1') },\n { label: 'Subtitle', keys: formatShortcut('mod+alt+2') },\n { label: 'Sub-subtitle', keys: formatShortcut('mod+alt+3') },\n { label: 'Bullet list', keys: formatShortcut('mod+shift+8') },\n { label: 'Numbered list', keys: formatShortcut('mod+shift+7') },\n { label: 'Continue a list, or leave it when the item is empty', keys: 'Enter' },\n { label: 'Indent item', keys: 'Tab' },\n { label: 'Outdent item', keys: formatShortcut('shift') + '+Tab' },\n];\n\nexport function ShortcutsReference({\n open,\n onOpenChange,\n}: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n}) {\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent className=\"sm:max-w-md\">\n <DialogHeader>\n <DialogTitle>Keyboard shortcuts</DialogTitle>\n <DialogDescription>Formatting without leaving the keyboard.</DialogDescription>\n </DialogHeader>\n <dl className=\"grid grid-cols-[1fr_auto] gap-x-4 gap-y-2 text-sm\">\n {ROWS.map((row) => (\n <div key={row.label} className=\"col-span-2 grid grid-cols-subgrid items-baseline\">\n <dt className=\"text-muted-foreground\">{row.label}</dt>\n <dd>\n <kbd className=\"rounded border bg-muted px-1.5 py-0.5 font-mono text-xs\">{row.keys}</kbd>\n </dd>\n </div>\n ))}\n </dl>\n </DialogContent>\n </Dialog>\n );\n}\n","'use client';\n\nimport { Keyboard } from 'lucide-react';\nimport { useQuoin } from '../context';\nimport { paletteBlocks } from '../registry';\nimport type { CaretRect } from './caret-coordinates';\nimport { TEXT_COMMANDS, type TextCommand } from './commands';\nimport { formatShortcut } from './shortcut-label';\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n CommandShortcut,\n} from '../ui/command';\nimport { Popover, PopoverAnchor, PopoverContent } from '../ui/popover';\n\nexport function SlashPalette({\n open,\n caret,\n onOpenChange,\n onTextCommand,\n onBlockCommand,\n onShortcuts,\n onDismiss,\n}: {\n open: boolean;\n caret: CaretRect | null;\n onOpenChange: (open: boolean) => void;\n onTextCommand: (command: TextCommand) => void;\n onBlockCommand: (type: string) => void;\n onShortcuts: () => void;\n onDismiss: () => void;\n}) {\n const { blockTypes } = useQuoin();\n const blockOptions = paletteBlocks(blockTypes);\n return (\n <Popover open={open} onOpenChange={onOpenChange}>\n <PopoverAnchor asChild>\n <span\n aria-hidden=\"true\"\n className=\"pointer-events-none absolute\"\n style={caret ? { top: caret.top, left: caret.left, height: caret.height } : { top: 0, left: 0 }}\n />\n </PopoverAnchor>\n <PopoverContent\n aria-label=\"Command palette\"\n align=\"start\"\n side=\"bottom\"\n sideOffset={4}\n className=\"w-72 p-0\"\n onEscapeKeyDown={(event) => {\n event.preventDefault();\n onDismiss();\n }}\n // Radix restores focus to the trigger on close, and this palette has an\n // aria-hidden anchor that cannot hold it, so the restore would drop focus\n // to the body. Both callers refocus the textarea before applying the edit.\n onCloseAutoFocus={(event) => event.preventDefault()}\n >\n <Command label=\"Search commands\">\n <CommandInput placeholder=\"Search commands\" />\n <CommandList>\n <CommandEmpty>No command found.</CommandEmpty>\n <CommandGroup heading=\"Text\">\n {TEXT_COMMANDS.map((command) => (\n <CommandItem\n key={command.id}\n value={`${command.label} ${command.keywords.join(' ')}`}\n onSelect={() => onTextCommand(command)}\n >\n <command.icon aria-hidden=\"true\" />\n <span>{command.label}</span>\n {command.hint ? <CommandShortcut>{formatShortcut(command.hint)}</CommandShortcut> : null}\n </CommandItem>\n ))}\n </CommandGroup>\n <CommandGroup heading=\"Blocks\">\n {blockOptions.map((option) => (\n <CommandItem key={option.type} value={option.label} onSelect={() => onBlockCommand(option.type)}>\n <option.icon aria-hidden=\"true\" />\n <span>{option.label}</span>\n </CommandItem>\n ))}\n </CommandGroup>\n <CommandGroup>\n <CommandItem value=\"keyboard shortcuts help\" onSelect={onShortcuts}>\n <Keyboard aria-hidden=\"true\" />\n <span>Keyboard shortcuts</span>\n </CommandItem>\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n );\n}\n","import {\n Code,\n Heading1,\n Heading2,\n Heading3,\n List,\n ListOrdered,\n ListTodo,\n Minus,\n Quote,\n Table,\n type LucideIcon,\n} from 'lucide-react';\n\n/** A slash-palette entry: how it is shown and searched, and the markdown it inserts. */\nexport type TextCommand = {\n id: string;\n label: string;\n keywords: string[];\n icon: LucideIcon;\n hint?: string;\n insert: string;\n caretOffset: number;\n selectLength?: number;\n /** Needs a blank line above it: a divider after a paragraph line parses as a\n * setext heading, and a GFM table cannot interrupt a paragraph at all. */\n separate: boolean;\n};\n\nconst TABLE = ['| Column | Column |', '| --- | --- |', '| | |'].join('\\n');\n\n/** The built-in slash-palette commands, in display order. */\nexport const TEXT_COMMANDS: TextCommand[] = [\n {\n id: 'heading',\n label: 'Heading',\n keywords: ['h1', 'title', 'heading', 'big'],\n icon: Heading1,\n hint: 'mod+alt+1',\n insert: '# ',\n caretOffset: 2,\n separate: false,\n },\n {\n id: 'subtitle',\n label: 'Subtitle',\n keywords: ['h2', 'subtitle', 'section', 'subheading'],\n icon: Heading2,\n hint: 'mod+alt+2',\n insert: '## ',\n caretOffset: 3,\n separate: false,\n },\n {\n id: 'subsubtitle',\n label: 'Sub-subtitle',\n keywords: ['h3', 'subsubtitle', 'minor'],\n icon: Heading3,\n hint: 'mod+alt+3',\n insert: '### ',\n caretOffset: 4,\n separate: false,\n },\n {\n id: 'bullet',\n label: 'Bullet list',\n keywords: ['bullet', 'unordered', 'ul', 'list', 'point'],\n icon: List,\n hint: 'mod+shift+8',\n insert: '- ',\n caretOffset: 2,\n separate: false,\n },\n {\n id: 'numbered',\n label: 'Numbered list',\n keywords: ['numbered', 'ordered', 'ol', 'steps'],\n icon: ListOrdered,\n hint: 'mod+shift+7',\n insert: '1. ',\n caretOffset: 3,\n separate: false,\n },\n {\n id: 'task',\n label: 'Task list',\n keywords: ['task', 'todo', 'checkbox', 'checklist'],\n icon: ListTodo,\n insert: '- [ ] ',\n caretOffset: 6,\n separate: false,\n },\n {\n id: 'quote',\n label: 'Quote',\n keywords: ['quote', 'blockquote', 'citation'],\n icon: Quote,\n insert: '> ',\n caretOffset: 2,\n separate: false,\n },\n {\n id: 'code',\n label: 'Code block',\n keywords: ['code', 'snippet', 'fence', 'pre'],\n icon: Code,\n insert: '```\\n\\n```',\n caretOffset: 3,\n separate: true,\n },\n {\n id: 'divider',\n label: 'Divider',\n keywords: ['divider', 'rule', 'hr', 'separator', 'break'],\n icon: Minus,\n insert: '---\\n',\n caretOffset: 4,\n separate: true,\n },\n {\n id: 'table',\n label: 'Table',\n keywords: ['table', 'grid', 'rows', 'columns'],\n icon: Table,\n insert: TABLE,\n caretOffset: 2,\n selectLength: 6,\n separate: true,\n },\n];\n","\"use client\"\n\nimport * as React from \"react\"\nimport { Command as CommandPrimitive } from \"cmdk\"\nimport { SearchIcon } from \"lucide-react\"\n\nimport { cn } from \"./cn\"\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n} from \"./dialog\"\n\nfunction Command({\n className,\n ...props\n}: React.ComponentProps<typeof CommandPrimitive>) {\n return (\n <CommandPrimitive\n data-slot=\"command\"\n className={cn(\n \"flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CommandDialog({\n title = \"Command Palette\",\n description = \"Search for a command to run...\",\n children,\n className,\n ...props\n}: React.ComponentProps<typeof Dialog> & {\n title?: string\n description?: string\n className?: string\n}) {\n return (\n <Dialog {...props}>\n <DialogHeader className=\"sr-only\">\n <DialogTitle>{title}</DialogTitle>\n <DialogDescription>{description}</DialogDescription>\n </DialogHeader>\n <DialogContent className={cn(\"overflow-hidden p-0\", className)}>\n <Command className=\"**:data-[slot=command-input-wrapper]:h-12 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]]:px-2 [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5\">\n {children}\n </Command>\n </DialogContent>\n </Dialog>\n )\n}\n\nfunction CommandInput({\n className,\n ...props\n}: React.ComponentProps<typeof CommandPrimitive.Input>) {\n return (\n <div\n data-slot=\"command-input-wrapper\"\n className=\"flex h-9 items-center gap-2 border-b px-3\"\n >\n <SearchIcon className=\"size-4 shrink-0 opacity-50\" />\n <CommandPrimitive.Input\n data-slot=\"command-input\"\n className={cn(\n \"flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-hidden placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50\",\n className\n )}\n {...props}\n />\n </div>\n )\n}\n\nfunction CommandList({\n className,\n ...props\n}: React.ComponentProps<typeof CommandPrimitive.List>) {\n return (\n <CommandPrimitive.List\n data-slot=\"command-list\"\n className={cn(\n \"max-h-[300px] scroll-py-1 overflow-x-hidden overflow-y-auto\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CommandEmpty({\n ...props\n}: React.ComponentProps<typeof CommandPrimitive.Empty>) {\n return (\n <CommandPrimitive.Empty\n data-slot=\"command-empty\"\n className=\"py-6 text-center text-sm\"\n {...props}\n />\n )\n}\n\nfunction CommandGroup({\n className,\n ...props\n}: React.ComponentProps<typeof CommandPrimitive.Group>) {\n return (\n <CommandPrimitive.Group\n data-slot=\"command-group\"\n className={cn(\n \"overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CommandSeparator({\n className,\n ...props\n}: React.ComponentProps<typeof CommandPrimitive.Separator>) {\n return (\n <CommandPrimitive.Separator\n data-slot=\"command-separator\"\n className={cn(\"-mx-1 h-px bg-border\", className)}\n {...props}\n />\n )\n}\n\nfunction CommandItem({\n className,\n ...props\n}: React.ComponentProps<typeof CommandPrimitive.Item>) {\n return (\n <CommandPrimitive.Item\n data-slot=\"command-item\"\n className={cn(\n \"relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CommandShortcut({\n className,\n ...props\n}: React.ComponentProps<\"span\">) {\n return (\n <span\n data-slot=\"command-shortcut\"\n className={cn(\n \"ml-auto text-xs tracking-widest text-muted-foreground\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n Command,\n CommandDialog,\n CommandInput,\n CommandList,\n CommandEmpty,\n CommandGroup,\n CommandItem,\n CommandShortcut,\n CommandSeparator,\n}\n","import * as React from \"react\";\nimport * as PopoverPrimitive from \"@radix-ui/react-popover\";\nimport { cn } from \"./cn\";\n\nfunction Popover(props: React.ComponentProps<typeof PopoverPrimitive.Root>) {\n return <PopoverPrimitive.Root data-slot=\"popover\" {...props} />;\n}\nfunction PopoverTrigger(props: React.ComponentProps<typeof PopoverPrimitive.Trigger>) {\n return <PopoverPrimitive.Trigger data-slot=\"popover-trigger\" {...props} />;\n}\nfunction PopoverAnchor(props: React.ComponentProps<typeof PopoverPrimitive.Anchor>) {\n return <PopoverPrimitive.Anchor data-slot=\"popover-anchor\" {...props} />;\n}\nfunction PopoverContent({ className, align = \"center\", sideOffset = 4, ...props }: React.ComponentProps<typeof PopoverPrimitive.Content>) {\n return (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n data-slot=\"popover-content\"\n align={align}\n sideOffset={sideOffset}\n className={cn(\n \"quoin bg-popover text-popover-foreground z-50 w-72 origin-(--radix-popover-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden\",\n className,\n )}\n {...props}\n />\n </PopoverPrimitive.Portal>\n );\n}\nexport { Popover, PopoverAnchor, PopoverTrigger, PopoverContent };\n","import * as React from 'react';\nimport { applyEdit, type Edit } from './edit';\nimport { indentList } from './indent-list';\nimport { toggleLinePrefix, type LinePrefix } from './line-toggles';\nimport { continueList } from './list-continuation';\nimport { shouldOpenPalette } from './slash-trigger';\nimport { linkPaste, wrapSelection, type WrapKind } from './wrap-selection';\n\nconst WRAP: Record<string, WrapKind> = { b: 'bold', i: 'italic', e: 'code', k: 'link' };\n\n// Shift turns the 8 key into \"*\", so the physical code is the only stable match.\nconst HEADING: Record<string, LinePrefix> = { Digit1: 'h1', Digit2: 'h2', Digit3: 'h3' };\nconst LIST: Record<string, LinePrefix> = { Digit7: 'ordered', Digit8: 'bullet' };\n\n/** Keyboard and paste handlers that give a plain textarea markdown shortcuts, list continuation, Tab indent and the slash palette trigger. */\nexport function useMarkdownKeymap({\n commit,\n onOpenPalette,\n}: {\n commit: (markdown: string) => void;\n onOpenPalette: () => void;\n}) {\n const onKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLTextAreaElement>) => {\n const el = event.currentTarget;\n const { value, selectionStart, selectionEnd } = el;\n const mod = event.metaKey || event.ctrlKey;\n\n const run = (edit: Edit | null) => {\n if (!edit) return;\n event.preventDefault();\n applyEdit(el, edit, commit);\n };\n\n if (mod && event.altKey) {\n const kind = HEADING[event.code];\n if (kind) run(toggleLinePrefix(kind, value, selectionStart, selectionEnd));\n return;\n }\n\n if (mod && event.shiftKey) {\n const kind = LIST[event.code];\n if (kind) run(toggleLinePrefix(kind, value, selectionStart, selectionEnd));\n return;\n }\n\n if (mod) {\n const kind = WRAP[event.key.toLowerCase()];\n if (kind) run(wrapSelection(kind, value, selectionStart, selectionEnd));\n return;\n }\n\n if (event.key === '/') {\n if (!shouldOpenPalette(value, selectionStart, selectionEnd)) return;\n event.preventDefault();\n onOpenPalette();\n return;\n }\n\n if (event.key === 'Enter' && !event.shiftKey) {\n run(continueList(value, selectionStart, 'Enter'));\n return;\n }\n\n if (event.key === 'Backspace' && selectionStart === selectionEnd) {\n run(continueList(value, selectionStart, 'Backspace'));\n return;\n }\n\n if (event.key === 'Tab') {\n run(indentList(value, selectionStart, selectionEnd, event.shiftKey ? -1 : 1));\n }\n },\n [commit, onOpenPalette],\n );\n\n const onPaste = React.useCallback(\n (event: React.ClipboardEvent<HTMLTextAreaElement>) => {\n const el = event.currentTarget;\n const edit = linkPaste(\n el.value,\n el.selectionStart,\n el.selectionEnd,\n event.clipboardData.getData('text/plain'),\n );\n if (!edit) return;\n event.preventDefault();\n applyEdit(el, edit, commit);\n },\n [commit],\n );\n\n return { onKeyDown, onPaste };\n}\n","import type { Edit } from './edit';\nimport { insideFence, lineAt, type Line } from './line-at';\n\nexport const LIST_MARKER = /^(\\s*)((?:[-*+] \\[[ xX]\\] )|(?:[-*+] )|(?:\\d+[.)] )|(?:> ))(.*)$/;\n\nconst INDENT = ' ';\n\nfunction nextMarker(marker: string): string {\n const ordered = /^(\\d+)([.)] )$/.exec(marker);\n if (ordered) return `${Number(ordered[1]) + 1}${ordered[2]}`;\n const task = /^([-*+]) \\[[ xX]\\] $/.exec(marker);\n if (task) return `${task[1]} [ ] `;\n return marker;\n}\n\n// Both the dead item on Enter and the caret at the content start on Backspace\n// mean the same thing: climb out one level, or drop the marker at the top.\nfunction climbOut(value: string, line: Line, indent: string, marker: string, content: string): Edit {\n const outdent = indent.length >= INDENT.length;\n\n if (outdent) {\n const text = indent.slice(INDENT.length) + marker + content;\n const at = line.start + indent.length - INDENT.length + marker.length;\n return {\n value: value.slice(0, line.start) + text + value.slice(line.end),\n selectionStart: at,\n selectionEnd: at,\n };\n }\n\n // A stripped marker with only a single newline above it reads to CommonMark\n // as a lazy continuation of the previous list item's paragraph, not a new\n // block, so a blank line is needed whenever that previous line is a list item.\n const leavesList = line.start > 0 && LIST_MARKER.test(lineAt(value, line.start - 1).text);\n const text = leavesList ? `\\n${content}` : content;\n const at = leavesList ? line.start + 1 : line.start;\n\n return {\n value: value.slice(0, line.start) + text + value.slice(line.end),\n selectionStart: at,\n selectionEnd: at,\n };\n}\n\n/** Continues a list item on Enter, or climbs out of the list on an empty item or Backspace at the marker; returns null when the caret is not in a list item or is inside a code fence, so the default key behaviour runs. */\nexport function continueList(\n value: string,\n caret: number,\n key: 'Enter' | 'Backspace',\n): Edit | null {\n if (insideFence(value, caret)) return null;\n\n const line = lineAt(value, caret);\n const match = LIST_MARKER.exec(line.text);\n if (!match) return null;\n\n const [, indent, marker, content] = match;\n\n if (key === 'Backspace') {\n if (caret !== line.start + indent.length + marker.length) return null;\n return climbOut(value, line, indent, marker, content);\n }\n\n if (content.trim() === '') return climbOut(value, line, indent, marker, content);\n\n const inserted = `\\n${indent}${nextMarker(marker)}`;\n const at = caret + inserted.length;\n return {\n value: value.slice(0, caret) + inserted + value.slice(caret),\n selectionStart: at,\n selectionEnd: at,\n };\n}\n","import type { Edit } from './edit';\nimport { insideFence, lineAt } from './line-at';\nimport { LIST_MARKER } from './list-continuation';\n\nconst INDENT = ' ';\n\nfunction indentOf(text: string): number {\n return /^\\s*/.exec(text)?.[0].length ?? 0;\n}\n\n// Indenting more than one level past the line above turns a list item into an\n// indented code block, so the first line of the range is capped against it.\nfunction shift(text: string, direction: 1 | -1, cap: number | undefined): string {\n const current = indentOf(text);\n if (direction === -1) return text.slice(Math.min(current, INDENT.length));\n if (cap !== undefined && current >= cap + INDENT.length) return text;\n return INDENT + text;\n}\n\n/** Indents or outdents the selected list items; returns null when the selection is not entirely list items, is inside a code fence, or cannot move further, so Tab keeps its default behaviour. */\nexport function indentList(\n value: string,\n selectionStart: number,\n selectionEnd: number,\n direction: 1 | -1,\n): Edit | null {\n if (insideFence(value, selectionStart)) return null;\n\n const first = lineAt(value, selectionStart);\n const last = lineAt(value, selectionEnd);\n const block = value.slice(first.start, last.end);\n const lines = block.split('\\n');\n if (!lines.every((text) => LIST_MARKER.test(text))) return null;\n\n const cap = first.start === 0 ? 0 : indentOf(lineAt(value, first.start - 1).text);\n const shifted = lines.map((text, i) => shift(text, direction, i === 0 ? cap : undefined));\n if (shifted.every((text, i) => text === lines[i])) return null;\n\n const joined = shifted.join('\\n');\n return {\n value: value.slice(0, first.start) + joined + value.slice(last.end),\n selectionStart: selectionStart + (shifted[0].length - lines[0].length),\n selectionEnd: selectionEnd + (joined.length - block.length),\n };\n}\n","import type { Edit } from './edit';\nimport { insideFence, isFenceDelimiter, lineAt } from './line-at';\n\n/** A line-level markdown prefix: a heading level, a bullet or a numbered item. */\nexport type LinePrefix = 'h1' | 'h2' | 'h3' | 'bullet' | 'ordered';\n\nconst EXISTING = /^(\\s*)(?:#{1,6} |[-*+] \\[[ xX]\\] |[-*+] |\\d+[.)] )?/;\n\nconst PREFIX: Record<LinePrefix, (index: number) => string> = {\n h1: () => '# ',\n h2: () => '## ',\n h3: () => '### ',\n bullet: () => '- ',\n ordered: (index) => `${index + 1}. `,\n};\n\nconst CARRIES: Record<LinePrefix, RegExp> = {\n h1: /^\\s*# /,\n h2: /^\\s*## /,\n h3: /^\\s*### /,\n bullet: /^\\s*[-*+] /,\n ordered: /^\\s*\\d+[.)] /,\n};\n\n/** Adds the prefix to every line in the selection, or removes it when every line already carries it; fenced code is left alone. */\nexport function toggleLinePrefix(\n kind: LinePrefix,\n value: string,\n selectionStart: number,\n selectionEnd: number,\n): Edit {\n const first = lineAt(value, selectionStart);\n const last = lineAt(value, selectionEnd);\n const block = value.slice(first.start, last.end);\n const lines = block.split('\\n');\n\n let offset = first.start;\n const eligible = lines.map((text) => {\n const at = offset;\n offset += text.length + 1;\n return !insideFence(value, at) && !isFenceDelimiter(text);\n });\n\n const carried = lines.every((text, i) => !eligible[i] || CARRIES[kind].test(text));\n\n const rewritten = lines.map((text, i) => {\n if (!eligible[i]) return text;\n const match = EXISTING.exec(text);\n const indent = match?.[1] ?? '';\n const body = text.slice(match?.[0].length ?? 0);\n return carried ? indent + body : indent + PREFIX[kind](i) + body;\n });\n\n const joined = rewritten.join('\\n');\n const next = value.slice(0, first.start) + joined + value.slice(last.end);\n\n if (selectionStart !== selectionEnd) {\n return { value: next, selectionStart: first.start, selectionEnd: first.start + joined.length };\n }\n\n const caret = Math.max(first.start, selectionStart + (rewritten[0].length - lines[0].length));\n return { value: next, selectionStart: caret, selectionEnd: caret };\n}\n","import { insideFence } from './line-at';\n\n/** Whether typing \"/\" here should open the command palette: only at a word start, with no selection and outside a code fence. */\nexport function shouldOpenPalette(\n value: string,\n selectionStart: number,\n selectionEnd: number,\n): boolean {\n if (selectionStart !== selectionEnd) return false;\n if (insideFence(value, selectionStart)) return false;\n if (selectionStart === 0) return true;\n\n const previous = value[selectionStart - 1];\n return previous === '\\n' || previous === ' ' || previous === '\\t';\n}\n","import type { Edit } from './edit';\n\n/** An inline markdown wrapper: bold, italic, code or a link. */\nexport type WrapKind = 'bold' | 'italic' | 'code' | 'link';\n\nconst DELIMITER: Record<Exclude<WrapKind, 'link'>, string> = {\n bold: '**',\n italic: '_',\n code: '`',\n};\n\nconst WHOLE_LINK = /^\\[([^\\]]*)\\]\\(([^)]*)\\)$/;\nconst BARE_URL = /^https?:\\/\\/[^\\s]+$/;\n\nfunction unwrap(value: string, start: number, end: number, delimiter: string): Edit | null {\n const selected = value.slice(start, end);\n const width = delimiter.length;\n\n if (selected.length >= 2 * width && selected.startsWith(delimiter) && selected.endsWith(delimiter)) {\n const inner = selected.slice(width, selected.length - width);\n return {\n value: value.slice(0, start) + inner + value.slice(end),\n selectionStart: start,\n selectionEnd: start + inner.length,\n };\n }\n\n const outside =\n start >= width &&\n value.slice(start - width, start) === delimiter &&\n value.slice(end, end + width) === delimiter;\n\n if (!outside) return null;\n\n return {\n value: value.slice(0, start - width) + selected + value.slice(end + width),\n selectionStart: start - width,\n selectionEnd: start - width + selected.length,\n };\n}\n\nfunction link(value: string, start: number, end: number): Edit {\n const selected = value.slice(start, end);\n const whole = WHOLE_LINK.exec(selected);\n\n if (whole) {\n const text = whole[1];\n return {\n value: value.slice(0, start) + text + value.slice(end),\n selectionStart: start,\n selectionEnd: start + text.length,\n };\n }\n\n const opened = `[${selected}](`;\n const at = selected === '' ? start + 1 : start + opened.length;\n return {\n value: value.slice(0, start) + opened + ')' + value.slice(end),\n selectionStart: at,\n selectionEnd: at,\n };\n}\n\n/** Wraps the selection in the markers for the kind, or removes them when it is already wrapped. */\nexport function wrapSelection(\n kind: WrapKind,\n value: string,\n selectionStart: number,\n selectionEnd: number,\n): Edit {\n if (kind === 'link') return link(value, selectionStart, selectionEnd);\n\n const delimiter = DELIMITER[kind];\n const stripped = unwrap(value, selectionStart, selectionEnd, delimiter);\n if (stripped) return stripped;\n\n const selected = value.slice(selectionStart, selectionEnd);\n\n if (kind === 'code' && selected.includes('\\n')) {\n const at = selectionStart + 4;\n return {\n value: value.slice(0, selectionStart) + '```\\n' + selected + '\\n```' + value.slice(selectionEnd),\n selectionStart: at,\n selectionEnd: at + selected.length,\n };\n }\n\n const at = selectionStart + delimiter.length;\n return {\n value: value.slice(0, selectionStart) + delimiter + selected + delimiter + value.slice(selectionEnd),\n selectionStart: at,\n selectionEnd: at + selected.length,\n };\n}\n\n/** Turns a pasted URL over a selection into a markdown link; returns null when nothing is selected or the paste is not a bare URL, so the paste goes through unchanged. */\nexport function linkPaste(\n value: string,\n selectionStart: number,\n selectionEnd: number,\n pasted: string,\n): Edit | null {\n if (selectionStart === selectionEnd) return null;\n\n const url = pasted.trim();\n if (!BARE_URL.test(url)) return null;\n\n const inserted = `[${value.slice(selectionStart, selectionEnd)}](${url})`;\n const at = selectionStart + inserted.length;\n return {\n value: value.slice(0, selectionStart) + inserted + value.slice(selectionEnd),\n selectionStart: at,\n selectionEnd: at,\n };\n}\n","import * as React from 'react';\nimport { caretRect, type CaretRect } from './caret-coordinates';\n\nexport function useSlashPalette(ref: React.RefObject<HTMLTextAreaElement | null>) {\n const [open, setOpen] = React.useState(false);\n const [caret, setCaret] = React.useState<CaretRect | null>(null);\n const offsetRef = React.useRef(0);\n\n const openAtCaret = React.useCallback(() => {\n const el = ref.current;\n if (!el) return;\n offsetRef.current = el.selectionStart;\n setCaret(caretRect(el));\n setOpen(true);\n }, [ref]);\n\n return { open, setOpen, caret, offsetRef, openAtCaret };\n}\n","type CopiedProperty =\n | 'boxSizing'\n | 'fontFamily'\n | 'fontSize'\n | 'fontStyle'\n | 'fontWeight'\n | 'letterSpacing'\n | 'lineHeight'\n | 'paddingBottom'\n | 'paddingLeft'\n | 'paddingRight'\n | 'paddingTop'\n | 'textIndent'\n | 'textTransform'\n | 'wordBreak'\n | 'wordSpacing'\n | 'borderBottomWidth'\n | 'borderLeftWidth'\n | 'borderRightWidth'\n | 'borderTopWidth';\n\nconst COPIED: CopiedProperty[] = [\n 'boxSizing',\n 'fontFamily',\n 'fontSize',\n 'fontStyle',\n 'fontWeight',\n 'letterSpacing',\n 'lineHeight',\n 'paddingBottom',\n 'paddingLeft',\n 'paddingRight',\n 'paddingTop',\n 'textIndent',\n 'textTransform',\n 'wordBreak',\n 'wordSpacing',\n 'borderBottomWidth',\n 'borderLeftWidth',\n 'borderRightWidth',\n 'borderTopWidth',\n];\n\n/** The caret's position and line height, in pixels relative to the textarea's top left corner. */\nexport type CaretRect = { top: number; left: number; height: number };\n\n/** A textarea exposes no caret geometry, so the text before the caret is laid\n * out again in a hidden div that copies the box's own metrics, and a marker at\n * the end of it is measured. Returns null when the textarea is not laid out\n * (hidden or detached), because there is nothing to measure. */\nexport function caretRect(el: HTMLTextAreaElement): CaretRect | null {\n if (el.offsetWidth === 0) return null;\n\n const style = window.getComputedStyle(el);\n const mirror = document.createElement('div');\n for (const property of COPIED) mirror.style[property] = style[property];\n mirror.style.position = 'absolute';\n mirror.style.top = '0';\n mirror.style.left = '-9999px';\n mirror.style.visibility = 'hidden';\n mirror.style.whiteSpace = 'pre-wrap';\n mirror.style.overflowWrap = 'break-word';\n mirror.style.width = `${el.clientWidth}px`;\n mirror.textContent = el.value.slice(0, el.selectionStart);\n\n const marker = document.createElement('span');\n marker.textContent = '\\u200b';\n mirror.appendChild(marker);\n document.body.appendChild(mirror);\n\n const top = marker.offsetTop;\n const left = marker.offsetLeft;\n const height = marker.offsetHeight || Number.parseFloat(style.lineHeight) || 0;\n mirror.remove();\n\n if (height === 0) return null;\n return { top: top - el.scrollTop, left, height };\n}\n","import * as React from 'react';\n\n/** Height follows the content, and is recomputed when the box gets narrower or\n * wider, because a re-wrap changes the line count without changing the value.\n * Only a width change refits: reacting to the height this hook just set would\n * feed the observer its own output. */\nexport function useAutoGrow<T extends HTMLTextAreaElement>(value: string) {\n const ref = React.useRef<T>(null);\n const lastWidth = React.useRef<number | null>(null);\n\n // Measuring means collapsing to \"auto\" first, which shrinks the page enough that\n // the browser clamps the scroll position, and growing back does not undo that.\n // Both steps run before paint, so restoring the scroll here is not visible.\n const fit = React.useCallback(() => {\n const el = ref.current;\n if (!el) return;\n const scroller = document.scrollingElement ?? document.documentElement;\n const scrollTop = scroller.scrollTop;\n el.style.height = 'auto';\n if (el.scrollHeight > 0) el.style.height = `${el.scrollHeight}px`;\n if (scroller.scrollTop !== scrollTop) scroller.scrollTop = scrollTop;\n }, []);\n\n React.useLayoutEffect(fit, [fit, value]);\n\n React.useEffect(() => {\n const el = ref.current;\n if (!el || typeof ResizeObserver === 'undefined') return;\n const observer = new ResizeObserver(([entry]) => {\n const width = entry.contentRect.width;\n if (width === lastWidth.current) return;\n lastWidth.current = width;\n fit();\n });\n observer.observe(el);\n return () => observer.disconnect();\n }, [fit]);\n\n return ref;\n}\n","export const str = (v: unknown) => (typeof v === 'string' ? v : '');\n","\"use client\";\n\nimport * as React from \"react\";\nimport * as SelectPrimitive from \"@radix-ui/react-select\";\nimport { CheckIcon, ChevronDownIcon, ChevronUpIcon } from \"lucide-react\";\nimport { cn } from \"./cn\";\nimport { TAP_TARGET_FLOOR } from \"./touch-target\";\n\nfunction Select(props: React.ComponentProps<typeof SelectPrimitive.Root>) {\n return <SelectPrimitive.Root data-slot=\"select\" {...props} />;\n}\nfunction SelectValue(props: React.ComponentProps<typeof SelectPrimitive.Value>) {\n return <SelectPrimitive.Value data-slot=\"select-value\" {...props} />;\n}\nfunction SelectTrigger({ className, children, ...props }: React.ComponentProps<typeof SelectPrimitive.Trigger>) {\n return (\n <SelectPrimitive.Trigger\n data-slot=\"select-trigger\"\n className={cn(\n \"border-input data-[placeholder]:text-muted-foreground flex h-9 w-full cursor-pointer items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm shadow-xs outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0\",\n TAP_TARGET_FLOOR,\n className,\n )}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <ChevronDownIcon className=\"size-4 opacity-50\" />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n );\n}\nfunction SelectContent({ className, children, position = \"popper\", ...props }: React.ComponentProps<typeof SelectPrimitive.Content>) {\n return (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n data-slot=\"select-content\"\n className={cn(\n \"quoin bg-popover text-popover-foreground relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-md border shadow-md\",\n position === \"popper\" && \"data-[side=bottom]:translate-y-1\",\n className,\n )}\n position={position}\n {...props}\n >\n <SelectPrimitive.ScrollUpButton className=\"flex cursor-default items-center justify-center py-1\">\n <ChevronUpIcon className=\"size-4\" />\n </SelectPrimitive.ScrollUpButton>\n <SelectPrimitive.Viewport className={cn(\"p-1\", position === \"popper\" && \"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]\")}>\n {children}\n </SelectPrimitive.Viewport>\n <SelectPrimitive.ScrollDownButton className=\"flex cursor-default items-center justify-center py-1\">\n <ChevronDownIcon className=\"size-4\" />\n </SelectPrimitive.ScrollDownButton>\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n );\n}\nfunction SelectItem({ className, children, ...props }: React.ComponentProps<typeof SelectPrimitive.Item>) {\n return (\n <SelectPrimitive.Item\n data-slot=\"select-item\"\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n TAP_TARGET_FLOOR,\n className,\n )}\n {...props}\n >\n <span className=\"absolute right-2 flex size-3.5 items-center justify-center\">\n <SelectPrimitive.ItemIndicator>\n <CheckIcon className=\"size-4\" />\n </SelectPrimitive.ItemIndicator>\n </span>\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n </SelectPrimitive.Item>\n );\n}\nexport { Select, SelectValue, SelectTrigger, SelectContent, SelectItem };\n","import * as React from \"react\";\nimport { cn } from \"./cn\";\n\nfunction Textarea({ className, ...props }: React.ComponentProps<\"textarea\">) {\n return (\n <textarea\n data-slot=\"textarea\"\n className={cn(\n \"border-input placeholder:text-muted-foreground flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none disabled:pointer-events-none disabled:opacity-50 md:text-sm\",\n \"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]\",\n \"aria-invalid:ring-destructive/20 aria-invalid:border-destructive\",\n className,\n )}\n {...props}\n />\n );\n}\n\nexport { Textarea };\n","'use client';\n\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../ui/select';\nimport { Textarea } from '../ui/textarea';\nimport type { BlockEditorProps } from '../types';\nimport { str } from './str';\n\nconst CALLOUT_TONES = ['info', 'tip', 'warning', 'success', 'danger'] as const;\n\nexport function CalloutBlockEditor({ data, onChange }: BlockEditorProps) {\n const set = (patch: Record<string, unknown>) => onChange({ ...data, ...patch });\n\n return (\n <div className=\"flex flex-col gap-2\">\n <div className=\"flex flex-col gap-1\">\n <span className=\"text-sm font-medium leading-none\">Tone</span>\n <Select value={str(data.tone) || 'info'} onValueChange={(v) => set({ tone: v })}>\n <SelectTrigger aria-label=\"Callout tone\" className=\"w-40 capitalize\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {CALLOUT_TONES.map((t) => (\n <SelectItem key={t} value={t} className=\"capitalize\">\n {t}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <label className=\"flex flex-col gap-1\">\n <span className=\"text-sm font-medium leading-none\">Callout text</span>\n <Textarea value={str(data.body)} onChange={(e) => set({ body: e.target.value })} className=\"text-sm\" />\n </label>\n </div>\n );\n}\n","import * as React from \"react\";\nimport { cn } from \"./cn\";\nimport { TAP_TARGET_FLOOR } from \"./touch-target\";\n\nfunction Input({ className, type, ...props }: React.ComponentProps<\"input\">) {\n return (\n <input\n type={type}\n data-slot=\"input\"\n className={cn(\n \"border-input placeholder:text-muted-foreground flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:opacity-50 md:text-sm\",\n \"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]\",\n \"aria-invalid:ring-destructive/20 aria-invalid:border-destructive\",\n TAP_TARGET_FLOOR,\n className,\n )}\n {...props}\n />\n );\n}\n\nexport { Input };\n","'use client';\n\nimport { Input } from '../ui/input';\nimport { Textarea } from '../ui/textarea';\nimport type { BlockEditorProps } from '../types';\nimport { str } from './str';\n\nexport function CodeBlockEditor({ data, onChange }: BlockEditorProps) {\n const set = (patch: Record<string, unknown>) => onChange({ ...data, ...patch });\n\n return (\n <div className=\"flex flex-col gap-2\">\n <label className=\"flex flex-col gap-1\">\n <span className=\"text-sm font-medium leading-none\">Language</span>\n <Input\n aria-label=\"Language\"\n value={str(data.language)}\n onChange={(e) => set({ language: e.target.value })}\n className=\"text-sm\"\n />\n </label>\n <label className=\"flex flex-col gap-1\">\n <span className=\"text-sm font-medium leading-none\">Code</span>\n <Textarea\n aria-label=\"Code\"\n value={str(data.code)}\n onChange={(e) => set({ code: e.target.value })}\n className=\"min-h-32 font-mono text-sm\"\n />\n </label>\n </div>\n );\n}\n","'use client';\n\nimport { useEffect, useRef } from 'react';\nimport { useQuoin } from '../context';\nimport { Input } from '../ui/input';\nimport { UploadField } from '../upload/UploadField';\nimport type { BlockEditorProps } from '../types';\nimport { str } from './str';\nimport { intrinsicSize } from './intrinsic-size';\n\nexport function ImageBlockEditor({ data, onChange }: BlockEditorProps) {\n const { resolveAssetUrl } = useQuoin();\n // Read through a ref: measuring the upload is async, and the alt/caption fields\n // stay editable while it runs.\n const latest = useRef(data);\n useEffect(() => {\n latest.current = data;\n });\n const set = (patch: Record<string, unknown>) => onChange({ ...latest.current, ...patch });\n\n const onUploaded = async (r: { storageKey: string }) => {\n const src = resolveAssetUrl(r.storageKey);\n const size = src ? await intrinsicSize(src) : null;\n set({ storageKey: r.storageKey, ...size });\n };\n\n return (\n <div className=\"flex flex-col gap-2\">\n <UploadField category=\"image\" label=\"Upload image\" onUploaded={onUploaded} />\n <label className=\"flex flex-col gap-1\">\n <span className=\"text-sm font-medium leading-none\">Alt text</span>\n <Input\n aria-label=\"Image alt text\"\n value={str(data.alt)}\n onChange={(e) => set({ alt: e.target.value })}\n className=\"text-sm\"\n />\n </label>\n <label className=\"flex flex-col gap-1\">\n <span className=\"text-sm font-medium leading-none\">Caption (optional)</span>\n <Input\n aria-label=\"Image caption\"\n value={str(data.caption)}\n onChange={(e) => set({ caption: e.target.value })}\n className=\"text-sm\"\n />\n </label>\n {str(data.storageKey) && <span className=\"text-xs text-muted-foreground\">Image attached ✓</span>}\n </div>\n );\n}\n","'use client';\n\nimport * as React from 'react';\nimport { useQuoin } from '../context';\nimport type { UploadResult } from '../types';\nimport { FilePickerButton } from './FilePickerButton';\n\n/** Disables itself both while an upload is in flight and when the host configured no `upload` function. */\nexport function UploadField({\n category,\n label,\n accept,\n onUploaded,\n}: {\n category: string;\n label: string;\n accept?: string;\n onUploaded: (result: UploadResult) => void;\n}) {\n const { upload, onError } = useQuoin();\n const [busy, setBusy] = React.useState(false);\n const [error, setError] = React.useState<string | null>(null);\n\n async function run(file: File) {\n if (!upload) return;\n setBusy(true);\n setError(null);\n let result: UploadResult;\n try {\n result = await upload(file, category);\n } catch (cause) {\n setError((cause instanceof Error && cause.message) || 'Upload failed.');\n setBusy(false);\n return;\n }\n setBusy(false);\n try {\n onUploaded(result);\n } catch (cause) {\n onError(cause instanceof Error ? cause : new Error(String(cause)));\n }\n }\n\n return (\n <div className=\"flex flex-col items-start gap-1.5\">\n <FilePickerButton\n label={label}\n accept={accept}\n disabled={busy || !upload}\n onPick={(file) => void run(file)}\n />\n {!upload && (\n <span role=\"note\" className=\"text-xs text-muted-foreground\">\n Uploads are not configured for this editor.\n </span>\n )}\n {busy && <span role=\"status\" className=\"text-xs text-muted-foreground\">Uploading...</span>}\n {error && (\n <span role=\"alert\" className=\"text-xs text-destructive\">\n {error}\n </span>\n )}\n </div>\n );\n}\n","export type IntrinsicSize = { width: number; height: number };\n\n/** Persisted onto the block so the reader can reserve the box before the bytes\n * arrive. Resolves null rather than rejecting: a drop without them still renders,\n * it just reflows. */\nexport function intrinsicSize(src: string): Promise<IntrinsicSize | null> {\n return new Promise((resolve) => {\n if (typeof window === 'undefined') return resolve(null);\n const img = new window.Image();\n img.onload = () => resolve({ width: img.naturalWidth, height: img.naturalHeight });\n img.onerror = () => resolve(null);\n img.src = src;\n });\n}\n","'use client';\n\nimport { UploadField } from '../upload/UploadField';\nimport type { BlockEditorProps } from '../types';\nimport { str } from './str';\n\nexport function FileBlockEditor({ data, onChange }: BlockEditorProps) {\n const set = (patch: Record<string, unknown>) => onChange({ ...data, ...patch });\n\n return (\n <div className=\"flex flex-col gap-2\">\n <UploadField\n category=\"file\"\n label=\"Upload file\"\n onUploaded={(r) => set({ storageKey: r.storageKey, filename: r.filename, size: r.size })}\n />\n {str(data.filename) && <span className=\"text-xs text-muted-foreground\">{str(data.filename)} ✓</span>}\n </div>\n );\n}\n","'use client';\n\nimport { useQuoin } from '../context';\nimport type { BlockPreviewProps } from '../types';\nimport { str } from './str';\n\nconst HINT = 'text-sm text-muted-foreground';\n\nconst TONE_BORDER: Record<string, string> = {\n info: 'border-primary',\n tip: 'border-accent-foreground',\n warning: 'border-muted-foreground',\n success: 'border-secondary-foreground',\n danger: 'border-destructive',\n};\n\nexport function MarkdownPreview({ data }: BlockPreviewProps) {\n const markdown = str(data.markdown);\n if (markdown.trim() === '') return <p className={HINT}>Empty markdown block</p>;\n return <div className=\"whitespace-pre-wrap text-base leading-7\">{markdown}</div>;\n}\n\nexport function CodePreview({ data }: BlockPreviewProps) {\n const code = str(data.code);\n if (code.trim() === '') return <p className={HINT}>Empty code block</p>;\n return (\n <pre className=\"overflow-x-auto rounded-md bg-muted p-3 text-sm\">\n <code>{code}</code>\n </pre>\n );\n}\n\nexport function ImagePreview({ data }: BlockPreviewProps) {\n const { resolveAssetUrl } = useQuoin();\n const key = str(data.storageKey);\n // Guard on the key, not the resolved URL: a prefixing resolver turns an empty key into a truthy, dead address.\n if (key === '') return <p className={HINT}>No image chosen</p>;\n return <img src={resolveAssetUrl(key)} alt={str(data.alt)} className=\"max-w-full rounded-md\" />;\n}\n\nexport function FilePreview({ data }: BlockPreviewProps) {\n const name = str(data.filename);\n if (name === '') return <p className={HINT}>No file chosen</p>;\n return <p className=\"text-sm\">{name}</p>;\n}\n\nexport function CalloutPreview({ data }: BlockPreviewProps) {\n const body = str(data.body);\n if (body.trim() === '') return <p className={HINT}>Empty callout</p>;\n const tone = str(data.tone) || 'info';\n const border = TONE_BORDER[tone] ?? 'border-border';\n return (\n <div data-tone={tone} className={`rounded-md border-l-4 ${border} bg-muted/50 p-3 text-sm`}>\n {body}\n </div>\n );\n}\n","import * as React from 'react';\nimport type { QuoinBlock } from '../types';\nimport { newBlockId } from './new-block-id';\n\n/** Handed back by `remove` and accepted by `undo` to restore that one block. */\nexport type UndoToken = number;\n\ntype Removed = { block: QuoinBlock; index: number };\n\ntype State = {\n blocks: QuoinBlock[];\n removals: Map<UndoToken, Removed>;\n};\n\ntype Action =\n | { type: 'insertAt'; index: number; block: QuoinBlock }\n | { type: 'update'; id: string; data: Record<string, unknown> }\n | { type: 'remove'; id: string; token: UndoToken }\n | { type: 'undo'; token: UndoToken }\n | { type: 'move'; index: number; dir: -1 | 1 }\n | { type: 'reorder'; from: number; to: number }\n | { type: 'reset'; blocks: QuoinBlock[] };\n\nlet removalSeq = 0;\n\nfunction reducer(state: State, action: Action): State {\n switch (action.type) {\n case 'insertAt': {\n const next = [...state.blocks];\n next.splice(Math.max(0, Math.min(action.index, state.blocks.length)), 0, action.block);\n return { ...state, blocks: next };\n }\n case 'update': {\n return {\n ...state,\n blocks: state.blocks.map((b) => (b.id === action.id ? { ...b, data: action.data } : b)),\n };\n }\n case 'remove': {\n const index = state.blocks.findIndex((b) => b.id === action.id);\n if (index === -1) return state;\n const removals = new Map(state.removals);\n removals.set(action.token, { block: state.blocks[index], index });\n return { blocks: state.blocks.filter((b) => b.id !== action.id), removals };\n }\n case 'undo': {\n const removal = state.removals.get(action.token);\n if (!removal) return state;\n const next = [...state.blocks];\n next.splice(Math.min(removal.index, state.blocks.length), 0, removal.block);\n const removals = new Map(state.removals);\n removals.delete(action.token);\n return { blocks: next, removals };\n }\n case 'move': {\n const j = action.index + action.dir;\n if (j < 0 || j >= state.blocks.length) return state;\n const next = [...state.blocks];\n [next[action.index], next[j]] = [next[j], next[action.index]];\n return { ...state, blocks: next };\n }\n case 'reorder': {\n const { from, to } = action;\n if (from < 0 || to < 0 || from >= state.blocks.length || to >= state.blocks.length) return state;\n const next = [...state.blocks];\n const [moved] = next.splice(from, 1);\n next.splice(to, 0, moved);\n return { ...state, blocks: next };\n }\n case 'reset':\n return { blocks: action.blocks, removals: new Map() };\n }\n}\n\n/** The document plus every way to change it; `reset` replaces the whole document and voids outstanding undo tokens. */\nexport type BlockList = {\n blocks: QuoinBlock[];\n insertAt: (index: number, type: string, data?: Record<string, unknown>) => string;\n update: (id: string, data: Record<string, unknown>) => void;\n remove: (id: string) => UndoToken;\n undo: (token: UndoToken) => void;\n move: (index: number, dir: -1 | 1) => void;\n reorder: (from: number, to: number) => void;\n reset: (blocks: QuoinBlock[]) => void;\n};\n\n/** Holds a document in a reducer and returns its blocks with insert, update, remove, undo, move, reorder and reset. Reads `initial` once. */\nexport function useBlockList(initial: QuoinBlock[]): BlockList {\n const [state, dispatch] = React.useReducer(reducer, { blocks: initial, removals: new Map() });\n\n const insertAt = React.useCallback(\n (index: number, type: string, data: Record<string, unknown> = {}): string => {\n const id = newBlockId();\n dispatch({ type: 'insertAt', index, block: { id, type, data } });\n return id;\n },\n [],\n );\n\n const update = React.useCallback((id: string, data: Record<string, unknown>) => {\n dispatch({ type: 'update', id, data });\n }, []);\n\n const remove = React.useCallback((id: string): UndoToken => {\n removalSeq += 1;\n const token = removalSeq;\n dispatch({ type: 'remove', id, token });\n return token;\n }, []);\n\n const undo = React.useCallback((token: UndoToken) => {\n dispatch({ type: 'undo', token });\n }, []);\n\n const move = React.useCallback((index: number, dir: -1 | 1) => {\n dispatch({ type: 'move', index, dir });\n }, []);\n\n const reorder = React.useCallback((from: number, to: number) => {\n dispatch({ type: 'reorder', from, to });\n }, []);\n\n const reset = React.useCallback((blocks: QuoinBlock[]) => {\n dispatch({ type: 'reset', blocks });\n }, []);\n\n return { blocks: state.blocks, insertAt, update, remove, undo, move, reorder, reset };\n}\n","/**\n * A fresh block id that cannot collide with one already in a persisted document.\n * It holds no counter, because a counter restarts on every page load and would\n * re-mint ids a host has stored.\n */\nexport function newBlockId(): string {\n const webCrypto = globalThis.crypto;\n if (webCrypto && typeof webCrypto.randomUUID === 'function') return webCrypto.randomUUID();\n // randomUUID is absent in insecure contexts and older runtimes.\n const random = () => Math.random().toString(36).slice(2, 10);\n return `blk-${Date.now().toString(36)}-${random()}${random()}`;\n}\n","import type { Announcements } from '@dnd-kit/core';\nimport { blockByType, type AnyBlockDefinition } from '../registry';\nimport type { QuoinBlock } from '../types';\n\nfunction describeBlock(blocks: QuoinBlock[], blockTypes: AnyBlockDefinition[], id: string): string {\n const index = blocks.findIndex((b) => b.id === id);\n if (index === -1) return 'block';\n const { type } = blocks[index];\n const label = blockByType(blockTypes, type)?.label ?? type;\n return `${label} block, position ${index + 1} of ${blocks.length}`;\n}\n\n/** The screen reader sentences a drag speaks, naming each block by its registered label and position. */\nexport function buildAnnouncements(blocks: QuoinBlock[], blockTypes: AnyBlockDefinition[]): Announcements {\n const describe = (id: string | number) => describeBlock(blocks, blockTypes, String(id));\n return {\n onDragStart({ active }) {\n return `Picked up ${describe(active.id)}.`;\n },\n onDragOver({ active, over }) {\n if (!over) return `${describe(active.id)} is no longer over a drop position.`;\n return `${describe(active.id)} was moved over ${describe(over.id)}.`;\n },\n onDragEnd({ active, over }) {\n if (!over) return `${describe(active.id)} was dropped.`;\n return `${describe(active.id)} was dropped over ${describe(over.id)}.`;\n },\n onDragCancel({ active }) {\n return `Dragging was cancelled. ${describe(active.id)} was dropped.`;\n },\n };\n}\n","'use client';\n\nimport { ArrowDown, ArrowUp, MoreHorizontal, Trash2 } from 'lucide-react';\nimport { Button } from '../ui/button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '../ui/dropdown-menu';\n\nexport function BlockActionsMenu({\n index,\n count,\n label,\n onMove,\n onDelete,\n}: {\n index: number;\n count: number;\n label: string;\n onMove: (index: number, dir: 1 | -1) => void;\n onDelete: () => void;\n}) {\n const position = index + 1;\n\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button type=\"button\" variant=\"ghost\" size=\"icon-sm\" aria-label={`${label} block ${position} options`}>\n <MoreHorizontal aria-hidden=\"true\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-48\">\n <DropdownMenuItem\n aria-label={`Move block ${position} up`}\n disabled={index === 0}\n onSelect={() => onMove(index, -1)}\n >\n <ArrowUp aria-hidden=\"true\" />\n <span>Move up</span>\n </DropdownMenuItem>\n <DropdownMenuItem\n aria-label={`Move block ${position} down`}\n disabled={index === count - 1}\n onSelect={() => onMove(index, 1)}\n >\n <ArrowDown aria-hidden=\"true\" />\n <span>Move down</span>\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n aria-label={`Delete block ${position}`}\n className=\"text-destructive focus:text-destructive\"\n onSelect={onDelete}\n >\n <Trash2 aria-hidden=\"true\" />\n <span>Delete</span>\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport * as DropdownMenuPrimitive from \"@radix-ui/react-dropdown-menu\";\nimport { CheckIcon, ChevronRightIcon, CircleIcon } from \"lucide-react\";\nimport { cn } from \"./cn\";\nimport { TAP_TARGET_FLOOR } from \"./touch-target\";\n\nfunction DropdownMenu(\n props: React.ComponentProps<typeof DropdownMenuPrimitive.Root>,\n) {\n return <DropdownMenuPrimitive.Root data-slot=\"dropdown-menu\" {...props} />;\n}\n\nfunction DropdownMenuTrigger(\n props: React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>,\n) {\n return (\n <DropdownMenuPrimitive.Trigger\n data-slot=\"dropdown-menu-trigger\"\n {...props}\n />\n );\n}\n\nfunction DropdownMenuContent({\n className,\n sideOffset = 4,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Content>) {\n return (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Content\n data-slot=\"dropdown-menu-content\"\n sideOffset={sideOffset}\n className={cn(\n \"quoin bg-popover text-popover-foreground z-50 min-w-[8rem] overflow-hidden rounded-md border p-1 shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n className,\n )}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n );\n}\n\nfunction DropdownMenuGroup(\n props: React.ComponentProps<typeof DropdownMenuPrimitive.Group>,\n) {\n return (\n <DropdownMenuPrimitive.Group data-slot=\"dropdown-menu-group\" {...props} />\n );\n}\n\nfunction DropdownMenuItem({\n className,\n inset,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {\n inset?: boolean;\n}) {\n return (\n <DropdownMenuPrimitive.Item\n data-slot=\"dropdown-menu-item\"\n data-inset={inset}\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none select-none data-[inset]:pl-8 data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg:not([class*='size-'])]:size-4\",\n TAP_TARGET_FLOOR,\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction DropdownMenuCheckboxItem({\n className,\n children,\n checked,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem>) {\n return (\n <DropdownMenuPrimitive.CheckboxItem\n data-slot=\"dropdown-menu-checkbox-item\"\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-none select-none\",\n className,\n )}\n checked={checked}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <CheckIcon className=\"size-4\" />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.CheckboxItem>\n );\n}\n\nfunction DropdownMenuRadioGroup(\n props: React.ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>,\n) {\n return (\n <DropdownMenuPrimitive.RadioGroup\n data-slot=\"dropdown-menu-radio-group\"\n {...props}\n />\n );\n}\n\nfunction DropdownMenuRadioItem({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem>) {\n return (\n <DropdownMenuPrimitive.RadioItem\n data-slot=\"dropdown-menu-radio-item\"\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-none select-none\",\n className,\n )}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <CircleIcon className=\"size-2 fill-current\" />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.RadioItem>\n );\n}\n\nfunction DropdownMenuLabel({\n className,\n inset,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Label> & {\n inset?: boolean;\n}) {\n return (\n <DropdownMenuPrimitive.Label\n data-slot=\"dropdown-menu-label\"\n data-inset={inset}\n className={cn(\n \"px-2 py-1.5 text-sm font-medium data-[inset]:pl-8\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction DropdownMenuSeparator({\n className,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Separator>) {\n return (\n <DropdownMenuPrimitive.Separator\n data-slot=\"dropdown-menu-separator\"\n className={cn(\"bg-border -mx-1 my-1 h-px\", className)}\n {...props}\n />\n );\n}\n\nfunction DropdownMenuShortcut({\n className,\n ...props\n}: React.ComponentProps<\"span\">) {\n return (\n <span\n data-slot=\"dropdown-menu-shortcut\"\n className={cn(\n \"text-muted-foreground ml-auto text-xs tracking-widest\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction DropdownMenuSub(\n props: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>,\n) {\n return <DropdownMenuPrimitive.Sub data-slot=\"dropdown-menu-sub\" {...props} />;\n}\n\nfunction DropdownMenuSubTrigger({\n className,\n inset,\n children,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & {\n inset?: boolean;\n}) {\n return (\n <DropdownMenuPrimitive.SubTrigger\n data-slot=\"dropdown-menu-sub-trigger\"\n data-inset={inset}\n className={cn(\n \"focus:bg-accent data-[state=open]:bg-accent flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-none select-none data-[inset]:pl-8\",\n className,\n )}\n {...props}\n >\n {children}\n <ChevronRightIcon className=\"ml-auto size-4\" />\n </DropdownMenuPrimitive.SubTrigger>\n );\n}\n\nfunction DropdownMenuSubContent({\n className,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>) {\n return (\n <DropdownMenuPrimitive.SubContent\n data-slot=\"dropdown-menu-sub-content\"\n className={cn(\n \"quoin bg-popover text-popover-foreground z-50 min-w-[8rem] overflow-hidden rounded-md border p-1 shadow-lg\",\n className,\n )}\n {...props}\n />\n );\n}\n\nexport {\n DropdownMenu,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuLabel,\n DropdownMenuItem,\n DropdownMenuCheckboxItem,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuSub,\n DropdownMenuSubTrigger,\n DropdownMenuSubContent,\n};\n","'use client';\n\nimport * as React from 'react';\nimport { Pencil } from 'lucide-react';\nimport { BlockEditor } from './BlockEditor';\nimport { sourceOffsetFor } from './source-offset';\nimport { useQuoin } from '../context';\nimport { blockByType } from '../registry';\nimport type { QuoinBlock } from '../types';\nimport { Button } from '../ui/button';\n\nconst INTERACTIVE_SELECTOR = 'a, button, input, textarea, select, [role=\"button\"], [tabindex], iframe';\n\n/** Radix renders Select, dropdown and popover content in a portal, so focus moving\n * into one leaves this block's DOM subtree while the author is still editing it. */\nconst PORTALLED_OVERLAY = '[data-radix-popper-content-wrapper], [role=\"dialog\"]';\n\n// A drag-select ends in a click on mouseup; bailing here keeps that click from\n// flipping the block into edit mode and wiping out the selection it just made.\nfunction hasSelectionWithin(container: HTMLElement): boolean {\n const selection = window.getSelection();\n if (!selection || selection.isCollapsed || selection.rangeCount === 0) return false;\n return container.contains(selection.getRangeAt(0).commonAncestorContainer);\n}\n\nfunction BlockCardImpl({\n block,\n index,\n editingByDefault = false,\n readOnly = false,\n initialSelection = null,\n onUpdate,\n onInsertBlock,\n}: {\n block: QuoinBlock;\n index: number;\n editingByDefault?: boolean;\n /** Draws the block at rest and never opens an editor, for a canvas that is only being read. */\n readOnly?: boolean;\n initialSelection?: { start: number; end: number } | null;\n onUpdate: (id: string, data: Record<string, unknown>) => void;\n onInsertBlock?: (index: number, type: string) => void;\n}) {\n const { blockTypes } = useQuoin();\n const definition = blockByType(blockTypes, block.type);\n const Preview = definition?.preview;\n const [editing, setEditing] = React.useState(editingByDefault && !readOnly);\n const editButtonRef = React.useRef<HTMLButtonElement>(null);\n const editorContainerRef = React.useRef<HTMLDivElement>(null);\n const returnFocusOnClose = React.useRef(false);\n const clickedTextRef = React.useRef<string | null>(null);\n const scrollTopRef = React.useRef<number | null>(null);\n\n const handleInsertBlock = React.useCallback(\n (type: string) => onInsertBlock?.(index + 1, type),\n [onInsertBlock, index],\n );\n\n const leaveEditing = React.useCallback(() => {\n returnFocusOnClose.current = true;\n setEditing(false);\n }, []);\n\n const settleRef = React.useRef<number | null>(null);\n\n const clearSettle = () => {\n if (settleRef.current === null) return;\n window.clearTimeout(settleRef.current);\n settleRef.current = null;\n };\n\n React.useEffect(() => clearSettle, []);\n\n function stillInside(node: Element | null): boolean {\n if (!node) return false;\n return Boolean(editorContainerRef.current?.contains(node)) || Boolean(node.closest(PORTALLED_OVERLAY));\n }\n\n // Editing ends when the author's attention goes elsewhere, so a block left\n // behind renders instead of stranding them on its markdown source. A pointer\n // event is read directly rather than through focus, which Radix moves around\n // asynchronously while an overlay or a freshly inserted block settles.\n React.useEffect(() => {\n if (!editing) return;\n function onPointerDown(e: PointerEvent) {\n if (stillInside(e.target as Element | null)) return;\n setEditing(false);\n }\n document.addEventListener('pointerdown', onPointerDown, true);\n return () => document.removeEventListener('pointerdown', onPointerDown, true);\n }, [editing]);\n\n function closeIfTabbedAway() {\n clearSettle();\n settleRef.current = window.setTimeout(() => {\n settleRef.current = null;\n if (stillInside(document.activeElement)) return;\n setEditing(false);\n }, 0);\n }\n\n // Focus on the click path must not scroll: the caret would otherwise land at the\n // top of the block and drag the viewport there, away from the line the author\n // actually aimed at.\n React.useEffect(() => {\n if (!editing) return;\n const field = editorContainerRef.current?.querySelector<HTMLElement>(\n 'textarea, input, [role=\"combobox\"]',\n );\n if (!field) return;\n\n const clicked = clickedTextRef.current;\n clickedTextRef.current = null;\n\n if (clicked === null || !(field instanceof HTMLTextAreaElement)) {\n field.focus();\n if (field instanceof HTMLTextAreaElement) {\n const at = initialSelection ?? { start: field.value.length, end: field.value.length };\n field.setSelectionRange(at.start, at.end);\n }\n return;\n }\n\n const offset = sourceOffsetFor(field.value, clicked);\n field.focus({ preventScroll: true });\n field.setSelectionRange(offset, offset);\n }, [editing, initialSelection]);\n\n // Replacing a tall rendered block with a one-row textarea shrinks the page, so\n // the browser clamps the scroll before the box can grow back. The position is\n // taken at the click and put back here, after the box has been sized.\n React.useLayoutEffect(() => {\n const scrollTop = scrollTopRef.current;\n scrollTopRef.current = null;\n if (!editing || scrollTop === null) return;\n const scroller = document.scrollingElement ?? document.documentElement;\n if (scroller.scrollTop !== scrollTop) scroller.scrollTop = scrollTop;\n }, [editing]);\n\n React.useEffect(() => {\n if (editing || !returnFocusOnClose.current) return;\n returnFocusOnClose.current = false;\n editButtonRef.current?.focus();\n }, [editing]);\n\n if (definition?.alwaysEditing && !readOnly) {\n return (\n <BlockEditor\n type={block.type}\n data={block.data}\n onChange={(data) => onUpdate(block.id, data)}\n onInsertBlock={handleInsertBlock}\n />\n );\n }\n\n if (editing) {\n return (\n <div\n ref={editorContainerRef}\n onKeyDown={(e) => {\n if (e.key === 'Tab') {\n closeIfTabbedAway();\n return;\n }\n if (e.key !== 'Escape') return;\n // Radix's DismissableLayer (Select, dropdowns, etc.) closes on a document\n // capture listener and never stops propagation, so this handler still\n // sees the Escape that already dismissed a nested overlay. Only collapse\n // when the key genuinely landed inside this editor's own DOM subtree, not\n // in a portalled overlay that merely propagates through the React tree.\n if (!editorContainerRef.current?.contains(e.target as Node)) return;\n returnFocusOnClose.current = true;\n setEditing(false);\n }}\n >\n <BlockEditor\n type={block.type}\n data={block.data}\n onChange={(data) => onUpdate(block.id, data)}\n onInsertBlock={handleInsertBlock}\n onDone={leaveEditing}\n />\n </div>\n );\n }\n\n const rest = Preview ? (\n <Preview data={block.data} blockId={block.id} />\n ) : definition ? (\n <p className=\"py-1 text-sm text-muted-foreground\">{definition.label}</p>\n ) : null;\n\n if (readOnly) return <div>{rest}</div>;\n\n return (\n <div className=\"group/card relative\">\n <div\n onClick={(e) => {\n const target = e.target as HTMLElement;\n if (target.closest(INTERACTIVE_SELECTOR)) return;\n if (hasSelectionWithin(e.currentTarget)) return;\n clickedTextRef.current = target.textContent ?? '';\n scrollTopRef.current = (document.scrollingElement ?? document.documentElement).scrollTop;\n setEditing(true);\n }}\n >\n {rest}\n </div>\n <Button\n ref={editButtonRef}\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label={`Edit block ${index + 1}`}\n onClick={() => setEditing(true)}\n className=\"absolute right-0 top-0 bg-background/90 opacity-0 transition-opacity group-hover/card:opacity-100 group-focus-within/card:opacity-100 focus-visible:opacity-100\"\n >\n <Pencil aria-hidden=\"true\" />\n </Button>\n </div>\n );\n}\n\nexport const BlockCard = React.memo(BlockCardImpl);\n","'use client';\n\nimport { useQuoin } from '../context';\nimport { blockByType } from '../registry';\nimport type { BlockEditorProps } from '../types';\n\nexport function BlockEditor({\n type,\n data,\n onChange,\n onInsertBlock,\n onDone,\n}: BlockEditorProps & { type: string }) {\n const { blockTypes } = useQuoin();\n const definition = blockByType(blockTypes, type);\n if (!definition) return null;\n const Editor = definition.editor;\n return <Editor data={data} onChange={onChange} onInsertBlock={onInsertBlock} onDone={onDone} />;\n}\n","/** Rendered markdown does not carry its own source positions, so the caret is\n * placed by finding the clicked text back in the source. Inline markup means a\n * paragraph's rendered text often is not a literal substring of it (\"**bold**\"\n * renders as \"bold\"), so progressively shorter leading probes are tried before\n * giving up on the top of the block. */\nconst PROBE_LENGTHS = [40, 20, 8];\n\nexport function sourceOffsetFor(source: string, clickedText: string): number {\n const text = clickedText.replace(/\\s+/g, ' ').trim();\n if (text === '') return 0;\n\n const whole = source.indexOf(text);\n if (whole !== -1) return whole;\n\n for (const length of PROBE_LENGTHS) {\n if (text.length < length) continue;\n const at = source.indexOf(text.slice(0, length));\n if (at !== -1) return at;\n }\n\n return 0;\n}\n","'use client';\n\nimport * as React from 'react';\nimport { Plus } from 'lucide-react';\nimport { useQuoin } from '../context';\nimport { paletteBlocks } from '../registry';\nimport { Button } from '../ui/button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '../ui/dropdown-menu';\n\nexport function BlockInserter({\n index,\n onInsert,\n label,\n}: {\n index: number;\n onInsert: (index: number, type: string, data?: Record<string, unknown>) => void;\n label: string;\n}) {\n const { blockTypes } = useQuoin();\n const options = paletteBlocks(blockTypes);\n const insertedAtRef = React.useRef<number | null>(null);\n\n function handleSelect(type: string) {\n insertedAtRef.current = index;\n onInsert(index, type);\n }\n\n function handleCloseAutoFocus(event: Event) {\n const insertedAt = insertedAtRef.current;\n insertedAtRef.current = null;\n if (insertedAt === null) return;\n\n event.preventDefault();\n const card = document.querySelector<HTMLElement>(`[data-block-index=\"${insertedAt}\"]`);\n if (!card) return;\n if (typeof card.scrollIntoView === 'function') {\n card.scrollIntoView({ block: 'center', behavior: 'smooth' });\n }\n card.querySelector<HTMLElement>('textarea, input, [role=\"combobox\"]')?.focus();\n }\n\n return (\n <div className=\"group/inserter relative flex h-6 items-center justify-center pointer-coarse:h-11\">\n <span\n aria-hidden=\"true\"\n className=\"absolute inset-x-0 top-1/2 h-px bg-border opacity-0 transition-opacity group-hover/inserter:opacity-100 group-focus-within/inserter:opacity-100\"\n />\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"icon-xs\"\n aria-label={label}\n className=\"relative z-10 rounded-full bg-background opacity-0 transition-opacity group-hover/inserter:opacity-100 group-focus-within/inserter:opacity-100 focus-visible:opacity-100 pointer-coarse:opacity-100\"\n >\n <Plus aria-hidden=\"true\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"center\" className=\"w-56\" onCloseAutoFocus={handleCloseAutoFocus}>\n {options.map((opt) => (\n <DropdownMenuItem key={opt.type} onSelect={() => handleSelect(opt.type)}>\n <opt.icon aria-hidden=\"true\" />\n <span>{opt.label}</span>\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n );\n}\n","'use client';\n\nimport * as React from 'react';\nimport type { ChangeEvent } from 'react';\nimport type { TextCommand } from '../markdown/commands';\nimport { insertCommand } from '../markdown/insert-command';\nimport { ShortcutsReference } from '../markdown/ShortcutsReference';\nimport { SlashPalette } from '../markdown/SlashPalette';\nimport { useSlashPalette } from '../markdown/useSlashPalette';\n\nconst LINE = [\n 'w-full resize-none rounded-md border-0 bg-transparent px-2 py-1 outline-none',\n 'text-base leading-7 placeholder:text-muted-foreground',\n 'transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:ring-ring/50',\n].join(' ');\n\nexport function DocumentStarter({\n autoFocus = false,\n onStart,\n onInsertBlock,\n}: {\n autoFocus?: boolean;\n onStart: (markdown: string, selection?: { start: number; end: number }) => void;\n onInsertBlock: (type: string) => void;\n}) {\n const ref = React.useRef<HTMLTextAreaElement>(null);\n const palette = useSlashPalette(ref);\n const [shortcutsOpen, setShortcutsOpen] = React.useState(false);\n\n // The line never keeps what is typed into it: the first character becomes a\n // block instead. Clearing the node directly rather than through state keeps\n // that true even when the handler causes no re-render of this component.\n function handleChange(e: ChangeEvent<HTMLTextAreaElement>) {\n const value = e.target.value;\n e.target.value = '';\n if (value === '') return;\n // A virtual keyboard, an IME or a paste delivers \"/\" with no keydown to\n // intercept, so the shortcut is recognised from the value as well.\n if (value === '/') palette.openAtCaret();\n else onStart(value);\n }\n\n function startWith(command: TextCommand) {\n palette.setOpen(false);\n const edit = insertCommand(command, '', 0);\n onStart(edit.value, { start: edit.selectionStart, end: edit.selectionEnd });\n }\n\n return (\n <div className=\"relative\">\n <textarea\n ref={ref}\n aria-label=\"Write something\"\n defaultValue=\"\"\n onChange={handleChange}\n onKeyDown={(e) => {\n if (e.key !== '/') return;\n e.preventDefault();\n palette.openAtCaret();\n }}\n autoFocus={autoFocus}\n rows={1}\n placeholder=\"Write, or press / for commands\"\n className={LINE}\n />\n <SlashPalette\n open={palette.open}\n caret={palette.caret}\n onOpenChange={palette.setOpen}\n onTextCommand={startWith}\n onBlockCommand={(type) => {\n palette.setOpen(false);\n onInsertBlock(type);\n }}\n onShortcuts={() => {\n palette.setOpen(false);\n setShortcutsOpen(true);\n }}\n onDismiss={() => palette.setOpen(false)}\n />\n <ShortcutsReference open={shortcutsOpen} onOpenChange={setShortcutsOpen} />\n </div>\n );\n}\n","export function reorderIndices(\n ids: string[],\n activeId: string,\n overId: string | null,\n): { from: number; to: number } | null {\n if (overId === null || activeId === overId) return null;\n const from = ids.indexOf(activeId);\n const to = ids.indexOf(overId);\n if (from === -1 || to === -1) return null;\n return { from, to };\n}\n","import type { QuoinBlock } from '../types';\n\nfunction sameData(a: Record<string, unknown>, b: Record<string, unknown>): boolean {\n if (a === b) return true;\n const keys = Object.keys(a);\n if (keys.length !== Object.keys(b).length) return false;\n return keys.every((key) => Object.hasOwn(b, key) && Object.is(a[key], b[key]));\n}\n\n/** Whether two documents hold the same blocks in the same order, comparing each block's data one level deep. */\nexport function sameBlocks(a: QuoinBlock[], b: QuoinBlock[]): boolean {\n if (a === b) return true;\n if (a.length !== b.length) return false;\n return a.every((block, i) => {\n const other = b[i];\n return block.id === other.id && block.type === other.type && sameData(block.data, other.data);\n });\n}\n","'use client';\n\nimport { useSortable } from '@dnd-kit/sortable';\nimport { CSS } from '@dnd-kit/utilities';\nimport { GripVertical } from 'lucide-react';\nimport type { ReactNode } from 'react';\nimport { Button } from '../ui/button';\nimport { cn } from '../ui/cn';\n\n/** The gutter only leaves the text column once the viewport is wide enough to\n * hold it beside a 68ch measure, which is past `lg`. Below that it stacks above\n * the block, where it also has to stay visible: hover is not available there. */\nconst GUTTER = [\n 'flex items-center justify-end gap-0.5 pb-1',\n 'lg:absolute lg:right-full lg:top-1 lg:justify-start lg:pb-0 lg:pr-1',\n 'lg:opacity-0 lg:transition-opacity',\n 'lg:group-hover/block:opacity-100 lg:group-focus-within/block:opacity-100',\n].join(' ');\n\nexport function SortableBlock({\n id,\n index,\n actions,\n children,\n}: {\n id: string;\n index: number;\n actions?: ReactNode;\n children: ReactNode;\n}) {\n const { attributes, listeners, setNodeRef, setActivatorNodeRef, transform, transition, isDragging } =\n useSortable({ id });\n\n return (\n <div\n ref={setNodeRef}\n style={{ transform: CSS.Transform.toString(transform), transition }}\n className={cn('group/block relative', isDragging && 'z-10 opacity-80')}\n >\n <div className={GUTTER}>\n {actions}\n <Button\n type=\"button\"\n ref={setActivatorNodeRef}\n variant=\"ghost\"\n size=\"icon-sm\"\n className=\"cursor-grab text-muted-foreground active:cursor-grabbing\"\n aria-label={`Reorder block ${index + 1}`}\n {...attributes}\n {...listeners}\n >\n <GripVertical aria-hidden=\"true\" />\n </Button>\n </div>\n <div\n data-block-index={index}\n className={cn(\n 'rounded-lg px-2 py-1 transition-colors',\n isDragging ? 'bg-card shadow-[var(--shadow-md)]' : 'group-hover/block:bg-muted/40',\n )}\n >\n {children}\n </div>\n </div>\n );\n}\n","import * as React from 'react';\n\n/** Where a debounced save stands, for a \"Saving...\" or \"Saved\" indicator. */\nexport type AutosaveStatus = 'idle' | 'saving' | 'saved' | 'retrying';\n\ntype SaveResult = { ok?: boolean } | void;\n\n/** What `useAutosave` tracks, how to build the payload, and how to persist it. */\nexport type UseAutosaveInput<T> = {\n /** The tracked fields. An edit to any of them marks dirty and restarts the debounce. */\n deps: React.DependencyList;\n build: () => T;\n save: (payload: T) => Promise<SaveResult> | SaveResult;\n debounceMs?: number;\n maxBackoffMs?: number;\n};\n\n/** The current save status and a way to retry a failed save immediately. */\nexport type UseAutosaveResult = {\n status: AutosaveStatus;\n retry: () => void;\n};\n\n/**\n * Debounced last-write-wins autosave. Nothing fires on mount, only after the first\n * real edit, and a rejected save backs off exponentially until it lands. `save` and\n * `build` are read at fire time, so passing fresh closures each render is safe.\n */\nexport function useAutosave<T>({\n deps,\n build,\n save,\n debounceMs = 2000,\n maxBackoffMs = 30000,\n}: UseAutosaveInput<T>): UseAutosaveResult {\n // The effect order below is load-bearing: the dirty flag must be set before the\n // scheduling effect reads it within the same commit, and the \"latest closure\" refs\n // must be assigned after commit rather than during render.\n const [status, setStatus] = React.useState<AutosaveStatus>('idle');\n const dirtyRef = React.useRef(false);\n const retryRef = React.useRef(0);\n const backoffRef = React.useRef<ReturnType<typeof setTimeout> | null>(null);\n const buildRef = React.useRef(build);\n const saveRef = React.useRef(save);\n const runRef = React.useRef<() => void>(() => {});\n\n React.useEffect(() => {\n buildRef.current = build;\n saveRef.current = save;\n runRef.current = () => {\n void (async () => {\n setStatus('saving');\n try {\n const res = await saveRef.current(buildRef.current());\n if (res && res.ok === false) throw new Error('save rejected');\n retryRef.current = 0;\n dirtyRef.current = false;\n setStatus('saved');\n } catch {\n setStatus('retrying');\n retryRef.current += 1;\n const delay = Math.min(debounceMs * 2 ** retryRef.current, maxBackoffMs);\n if (backoffRef.current) clearTimeout(backoffRef.current);\n backoffRef.current = setTimeout(() => runRef.current(), delay);\n }\n })();\n };\n });\n\n // Compares values rather than counting mounts: React's development remount\n // re-runs this effect with identical deps, and a \"have I mounted\" flag survives\n // that remount, so a flag marks an untouched editor dirty and autosaves it.\n const seenRef = React.useRef<React.DependencyList | null>(null);\n React.useEffect(() => {\n const seen = seenRef.current;\n seenRef.current = deps;\n if (seen === null) return;\n const unchanged = seen.length === deps.length && seen.every((v, i) => v === deps[i]);\n if (!unchanged) dirtyRef.current = true;\n // eslint-disable-next-line react-hooks/exhaustive-deps -- the caller owns the tracked fields\n }, deps);\n\n React.useEffect(() => {\n if (!dirtyRef.current) return;\n const handle = setTimeout(() => runRef.current(), debounceMs);\n return () => clearTimeout(handle);\n // eslint-disable-next-line react-hooks/exhaustive-deps -- the caller owns the tracked fields\n }, deps);\n\n React.useEffect(\n () => () => {\n if (backoffRef.current) clearTimeout(backoffRef.current);\n },\n [],\n );\n\n const retry = React.useCallback(() => {\n if (backoffRef.current) clearTimeout(backoffRef.current);\n runRef.current();\n }, []);\n\n return { status, retry };\n}\n"],"mappings":"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","names":["React","Code","React","jsx","jsx","jsx","jsxs","jsx","jsx","jsxs","jsx","jsx","jsxs","jsx","jsxs","jsxs","jsx","jsx","jsx","jsx","jsx","jsxs","React","text","at","INDENT","at","React","React","jsx","jsxs","jsx","jsxs","jsx","jsx","jsxs","jsx","jsx","jsxs","useEffect","useRef","React","jsx","jsxs","jsx","jsxs","useRef","useEffect","jsx","jsxs","jsx","Code","React","CheckIcon","jsx","jsxs","jsx","jsx","jsx","jsxs","React","jsx","jsx","jsxs","React","jsx","jsxs","React","jsx","jsxs","jsx","jsxs","jsx","jsxs","newBlockId","id","React"]}
|
|
1
|
+
{"version":3,"sources":["../src/canvas/BlockCanvas.tsx","../src/context.tsx","../src/registry.ts","../src/blocks/core.ts","../src/blocks/MarkdownBlockEditor.tsx","../src/upload/FilePickerButton.tsx","../src/ui/button.tsx","../src/ui/cn.ts","../src/ui/touch-target.ts","../src/markdown/edit.ts","../src/markdown/line-at.ts","../src/markdown/insert-command.ts","../src/markdown/shortcut-label.ts","../src/ui/dialog.tsx","../src/markdown/ShortcutsReference.tsx","../src/markdown/SlashPalette.tsx","../src/markdown/commands.ts","../src/ui/command.tsx","../src/ui/popover.tsx","../src/markdown/useMarkdownKeymap.ts","../src/markdown/list-continuation.ts","../src/markdown/indent-list.ts","../src/markdown/line-toggles.ts","../src/markdown/slash-trigger.ts","../src/markdown/wrap-selection.ts","../src/markdown/useSlashPalette.ts","../src/markdown/caret-coordinates.ts","../src/hooks/useAutoGrow.ts","../src/blocks/str.ts","../src/ui/select.tsx","../src/ui/textarea.tsx","../src/blocks/CalloutBlockEditor.tsx","../src/ui/input.tsx","../src/blocks/CodeBlockEditor.tsx","../src/blocks/ImageBlockEditor.tsx","../src/upload/UploadField.tsx","../src/blocks/intrinsic-size.ts","../src/blocks/FileBlockEditor.tsx","../src/blocks/previews.tsx","../src/hooks/useBlockList.ts","../src/hooks/new-block-id.ts","../src/canvas/announcements.ts","../src/canvas/BlockActionsMenu.tsx","../src/ui/dropdown-menu.tsx","../src/canvas/BlockCard.tsx","../src/canvas/BlockEditor.tsx","../src/canvas/source-offset.ts","../src/canvas/BlockInserter.tsx","../src/canvas/DocumentStarter.tsx","../src/canvas/reorder-indices.ts","../src/canvas/same-blocks.ts","../src/canvas/SortableBlock.tsx","../src/hooks/useAutosave.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport {\n DndContext,\n KeyboardSensor,\n PointerSensor,\n closestCenter,\n useSensor,\n useSensors,\n type DragEndEvent,\n} from '@dnd-kit/core';\nimport { restrictToVerticalAxis } from '@dnd-kit/modifiers';\nimport { SortableContext, sortableKeyboardCoordinates, verticalListSortingStrategy } from '@dnd-kit/sortable';\nimport { QuoinProvider } from '../context';\nimport { blockByType, type AnyBlockDefinition } from '../registry';\nimport { coreBlocks } from '../blocks/core';\nimport type { QuoinBlock, UploadFn } from '../types';\nimport { useBlockList } from '../hooks/useBlockList';\nimport { cn } from '../ui/cn';\nimport { buildAnnouncements } from './announcements';\nimport { BlockActionsMenu } from './BlockActionsMenu';\nimport { BlockCard } from './BlockCard';\nimport { BlockInserter } from './BlockInserter';\nimport { DocumentStarter } from './DocumentStarter';\nimport { reorderIndices } from './reorder-indices';\nimport { sameBlocks } from './same-blocks';\nimport { SortableBlock } from './SortableBlock';\n\n/** Props for `BlockCanvas`; `blocks` and `onChange` are the whole document contract. */\nexport type BlockCanvasProps = {\n /**\n * The document. Update it synchronously from `onChange`, as with a controlled `<input value onChange>`.\n * Applying the edit late is tolerated as long as what comes back is one of the arrays the canvas emitted:\n * it recognises its own output even several keystrokes behind, so a transition or a debounced setter is safe.\n * A store that rebuilds the document on the way through hands back a structural copy instead, which arrives\n * behind the canvas's own state and reads as a foreign document. That does not revert the edit cleanly: the\n * characters the copy predates are dropped and the ones typed after them are kept.\n * A new array that differs from the last one you supplied replaces what the canvas shows, which is how a host\n * loads, undoes or merges. An array structurally equal to the last one you supplied is ignored, so a \"discard\n * changes\" button that hands back the original document does nothing; remount the canvas with a React `key` to\n * force a reset. The comparison is shallow over each block's `data`: a host whose block `data` holds nested\n * objects rebuilt on every render, and which does not echo `onChange` back, can still lose an edit. The core\n * block types all have flat data, so this only affects custom blocks.\n */\n blocks: QuoinBlock[];\n onChange: (blocks: QuoinBlock[]) => void;\n /** Defaults to the five core block types. Pass `[...coreBlocks, yours]` to extend them. */\n blockTypes?: AnyBlockDefinition[];\n upload?: UploadFn;\n resolveAssetUrl?: (storageKey: string) => string;\n onError?: (error: Error) => void;\n /** Renders the document with no inserters, menus, drag handles or editors. */\n readOnly?: boolean;\n /** Added to the root element's own classes rather than replacing them. */\n className?: string;\n id?: string;\n /** Names the document for assistive technology; the root then becomes a labelled group. */\n 'aria-label'?: string;\n};\n\ntype Selection = { start: number; end: number };\n\n/** A host may coalesce or drop echoes, so the outstanding set is capped instead of trusted to drain. */\nconst UNACKNOWLEDGED_LIMIT = 64;\n\nfunction remember(outstanding: Set<QuoinBlock[]>, blocks: QuoinBlock[]) {\n outstanding.add(blocks);\n while (outstanding.size > UNACKNOWLEDGED_LIMIT) {\n const oldest = outstanding.values().next();\n if (oldest.done) return;\n outstanding.delete(oldest.value);\n }\n}\n\nfunction Canvas({\n blocks,\n onChange,\n blockTypes,\n readOnly,\n className,\n id,\n 'aria-label': ariaLabel,\n}: Pick<BlockCanvasProps, 'blocks' | 'onChange' | 'readOnly' | 'className' | 'id' | 'aria-label'> & {\n blockTypes: AnyBlockDefinition[];\n}) {\n const list = useBlockList(blocks);\n const { insertAt, update, remove, move, reorder, reset } = list;\n const sensors = useSensors(\n useSensor(PointerSensor, { activationConstraint: { distance: 4 } }),\n useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates }),\n );\n const dndId = React.useId();\n const [newBlockId, setNewBlockId] = React.useState<string | null>(null);\n const [seedSelection, setSeedSelection] = React.useState<Selection | null>(null);\n const listRef = React.useRef<HTMLDivElement>(null);\n const pendingDeleteIndexRef = React.useRef<number | null>(null);\n const announcements = React.useMemo(\n () => buildAnnouncements(list.blocks, blockTypes),\n [list.blocks, blockTypes],\n );\n\n // The reducer reads `blocks` once, so the two effects below carry the document\n // across the boundary in both directions. An array this canvas emitted is\n // recognised when the host hands it back and is not reset; an array the host\n // supplies is foreign and is. Seeding the refs with the first `blocks` keeps\n // mounting from reporting a change nobody made.\n const lastEmitted = React.useRef<QuoinBlock[]>(blocks);\n const lastSupplied = React.useRef<QuoinBlock[]>(blocks);\n // Every emission still waiting to come back, not just the newest: a host that applies\n // edits late hands back an array from several keystrokes ago, and recognising only the\n // newest would read that as a foreign document and overwrite live text with it.\n const unacknowledged = React.useRef<Set<QuoinBlock[]>>(new Set());\n\n React.useEffect(() => {\n if (list.blocks === lastEmitted.current) return;\n lastEmitted.current = list.blocks;\n remember(unacknowledged.current, list.blocks);\n onChange(list.blocks);\n }, [list.blocks, onChange]);\n\n React.useEffect(() => {\n const previous = lastSupplied.current;\n lastSupplied.current = blocks;\n if (unacknowledged.current.has(blocks)) {\n // Caught up: anything older than this emission has been echoed or coalesced away.\n // Everything before then is forgotten, so a host replaying one of these arrays from\n // its own undo stack later is a document the canvas accepts rather than ignores.\n if (blocks === lastEmitted.current) unacknowledged.current.clear();\n return;\n }\n // A host that builds a fresh array on every render, without echoing edits, would\n // otherwise wipe them on any unrelated re-render. An undo replays a different array.\n if (sameBlocks(blocks, previous) || sameBlocks(blocks, list.blocks)) return;\n unacknowledged.current.clear();\n lastEmitted.current = blocks;\n reset(blocks);\n }, [blocks, reset]);\n\n const insertPlain = React.useCallback(\n (index: number, type: string, data?: Record<string, unknown>) => {\n setSeedSelection(null);\n const seed = data ?? blockByType(blockTypes, type)?.initialData?.() ?? {};\n setNewBlockId(insertAt(index, type, seed));\n },\n [insertAt, blockTypes],\n );\n\n function handleDelete(index: number, id: string) {\n pendingDeleteIndexRef.current = index;\n remove(id);\n }\n\n React.useEffect(() => {\n const index = pendingDeleteIndexRef.current;\n pendingDeleteIndexRef.current = null;\n if (index === null || !listRef.current) return;\n const landingIndex = Math.min(index, list.blocks.length - 1);\n const card =\n landingIndex >= 0 ? listRef.current.querySelector<HTMLElement>(`[data-block-index=\"${landingIndex}\"]`) : null;\n (card?.querySelector<HTMLElement>('button') ?? listRef.current.querySelector<HTMLElement>('button'))?.focus();\n }, [list.blocks]);\n\n function handleDragEnd(event: DragEndEvent) {\n const { active, over } = event;\n const result = reorderIndices(\n list.blocks.map((b) => b.id),\n String(active.id),\n over ? String(over.id) : null,\n );\n if (result) reorder(result.from, result.to);\n }\n\n const rootProps = {\n ref: listRef,\n id,\n className: cn('quoin flex flex-col', className),\n role: ariaLabel ? 'group' : undefined,\n 'aria-label': ariaLabel,\n };\n\n if (readOnly) {\n return (\n <div {...rootProps}>\n <ul className=\"flex flex-col\">\n {list.blocks.map((b, i) => (\n <li key={b.id}>\n <div data-block-index={i} className=\"rounded-lg px-2 py-1\">\n <BlockCard block={b} index={i} editingByDefault={false} readOnly onUpdate={update} />\n </div>\n </li>\n ))}\n </ul>\n </div>\n );\n }\n\n return (\n <div {...rootProps}>\n <BlockInserter index={0} onInsert={insertPlain} label=\"Insert a block at the start\" />\n <DndContext\n id={dndId}\n sensors={sensors}\n collisionDetection={closestCenter}\n modifiers={[restrictToVerticalAxis]}\n accessibility={{ announcements }}\n onDragEnd={handleDragEnd}\n >\n <SortableContext items={list.blocks.map((b) => b.id)} strategy={verticalListSortingStrategy}>\n <ul className=\"flex flex-col\">\n {list.blocks.map((b, i) => (\n <li key={b.id}>\n <SortableBlock\n id={b.id}\n index={i}\n actions={\n <BlockActionsMenu\n index={i}\n count={list.blocks.length}\n label={blockByType(blockTypes, b.type)?.label ?? b.type}\n onMove={move}\n onDelete={() => handleDelete(i, b.id)}\n />\n }\n >\n <BlockCard\n block={b}\n index={i}\n editingByDefault={b.id === newBlockId}\n initialSelection={b.id === newBlockId ? seedSelection : null}\n onUpdate={update}\n onInsertBlock={insertPlain}\n />\n </SortableBlock>\n <BlockInserter\n index={i + 1}\n onInsert={insertPlain}\n label={`Insert a block after block ${i + 1}`}\n />\n </li>\n ))}\n </ul>\n </SortableContext>\n </DndContext>\n <DocumentStarter\n autoFocus={list.blocks.length === 0}\n onStart={(markdown, selection) => {\n setSeedSelection(selection ?? null);\n setNewBlockId(insertAt(list.blocks.length, 'MARKDOWN', { markdown }));\n }}\n onInsertBlock={(type) => insertPlain(list.blocks.length, type)}\n />\n </div>\n );\n}\n\n/** The editor: renders `blocks`, reports every edit through `onChange`, and accepts a new `blocks` array from outside at any time. */\nexport function BlockCanvas({\n blocks,\n onChange,\n blockTypes = coreBlocks,\n upload,\n resolveAssetUrl,\n onError,\n readOnly = false,\n className,\n id,\n 'aria-label': ariaLabel,\n}: BlockCanvasProps) {\n const config = React.useMemo(\n () => ({ blockTypes, upload, resolveAssetUrl, onError }),\n [blockTypes, upload, resolveAssetUrl, onError],\n );\n return (\n <QuoinProvider value={config}>\n <Canvas\n blocks={blocks}\n onChange={onChange}\n blockTypes={blockTypes}\n readOnly={readOnly}\n className={className}\n id={id}\n aria-label={ariaLabel}\n />\n </QuoinProvider>\n );\n}\n","'use client';\n\nimport * as React from 'react';\nimport type { AnyBlockDefinition } from './registry';\nimport type { UploadFn } from './types';\n\n/** The resolved canvas configuration every block editor reads through `useQuoin`. */\nexport type QuoinConfig = {\n blockTypes: AnyBlockDefinition[];\n /** Absent when the host has not wired uploads; upload fields then render disabled. */\n upload?: UploadFn;\n resolveAssetUrl: (storageKey: string) => string;\n onError: (error: Error) => void;\n};\n\n/** What a host passes to `QuoinProvider`: only the block types are required. */\nexport type QuoinConfigInput = Partial<QuoinConfig> & {\n blockTypes: AnyBlockDefinition[];\n};\n\nconst QuoinContext = React.createContext<QuoinConfig | null>(null);\n\n/** Supplies the block registry and the host couplings (upload, asset URLs, error reporting) to every block below it. */\nexport function QuoinProvider({\n value,\n children,\n}: {\n value: QuoinConfigInput;\n children: React.ReactNode;\n}) {\n const { blockTypes, upload, resolveAssetUrl, onError } = value;\n const config = React.useMemo<QuoinConfig>(\n () => ({\n blockTypes,\n upload,\n // Identity default: an empty key resolves to an empty string, which stays falsy\n // wherever a resolved URL is tested for \"no asset chosen yet\".\n resolveAssetUrl: resolveAssetUrl ?? ((key: string) => key),\n onError: onError ?? ((error: Error) => console.error(error)),\n }),\n [blockTypes, upload, resolveAssetUrl, onError],\n );\n return <QuoinContext.Provider value={config}>{children}</QuoinContext.Provider>;\n}\n\n/** Reads the canvas configuration. Throws outside a QuoinProvider rather than returning a silent default. */\nexport function useQuoin(): QuoinConfig {\n const config = React.useContext(QuoinContext);\n if (!config) throw new Error('useQuoin must be used inside a QuoinProvider.');\n return config;\n}\n","import type { ComponentType } from 'react';\nimport type { LucideIcon } from 'lucide-react';\nimport type { BlockEditorProps, BlockPreviewProps } from './types';\n\n/** Describes one block type: how to label it, how to draw it at rest, how to edit it. */\nexport type BlockDefinition<D extends object = Record<string, unknown>> = {\n type: string;\n label: string;\n icon: LucideIcon;\n editor: ComponentType<BlockEditorProps<D>>;\n /**\n * What the block shows when it is not being edited. Optional so a host can register an\n * edit-only block type, and overridable so a host can supply rich rendering (a full\n * markdown pipeline, a chart) without Quoin depending on one.\n */\n preview?: ComponentType<BlockPreviewProps<D>>;\n /**\n * Called when a new block of this type is inserted, to seed its data.\n * `NoInfer` keeps `D` inferred from `editor` and `preview` alone, so the seed is checked\n * against the editor's data type instead of widening it.\n */\n initialData?: () => NoInfer<D>;\n /** Whether the block is offered in the slash palette and inserter; defaults to true. */\n inSlashPalette?: boolean;\n /**\n * Renders this block's editor permanently instead of a preview you click to edit.\n * Also supply a `preview`: a read-only canvas draws the preview rather than the editor,\n * so without one the block's content is invisible there.\n */\n alwaysEditing?: boolean;\n};\n\n/** A definition with its data type erased, so definitions of different shapes compose in one array. */\nexport type AnyBlockDefinition = BlockDefinition<Record<string, unknown>>;\n\n/**\n * Types `data` inside your editor component, then erases the generic on the way out.\n * The erasure is deliberate: `D` appears in both covariant and contravariant positions\n * on `editor`, so without it an array of differently-shaped definitions will not typecheck.\n * `initialData` is checked against the editor's data type. That relies on `NoInfer`, so\n * TypeScript 5.4 or later is required.\n */\nexport function defineBlock<D extends object>(definition: BlockDefinition<D>): AnyBlockDefinition {\n return definition as unknown as AnyBlockDefinition;\n}\n\n/** The definition for a type, or undefined; the last registration of a type wins, so a host can override a core block. */\nexport function blockByType(\n definitions: AnyBlockDefinition[],\n type: string,\n): AnyBlockDefinition | undefined {\n for (let i = definitions.length - 1; i >= 0; i -= 1) {\n if (definitions[i].type === type) return definitions[i];\n }\n return undefined;\n}\n\n/** The definitions offered in the slash palette, in registration order, one per type, with the last registration of a type winning. */\nexport function paletteBlocks(definitions: AnyBlockDefinition[]): AnyBlockDefinition[] {\n const seen = new Set<string>();\n const out: AnyBlockDefinition[] = [];\n for (let i = definitions.length - 1; i >= 0; i -= 1) {\n const d = definitions[i];\n if (seen.has(d.type)) continue;\n // Claim the type BEFORE honouring the opt-out, so a hidden override suppresses the\n // definition it replaces instead of letting the earlier one reappear. Without this,\n // the palette can offer a block that `blockByType` resolves to a different definition.\n seen.add(d.type);\n if (d.inSlashPalette === false) continue;\n out.push(d);\n }\n return out.reverse();\n}\n","import { Code, FileText, MessageSquare, Image, Paperclip } from 'lucide-react';\nimport { defineBlock, type AnyBlockDefinition } from '../registry';\nimport { MarkdownBlockEditor } from './MarkdownBlockEditor';\nimport { CalloutBlockEditor } from './CalloutBlockEditor';\nimport { CodeBlockEditor } from './CodeBlockEditor';\nimport { ImageBlockEditor } from './ImageBlockEditor';\nimport { FileBlockEditor } from './FileBlockEditor';\nimport {\n MarkdownPreview,\n CalloutPreview,\n CodePreview,\n ImagePreview,\n FilePreview,\n} from './previews';\n\n/** The block types Quoin ships with. Spread them alongside your own definitions. */\nexport const coreBlocks: AnyBlockDefinition[] = [\n defineBlock({\n type: 'MARKDOWN',\n label: 'Markdown',\n icon: FileText,\n editor: MarkdownBlockEditor,\n preview: MarkdownPreview,\n initialData: () => ({ markdown: '' }),\n }),\n defineBlock({\n type: 'CALLOUT',\n label: 'Callout',\n icon: MessageSquare,\n editor: CalloutBlockEditor,\n preview: CalloutPreview,\n initialData: () => ({ tone: 'info', body: '' }),\n }),\n defineBlock({\n type: 'CODE',\n label: 'Code',\n icon: Code,\n editor: CodeBlockEditor,\n preview: CodePreview,\n initialData: () => ({ language: '', code: '' }),\n }),\n defineBlock({\n type: 'IMAGE',\n label: 'Image',\n icon: Image,\n editor: ImageBlockEditor,\n preview: ImagePreview,\n initialData: () => ({ storageKey: '', alt: '' }),\n }),\n defineBlock({\n type: 'FILE',\n label: 'File',\n icon: Paperclip,\n editor: FileBlockEditor,\n preview: FilePreview,\n initialData: () => ({ storageKey: '', filename: '' }),\n }),\n];\n","'use client';\n\nimport * as React from 'react';\nimport { useQuoin } from '../context';\nimport { FilePickerButton } from '../upload/FilePickerButton';\nimport { applyEdit } from '../markdown/edit';\nimport { insertCommand } from '../markdown/insert-command';\nimport { ShortcutsReference } from '../markdown/ShortcutsReference';\nimport { SlashPalette } from '../markdown/SlashPalette';\nimport { useMarkdownKeymap } from '../markdown/useMarkdownKeymap';\nimport { useSlashPalette } from '../markdown/useSlashPalette';\nimport type { TextCommand } from '../markdown/commands';\nimport { useAutoGrow } from '../hooks/useAutoGrow';\nimport type { BlockEditorProps } from '../types';\nimport { str } from './str';\n\nconst BOX = [\n '-mx-2 min-h-7 w-[calc(100%+1rem)] resize-none rounded-md border-0 bg-transparent px-2 py-0',\n 'text-base leading-7 outline-none placeholder:text-muted-foreground',\n 'transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:ring-ring/50',\n].join(' ');\n\nexport function MarkdownBlockEditor({ data, onChange, onInsertBlock, onDone }: BlockEditorProps) {\n const { onError } = useQuoin();\n const markdown = str(data.markdown);\n const ref = useAutoGrow<HTMLTextAreaElement>(markdown);\n const palette = useSlashPalette(ref);\n const [shortcutsOpen, setShortcutsOpen] = React.useState(false);\n\n const set = (patch: Record<string, unknown>) => onChange({ ...data, ...patch });\n // The keymap memoises its handlers on this, so a fresh closure every render would\n // rebuild them on every render too, including the ones a palette or dialog causes.\n const commit = React.useCallback(\n (next: string) => onChange({ ...data, markdown: next }),\n [data, onChange],\n );\n\n const keymap = useMarkdownKeymap({ commit, onOpenPalette: palette.openAtCaret });\n\n function reopenBox(): HTMLTextAreaElement | null {\n const el = ref.current;\n el?.focus({ preventScroll: true });\n return el ?? null;\n }\n\n function runTextCommand(command: TextCommand) {\n palette.setOpen(false);\n const el = reopenBox();\n if (!el) return;\n applyEdit(el, insertCommand(command, el.value, palette.offsetRef.current), commit);\n }\n\n function writeLiteralSlash() {\n palette.setOpen(false);\n const el = reopenBox();\n if (!el) return;\n const at = palette.offsetRef.current;\n applyEdit(\n el,\n { value: `${el.value.slice(0, at)}/${el.value.slice(at)}`, selectionStart: at + 1, selectionEnd: at + 1 },\n commit,\n );\n }\n\n function readMarkdownFile(file: File) {\n const reader = new FileReader();\n reader.onload = () => {\n const text = typeof reader.result === 'string' ? reader.result : '';\n if (text.trim() === '') {\n onError(new Error(`${file.name} is empty.`));\n return;\n }\n set({ markdown: text });\n onDone?.();\n };\n reader.onerror = () => onError(new Error(`Could not read ${file.name}.`));\n reader.readAsText(file);\n }\n\n return (\n <div className=\"relative flex flex-col gap-3\">\n <textarea\n ref={ref}\n aria-label=\"Markdown\"\n value={markdown}\n rows={1}\n placeholder=\"Write, or press / for commands\"\n onChange={(e) => set({ markdown: e.target.value })}\n onKeyDown={keymap.onKeyDown}\n onPaste={keymap.onPaste}\n className={BOX}\n />\n <SlashPalette\n open={palette.open}\n caret={palette.caret}\n onOpenChange={palette.setOpen}\n onTextCommand={runTextCommand}\n onBlockCommand={(type) => {\n palette.setOpen(false);\n onInsertBlock?.(type);\n }}\n onShortcuts={() => {\n palette.setOpen(false);\n setShortcutsOpen(true);\n }}\n onDismiss={writeLiteralSlash}\n />\n <ShortcutsReference open={shortcutsOpen} onOpenChange={setShortcutsOpen} />\n {markdown.trim() === '' && (\n <FilePickerButton\n label=\"Upload .md\"\n accept=\".md,text/markdown,text/plain\"\n onPick={readMarkdownFile}\n />\n )}\n </div>\n );\n}\n","'use client';\n\nimport { Upload } from 'lucide-react';\nimport { Button } from '../ui/button';\n\n/** The input itself stays focusable and labelled, laid transparently over the\n * button, so the keyboard and the pointer both land on the real control. The\n * wrapper paints the focus ring the invisible input cannot show. */\nexport function FilePickerButton({\n label,\n accept,\n disabled,\n onPick,\n}: {\n label: string;\n accept?: string;\n disabled?: boolean;\n onPick: (file: File) => void;\n}) {\n return (\n <span className=\"relative inline-flex rounded-md has-[:focus-visible]:ring-[3px] has-[:focus-visible]:ring-ring/50\">\n <Button asChild variant=\"outline\" size=\"sm\">\n <span aria-hidden=\"true\" className={disabled ? 'pointer-events-none opacity-50' : undefined}>\n <Upload aria-hidden=\"true\" />\n {label}\n </span>\n </Button>\n <input\n type=\"file\"\n accept={accept}\n aria-label={label}\n disabled={disabled}\n className=\"absolute inset-0 cursor-pointer opacity-0 disabled:cursor-not-allowed\"\n onChange={(e) => {\n const file = e.target.files?.[0];\n // Clear so picking the same file again still fires `change`, which is what makes retry after a failed upload work.\n e.target.value = '';\n if (file) onPick(file);\n }}\n />\n </span>\n );\n}\n","import * as React from \"react\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { cn } from \"./cn\";\nimport { SQUARE_TAP_TARGET_FLOOR, TAP_TARGET_FLOOR } from \"./touch-target\";\n\n/** Class variants for the button primitive, reusable on other elements. */\nconst buttonVariants = cva(\n \"inline-flex cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-[color,background-color,border-color,box-shadow,opacity] disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 shrink-0 outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50\",\n {\n variants: {\n variant: {\n default:\n \"bg-primary text-primary-foreground shadow-xs hover:bg-primary/90\",\n destructive:\n \"bg-destructive text-white shadow-xs hover:bg-destructive/90 dark:bg-destructive/60 dark:hover:bg-destructive/75\",\n outline:\n \"border border-input bg-transparent shadow-xs hover:bg-accent hover:text-accent-foreground\",\n secondary:\n \"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80\",\n ghost: \"hover:bg-accent hover:text-accent-foreground\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: `h-9 px-4 py-2 has-[>svg]:px-3 ${TAP_TARGET_FLOOR}`,\n xs: `h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3 ${TAP_TARGET_FLOOR}`,\n sm: `h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5 ${TAP_TARGET_FLOOR}`,\n lg: `h-10 rounded-md px-6 has-[>svg]:px-4 ${TAP_TARGET_FLOOR}`,\n icon: `size-9 ${SQUARE_TAP_TARGET_FLOOR}`,\n \"icon-xs\": `size-6 rounded-md [&_svg:not([class*='size-'])]:size-3 ${SQUARE_TAP_TARGET_FLOOR}`,\n \"icon-sm\": `size-8 ${SQUARE_TAP_TARGET_FLOOR}`,\n \"icon-lg\": `size-10 ${SQUARE_TAP_TARGET_FLOOR}`,\n },\n },\n defaultVariants: { variant: \"default\", size: \"default\" },\n },\n);\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & { asChild?: boolean }) {\n const Comp = asChild ? Slot : \"button\";\n return (\n <Comp\n data-slot=\"button\"\n data-variant={variant}\n data-size={size}\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n );\n}\n\nexport { Button, buttonVariants };\n","import { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\n/** Merges class names, with later Tailwind utilities overriding earlier conflicting ones. */\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","/** 44px is the platform minimum for a finger. It is applied as a floor rather than\n * a height so a control keeps its own pointer-precise size, and only where the\n * primary pointer is coarse so mouse-driven layouts keep their density. */\nexport const TAP_TARGET_FLOOR = 'pointer-coarse:min-h-11';\n\n/** The pointer-coarse sizing floor on both axes, for square icon controls. */\nexport const SQUARE_TAP_TARGET_FLOOR = `${TAP_TARGET_FLOOR} pointer-coarse:min-w-11`;\n\n/** For an icon control pinned to a corner, where growing the box would drag the icon\n * inward. The target is a centred, transparent pseudo-element instead, so the hit\n * area reaches 44px while the icon keeps its own size and position. Requires the\n * control to be positioned, which a pinned one already is. */\nexport const ICON_TAP_TARGET_FLOOR = [\n \"pointer-coarse:before:absolute pointer-coarse:before:top-1/2 pointer-coarse:before:left-1/2\",\n 'pointer-coarse:before:size-11 pointer-coarse:before:-translate-x-1/2 pointer-coarse:before:-translate-y-1/2',\n \"pointer-coarse:before:content-['']\",\n].join(' ');\n","/** A text transform result: the next value and where the selection should land. */\nexport type Edit = { value: string; selectionStart: number; selectionEnd: number };\n\nfunction changedSpan(before: string, after: string) {\n let start = 0;\n const shortest = Math.min(before.length, after.length);\n while (start < shortest && before[start] === after[start]) start += 1;\n\n let endBefore = before.length;\n let endAfter = after.length;\n while (endBefore > start && endAfter > start && before[endBefore - 1] === after[endAfter - 1]) {\n endBefore -= 1;\n endAfter -= 1;\n }\n\n return { start, endBefore, replacement: after.slice(start, endAfter) };\n}\n\n// Writing through execCommand keeps the transform as one entry on the browser's\n// own undo stack. Either path commits el.value rather than the edit's intended\n// value: a browser is trusted to write what it was asked, and if it ever\n// wrote something else, committing our own intent instead would silently\n// diverge React's state from the DOM.\nfunction writeNatively(el: HTMLTextAreaElement, replacement: string): boolean {\n if (typeof document.execCommand !== 'function') return false;\n try {\n return replacement === ''\n ? document.execCommand('delete')\n : document.execCommand('insertText', false, replacement);\n } catch {\n return false;\n }\n}\n\n/** Applies an edit to a textarea through the native undo stack when the browser allows it, so Ctrl+Z still works. */\nexport function applyEdit(\n el: HTMLTextAreaElement,\n edit: Edit,\n commit: (value: string) => void,\n): void {\n if (el.value !== edit.value) {\n const { start, endBefore, replacement } = changedSpan(el.value, edit.value);\n el.setSelectionRange(start, endBefore);\n if (!writeNatively(el, replacement)) {\n el.value = edit.value;\n }\n commit(el.value);\n }\n el.setSelectionRange(edit.selectionStart, edit.selectionEnd);\n}\n","const FENCE = /^ {0,3}(```|~~~)/;\n\nexport type Line = { start: number; end: number; text: string };\n\n/** The line containing the offset, with its start and end offsets and its text (no trailing newline). */\nexport function lineAt(value: string, offset: number): Line {\n const start = value.lastIndexOf('\\n', offset - 1) + 1;\n const next = value.indexOf('\\n', offset);\n const end = next === -1 ? value.length : next;\n return { start, end, text: value.slice(start, end) };\n}\n\nexport function isFenceDelimiter(text: string): boolean {\n return FENCE.test(text);\n}\n\nexport function insideFence(value: string, offset: number): boolean {\n const lines = value.slice(0, offset).split('\\n');\n if (isFenceDelimiter(lines[lines.length - 1])) return true;\n\n let open = false;\n for (let i = 0; i < lines.length - 1; i += 1) {\n if (isFenceDelimiter(lines[i])) open = !open;\n }\n return open;\n}\n","import type { Edit } from './edit';\nimport { lineAt } from './line-at';\n\n/** The fields `insertCommand` needs. `TextCommand` satisfies this structurally. */\nexport type InsertableCommand = {\n insert: string;\n caretOffset: number;\n selectLength?: number;\n separate: boolean;\n};\n\n/** Inserts a command's markdown at the caret, starting a new line (or a blank line if it asks) when the caret is mid-line. */\nexport function insertCommand(command: InsertableCommand, value: string, caret: number): Edit {\n const line = lineAt(value, caret);\n const before = value.slice(line.start, caret).replace(/[ \\t]+$/, '');\n const cut = line.start + before.length;\n const prefix = before.trim() === '' ? '' : command.separate ? '\\n\\n' : '\\n';\n const at = cut + prefix.length + command.caretOffset;\n\n return {\n value: value.slice(0, cut) + prefix + command.insert + value.slice(caret),\n selectionStart: at,\n selectionEnd: at + (command.selectLength ?? 0),\n };\n}\n","const MAC_LABEL: Record<string, string> = { mod: '⌘', alt: '⌥', shift: '⇧' };\nconst OTHER_LABEL: Record<string, string> = { mod: 'Ctrl', alt: 'Alt', shift: 'Shift' };\n\nfunction onMac(): boolean {\n if (typeof navigator === 'undefined') return false;\n return /Mac|iPhone|iPad/.test(navigator.userAgent);\n}\n\n/** Renders a \"mod+shift+b\" style hint as the platform's own label, such as ⌘⇧B on a Mac and Ctrl+Shift+B elsewhere. */\nexport function formatShortcut(hint: string): string {\n const mac = onMac();\n const labels = mac ? MAC_LABEL : OTHER_LABEL;\n const parts = hint.split('+').map((part) => labels[part] ?? part.toUpperCase());\n return parts.join(mac ? '' : '+');\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport * as DialogPrimitive from \"@radix-ui/react-dialog\";\nimport { XIcon } from \"lucide-react\";\nimport { cn } from \"./cn\";\nimport { ICON_TAP_TARGET_FLOOR } from \"./touch-target\";\n\nfunction Dialog(props: React.ComponentProps<typeof DialogPrimitive.Root>) {\n return <DialogPrimitive.Root data-slot=\"dialog\" {...props} />;\n}\n\nfunction DialogTrigger(\n props: React.ComponentProps<typeof DialogPrimitive.Trigger>,\n) {\n return <DialogPrimitive.Trigger data-slot=\"dialog-trigger\" {...props} />;\n}\n\nfunction DialogPortal(\n props: React.ComponentProps<typeof DialogPrimitive.Portal>,\n) {\n return <DialogPrimitive.Portal data-slot=\"dialog-portal\" {...props} />;\n}\n\nfunction DialogClose(\n props: React.ComponentProps<typeof DialogPrimitive.Close>,\n) {\n return <DialogPrimitive.Close data-slot=\"dialog-close\" {...props} />;\n}\n\nfunction DialogOverlay({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Overlay>) {\n return (\n <DialogPrimitive.Overlay\n data-slot=\"dialog-overlay\"\n className={cn(\n \"quoin fixed inset-0 z-50 bg-black/50 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction DialogContent({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Content>) {\n return (\n <DialogPortal>\n <DialogOverlay />\n <DialogPrimitive.Content\n data-slot=\"dialog-content\"\n className={cn(\n \"quoin bg-popover fixed top-[50%] left-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n className,\n )}\n {...props}\n >\n {children}\n <DialogPrimitive.Close\n className={cn(\n \"ring-offset-background focus:ring-ring absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-none\",\n ICON_TAP_TARGET_FLOOR,\n )}\n >\n <XIcon />\n <span className=\"sr-only\">Close</span>\n </DialogPrimitive.Close>\n </DialogPrimitive.Content>\n </DialogPortal>\n );\n}\n\nfunction DialogHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"dialog-header\"\n className={cn(\"flex flex-col gap-2 text-center sm:text-left\", className)}\n {...props}\n />\n );\n}\n\nfunction DialogFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"dialog-footer\"\n className={cn(\n \"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction DialogTitle({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Title>) {\n return (\n <DialogPrimitive.Title\n data-slot=\"dialog-title\"\n className={cn(\"text-lg leading-none font-semibold\", className)}\n {...props}\n />\n );\n}\n\nfunction DialogDescription({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Description>) {\n return (\n <DialogPrimitive.Description\n data-slot=\"dialog-description\"\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n );\n}\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n};\n","'use client';\n\nimport { formatShortcut } from './shortcut-label';\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n} from '../ui/dialog';\n\nconst ROWS: Array<{ label: string; keys: string }> = [\n { label: 'Open the command palette', keys: '/' },\n { label: 'Bold', keys: formatShortcut('mod+b') },\n { label: 'Italic', keys: formatShortcut('mod+i') },\n { label: 'Inline code', keys: formatShortcut('mod+e') },\n { label: 'Link', keys: formatShortcut('mod+k') },\n { label: 'Heading', keys: formatShortcut('mod+alt+1') },\n { label: 'Subtitle', keys: formatShortcut('mod+alt+2') },\n { label: 'Sub-subtitle', keys: formatShortcut('mod+alt+3') },\n { label: 'Bullet list', keys: formatShortcut('mod+shift+8') },\n { label: 'Numbered list', keys: formatShortcut('mod+shift+7') },\n { label: 'Continue a list, or leave it when the item is empty', keys: 'Enter' },\n { label: 'Indent item', keys: 'Tab' },\n { label: 'Outdent item', keys: formatShortcut('shift') + '+Tab' },\n];\n\nexport function ShortcutsReference({\n open,\n onOpenChange,\n}: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n}) {\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent className=\"sm:max-w-md\">\n <DialogHeader>\n <DialogTitle>Keyboard shortcuts</DialogTitle>\n <DialogDescription>Formatting without leaving the keyboard.</DialogDescription>\n </DialogHeader>\n <dl className=\"grid grid-cols-[1fr_auto] gap-x-4 gap-y-2 text-sm\">\n {ROWS.map((row) => (\n <div key={row.label} className=\"col-span-2 grid grid-cols-subgrid items-baseline\">\n <dt className=\"text-muted-foreground\">{row.label}</dt>\n <dd>\n <kbd className=\"rounded border bg-muted px-1.5 py-0.5 font-mono text-xs\">{row.keys}</kbd>\n </dd>\n </div>\n ))}\n </dl>\n </DialogContent>\n </Dialog>\n );\n}\n","'use client';\n\nimport { Keyboard } from 'lucide-react';\nimport { useQuoin } from '../context';\nimport { paletteBlocks } from '../registry';\nimport type { CaretRect } from './caret-coordinates';\nimport { TEXT_COMMANDS, type TextCommand } from './commands';\nimport { formatShortcut } from './shortcut-label';\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n CommandShortcut,\n} from '../ui/command';\nimport { Popover, PopoverAnchor, PopoverContent } from '../ui/popover';\n\nexport function SlashPalette({\n open,\n caret,\n onOpenChange,\n onTextCommand,\n onBlockCommand,\n onShortcuts,\n onDismiss,\n}: {\n open: boolean;\n caret: CaretRect | null;\n onOpenChange: (open: boolean) => void;\n onTextCommand: (command: TextCommand) => void;\n onBlockCommand: (type: string) => void;\n onShortcuts: () => void;\n onDismiss: () => void;\n}) {\n const { blockTypes } = useQuoin();\n const blockOptions = paletteBlocks(blockTypes);\n return (\n <Popover open={open} onOpenChange={onOpenChange}>\n <PopoverAnchor asChild>\n <span\n aria-hidden=\"true\"\n className=\"pointer-events-none absolute\"\n style={caret ? { top: caret.top, left: caret.left, height: caret.height } : { top: 0, left: 0 }}\n />\n </PopoverAnchor>\n <PopoverContent\n aria-label=\"Command palette\"\n align=\"start\"\n side=\"bottom\"\n sideOffset={4}\n className=\"w-72 p-0\"\n onEscapeKeyDown={(event) => {\n event.preventDefault();\n onDismiss();\n }}\n // Radix restores focus to the trigger on close, and this palette has an\n // aria-hidden anchor that cannot hold it, so the restore would drop focus\n // to the body. Both callers refocus the textarea before applying the edit.\n onCloseAutoFocus={(event) => event.preventDefault()}\n >\n <Command label=\"Search commands\">\n <CommandInput placeholder=\"Search commands\" />\n <CommandList>\n <CommandEmpty>No command found.</CommandEmpty>\n <CommandGroup heading=\"Text\">\n {TEXT_COMMANDS.map((command) => (\n <CommandItem\n key={command.id}\n value={`${command.label} ${command.keywords.join(' ')}`}\n onSelect={() => onTextCommand(command)}\n >\n <command.icon aria-hidden=\"true\" />\n <span>{command.label}</span>\n {command.hint ? <CommandShortcut>{formatShortcut(command.hint)}</CommandShortcut> : null}\n </CommandItem>\n ))}\n </CommandGroup>\n <CommandGroup heading=\"Blocks\">\n {blockOptions.map((option) => (\n <CommandItem key={option.type} value={option.label} onSelect={() => onBlockCommand(option.type)}>\n <option.icon aria-hidden=\"true\" />\n <span>{option.label}</span>\n </CommandItem>\n ))}\n </CommandGroup>\n <CommandGroup>\n <CommandItem value=\"keyboard shortcuts help\" onSelect={onShortcuts}>\n <Keyboard aria-hidden=\"true\" />\n <span>Keyboard shortcuts</span>\n </CommandItem>\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n );\n}\n","import {\n Code,\n Heading1,\n Heading2,\n Heading3,\n List,\n ListOrdered,\n ListTodo,\n Minus,\n Quote,\n Table,\n type LucideIcon,\n} from 'lucide-react';\n\n/** A slash-palette entry: how it is shown and searched, and the markdown it inserts. */\nexport type TextCommand = {\n id: string;\n label: string;\n keywords: string[];\n icon: LucideIcon;\n hint?: string;\n insert: string;\n caretOffset: number;\n selectLength?: number;\n /** Needs a blank line above it: a divider after a paragraph line parses as a\n * setext heading, and a GFM table cannot interrupt a paragraph at all. */\n separate: boolean;\n};\n\nconst TABLE = ['| Column | Column |', '| --- | --- |', '| | |'].join('\\n');\n\n/** The built-in slash-palette commands, in display order. */\nexport const TEXT_COMMANDS: TextCommand[] = [\n {\n id: 'heading',\n label: 'Heading',\n keywords: ['h1', 'title', 'heading', 'big'],\n icon: Heading1,\n hint: 'mod+alt+1',\n insert: '# ',\n caretOffset: 2,\n separate: false,\n },\n {\n id: 'subtitle',\n label: 'Subtitle',\n keywords: ['h2', 'subtitle', 'section', 'subheading'],\n icon: Heading2,\n hint: 'mod+alt+2',\n insert: '## ',\n caretOffset: 3,\n separate: false,\n },\n {\n id: 'subsubtitle',\n label: 'Sub-subtitle',\n keywords: ['h3', 'subsubtitle', 'minor'],\n icon: Heading3,\n hint: 'mod+alt+3',\n insert: '### ',\n caretOffset: 4,\n separate: false,\n },\n {\n id: 'bullet',\n label: 'Bullet list',\n keywords: ['bullet', 'unordered', 'ul', 'list', 'point'],\n icon: List,\n hint: 'mod+shift+8',\n insert: '- ',\n caretOffset: 2,\n separate: false,\n },\n {\n id: 'numbered',\n label: 'Numbered list',\n keywords: ['numbered', 'ordered', 'ol', 'steps'],\n icon: ListOrdered,\n hint: 'mod+shift+7',\n insert: '1. ',\n caretOffset: 3,\n separate: false,\n },\n {\n id: 'task',\n label: 'Task list',\n keywords: ['task', 'todo', 'checkbox', 'checklist'],\n icon: ListTodo,\n insert: '- [ ] ',\n caretOffset: 6,\n separate: false,\n },\n {\n id: 'quote',\n label: 'Quote',\n keywords: ['quote', 'blockquote', 'citation'],\n icon: Quote,\n insert: '> ',\n caretOffset: 2,\n separate: false,\n },\n {\n id: 'code',\n label: 'Code block',\n keywords: ['code', 'snippet', 'fence', 'pre'],\n icon: Code,\n insert: '```\\n\\n```',\n caretOffset: 3,\n separate: true,\n },\n {\n id: 'divider',\n label: 'Divider',\n keywords: ['divider', 'rule', 'hr', 'separator', 'break'],\n icon: Minus,\n insert: '---\\n',\n caretOffset: 4,\n separate: true,\n },\n {\n id: 'table',\n label: 'Table',\n keywords: ['table', 'grid', 'rows', 'columns'],\n icon: Table,\n insert: TABLE,\n caretOffset: 2,\n selectLength: 6,\n separate: true,\n },\n];\n","\"use client\"\n\nimport * as React from \"react\"\nimport { Command as CommandPrimitive } from \"cmdk\"\nimport { SearchIcon } from \"lucide-react\"\n\nimport { cn } from \"./cn\"\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n} from \"./dialog\"\n\nfunction Command({\n className,\n ...props\n}: React.ComponentProps<typeof CommandPrimitive>) {\n return (\n <CommandPrimitive\n data-slot=\"command\"\n className={cn(\n \"flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CommandDialog({\n title = \"Command Palette\",\n description = \"Search for a command to run...\",\n children,\n className,\n ...props\n}: React.ComponentProps<typeof Dialog> & {\n title?: string\n description?: string\n className?: string\n}) {\n return (\n <Dialog {...props}>\n <DialogHeader className=\"sr-only\">\n <DialogTitle>{title}</DialogTitle>\n <DialogDescription>{description}</DialogDescription>\n </DialogHeader>\n <DialogContent className={cn(\"overflow-hidden p-0\", className)}>\n <Command className=\"**:data-[slot=command-input-wrapper]:h-12 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]]:px-2 [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5\">\n {children}\n </Command>\n </DialogContent>\n </Dialog>\n )\n}\n\nfunction CommandInput({\n className,\n ...props\n}: React.ComponentProps<typeof CommandPrimitive.Input>) {\n return (\n <div\n data-slot=\"command-input-wrapper\"\n className=\"flex h-9 items-center gap-2 border-b px-3\"\n >\n <SearchIcon className=\"size-4 shrink-0 opacity-50\" />\n <CommandPrimitive.Input\n data-slot=\"command-input\"\n className={cn(\n \"flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-hidden placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50\",\n className\n )}\n {...props}\n />\n </div>\n )\n}\n\nfunction CommandList({\n className,\n ...props\n}: React.ComponentProps<typeof CommandPrimitive.List>) {\n return (\n <CommandPrimitive.List\n data-slot=\"command-list\"\n className={cn(\n \"max-h-[300px] scroll-py-1 overflow-x-hidden overflow-y-auto\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CommandEmpty({\n ...props\n}: React.ComponentProps<typeof CommandPrimitive.Empty>) {\n return (\n <CommandPrimitive.Empty\n data-slot=\"command-empty\"\n className=\"py-6 text-center text-sm\"\n {...props}\n />\n )\n}\n\nfunction CommandGroup({\n className,\n ...props\n}: React.ComponentProps<typeof CommandPrimitive.Group>) {\n return (\n <CommandPrimitive.Group\n data-slot=\"command-group\"\n className={cn(\n \"overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CommandSeparator({\n className,\n ...props\n}: React.ComponentProps<typeof CommandPrimitive.Separator>) {\n return (\n <CommandPrimitive.Separator\n data-slot=\"command-separator\"\n className={cn(\"-mx-1 h-px bg-border\", className)}\n {...props}\n />\n )\n}\n\nfunction CommandItem({\n className,\n ...props\n}: React.ComponentProps<typeof CommandPrimitive.Item>) {\n return (\n <CommandPrimitive.Item\n data-slot=\"command-item\"\n className={cn(\n \"relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CommandShortcut({\n className,\n ...props\n}: React.ComponentProps<\"span\">) {\n return (\n <span\n data-slot=\"command-shortcut\"\n className={cn(\n \"ml-auto text-xs tracking-widest text-muted-foreground\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n Command,\n CommandDialog,\n CommandInput,\n CommandList,\n CommandEmpty,\n CommandGroup,\n CommandItem,\n CommandShortcut,\n CommandSeparator,\n}\n","import * as React from \"react\";\nimport * as PopoverPrimitive from \"@radix-ui/react-popover\";\nimport { cn } from \"./cn\";\n\nfunction Popover(props: React.ComponentProps<typeof PopoverPrimitive.Root>) {\n return <PopoverPrimitive.Root data-slot=\"popover\" {...props} />;\n}\nfunction PopoverTrigger(props: React.ComponentProps<typeof PopoverPrimitive.Trigger>) {\n return <PopoverPrimitive.Trigger data-slot=\"popover-trigger\" {...props} />;\n}\nfunction PopoverAnchor(props: React.ComponentProps<typeof PopoverPrimitive.Anchor>) {\n return <PopoverPrimitive.Anchor data-slot=\"popover-anchor\" {...props} />;\n}\nfunction PopoverContent({ className, align = \"center\", sideOffset = 4, ...props }: React.ComponentProps<typeof PopoverPrimitive.Content>) {\n return (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n data-slot=\"popover-content\"\n align={align}\n sideOffset={sideOffset}\n className={cn(\n \"quoin bg-popover text-popover-foreground z-50 w-72 origin-(--radix-popover-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden\",\n className,\n )}\n {...props}\n />\n </PopoverPrimitive.Portal>\n );\n}\nexport { Popover, PopoverAnchor, PopoverTrigger, PopoverContent };\n","import * as React from 'react';\nimport { applyEdit, type Edit } from './edit';\nimport { indentList } from './indent-list';\nimport { toggleLinePrefix, type LinePrefix } from './line-toggles';\nimport { continueList } from './list-continuation';\nimport { shouldOpenPalette } from './slash-trigger';\nimport { linkPaste, wrapSelection, type WrapKind } from './wrap-selection';\n\nconst WRAP: Record<string, WrapKind> = { b: 'bold', i: 'italic', e: 'code', k: 'link' };\n\n// Shift turns the 8 key into \"*\", so the physical code is the only stable match.\nconst HEADING: Record<string, LinePrefix> = { Digit1: 'h1', Digit2: 'h2', Digit3: 'h3' };\nconst LIST: Record<string, LinePrefix> = { Digit7: 'ordered', Digit8: 'bullet' };\n\n/** Keyboard and paste handlers that give a plain textarea markdown shortcuts, list continuation, Tab indent and the slash palette trigger. */\nexport function useMarkdownKeymap({\n commit,\n onOpenPalette,\n}: {\n commit: (markdown: string) => void;\n onOpenPalette: () => void;\n}) {\n const onKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLTextAreaElement>) => {\n const el = event.currentTarget;\n const { value, selectionStart, selectionEnd } = el;\n const mod = event.metaKey || event.ctrlKey;\n\n const run = (edit: Edit | null) => {\n if (!edit) return;\n event.preventDefault();\n applyEdit(el, edit, commit);\n };\n\n if (mod && event.altKey) {\n const kind = HEADING[event.code];\n if (kind) run(toggleLinePrefix(kind, value, selectionStart, selectionEnd));\n return;\n }\n\n if (mod && event.shiftKey) {\n const kind = LIST[event.code];\n if (kind) run(toggleLinePrefix(kind, value, selectionStart, selectionEnd));\n return;\n }\n\n if (mod) {\n const kind = WRAP[event.key.toLowerCase()];\n if (kind) run(wrapSelection(kind, value, selectionStart, selectionEnd));\n return;\n }\n\n if (event.key === '/') {\n if (!shouldOpenPalette(value, selectionStart, selectionEnd)) return;\n event.preventDefault();\n onOpenPalette();\n return;\n }\n\n if (event.key === 'Enter' && !event.shiftKey) {\n run(continueList(value, selectionStart, 'Enter'));\n return;\n }\n\n if (event.key === 'Backspace' && selectionStart === selectionEnd) {\n run(continueList(value, selectionStart, 'Backspace'));\n return;\n }\n\n if (event.key === 'Tab') {\n run(indentList(value, selectionStart, selectionEnd, event.shiftKey ? -1 : 1));\n }\n },\n [commit, onOpenPalette],\n );\n\n const onPaste = React.useCallback(\n (event: React.ClipboardEvent<HTMLTextAreaElement>) => {\n const el = event.currentTarget;\n const edit = linkPaste(\n el.value,\n el.selectionStart,\n el.selectionEnd,\n event.clipboardData.getData('text/plain'),\n );\n if (!edit) return;\n event.preventDefault();\n applyEdit(el, edit, commit);\n },\n [commit],\n );\n\n return { onKeyDown, onPaste };\n}\n","import type { Edit } from './edit';\nimport { insideFence, lineAt, type Line } from './line-at';\n\nexport const LIST_MARKER = /^(\\s*)((?:[-*+] \\[[ xX]\\] )|(?:[-*+] )|(?:\\d+[.)] )|(?:> ))(.*)$/;\n\nconst INDENT = ' ';\n\nfunction nextMarker(marker: string): string {\n const ordered = /^(\\d+)([.)] )$/.exec(marker);\n if (ordered) return `${Number(ordered[1]) + 1}${ordered[2]}`;\n const task = /^([-*+]) \\[[ xX]\\] $/.exec(marker);\n if (task) return `${task[1]} [ ] `;\n return marker;\n}\n\n// Both the dead item on Enter and the caret at the content start on Backspace\n// mean the same thing: climb out one level, or drop the marker at the top.\nfunction climbOut(value: string, line: Line, indent: string, marker: string, content: string): Edit {\n const outdent = indent.length >= INDENT.length;\n\n if (outdent) {\n const text = indent.slice(INDENT.length) + marker + content;\n const at = line.start + indent.length - INDENT.length + marker.length;\n return {\n value: value.slice(0, line.start) + text + value.slice(line.end),\n selectionStart: at,\n selectionEnd: at,\n };\n }\n\n // A stripped marker with only a single newline above it reads to CommonMark\n // as a lazy continuation of the previous list item's paragraph, not a new\n // block, so a blank line is needed whenever that previous line is a list item.\n const leavesList = line.start > 0 && LIST_MARKER.test(lineAt(value, line.start - 1).text);\n const text = leavesList ? `\\n${content}` : content;\n const at = leavesList ? line.start + 1 : line.start;\n\n return {\n value: value.slice(0, line.start) + text + value.slice(line.end),\n selectionStart: at,\n selectionEnd: at,\n };\n}\n\n/** Continues a list item on Enter, or climbs out of the list on an empty item or Backspace at the marker; returns null when the caret is not in a list item or is inside a code fence, so the default key behaviour runs. */\nexport function continueList(\n value: string,\n caret: number,\n key: 'Enter' | 'Backspace',\n): Edit | null {\n if (insideFence(value, caret)) return null;\n\n const line = lineAt(value, caret);\n const match = LIST_MARKER.exec(line.text);\n if (!match) return null;\n\n const [, indent, marker, content] = match;\n\n if (key === 'Backspace') {\n if (caret !== line.start + indent.length + marker.length) return null;\n return climbOut(value, line, indent, marker, content);\n }\n\n if (content.trim() === '') return climbOut(value, line, indent, marker, content);\n\n const inserted = `\\n${indent}${nextMarker(marker)}`;\n const at = caret + inserted.length;\n return {\n value: value.slice(0, caret) + inserted + value.slice(caret),\n selectionStart: at,\n selectionEnd: at,\n };\n}\n","import type { Edit } from './edit';\nimport { insideFence, lineAt } from './line-at';\nimport { LIST_MARKER } from './list-continuation';\n\nconst INDENT = ' ';\n\nfunction indentOf(text: string): number {\n return /^\\s*/.exec(text)?.[0].length ?? 0;\n}\n\n// Indenting more than one level past the line above turns a list item into an\n// indented code block, so the first line of the range is capped against it.\nfunction shift(text: string, direction: 1 | -1, cap: number | undefined): string {\n const current = indentOf(text);\n if (direction === -1) return text.slice(Math.min(current, INDENT.length));\n if (cap !== undefined && current >= cap + INDENT.length) return text;\n return INDENT + text;\n}\n\n/** Indents or outdents the selected list items; returns null when the selection is not entirely list items, is inside a code fence, or cannot move further, so Tab keeps its default behaviour. */\nexport function indentList(\n value: string,\n selectionStart: number,\n selectionEnd: number,\n direction: 1 | -1,\n): Edit | null {\n if (insideFence(value, selectionStart)) return null;\n\n const first = lineAt(value, selectionStart);\n const last = lineAt(value, selectionEnd);\n const block = value.slice(first.start, last.end);\n const lines = block.split('\\n');\n if (!lines.every((text) => LIST_MARKER.test(text))) return null;\n\n const cap = first.start === 0 ? 0 : indentOf(lineAt(value, first.start - 1).text);\n const shifted = lines.map((text, i) => shift(text, direction, i === 0 ? cap : undefined));\n if (shifted.every((text, i) => text === lines[i])) return null;\n\n const joined = shifted.join('\\n');\n return {\n value: value.slice(0, first.start) + joined + value.slice(last.end),\n selectionStart: selectionStart + (shifted[0].length - lines[0].length),\n selectionEnd: selectionEnd + (joined.length - block.length),\n };\n}\n","import type { Edit } from './edit';\nimport { insideFence, isFenceDelimiter, lineAt } from './line-at';\n\n/** A line-level markdown prefix: a heading level, a bullet or a numbered item. */\nexport type LinePrefix = 'h1' | 'h2' | 'h3' | 'bullet' | 'ordered';\n\nconst EXISTING = /^(\\s*)(?:#{1,6} |[-*+] \\[[ xX]\\] |[-*+] |\\d+[.)] )?/;\n\nconst PREFIX: Record<LinePrefix, (index: number) => string> = {\n h1: () => '# ',\n h2: () => '## ',\n h3: () => '### ',\n bullet: () => '- ',\n ordered: (index) => `${index + 1}. `,\n};\n\nconst CARRIES: Record<LinePrefix, RegExp> = {\n h1: /^\\s*# /,\n h2: /^\\s*## /,\n h3: /^\\s*### /,\n bullet: /^\\s*[-*+] /,\n ordered: /^\\s*\\d+[.)] /,\n};\n\n/** Adds the prefix to every line in the selection, or removes it when every line already carries it; fenced code is left alone. */\nexport function toggleLinePrefix(\n kind: LinePrefix,\n value: string,\n selectionStart: number,\n selectionEnd: number,\n): Edit {\n const first = lineAt(value, selectionStart);\n const last = lineAt(value, selectionEnd);\n const block = value.slice(first.start, last.end);\n const lines = block.split('\\n');\n\n let offset = first.start;\n const eligible = lines.map((text) => {\n const at = offset;\n offset += text.length + 1;\n return !insideFence(value, at) && !isFenceDelimiter(text);\n });\n\n const carried = lines.every((text, i) => !eligible[i] || CARRIES[kind].test(text));\n\n const rewritten = lines.map((text, i) => {\n if (!eligible[i]) return text;\n const match = EXISTING.exec(text);\n const indent = match?.[1] ?? '';\n const body = text.slice(match?.[0].length ?? 0);\n return carried ? indent + body : indent + PREFIX[kind](i) + body;\n });\n\n const joined = rewritten.join('\\n');\n const next = value.slice(0, first.start) + joined + value.slice(last.end);\n\n if (selectionStart !== selectionEnd) {\n return { value: next, selectionStart: first.start, selectionEnd: first.start + joined.length };\n }\n\n const caret = Math.max(first.start, selectionStart + (rewritten[0].length - lines[0].length));\n return { value: next, selectionStart: caret, selectionEnd: caret };\n}\n","import { insideFence } from './line-at';\n\n/** Whether typing \"/\" here should open the command palette: only at a word start, with no selection and outside a code fence. */\nexport function shouldOpenPalette(\n value: string,\n selectionStart: number,\n selectionEnd: number,\n): boolean {\n if (selectionStart !== selectionEnd) return false;\n if (insideFence(value, selectionStart)) return false;\n if (selectionStart === 0) return true;\n\n const previous = value[selectionStart - 1];\n return previous === '\\n' || previous === ' ' || previous === '\\t';\n}\n","import type { Edit } from './edit';\n\n/** An inline markdown wrapper: bold, italic, code or a link. */\nexport type WrapKind = 'bold' | 'italic' | 'code' | 'link';\n\nconst DELIMITER: Record<Exclude<WrapKind, 'link'>, string> = {\n bold: '**',\n italic: '_',\n code: '`',\n};\n\nconst WHOLE_LINK = /^\\[([^\\]]*)\\]\\(([^)]*)\\)$/;\nconst BARE_URL = /^https?:\\/\\/[^\\s]+$/;\n\nfunction unwrap(value: string, start: number, end: number, delimiter: string): Edit | null {\n const selected = value.slice(start, end);\n const width = delimiter.length;\n\n if (selected.length >= 2 * width && selected.startsWith(delimiter) && selected.endsWith(delimiter)) {\n const inner = selected.slice(width, selected.length - width);\n return {\n value: value.slice(0, start) + inner + value.slice(end),\n selectionStart: start,\n selectionEnd: start + inner.length,\n };\n }\n\n const outside =\n start >= width &&\n value.slice(start - width, start) === delimiter &&\n value.slice(end, end + width) === delimiter;\n\n if (!outside) return null;\n\n return {\n value: value.slice(0, start - width) + selected + value.slice(end + width),\n selectionStart: start - width,\n selectionEnd: start - width + selected.length,\n };\n}\n\nfunction link(value: string, start: number, end: number): Edit {\n const selected = value.slice(start, end);\n const whole = WHOLE_LINK.exec(selected);\n\n if (whole) {\n const text = whole[1];\n return {\n value: value.slice(0, start) + text + value.slice(end),\n selectionStart: start,\n selectionEnd: start + text.length,\n };\n }\n\n const opened = `[${selected}](`;\n const at = selected === '' ? start + 1 : start + opened.length;\n return {\n value: value.slice(0, start) + opened + ')' + value.slice(end),\n selectionStart: at,\n selectionEnd: at,\n };\n}\n\n/** Wraps the selection in the markers for the kind, or removes them when it is already wrapped. */\nexport function wrapSelection(\n kind: WrapKind,\n value: string,\n selectionStart: number,\n selectionEnd: number,\n): Edit {\n if (kind === 'link') return link(value, selectionStart, selectionEnd);\n\n const delimiter = DELIMITER[kind];\n const stripped = unwrap(value, selectionStart, selectionEnd, delimiter);\n if (stripped) return stripped;\n\n const selected = value.slice(selectionStart, selectionEnd);\n\n if (kind === 'code' && selected.includes('\\n')) {\n const at = selectionStart + 4;\n return {\n value: value.slice(0, selectionStart) + '```\\n' + selected + '\\n```' + value.slice(selectionEnd),\n selectionStart: at,\n selectionEnd: at + selected.length,\n };\n }\n\n const at = selectionStart + delimiter.length;\n return {\n value: value.slice(0, selectionStart) + delimiter + selected + delimiter + value.slice(selectionEnd),\n selectionStart: at,\n selectionEnd: at + selected.length,\n };\n}\n\n/** Turns a pasted URL over a selection into a markdown link; returns null when nothing is selected or the paste is not a bare URL, so the paste goes through unchanged. */\nexport function linkPaste(\n value: string,\n selectionStart: number,\n selectionEnd: number,\n pasted: string,\n): Edit | null {\n if (selectionStart === selectionEnd) return null;\n\n const url = pasted.trim();\n if (!BARE_URL.test(url)) return null;\n\n const inserted = `[${value.slice(selectionStart, selectionEnd)}](${url})`;\n const at = selectionStart + inserted.length;\n return {\n value: value.slice(0, selectionStart) + inserted + value.slice(selectionEnd),\n selectionStart: at,\n selectionEnd: at,\n };\n}\n","import * as React from 'react';\nimport { caretRect, type CaretRect } from './caret-coordinates';\n\nexport function useSlashPalette(ref: React.RefObject<HTMLTextAreaElement | null>) {\n const [open, setOpen] = React.useState(false);\n const [caret, setCaret] = React.useState<CaretRect | null>(null);\n const offsetRef = React.useRef(0);\n\n const openAtCaret = React.useCallback(() => {\n const el = ref.current;\n if (!el) return;\n offsetRef.current = el.selectionStart;\n setCaret(caretRect(el));\n setOpen(true);\n }, [ref]);\n\n return { open, setOpen, caret, offsetRef, openAtCaret };\n}\n","type CopiedProperty =\n | 'boxSizing'\n | 'fontFamily'\n | 'fontSize'\n | 'fontStyle'\n | 'fontWeight'\n | 'letterSpacing'\n | 'lineHeight'\n | 'paddingBottom'\n | 'paddingLeft'\n | 'paddingRight'\n | 'paddingTop'\n | 'textIndent'\n | 'textTransform'\n | 'wordBreak'\n | 'wordSpacing'\n | 'borderBottomWidth'\n | 'borderLeftWidth'\n | 'borderRightWidth'\n | 'borderTopWidth';\n\nconst COPIED: CopiedProperty[] = [\n 'boxSizing',\n 'fontFamily',\n 'fontSize',\n 'fontStyle',\n 'fontWeight',\n 'letterSpacing',\n 'lineHeight',\n 'paddingBottom',\n 'paddingLeft',\n 'paddingRight',\n 'paddingTop',\n 'textIndent',\n 'textTransform',\n 'wordBreak',\n 'wordSpacing',\n 'borderBottomWidth',\n 'borderLeftWidth',\n 'borderRightWidth',\n 'borderTopWidth',\n];\n\n/** The caret's position and line height, in pixels relative to the textarea's top left corner. */\nexport type CaretRect = { top: number; left: number; height: number };\n\n/** A textarea exposes no caret geometry, so the text before the caret is laid\n * out again in a hidden div that copies the box's own metrics, and a marker at\n * the end of it is measured. Returns null when the textarea is not laid out\n * (hidden or detached), because there is nothing to measure. */\nexport function caretRect(el: HTMLTextAreaElement): CaretRect | null {\n if (el.offsetWidth === 0) return null;\n\n const style = window.getComputedStyle(el);\n const mirror = document.createElement('div');\n for (const property of COPIED) mirror.style[property] = style[property];\n mirror.style.position = 'absolute';\n mirror.style.top = '0';\n mirror.style.left = '-9999px';\n mirror.style.visibility = 'hidden';\n mirror.style.whiteSpace = 'pre-wrap';\n mirror.style.overflowWrap = 'break-word';\n mirror.style.width = `${el.clientWidth}px`;\n mirror.textContent = el.value.slice(0, el.selectionStart);\n\n const marker = document.createElement('span');\n marker.textContent = '\\u200b';\n mirror.appendChild(marker);\n document.body.appendChild(mirror);\n\n const top = marker.offsetTop;\n const left = marker.offsetLeft;\n const height = marker.offsetHeight || Number.parseFloat(style.lineHeight) || 0;\n mirror.remove();\n\n if (height === 0) return null;\n return { top: top - el.scrollTop, left, height };\n}\n","import * as React from 'react';\n\n/** Height follows the content, and is recomputed when the box gets narrower or\n * wider, because a re-wrap changes the line count without changing the value.\n * Only a width change refits: reacting to the height this hook just set would\n * feed the observer its own output. */\nexport function useAutoGrow<T extends HTMLTextAreaElement>(value: string) {\n const ref = React.useRef<T>(null);\n const lastWidth = React.useRef<number | null>(null);\n\n // Measuring means collapsing to \"auto\" first, which shrinks the page enough that\n // the browser clamps the scroll position, and growing back does not undo that.\n // Both steps run before paint, so restoring the scroll here is not visible.\n const fit = React.useCallback(() => {\n const el = ref.current;\n if (!el) return;\n const scroller = document.scrollingElement ?? document.documentElement;\n const scrollTop = scroller.scrollTop;\n el.style.height = 'auto';\n if (el.scrollHeight > 0) el.style.height = `${el.scrollHeight}px`;\n if (scroller.scrollTop !== scrollTop) scroller.scrollTop = scrollTop;\n }, []);\n\n React.useLayoutEffect(fit, [fit, value]);\n\n React.useEffect(() => {\n const el = ref.current;\n if (!el || typeof ResizeObserver === 'undefined') return;\n const observer = new ResizeObserver(([entry]) => {\n const width = entry.contentRect.width;\n if (width === lastWidth.current) return;\n lastWidth.current = width;\n fit();\n });\n observer.observe(el);\n return () => observer.disconnect();\n }, [fit]);\n\n return ref;\n}\n","export const str = (v: unknown) => (typeof v === 'string' ? v : '');\n","\"use client\";\n\nimport * as React from \"react\";\nimport * as SelectPrimitive from \"@radix-ui/react-select\";\nimport { CheckIcon, ChevronDownIcon, ChevronUpIcon } from \"lucide-react\";\nimport { cn } from \"./cn\";\nimport { TAP_TARGET_FLOOR } from \"./touch-target\";\n\nfunction Select(props: React.ComponentProps<typeof SelectPrimitive.Root>) {\n return <SelectPrimitive.Root data-slot=\"select\" {...props} />;\n}\nfunction SelectValue(props: React.ComponentProps<typeof SelectPrimitive.Value>) {\n return <SelectPrimitive.Value data-slot=\"select-value\" {...props} />;\n}\nfunction SelectTrigger({ className, children, ...props }: React.ComponentProps<typeof SelectPrimitive.Trigger>) {\n return (\n <SelectPrimitive.Trigger\n data-slot=\"select-trigger\"\n className={cn(\n \"border-input data-[placeholder]:text-muted-foreground flex h-9 w-full cursor-pointer items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm shadow-xs outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0\",\n TAP_TARGET_FLOOR,\n className,\n )}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <ChevronDownIcon className=\"size-4 opacity-50\" />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n );\n}\nfunction SelectContent({ className, children, position = \"popper\", ...props }: React.ComponentProps<typeof SelectPrimitive.Content>) {\n return (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n data-slot=\"select-content\"\n className={cn(\n \"quoin bg-popover text-popover-foreground relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-md border shadow-md\",\n position === \"popper\" && \"data-[side=bottom]:translate-y-1\",\n className,\n )}\n position={position}\n {...props}\n >\n <SelectPrimitive.ScrollUpButton className=\"flex cursor-default items-center justify-center py-1\">\n <ChevronUpIcon className=\"size-4\" />\n </SelectPrimitive.ScrollUpButton>\n <SelectPrimitive.Viewport className={cn(\"p-1\", position === \"popper\" && \"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]\")}>\n {children}\n </SelectPrimitive.Viewport>\n <SelectPrimitive.ScrollDownButton className=\"flex cursor-default items-center justify-center py-1\">\n <ChevronDownIcon className=\"size-4\" />\n </SelectPrimitive.ScrollDownButton>\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n );\n}\nfunction SelectItem({ className, children, ...props }: React.ComponentProps<typeof SelectPrimitive.Item>) {\n return (\n <SelectPrimitive.Item\n data-slot=\"select-item\"\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n TAP_TARGET_FLOOR,\n className,\n )}\n {...props}\n >\n <span className=\"absolute right-2 flex size-3.5 items-center justify-center\">\n <SelectPrimitive.ItemIndicator>\n <CheckIcon className=\"size-4\" />\n </SelectPrimitive.ItemIndicator>\n </span>\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n </SelectPrimitive.Item>\n );\n}\nexport { Select, SelectValue, SelectTrigger, SelectContent, SelectItem };\n","import * as React from \"react\";\nimport { cn } from \"./cn\";\n\nfunction Textarea({ className, ...props }: React.ComponentProps<\"textarea\">) {\n return (\n <textarea\n data-slot=\"textarea\"\n className={cn(\n \"border-input placeholder:text-muted-foreground flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none disabled:pointer-events-none disabled:opacity-50 md:text-sm\",\n \"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]\",\n \"aria-invalid:ring-destructive/20 aria-invalid:border-destructive\",\n className,\n )}\n {...props}\n />\n );\n}\n\nexport { Textarea };\n","'use client';\n\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../ui/select';\nimport { Textarea } from '../ui/textarea';\nimport type { BlockEditorProps } from '../types';\nimport { str } from './str';\n\nconst CALLOUT_TONES = ['info', 'tip', 'warning', 'success', 'danger'] as const;\n\nexport function CalloutBlockEditor({ data, onChange }: BlockEditorProps) {\n const set = (patch: Record<string, unknown>) => onChange({ ...data, ...patch });\n\n return (\n <div className=\"flex flex-col gap-2\">\n <div className=\"flex flex-col gap-1\">\n <span className=\"text-sm font-medium leading-none\">Tone</span>\n <Select value={str(data.tone) || 'info'} onValueChange={(v) => set({ tone: v })}>\n <SelectTrigger aria-label=\"Callout tone\" className=\"w-40 capitalize\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {CALLOUT_TONES.map((t) => (\n <SelectItem key={t} value={t} className=\"capitalize\">\n {t}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <label className=\"flex flex-col gap-1\">\n <span className=\"text-sm font-medium leading-none\">Callout text</span>\n <Textarea value={str(data.body)} onChange={(e) => set({ body: e.target.value })} className=\"text-sm\" />\n </label>\n </div>\n );\n}\n","import * as React from \"react\";\nimport { cn } from \"./cn\";\nimport { TAP_TARGET_FLOOR } from \"./touch-target\";\n\nfunction Input({ className, type, ...props }: React.ComponentProps<\"input\">) {\n return (\n <input\n type={type}\n data-slot=\"input\"\n className={cn(\n \"border-input placeholder:text-muted-foreground flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:opacity-50 md:text-sm\",\n \"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]\",\n \"aria-invalid:ring-destructive/20 aria-invalid:border-destructive\",\n TAP_TARGET_FLOOR,\n className,\n )}\n {...props}\n />\n );\n}\n\nexport { Input };\n","'use client';\n\nimport { Input } from '../ui/input';\nimport { Textarea } from '../ui/textarea';\nimport type { BlockEditorProps } from '../types';\nimport { str } from './str';\n\nexport function CodeBlockEditor({ data, onChange }: BlockEditorProps) {\n const set = (patch: Record<string, unknown>) => onChange({ ...data, ...patch });\n\n return (\n <div className=\"flex flex-col gap-2\">\n <label className=\"flex flex-col gap-1\">\n <span className=\"text-sm font-medium leading-none\">Language</span>\n <Input\n aria-label=\"Language\"\n value={str(data.language)}\n onChange={(e) => set({ language: e.target.value })}\n className=\"text-sm\"\n />\n </label>\n <label className=\"flex flex-col gap-1\">\n <span className=\"text-sm font-medium leading-none\">Code</span>\n <Textarea\n aria-label=\"Code\"\n value={str(data.code)}\n onChange={(e) => set({ code: e.target.value })}\n className=\"min-h-32 font-mono text-sm\"\n />\n </label>\n </div>\n );\n}\n","'use client';\n\nimport { useEffect, useRef } from 'react';\nimport { useQuoin } from '../context';\nimport { Input } from '../ui/input';\nimport { UploadField } from '../upload/UploadField';\nimport type { BlockEditorProps } from '../types';\nimport { str } from './str';\nimport { intrinsicSize } from './intrinsic-size';\n\nexport function ImageBlockEditor({ data, onChange }: BlockEditorProps) {\n const { resolveAssetUrl } = useQuoin();\n // Read through a ref: measuring the upload is async, and the alt/caption fields\n // stay editable while it runs.\n const latest = useRef(data);\n useEffect(() => {\n latest.current = data;\n });\n const set = (patch: Record<string, unknown>) => onChange({ ...latest.current, ...patch });\n\n const onUploaded = async (r: { storageKey: string }) => {\n const src = resolveAssetUrl(r.storageKey);\n const size = src ? await intrinsicSize(src) : null;\n set({ storageKey: r.storageKey, ...size });\n };\n\n return (\n <div className=\"flex flex-col gap-2\">\n <UploadField category=\"image\" label=\"Upload image\" onUploaded={onUploaded} />\n <label className=\"flex flex-col gap-1\">\n <span className=\"text-sm font-medium leading-none\">Alt text</span>\n <Input\n aria-label=\"Image alt text\"\n value={str(data.alt)}\n onChange={(e) => set({ alt: e.target.value })}\n className=\"text-sm\"\n />\n </label>\n <label className=\"flex flex-col gap-1\">\n <span className=\"text-sm font-medium leading-none\">Caption (optional)</span>\n <Input\n aria-label=\"Image caption\"\n value={str(data.caption)}\n onChange={(e) => set({ caption: e.target.value })}\n className=\"text-sm\"\n />\n </label>\n {str(data.storageKey) && <span className=\"text-xs text-muted-foreground\">Image attached ✓</span>}\n </div>\n );\n}\n","'use client';\n\nimport * as React from 'react';\nimport { useQuoin } from '../context';\nimport type { UploadResult } from '../types';\nimport { FilePickerButton } from './FilePickerButton';\n\n/** Disables itself both while an upload is in flight and when the host configured no `upload` function. */\nexport function UploadField({\n category,\n label,\n accept,\n onUploaded,\n}: {\n category: string;\n label: string;\n accept?: string;\n onUploaded: (result: UploadResult) => void;\n}) {\n const { upload, onError } = useQuoin();\n const [busy, setBusy] = React.useState(false);\n const [error, setError] = React.useState<string | null>(null);\n\n async function run(file: File) {\n if (!upload) return;\n setBusy(true);\n setError(null);\n let result: UploadResult;\n try {\n result = await upload(file, category);\n } catch (cause) {\n setError((cause instanceof Error && cause.message) || 'Upload failed.');\n setBusy(false);\n return;\n }\n setBusy(false);\n try {\n onUploaded(result);\n } catch (cause) {\n onError(cause instanceof Error ? cause : new Error(String(cause)));\n }\n }\n\n return (\n <div className=\"flex flex-col items-start gap-1.5\">\n <FilePickerButton\n label={label}\n accept={accept}\n disabled={busy || !upload}\n onPick={(file) => void run(file)}\n />\n {!upload && (\n <span role=\"note\" className=\"text-xs text-muted-foreground\">\n Uploads are not configured for this editor.\n </span>\n )}\n {busy && <span role=\"status\" className=\"text-xs text-muted-foreground\">Uploading...</span>}\n {error && (\n <span role=\"alert\" className=\"text-xs text-destructive\">\n {error}\n </span>\n )}\n </div>\n );\n}\n","export type IntrinsicSize = { width: number; height: number };\n\n/** Persisted onto the block so the reader can reserve the box before the bytes\n * arrive. Resolves null rather than rejecting: a drop without them still renders,\n * it just reflows. */\nexport function intrinsicSize(src: string): Promise<IntrinsicSize | null> {\n return new Promise((resolve) => {\n if (typeof window === 'undefined') return resolve(null);\n const img = new window.Image();\n img.onload = () => resolve({ width: img.naturalWidth, height: img.naturalHeight });\n img.onerror = () => resolve(null);\n img.src = src;\n });\n}\n","'use client';\n\nimport { UploadField } from '../upload/UploadField';\nimport type { BlockEditorProps } from '../types';\nimport { str } from './str';\n\nexport function FileBlockEditor({ data, onChange }: BlockEditorProps) {\n const set = (patch: Record<string, unknown>) => onChange({ ...data, ...patch });\n\n return (\n <div className=\"flex flex-col gap-2\">\n <UploadField\n category=\"file\"\n label=\"Upload file\"\n onUploaded={(r) => set({ storageKey: r.storageKey, filename: r.filename, size: r.size })}\n />\n {str(data.filename) && <span className=\"text-xs text-muted-foreground\">{str(data.filename)} ✓</span>}\n </div>\n );\n}\n","'use client';\n\nimport { useQuoin } from '../context';\nimport type { BlockPreviewProps } from '../types';\nimport { str } from './str';\n\nconst HINT = 'text-sm text-muted-foreground';\n\nconst TONE_BORDER: Record<string, string> = {\n info: 'border-primary',\n tip: 'border-accent-foreground',\n warning: 'border-muted-foreground',\n success: 'border-secondary-foreground',\n danger: 'border-destructive',\n};\n\nexport function MarkdownPreview({ data }: BlockPreviewProps) {\n const markdown = str(data.markdown);\n if (markdown.trim() === '') return <p className={HINT}>Empty markdown block</p>;\n return <div className=\"whitespace-pre-wrap text-base leading-7\">{markdown}</div>;\n}\n\nexport function CodePreview({ data }: BlockPreviewProps) {\n const code = str(data.code);\n if (code.trim() === '') return <p className={HINT}>Empty code block</p>;\n return (\n <pre className=\"overflow-x-auto rounded-md bg-muted p-3 text-sm\">\n <code>{code}</code>\n </pre>\n );\n}\n\nexport function ImagePreview({ data }: BlockPreviewProps) {\n const { resolveAssetUrl } = useQuoin();\n const key = str(data.storageKey);\n // Guard on the key, not the resolved URL: a prefixing resolver turns an empty key into a truthy, dead address.\n if (key === '') return <p className={HINT}>No image chosen</p>;\n return <img src={resolveAssetUrl(key)} alt={str(data.alt)} className=\"max-w-full rounded-md\" />;\n}\n\nexport function FilePreview({ data }: BlockPreviewProps) {\n const name = str(data.filename);\n if (name === '') return <p className={HINT}>No file chosen</p>;\n return <p className=\"text-sm\">{name}</p>;\n}\n\nexport function CalloutPreview({ data }: BlockPreviewProps) {\n const body = str(data.body);\n if (body.trim() === '') return <p className={HINT}>Empty callout</p>;\n const tone = str(data.tone) || 'info';\n const border = TONE_BORDER[tone] ?? 'border-border';\n return (\n <div data-tone={tone} className={`rounded-md border-l-4 ${border} bg-muted/50 p-3 text-sm`}>\n {body}\n </div>\n );\n}\n","import * as React from 'react';\nimport type { QuoinBlock } from '../types';\nimport { newBlockId } from './new-block-id';\n\n/** Handed back by `remove` and accepted by `undo` to restore that one block. */\nexport type UndoToken = number;\n\ntype Removed = { block: QuoinBlock; index: number };\n\ntype State = {\n blocks: QuoinBlock[];\n removals: Map<UndoToken, Removed>;\n};\n\ntype Action =\n | { type: 'insertAt'; index: number; block: QuoinBlock }\n | { type: 'update'; id: string; data: Record<string, unknown> }\n | { type: 'remove'; id: string; token: UndoToken }\n | { type: 'undo'; token: UndoToken }\n | { type: 'move'; index: number; dir: -1 | 1 }\n | { type: 'reorder'; from: number; to: number }\n | { type: 'reset'; blocks: QuoinBlock[] };\n\nlet removalSeq = 0;\n\n/** A canvas may never call `undo`, so the oldest removals are dropped rather than kept\n * for the lifetime of the document. The cap is far past any run of deletes a person\n * would undo one by one. */\nconst UNDO_DEPTH = 20;\n\nfunction reducer(state: State, action: Action): State {\n switch (action.type) {\n case 'insertAt': {\n const next = [...state.blocks];\n next.splice(Math.max(0, Math.min(action.index, state.blocks.length)), 0, action.block);\n return { ...state, blocks: next };\n }\n case 'update': {\n return {\n ...state,\n blocks: state.blocks.map((b) => (b.id === action.id ? { ...b, data: action.data } : b)),\n };\n }\n case 'remove': {\n const index = state.blocks.findIndex((b) => b.id === action.id);\n if (index === -1) return state;\n const removals = new Map(state.removals);\n removals.set(action.token, { block: state.blocks[index], index });\n while (removals.size > UNDO_DEPTH) {\n const oldest = removals.keys().next();\n if (oldest.done) break;\n removals.delete(oldest.value);\n }\n return { blocks: state.blocks.filter((b) => b.id !== action.id), removals };\n }\n case 'undo': {\n const removal = state.removals.get(action.token);\n if (!removal) return state;\n const next = [...state.blocks];\n next.splice(Math.min(removal.index, state.blocks.length), 0, removal.block);\n const removals = new Map(state.removals);\n removals.delete(action.token);\n return { blocks: next, removals };\n }\n case 'move': {\n const j = action.index + action.dir;\n if (j < 0 || j >= state.blocks.length) return state;\n const next = [...state.blocks];\n [next[action.index], next[j]] = [next[j], next[action.index]];\n return { ...state, blocks: next };\n }\n case 'reorder': {\n const { from, to } = action;\n if (from < 0 || to < 0 || from >= state.blocks.length || to >= state.blocks.length) return state;\n const next = [...state.blocks];\n const [moved] = next.splice(from, 1);\n next.splice(to, 0, moved);\n return { ...state, blocks: next };\n }\n case 'reset':\n return { blocks: action.blocks, removals: new Map() };\n }\n}\n\n/** The document plus every way to change it; `reset` replaces the whole document and voids outstanding undo tokens. */\nexport type BlockList = {\n blocks: QuoinBlock[];\n insertAt: (index: number, type: string, data?: Record<string, unknown>) => string;\n update: (id: string, data: Record<string, unknown>) => void;\n /** Returns a token `undo` restores that block with; only the last 20 removals stay restorable. */\n remove: (id: string) => UndoToken;\n undo: (token: UndoToken) => void;\n move: (index: number, dir: -1 | 1) => void;\n reorder: (from: number, to: number) => void;\n reset: (blocks: QuoinBlock[]) => void;\n};\n\n/** Holds a document in a reducer and returns its blocks with insert, update, remove, undo, move, reorder and reset. Reads `initial` once. */\nexport function useBlockList(initial: QuoinBlock[]): BlockList {\n const [state, dispatch] = React.useReducer(reducer, { blocks: initial, removals: new Map() });\n\n const insertAt = React.useCallback(\n (index: number, type: string, data: Record<string, unknown> = {}): string => {\n const id = newBlockId();\n dispatch({ type: 'insertAt', index, block: { id, type, data } });\n return id;\n },\n [],\n );\n\n const update = React.useCallback((id: string, data: Record<string, unknown>) => {\n dispatch({ type: 'update', id, data });\n }, []);\n\n const remove = React.useCallback((id: string): UndoToken => {\n removalSeq += 1;\n const token = removalSeq;\n dispatch({ type: 'remove', id, token });\n return token;\n }, []);\n\n const undo = React.useCallback((token: UndoToken) => {\n dispatch({ type: 'undo', token });\n }, []);\n\n const move = React.useCallback((index: number, dir: -1 | 1) => {\n dispatch({ type: 'move', index, dir });\n }, []);\n\n const reorder = React.useCallback((from: number, to: number) => {\n dispatch({ type: 'reorder', from, to });\n }, []);\n\n const reset = React.useCallback((blocks: QuoinBlock[]) => {\n dispatch({ type: 'reset', blocks });\n }, []);\n\n return { blocks: state.blocks, insertAt, update, remove, undo, move, reorder, reset };\n}\n","/**\n * A fresh block id that cannot collide with one already in a persisted document.\n * It holds no counter, because a counter restarts on every page load and would\n * re-mint ids a host has stored.\n */\nexport function newBlockId(): string {\n const webCrypto = globalThis.crypto;\n if (webCrypto && typeof webCrypto.randomUUID === 'function') return webCrypto.randomUUID();\n // randomUUID is absent in insecure contexts and older runtimes.\n const random = () => Math.random().toString(36).slice(2, 10);\n return `blk-${Date.now().toString(36)}-${random()}${random()}`;\n}\n","import type { Announcements } from '@dnd-kit/core';\nimport { blockByType, type AnyBlockDefinition } from '../registry';\nimport type { QuoinBlock } from '../types';\n\nfunction describeBlock(blocks: QuoinBlock[], blockTypes: AnyBlockDefinition[], id: string): string {\n const index = blocks.findIndex((b) => b.id === id);\n if (index === -1) return 'block';\n const { type } = blocks[index];\n const label = blockByType(blockTypes, type)?.label ?? type;\n return `${label} block, position ${index + 1} of ${blocks.length}`;\n}\n\n/** The screen reader sentences a drag speaks, naming each block by its registered label and position. */\nexport function buildAnnouncements(blocks: QuoinBlock[], blockTypes: AnyBlockDefinition[]): Announcements {\n const describe = (id: string | number) => describeBlock(blocks, blockTypes, String(id));\n return {\n onDragStart({ active }) {\n return `Picked up ${describe(active.id)}.`;\n },\n onDragOver({ active, over }) {\n if (!over) return `${describe(active.id)} is no longer over a drop position.`;\n return `${describe(active.id)} was moved over ${describe(over.id)}.`;\n },\n onDragEnd({ active, over }) {\n if (!over) return `${describe(active.id)} was dropped.`;\n return `${describe(active.id)} was dropped over ${describe(over.id)}.`;\n },\n onDragCancel({ active }) {\n return `Dragging was cancelled. ${describe(active.id)} was dropped.`;\n },\n };\n}\n","'use client';\n\nimport { ArrowDown, ArrowUp, MoreHorizontal, Trash2 } from 'lucide-react';\nimport { Button } from '../ui/button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '../ui/dropdown-menu';\n\nexport function BlockActionsMenu({\n index,\n count,\n label,\n onMove,\n onDelete,\n}: {\n index: number;\n count: number;\n label: string;\n onMove: (index: number, dir: 1 | -1) => void;\n onDelete: () => void;\n}) {\n const position = index + 1;\n\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button type=\"button\" variant=\"ghost\" size=\"icon-sm\" aria-label={`${label} block ${position} options`}>\n <MoreHorizontal aria-hidden=\"true\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-48\">\n <DropdownMenuItem\n aria-label={`Move block ${position} up`}\n disabled={index === 0}\n onSelect={() => onMove(index, -1)}\n >\n <ArrowUp aria-hidden=\"true\" />\n <span>Move up</span>\n </DropdownMenuItem>\n <DropdownMenuItem\n aria-label={`Move block ${position} down`}\n disabled={index === count - 1}\n onSelect={() => onMove(index, 1)}\n >\n <ArrowDown aria-hidden=\"true\" />\n <span>Move down</span>\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n aria-label={`Delete block ${position}`}\n className=\"text-destructive focus:text-destructive\"\n onSelect={onDelete}\n >\n <Trash2 aria-hidden=\"true\" />\n <span>Delete</span>\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport * as DropdownMenuPrimitive from \"@radix-ui/react-dropdown-menu\";\nimport { CheckIcon, ChevronRightIcon, CircleIcon } from \"lucide-react\";\nimport { cn } from \"./cn\";\nimport { TAP_TARGET_FLOOR } from \"./touch-target\";\n\nfunction DropdownMenu(\n props: React.ComponentProps<typeof DropdownMenuPrimitive.Root>,\n) {\n return <DropdownMenuPrimitive.Root data-slot=\"dropdown-menu\" {...props} />;\n}\n\nfunction DropdownMenuTrigger(\n props: React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>,\n) {\n return (\n <DropdownMenuPrimitive.Trigger\n data-slot=\"dropdown-menu-trigger\"\n {...props}\n />\n );\n}\n\nfunction DropdownMenuContent({\n className,\n sideOffset = 4,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Content>) {\n return (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Content\n data-slot=\"dropdown-menu-content\"\n sideOffset={sideOffset}\n className={cn(\n \"quoin bg-popover text-popover-foreground z-50 min-w-[8rem] overflow-hidden rounded-md border p-1 shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n className,\n )}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n );\n}\n\nfunction DropdownMenuGroup(\n props: React.ComponentProps<typeof DropdownMenuPrimitive.Group>,\n) {\n return (\n <DropdownMenuPrimitive.Group data-slot=\"dropdown-menu-group\" {...props} />\n );\n}\n\nfunction DropdownMenuItem({\n className,\n inset,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {\n inset?: boolean;\n}) {\n return (\n <DropdownMenuPrimitive.Item\n data-slot=\"dropdown-menu-item\"\n data-inset={inset}\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none select-none data-[inset]:pl-8 data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg:not([class*='size-'])]:size-4\",\n TAP_TARGET_FLOOR,\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction DropdownMenuCheckboxItem({\n className,\n children,\n checked,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem>) {\n return (\n <DropdownMenuPrimitive.CheckboxItem\n data-slot=\"dropdown-menu-checkbox-item\"\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-none select-none\",\n className,\n )}\n checked={checked}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <CheckIcon className=\"size-4\" />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.CheckboxItem>\n );\n}\n\nfunction DropdownMenuRadioGroup(\n props: React.ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>,\n) {\n return (\n <DropdownMenuPrimitive.RadioGroup\n data-slot=\"dropdown-menu-radio-group\"\n {...props}\n />\n );\n}\n\nfunction DropdownMenuRadioItem({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem>) {\n return (\n <DropdownMenuPrimitive.RadioItem\n data-slot=\"dropdown-menu-radio-item\"\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-none select-none\",\n className,\n )}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <CircleIcon className=\"size-2 fill-current\" />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.RadioItem>\n );\n}\n\nfunction DropdownMenuLabel({\n className,\n inset,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Label> & {\n inset?: boolean;\n}) {\n return (\n <DropdownMenuPrimitive.Label\n data-slot=\"dropdown-menu-label\"\n data-inset={inset}\n className={cn(\n \"px-2 py-1.5 text-sm font-medium data-[inset]:pl-8\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction DropdownMenuSeparator({\n className,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Separator>) {\n return (\n <DropdownMenuPrimitive.Separator\n data-slot=\"dropdown-menu-separator\"\n className={cn(\"bg-border -mx-1 my-1 h-px\", className)}\n {...props}\n />\n );\n}\n\nfunction DropdownMenuShortcut({\n className,\n ...props\n}: React.ComponentProps<\"span\">) {\n return (\n <span\n data-slot=\"dropdown-menu-shortcut\"\n className={cn(\n \"text-muted-foreground ml-auto text-xs tracking-widest\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction DropdownMenuSub(\n props: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>,\n) {\n return <DropdownMenuPrimitive.Sub data-slot=\"dropdown-menu-sub\" {...props} />;\n}\n\nfunction DropdownMenuSubTrigger({\n className,\n inset,\n children,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & {\n inset?: boolean;\n}) {\n return (\n <DropdownMenuPrimitive.SubTrigger\n data-slot=\"dropdown-menu-sub-trigger\"\n data-inset={inset}\n className={cn(\n \"focus:bg-accent data-[state=open]:bg-accent flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-none select-none data-[inset]:pl-8\",\n className,\n )}\n {...props}\n >\n {children}\n <ChevronRightIcon className=\"ml-auto size-4\" />\n </DropdownMenuPrimitive.SubTrigger>\n );\n}\n\nfunction DropdownMenuSubContent({\n className,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>) {\n return (\n <DropdownMenuPrimitive.SubContent\n data-slot=\"dropdown-menu-sub-content\"\n className={cn(\n \"quoin bg-popover text-popover-foreground z-50 min-w-[8rem] overflow-hidden rounded-md border p-1 shadow-lg\",\n className,\n )}\n {...props}\n />\n );\n}\n\nexport {\n DropdownMenu,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuLabel,\n DropdownMenuItem,\n DropdownMenuCheckboxItem,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuSub,\n DropdownMenuSubTrigger,\n DropdownMenuSubContent,\n};\n","'use client';\n\nimport * as React from 'react';\nimport { Pencil } from 'lucide-react';\nimport { BlockEditor } from './BlockEditor';\nimport { renderedOffsetAt, sourceOffsetFor, type ClickProbe } from './source-offset';\nimport { useQuoin } from '../context';\nimport { blockByType } from '../registry';\nimport type { QuoinBlock } from '../types';\nimport { Button } from '../ui/button';\n\nconst INTERACTIVE_SELECTOR = 'a, button, input, textarea, select, [role=\"button\"], [tabindex], iframe';\n\n/** Radix renders Select, dropdown and popover content in a portal, so focus moving\n * into one leaves this block's DOM subtree while the author is still editing it. */\nconst PORTALLED_OVERLAY = '[data-radix-popper-content-wrapper], [role=\"dialog\"]';\n\n// A drag-select ends in a click on mouseup; bailing here keeps that click from\n// flipping the block into edit mode and wiping out the selection it just made.\nfunction hasSelectionWithin(container: HTMLElement): boolean {\n const selection = window.getSelection();\n if (!selection || selection.isCollapsed || selection.rangeCount === 0) return false;\n return container.contains(selection.getRangeAt(0).commonAncestorContainer);\n}\n\nfunction BlockCardImpl({\n block,\n index,\n editingByDefault = false,\n readOnly = false,\n initialSelection = null,\n onUpdate,\n onInsertBlock,\n}: {\n block: QuoinBlock;\n index: number;\n editingByDefault?: boolean;\n /** Draws the block at rest and never opens an editor, for a canvas that is only being read. */\n readOnly?: boolean;\n initialSelection?: { start: number; end: number } | null;\n onUpdate: (id: string, data: Record<string, unknown>) => void;\n onInsertBlock?: (index: number, type: string) => void;\n}) {\n const { blockTypes, onError } = useQuoin();\n const definition = blockByType(blockTypes, block.type);\n const Preview = definition?.preview;\n const [editing, setEditing] = React.useState(editingByDefault && !readOnly);\n const editButtonRef = React.useRef<HTMLButtonElement>(null);\n const editorContainerRef = React.useRef<HTMLDivElement>(null);\n const returnFocusOnClose = React.useRef(false);\n const clickedRef = React.useRef<ClickProbe | null>(null);\n const scrollTopRef = React.useRef<number | null>(null);\n\n const handleInsertBlock = React.useCallback(\n (type: string) => onInsertBlock?.(index + 1, type),\n [onInsertBlock, index],\n );\n\n const leaveEditing = React.useCallback(() => {\n returnFocusOnClose.current = true;\n setEditing(false);\n }, []);\n\n const settleRef = React.useRef<number | null>(null);\n\n const clearSettle = () => {\n if (settleRef.current === null) return;\n window.clearTimeout(settleRef.current);\n settleRef.current = null;\n };\n\n React.useEffect(() => clearSettle, []);\n\n function stillInside(node: Element | null): boolean {\n if (!node) return false;\n return Boolean(editorContainerRef.current?.contains(node)) || Boolean(node.closest(PORTALLED_OVERLAY));\n }\n\n // Editing ends when the author's attention goes elsewhere, so a block left\n // behind renders instead of stranding them on its markdown source. A pointer\n // event is read directly rather than through focus, which Radix moves around\n // asynchronously while an overlay or a freshly inserted block settles.\n React.useEffect(() => {\n if (!editing) return;\n function onPointerDown(e: PointerEvent) {\n if (stillInside(e.target as Element | null)) return;\n setEditing(false);\n }\n document.addEventListener('pointerdown', onPointerDown, true);\n return () => document.removeEventListener('pointerdown', onPointerDown, true);\n }, [editing]);\n\n function closeIfTabbedAway() {\n clearSettle();\n settleRef.current = window.setTimeout(() => {\n settleRef.current = null;\n if (stillInside(document.activeElement)) return;\n setEditing(false);\n }, 0);\n }\n\n // Focus on the click path must not scroll: the caret is placed after focus, so the\n // browser would otherwise drag the viewport to wherever the box's selection starts\n // out, away from the line the author actually aimed at.\n React.useEffect(() => {\n if (!editing) return;\n const field = editorContainerRef.current?.querySelector<HTMLElement>(\n 'textarea, input, [role=\"combobox\"]',\n );\n if (!field) return;\n\n const clicked = clickedRef.current;\n clickedRef.current = null;\n\n if (clicked === null || !(field instanceof HTMLTextAreaElement)) {\n field.focus();\n if (field instanceof HTMLTextAreaElement) {\n const at = initialSelection ?? { start: field.value.length, end: field.value.length };\n field.setSelectionRange(at.start, at.end);\n }\n return;\n }\n\n const offset = sourceOffsetFor(field.value, clicked);\n field.focus({ preventScroll: true });\n field.setSelectionRange(offset, offset);\n }, [editing, initialSelection]);\n\n // Replacing a tall rendered block with a one-row textarea shrinks the page, so\n // the browser clamps the scroll before the box can grow back. The position is\n // taken at the click and put back here, after the box has been sized.\n React.useLayoutEffect(() => {\n const scrollTop = scrollTopRef.current;\n scrollTopRef.current = null;\n if (!editing || scrollTop === null) return;\n const scroller = document.scrollingElement ?? document.documentElement;\n if (scroller.scrollTop !== scrollTop) scroller.scrollTop = scrollTop;\n }, [editing]);\n\n React.useEffect(() => {\n if (editing || !returnFocusOnClose.current) return;\n returnFocusOnClose.current = false;\n editButtonRef.current?.focus();\n }, [editing]);\n\n // A block whose type no host registered draws its type rather than nothing, so a\n // document authored with a plugin block does not look empty, and the host is told\n // once per type instead of on every render.\n const reportedType = React.useRef<string | null>(null);\n React.useEffect(() => {\n if (definition || reportedType.current === block.type) return;\n reportedType.current = block.type;\n onError(new Error(`No block type is registered for \"${block.type}\".`));\n }, [definition, block.type, onError]);\n\n if (definition?.alwaysEditing && !readOnly) {\n return (\n <BlockEditor\n type={block.type}\n data={block.data}\n onChange={(data) => onUpdate(block.id, data)}\n onInsertBlock={handleInsertBlock}\n />\n );\n }\n\n if (editing) {\n return (\n <div\n ref={editorContainerRef}\n onKeyDown={(e) => {\n if (e.key === 'Tab') {\n closeIfTabbedAway();\n return;\n }\n if (e.key !== 'Escape') return;\n // Radix's DismissableLayer (Select, dropdowns, etc.) closes on a document\n // capture listener and never stops propagation, so this handler still\n // sees the Escape that already dismissed a nested overlay. Only collapse\n // when the key genuinely landed inside this editor's own DOM subtree, not\n // in a portalled overlay that merely propagates through the React tree.\n if (!editorContainerRef.current?.contains(e.target as Node)) return;\n returnFocusOnClose.current = true;\n setEditing(false);\n }}\n >\n <BlockEditor\n type={block.type}\n data={block.data}\n onChange={(data) => onUpdate(block.id, data)}\n onInsertBlock={handleInsertBlock}\n onDone={leaveEditing}\n />\n </div>\n );\n }\n\n const rest = Preview ? (\n <Preview data={block.data} blockId={block.id} />\n ) : (\n <p className=\"py-1 text-sm text-muted-foreground\">{definition?.label ?? block.type}</p>\n );\n\n if (readOnly) return <div>{rest}</div>;\n\n return (\n <div className=\"group/card relative\">\n <div\n onClick={(e) => {\n const target = e.target as HTMLElement;\n if (target.closest(INTERACTIVE_SELECTOR)) return;\n if (hasSelectionWithin(e.currentTarget)) return;\n clickedRef.current = {\n rendered: e.currentTarget.textContent ?? '',\n clickedText: target.textContent ?? '',\n renderedOffset: renderedOffsetAt(e.currentTarget, e.clientX, e.clientY),\n };\n scrollTopRef.current = (document.scrollingElement ?? document.documentElement).scrollTop;\n setEditing(true);\n }}\n >\n {rest}\n </div>\n <Button\n ref={editButtonRef}\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label={`Edit block ${index + 1}`}\n onClick={() => setEditing(true)}\n className=\"absolute right-0 top-0 bg-background/90 opacity-0 transition-opacity group-hover/card:opacity-100 group-focus-within/card:opacity-100 focus-visible:opacity-100\"\n >\n <Pencil aria-hidden=\"true\" />\n </Button>\n </div>\n );\n}\n\nexport const BlockCard = React.memo(BlockCardImpl);\n","'use client';\n\nimport { useQuoin } from '../context';\nimport { blockByType } from '../registry';\nimport type { BlockEditorProps } from '../types';\n\nexport function BlockEditor({\n type,\n data,\n onChange,\n onInsertBlock,\n onDone,\n}: BlockEditorProps & { type: string }) {\n const { blockTypes } = useQuoin();\n const definition = blockByType(blockTypes, type);\n if (!definition) return null;\n const Editor = definition.editor;\n return <Editor data={data} onChange={onChange} onInsertBlock={onInsertBlock} onDone={onDone} />;\n}\n","/** What a click on a block's rendered body says about where the caret belongs. */\nexport type ClickProbe = {\n /** The whole text the preview drew for the block. */\n rendered: string;\n /** The text of the element the click actually landed on. */\n clickedText: string;\n /** Character offset of the click within `rendered`, or null when the browser places no caret there. */\n renderedOffset: number | null;\n};\n\ntype CaretPosition = { offsetNode: Node; offset: number };\n\ntype CaretDocument = Document & {\n caretPositionFromPoint?: (x: number, y: number) => CaretPosition | null;\n caretRangeFromPoint?: (x: number, y: number) => Range | null;\n};\n\nfunction caretPositionAt(x: number, y: number): CaretPosition | null {\n const doc = document as CaretDocument;\n const position = doc.caretPositionFromPoint?.(x, y);\n if (position) return position;\n const range = doc.caretRangeFromPoint?.(x, y);\n return range ? { offsetNode: range.startContainer, offset: range.startOffset } : null;\n}\n\n/** Character offset of the point within `container`'s text, or null when no caret can be placed there. */\nexport function renderedOffsetAt(container: HTMLElement, x: number, y: number): number | null {\n const position = caretPositionAt(x, y);\n if (!position || position.offsetNode.nodeType !== Node.TEXT_NODE) return null;\n if (!container.contains(position.offsetNode)) return null;\n\n const walker = document.createTreeWalker(container, NodeFilter.SHOW_TEXT);\n let before = 0;\n while (walker.nextNode()) {\n if (walker.currentNode === position.offsetNode) return before + position.offset;\n before += walker.currentNode.textContent?.length ?? 0;\n }\n return null;\n}\n\nconst PROBE_LENGTHS = [40, 20, 8];\n\n/** A custom preview draws something other than the source, so the clicked text is looked\n * back up in it. Collapsing runs of whitespace is what lets a wrapped rendering match a\n * single source line, but it also makes a multi-line clicked string unfindable, so the\n * literal text is tried first and the collapsed form only after it. */\nfunction search(source: string, probe: ClickProbe): number {\n const literal = probe.clickedText.trim();\n // Clicking the block rather than a line inside it locates nothing. The end is where an\n // author can carry on writing; the top is the one place they certainly did not aim at.\n if (literal === '' || literal === probe.rendered.trim()) return source.length;\n\n const candidates = [literal, literal.replace(/\\s+/g, ' ')];\n for (const text of candidates) {\n const whole = source.indexOf(text);\n if (whole !== -1) return whole;\n }\n for (const length of PROBE_LENGTHS) {\n for (const text of candidates) {\n if (text.length < length) continue;\n const at = source.indexOf(text.slice(0, length));\n if (at !== -1) return at;\n }\n }\n return source.length;\n}\n\n/** Where in `source` the caret belongs for a click the preview reported through `probe`. */\nexport function sourceOffsetFor(source: string, probe: ClickProbe): number {\n // The stock previews draw the source verbatim, so the browser's own caret position is\n // the answer, with no searching and no ambiguity between repeated lines.\n if (probe.renderedOffset !== null && probe.rendered === source) {\n return Math.max(0, Math.min(probe.renderedOffset, source.length));\n }\n return search(source, probe);\n}\n","'use client';\n\nimport * as React from 'react';\nimport { Plus } from 'lucide-react';\nimport { useQuoin } from '../context';\nimport { paletteBlocks } from '../registry';\nimport { Button } from '../ui/button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '../ui/dropdown-menu';\n\nexport function BlockInserter({\n index,\n onInsert,\n label,\n}: {\n index: number;\n onInsert: (index: number, type: string, data?: Record<string, unknown>) => void;\n label: string;\n}) {\n const { blockTypes } = useQuoin();\n const options = paletteBlocks(blockTypes);\n const insertedAtRef = React.useRef<number | null>(null);\n\n function handleSelect(type: string) {\n insertedAtRef.current = index;\n onInsert(index, type);\n }\n\n function handleCloseAutoFocus(event: Event) {\n const insertedAt = insertedAtRef.current;\n insertedAtRef.current = null;\n if (insertedAt === null) return;\n\n event.preventDefault();\n const card = document.querySelector<HTMLElement>(`[data-block-index=\"${insertedAt}\"]`);\n if (!card) return;\n if (typeof card.scrollIntoView === 'function') {\n card.scrollIntoView({ block: 'center', behavior: 'smooth' });\n }\n card.querySelector<HTMLElement>('textarea, input, [role=\"combobox\"]')?.focus();\n }\n\n return (\n <div className=\"group/inserter relative flex h-6 items-center justify-center pointer-coarse:h-11\">\n <span\n aria-hidden=\"true\"\n className=\"absolute inset-x-0 top-1/2 h-px bg-border opacity-0 transition-opacity group-hover/inserter:opacity-100 group-focus-within/inserter:opacity-100\"\n />\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"icon-xs\"\n aria-label={label}\n className=\"relative z-10 rounded-full bg-background opacity-0 transition-opacity group-hover/inserter:opacity-100 group-focus-within/inserter:opacity-100 focus-visible:opacity-100 pointer-coarse:opacity-100\"\n >\n <Plus aria-hidden=\"true\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"center\" className=\"w-56\" onCloseAutoFocus={handleCloseAutoFocus}>\n {options.map((opt) => (\n <DropdownMenuItem key={opt.type} onSelect={() => handleSelect(opt.type)}>\n <opt.icon aria-hidden=\"true\" />\n <span>{opt.label}</span>\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n );\n}\n","'use client';\n\nimport * as React from 'react';\nimport type { ChangeEvent } from 'react';\nimport type { TextCommand } from '../markdown/commands';\nimport { insertCommand } from '../markdown/insert-command';\nimport { ShortcutsReference } from '../markdown/ShortcutsReference';\nimport { SlashPalette } from '../markdown/SlashPalette';\nimport { useSlashPalette } from '../markdown/useSlashPalette';\n\nconst LINE = [\n 'w-full resize-none rounded-md border-0 bg-transparent px-2 py-1 outline-none',\n 'text-base leading-7 placeholder:text-muted-foreground',\n 'transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:ring-ring/50',\n].join(' ');\n\nexport function DocumentStarter({\n autoFocus = false,\n onStart,\n onInsertBlock,\n}: {\n autoFocus?: boolean;\n onStart: (markdown: string, selection?: { start: number; end: number }) => void;\n onInsertBlock: (type: string) => void;\n}) {\n const ref = React.useRef<HTMLTextAreaElement>(null);\n const palette = useSlashPalette(ref);\n const [shortcutsOpen, setShortcutsOpen] = React.useState(false);\n\n // The line never keeps what is typed into it: the first character becomes a\n // block instead. Clearing the node directly rather than through state keeps\n // that true even when the handler causes no re-render of this component.\n function handleChange(e: ChangeEvent<HTMLTextAreaElement>) {\n const value = e.target.value;\n e.target.value = '';\n if (value === '') return;\n // A virtual keyboard, an IME or a paste delivers \"/\" with no keydown to\n // intercept, so the shortcut is recognised from the value as well.\n if (value === '/') palette.openAtCaret();\n else onStart(value);\n }\n\n function startWith(command: TextCommand) {\n palette.setOpen(false);\n const edit = insertCommand(command, '', 0);\n onStart(edit.value, { start: edit.selectionStart, end: edit.selectionEnd });\n }\n\n return (\n <div className=\"relative\">\n <textarea\n ref={ref}\n aria-label=\"Write something\"\n defaultValue=\"\"\n onChange={handleChange}\n onKeyDown={(e) => {\n if (e.key !== '/') return;\n e.preventDefault();\n palette.openAtCaret();\n }}\n autoFocus={autoFocus}\n rows={1}\n placeholder=\"Write, or press / for commands\"\n className={LINE}\n />\n <SlashPalette\n open={palette.open}\n caret={palette.caret}\n onOpenChange={palette.setOpen}\n onTextCommand={startWith}\n onBlockCommand={(type) => {\n palette.setOpen(false);\n onInsertBlock(type);\n }}\n onShortcuts={() => {\n palette.setOpen(false);\n setShortcutsOpen(true);\n }}\n onDismiss={() => palette.setOpen(false)}\n />\n <ShortcutsReference open={shortcutsOpen} onOpenChange={setShortcutsOpen} />\n </div>\n );\n}\n","export function reorderIndices(\n ids: string[],\n activeId: string,\n overId: string | null,\n): { from: number; to: number } | null {\n if (overId === null || activeId === overId) return null;\n const from = ids.indexOf(activeId);\n const to = ids.indexOf(overId);\n if (from === -1 || to === -1) return null;\n return { from, to };\n}\n","import type { QuoinBlock } from '../types';\n\nfunction sameData(a: Record<string, unknown>, b: Record<string, unknown>): boolean {\n if (a === b) return true;\n const keys = Object.keys(a);\n if (keys.length !== Object.keys(b).length) return false;\n return keys.every((key) => Object.hasOwn(b, key) && Object.is(a[key], b[key]));\n}\n\n/** Whether two documents hold the same blocks in the same order, comparing each block's data one level deep. */\nexport function sameBlocks(a: QuoinBlock[], b: QuoinBlock[]): boolean {\n if (a === b) return true;\n if (a.length !== b.length) return false;\n return a.every((block, i) => {\n const other = b[i];\n return block.id === other.id && block.type === other.type && sameData(block.data, other.data);\n });\n}\n","'use client';\n\nimport { useSortable } from '@dnd-kit/sortable';\nimport { CSS } from '@dnd-kit/utilities';\nimport { GripVertical } from 'lucide-react';\nimport type { ReactNode } from 'react';\nimport { Button } from '../ui/button';\nimport { cn } from '../ui/cn';\n\n/** The gutter only leaves the text column once the viewport is wide enough to\n * hold it beside a 68ch measure, which is past `lg`. Below that it stacks above\n * the block, where it also has to stay visible: hover is not available there. */\nconst GUTTER = [\n 'flex items-center justify-end gap-0.5 pb-1',\n 'lg:absolute lg:right-full lg:top-1 lg:justify-start lg:pb-0 lg:pr-1',\n 'lg:opacity-0 lg:transition-opacity',\n 'lg:group-hover/block:opacity-100 lg:group-focus-within/block:opacity-100',\n].join(' ');\n\nexport function SortableBlock({\n id,\n index,\n actions,\n children,\n}: {\n id: string;\n index: number;\n actions?: ReactNode;\n children: ReactNode;\n}) {\n const { attributes, listeners, setNodeRef, setActivatorNodeRef, transform, transition, isDragging } =\n useSortable({ id });\n\n return (\n <div\n ref={setNodeRef}\n style={{ transform: CSS.Transform.toString(transform), transition }}\n className={cn('group/block relative', isDragging && 'z-10 opacity-80')}\n >\n <div className={GUTTER}>\n {actions}\n <Button\n type=\"button\"\n ref={setActivatorNodeRef}\n variant=\"ghost\"\n size=\"icon-sm\"\n className=\"cursor-grab text-muted-foreground active:cursor-grabbing\"\n aria-label={`Reorder block ${index + 1}`}\n {...attributes}\n {...listeners}\n >\n <GripVertical aria-hidden=\"true\" />\n </Button>\n </div>\n <div\n data-block-index={index}\n className={cn(\n 'rounded-lg px-2 py-1 transition-colors',\n isDragging ? 'bg-card shadow-[var(--shadow-md)]' : 'group-hover/block:bg-muted/40',\n )}\n >\n {children}\n </div>\n </div>\n );\n}\n","import * as React from 'react';\n\n/** Where a debounced save stands, for a \"Saving...\" or \"Saved\" indicator. */\nexport type AutosaveStatus = 'idle' | 'saving' | 'saved' | 'retrying';\n\ntype SaveResult = { ok?: boolean } | void;\n\n/** What `useAutosave` tracks, how to build the payload, and how to persist it. */\nexport type UseAutosaveInput<T> = {\n /** The tracked fields. An edit to any of them marks dirty and restarts the debounce. */\n deps: React.DependencyList;\n build: () => T;\n save: (payload: T) => Promise<SaveResult> | SaveResult;\n debounceMs?: number;\n maxBackoffMs?: number;\n};\n\n/** The current save status and a way to retry a failed save immediately. */\nexport type UseAutosaveResult = {\n status: AutosaveStatus;\n retry: () => void;\n};\n\n/**\n * Debounced last-write-wins autosave. Nothing fires on mount, only after the first\n * real edit, and a rejected save backs off exponentially until it lands. `save` and\n * `build` are read at fire time, so passing fresh closures each render is safe.\n */\nexport function useAutosave<T>({\n deps,\n build,\n save,\n debounceMs = 2000,\n maxBackoffMs = 30000,\n}: UseAutosaveInput<T>): UseAutosaveResult {\n // The effect order below is load-bearing: the dirty flag must be set before the\n // scheduling effect reads it within the same commit, and the \"latest closure\" refs\n // must be assigned after commit rather than during render.\n const [status, setStatus] = React.useState<AutosaveStatus>('idle');\n const dirtyRef = React.useRef(false);\n const retryRef = React.useRef(0);\n const backoffRef = React.useRef<ReturnType<typeof setTimeout> | null>(null);\n const buildRef = React.useRef(build);\n const saveRef = React.useRef(save);\n const runRef = React.useRef<() => void>(() => {});\n\n React.useEffect(() => {\n buildRef.current = build;\n saveRef.current = save;\n runRef.current = () => {\n void (async () => {\n setStatus('saving');\n try {\n const res = await saveRef.current(buildRef.current());\n if (res && res.ok === false) throw new Error('save rejected');\n retryRef.current = 0;\n dirtyRef.current = false;\n setStatus('saved');\n } catch {\n setStatus('retrying');\n retryRef.current += 1;\n const delay = Math.min(debounceMs * 2 ** retryRef.current, maxBackoffMs);\n if (backoffRef.current) clearTimeout(backoffRef.current);\n backoffRef.current = setTimeout(() => runRef.current(), delay);\n }\n })();\n };\n });\n\n // Compares values rather than counting mounts: React's development remount\n // re-runs this effect with identical deps, and a \"have I mounted\" flag survives\n // that remount, so a flag marks an untouched editor dirty and autosaves it.\n const seenRef = React.useRef<React.DependencyList | null>(null);\n React.useEffect(() => {\n const seen = seenRef.current;\n seenRef.current = deps;\n if (seen === null) return;\n const unchanged = seen.length === deps.length && seen.every((v, i) => v === deps[i]);\n if (!unchanged) dirtyRef.current = true;\n // eslint-disable-next-line react-hooks/exhaustive-deps -- the caller owns the tracked fields\n }, deps);\n\n React.useEffect(() => {\n if (!dirtyRef.current) return;\n const handle = setTimeout(() => runRef.current(), debounceMs);\n return () => clearTimeout(handle);\n // eslint-disable-next-line react-hooks/exhaustive-deps -- the caller owns the tracked fields\n }, deps);\n\n React.useEffect(\n () => () => {\n if (backoffRef.current) clearTimeout(backoffRef.current);\n },\n [],\n );\n\n const retry = React.useCallback(() => {\n if (backoffRef.current) clearTimeout(backoffRef.current);\n runRef.current();\n }, []);\n\n return { status, retry };\n}\n"],"mappings":"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","names":["React","Code","React","jsx","jsx","jsx","jsxs","jsx","jsx","jsxs","jsx","jsx","jsxs","jsx","jsxs","jsxs","jsx","jsx","jsx","jsx","jsx","jsxs","React","text","at","INDENT","at","React","React","jsx","jsxs","jsx","jsxs","jsx","jsx","jsxs","jsx","jsx","jsxs","useEffect","useRef","React","jsx","jsxs","jsx","jsxs","useRef","useEffect","jsx","jsxs","jsx","Code","React","CheckIcon","jsx","jsxs","jsx","jsx","jsx","jsxs","React","jsx","jsx","jsxs","React","jsx","jsxs","React","jsx","jsxs","jsx","jsxs","jsx","jsxs","newBlockId","id","React"]}
|