@humbdb/ui 0.0.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/LICENSE +21 -0
- package/README.md +6 -0
- package/dist/index.d.ts +142 -0
- package/dist/index.js +1221 -0
- package/dist/index.js.map +1 -0
- package/package.json +42 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/console-log.tsx","../src/components/files-browser.tsx","../src/cn.ts","../src/components/spinner.tsx","../src/components/table-detail.tsx","../src/components/type-icon.tsx","../src/components/schema-grid.tsx","../src/components/schema-tree.tsx","../src/components/sidebar.tsx","../src/components/status-bar.tsx","../src/components/tab-bar.tsx","../src/components/title-bar.tsx","../src/components/rows-table.tsx","../src/format-cell.ts","../src/components/query-runner.tsx"],"sourcesContent":["import type { ConsoleEvent } from \"@humbdb/core\";\nimport { Trash2 } from \"lucide-react\";\nimport type { ReactNode } from \"react\";\n\nexport interface ConsoleLogProps {\n events: ConsoleEvent[];\n onClear: () => void;\n}\n\nconst LEVEL_COLOR: Record<ConsoleEvent[\"level\"], string | undefined> = {\n info: undefined,\n warn: \"var(--c-amber)\",\n error: \"var(--c-red)\"\n};\n\nfunction formatTime(timestamp: string): string {\n return new Date(timestamp).toLocaleTimeString(\"en-US\", { hour12: false });\n}\n\n/** A read-only stream of recent connection/query events (DF-07), with a client-side Clear action. */\nexport function ConsoleLog({ events, onClear }: ConsoleLogProps): ReactNode {\n return (\n <div\n data-testid=\"console-log\"\n className=\"flex h-full flex-col overflow-hidden rounded-[3px] border border-border\"\n >\n <div className=\"flex shrink-0 items-center gap-2 border-b border-border px-3 py-2\">\n <span className=\"font-mono text-[9px] uppercase tracking-widest text-muted-foreground\">\n Console\n </span>\n <button\n type=\"button\"\n onClick={onClear}\n className=\"ml-auto flex items-center gap-1 rounded-[3px] px-2 py-1 text-[11px] text-muted-foreground hover:bg-accent\"\n >\n <Trash2 className=\"h-2.5 w-2.5\" />\n Clear\n </button>\n </div>\n\n <div className=\"flex-1 space-y-0.5 overflow-auto p-3\">\n {events.length === 0 ? (\n <p className=\"font-mono text-[11px] text-muted-foreground/50\">No events yet.</p>\n ) : (\n events.map((event) => (\n <div key={event.id} className=\"flex items-start gap-3 py-0.5 font-mono text-[11px]\">\n <span className=\"shrink-0 tabular-nums text-muted-foreground/30\">\n {formatTime(event.timestamp)}\n </span>\n <span\n className=\"w-9 shrink-0 text-right text-[10px]\"\n style={{ color: LEVEL_COLOR[event.level] }}\n >\n {event.level === \"info\" ? (\n <span className=\"text-muted-foreground/40\">{event.level}</span>\n ) : (\n event.level\n )}\n </span>\n <span\n className={event.level === \"info\" ? \"text-foreground/65\" : \"\"}\n style={{ color: LEVEL_COLOR[event.level] }}\n >\n {event.message}\n </span>\n </div>\n ))\n )}\n <div className=\"flex items-center gap-1.5 pt-2\">\n <span className=\"font-mono text-[11px]\" style={{ color: \"var(--c-green)\" }}>\n ❯\n </span>\n <span className=\"animate-pulse font-mono text-[11px] text-muted-foreground/25\">█</span>\n </div>\n </div>\n </div>\n );\n}\n","import type { FileNode } from \"@humbdb/core\";\nimport { File, FileCode2, FolderOpen } from \"lucide-react\";\nimport type { ReactNode } from \"react\";\nimport { useState } from \"react\";\nimport { cn } from \"../cn.js\";\nimport { Spinner } from \"./spinner.js\";\n\nexport interface FilesBrowserProps {\n tree: FileNode[];\n selectedPath?: string;\n onSelectFile: (path: string) => void;\n content?: string;\n isContentLoading?: boolean;\n contentError?: string;\n}\n\nfunction TreeRow({\n node,\n depth,\n selectedPath,\n onSelectFile\n}: {\n node: FileNode;\n depth: number;\n selectedPath?: string;\n onSelectFile: (path: string) => void;\n}): ReactNode {\n const [open, setOpen] = useState(depth < 1);\n const isSelected = node.type === \"file\" && node.path === selectedPath;\n\n return (\n <div>\n <div\n role={node.type === \"file\" ? \"button\" : undefined}\n aria-pressed={node.type === \"file\" ? isSelected : undefined}\n className={cn(\n \"mx-1 flex cursor-pointer select-none items-center gap-1.5 rounded-[2px] py-[3px] pr-2 hover:bg-sidebar-accent\",\n isSelected && \"bg-primary/10\"\n )}\n style={{ paddingLeft: `${8 + depth * 14}px` }}\n onClick={() => {\n if (node.type === \"directory\") setOpen((current) => !current);\n else onSelectFile(node.path);\n }}\n >\n {node.type === \"directory\" ? (\n <svg\n viewBox=\"0 0 24 24\"\n className={cn(\n \"h-2.5 w-2.5 shrink-0 text-muted-foreground/60 transition-transform\",\n open && \"rotate-90\"\n )}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n >\n <path d=\"m9 18 6-6-6-6\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n ) : (\n <span className=\"w-2.5 shrink-0\" />\n )}\n\n {node.type === \"directory\" ? (\n <FolderOpen className=\"h-3 w-3 shrink-0\" style={{ color: \"var(--c-amber)\" }} />\n ) : (\n <File className=\"h-3 w-3 shrink-0\" style={{ color: \"var(--c-blue)\" }} />\n )}\n\n <span\n className={cn(\n \"truncate font-mono text-[11px] text-foreground/70\",\n isSelected ? \"text-foreground\" : \"hover:text-foreground\"\n )}\n >\n {node.name}\n </span>\n </div>\n\n {node.type === \"directory\" && open && (\n <div>\n {node.children?.map((child) => (\n <TreeRow\n key={child.path}\n node={child}\n depth={depth + 1}\n selectedPath={selectedPath}\n onSelectFile={onSelectFile}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\n/** A read-only browser for `.sql` files (DF-06): a folder/file tree plus a line-numbered preview. */\nexport function FilesBrowser({\n tree,\n selectedPath,\n onSelectFile,\n content,\n isContentLoading,\n contentError\n}: FilesBrowserProps): ReactNode {\n const lines = content?.split(\"\\n\") ?? [];\n\n return (\n <div\n data-testid=\"files-browser\"\n className=\"flex h-full overflow-hidden rounded-[3px] border border-border\"\n >\n <nav className=\"w-48 shrink-0 overflow-y-auto border-r border-border bg-sidebar py-1\">\n {tree.map((node) => (\n <TreeRow\n key={node.path}\n node={node}\n depth={0}\n selectedPath={selectedPath}\n onSelectFile={onSelectFile}\n />\n ))}\n </nav>\n\n <div className=\"flex min-w-0 flex-1 flex-col overflow-hidden\">\n <div className=\"flex shrink-0 items-center gap-2 border-b border-border bg-card px-3 py-2\">\n <FileCode2 className=\"h-3 w-3 shrink-0\" style={{ color: \"var(--c-blue)\" }} />\n <span className=\"truncate font-mono text-[11px] text-foreground\">\n {selectedPath ?? \"Select a file\"}\n </span>\n </div>\n\n {isContentLoading ? (\n <p className=\"flex items-center gap-1.5 p-3 text-[13px] text-muted-foreground\">\n <Spinner /> Loading file...\n </p>\n ) : contentError ? (\n <p className=\"p-3 text-[13px] text-muted-foreground\">{contentError}</p>\n ) : content === undefined ? (\n <p className=\"p-3 font-mono text-[11px] text-muted-foreground\">No file selected.</p>\n ) : (\n <div className=\"flex flex-1 overflow-auto\">\n <div\n aria-hidden=\"true\"\n className=\"shrink-0 select-none border-r border-border bg-background pr-3 pt-3 text-right font-mono text-[11px] text-muted-foreground/30\"\n style={{ minWidth: \"44px\" }}\n >\n {lines.map((_, index) => (\n <div key={index} style={{ lineHeight: \"20px\" }}>\n {index + 1}\n </div>\n ))}\n </div>\n <pre className=\"flex-1 whitespace-pre p-3 font-mono text-[12px] leading-5 text-foreground/80\">\n {content}\n </pre>\n </div>\n )}\n </div>\n </div>\n );\n}\n","import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/** Merge Tailwind class names, resolving conflicts (e.g. `p-2 p-4` -> `p-4`). shadcn-style helper. */\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","import { Loader2 } from \"lucide-react\";\nimport type { ReactNode } from \"react\";\nimport { cn } from \"../cn.js\";\n\nexport interface SpinnerProps {\n className?: string;\n}\n\n/** A small spinning loading indicator. Size/color via className (defaults to muted, 12px). */\nexport function Spinner({ className }: SpinnerProps): ReactNode {\n return (\n <Loader2\n className={cn(\"h-3 w-3 animate-spin text-muted-foreground\", className)}\n aria-hidden=\"true\"\n />\n );\n}\n","import type { TableMetadata } from \"@humbdb/core\";\nimport { Link, Table2 } from \"lucide-react\";\nimport type { ReactNode } from \"react\";\nimport { TypeIcon } from \"./type-icon.js\";\n\nexport interface TableDetailProps {\n table: TableMetadata;\n}\n\n/**\n * Columns, primary key, indexes, and approximate row count for a single table. Also reused as\n * each card in `SchemaGrid`, the Schema tab's full-database overview.\n */\nexport function TableDetail({ table }: TableDetailProps): ReactNode {\n return (\n <div\n data-testid=\"table-detail\"\n className=\"max-w-xl overflow-hidden rounded-[3px] border border-border\"\n >\n <div className=\"flex items-center gap-2 border-b border-border bg-card px-3 py-2\">\n <Table2 className=\"h-3 w-3 shrink-0\" style={{ color: \"var(--c-blue)\" }} />\n <span className=\"font-mono text-[12px] font-medium text-foreground\">{table.name}</span>\n {table.rowCount !== undefined && (\n <span className=\"ml-auto font-mono text-[10px] text-muted-foreground\">\n ~{table.rowCount.toLocaleString()} row{table.rowCount === 1 ? \"\" : \"s\"}\n </span>\n )}\n </div>\n\n <div className=\"bg-background\">\n {table.columns.map((column, index) => (\n <div\n key={column.name}\n className={\n \"flex items-center gap-2 px-3 py-1.5 font-mono text-[11px] hover:bg-accent/50\" +\n (index !== 0 ? \" border-t border-border-subtle\" : \"\")\n }\n >\n <TypeIcon dataType={column.dataType} />\n <span\n className={column.isPrimaryKey || column.isForeignKey ? \"\" : \"text-foreground/80\"}\n style={{\n color: column.isPrimaryKey\n ? \"var(--c-amber)\"\n : column.isForeignKey\n ? \"var(--c-blue)\"\n : undefined\n }}\n >\n {column.name}\n </span>\n {column.isPrimaryKey && (\n <span\n className=\"rounded-[2px] border px-1 text-[8px]\"\n style={{\n color: \"var(--c-amber)\",\n borderColor: \"color-mix(in srgb, var(--c-amber) 30%, transparent)\"\n }}\n >\n PK\n </span>\n )}\n {column.isForeignKey && (\n <span\n className=\"flex items-center gap-0.5 rounded-[2px] border px-1 text-[8px]\"\n style={{\n color: \"var(--c-blue)\",\n borderColor: \"color-mix(in srgb, var(--c-blue) 30%, transparent)\"\n }}\n >\n <Link className=\"h-2 w-2\" />\n FK\n </span>\n )}\n <span className=\"ml-auto text-[9px] text-muted-foreground/40\">{column.dataType}</span>\n {column.nullable && <span className=\"text-[9px] text-muted-foreground/30\">null</span>}\n </div>\n ))}\n </div>\n\n {table.indexes && table.indexes.length > 0 && (\n <div className=\"border-t border-border bg-card px-3 py-2\">\n <ul className=\"space-y-0.5 font-mono text-[10px] text-muted-foreground\">\n {table.indexes.map((index) => (\n <li key={index.name}>\n {index.name} ({index.columns.join(\", \")})\n {index.primary ? \" · primary key\" : index.unique ? \" · unique\" : \"\"}\n </li>\n ))}\n </ul>\n </div>\n )}\n </div>\n );\n}\n","import { Calendar, Hash, ToggleLeft, Type } from \"lucide-react\";\nimport type { ReactNode } from \"react\";\n\nexport interface TypeIconProps {\n dataType: string;\n}\n\n/**\n * Column-kind classification for `ColumnMetadata.dataType`, which is engine-reported text, not a\n * normalized enum: Postgres reports `information_schema` names (\"integer\", \"character varying\",\n * \"timestamp with time zone\"), SQLite reports raw declared types (\"INTEGER\", \"TEXT\", \"REAL\", or\n * \"any\" - see packages/drivers/sqlite). Prefix-matched case-insensitively so both read the same way.\n */\nfunction classify(dataType: string): \"numeric\" | \"text\" | \"boolean\" | \"datetime\" | \"other\" {\n const type = dataType.toLowerCase();\n if (\n type.startsWith(\"int\") ||\n type.startsWith(\"numeric\") ||\n type.startsWith(\"decimal\") ||\n type.startsWith(\"float\") ||\n type.startsWith(\"double\") ||\n type.startsWith(\"real\") ||\n type.startsWith(\"serial\")\n ) {\n return \"numeric\";\n }\n if (type.startsWith(\"bool\")) return \"boolean\";\n if (type.startsWith(\"timestamp\") || type.startsWith(\"date\") || type.startsWith(\"time\")) {\n return \"datetime\";\n }\n if (\n type.startsWith(\"char\") ||\n type.startsWith(\"varchar\") ||\n type.startsWith(\"text\") ||\n type.startsWith(\"uuid\") ||\n type.startsWith(\"json\")\n ) {\n return \"text\";\n }\n return \"other\";\n}\n\n/** A small colored icon for a column's data type, matching docs/references/design-system.md's mapping. */\nexport function TypeIcon({ dataType }: TypeIconProps): ReactNode {\n switch (classify(dataType)) {\n case \"numeric\":\n return <Hash className=\"h-2.5 w-2.5 shrink-0\" style={{ color: \"var(--c-amber)\" }} />;\n case \"text\":\n return <Type className=\"h-2.5 w-2.5 shrink-0\" style={{ color: \"var(--c-blue)\" }} />;\n case \"boolean\":\n return <ToggleLeft className=\"h-2.5 w-2.5 shrink-0\" style={{ color: \"var(--c-green)\" }} />;\n case \"datetime\":\n return <Calendar className=\"h-2.5 w-2.5 shrink-0\" style={{ color: \"var(--c-purple)\" }} />;\n default:\n return <Hash className=\"h-2.5 w-2.5 shrink-0 text-muted-foreground\" />;\n }\n}\n","import type { TableMetadata } from \"@humbdb/core\";\nimport type { ReactNode } from \"react\";\nimport { TableDetail } from \"./table-detail.js\";\n\nexport interface SchemaGridProps {\n tables: TableMetadata[];\n}\n\n/** Full-database overview: every table as a card, reusing TableDetail's column-row pattern. */\nexport function SchemaGrid({ tables }: SchemaGridProps): ReactNode {\n return (\n <div\n data-testid=\"schema-grid\"\n className=\"grid gap-3\"\n style={{ gridTemplateColumns: \"repeat(auto-fill, minmax(260px, 1fr))\" }}\n >\n {tables.map((table) => (\n <TableDetail key={`${table.schema}.${table.name}`} table={table} />\n ))}\n </div>\n );\n}\n","import type { ConnectionStatus, SchemaMetadata } from \"@humbdb/core\";\nimport { Circle, FolderOpen, Table2 } from \"lucide-react\";\nimport type { ReactNode } from \"react\";\nimport { useMemo, useState } from \"react\";\nimport { cn } from \"../cn.js\";\n\nexport interface SelectedTable {\n schema: string;\n table: string;\n}\n\nexport interface SchemaTreeProps {\n target: string | null;\n status: ConnectionStatus;\n schemas: SchemaMetadata[];\n selected?: SelectedTable;\n onSelect: (schema: string, table: string) => void;\n}\n\ntype NodeType = \"connection\" | \"schema\" | \"table\";\n\ninterface Node {\n id: string;\n name: string;\n type: NodeType;\n schema?: string;\n children?: Node[];\n}\n\nconst STATUS_DOT_COLOR: Record<ConnectionStatus, string> = {\n connected: \"var(--c-green)\",\n disconnected: \"var(--c-red)\",\n unconfigured: \"rgb(var(--muted-foreground))\"\n};\n\nfunction buildTree(target: string | null, schemas: SchemaMetadata[]): Node {\n return {\n id: \"connection\",\n name: target ?? \"not connected\",\n type: \"connection\",\n children: schemas.map((schema) => ({\n id: `schema:${schema.name}`,\n name: schema.name,\n type: \"schema\",\n children: schema.tables.map((table) => ({\n id: `table:${schema.name}:${table}`,\n name: table,\n type: \"table\",\n schema: schema.name\n }))\n }))\n };\n}\n\nfunction collectMatchIds(node: Node, query: string, ancestors: string[] = []): Set<string> {\n const result = new Set<string>();\n const path = [...ancestors, node.id];\n if (node.name.toLowerCase().includes(query.toLowerCase())) {\n for (const id of path) result.add(id);\n }\n for (const child of node.children ?? []) {\n for (const id of collectMatchIds(child, query, path)) result.add(id);\n }\n return result;\n}\n\nfunction highlight(text: string, query: string): ReactNode {\n if (!query) return text;\n const index = text.toLowerCase().indexOf(query.toLowerCase());\n if (index === -1) return text;\n return (\n <>\n {text.slice(0, index)}\n <mark className=\"rounded-[1px] bg-[color-mix(in_srgb,var(--c-blue)_25%,transparent)] text-[var(--c-blue)]\">\n {text.slice(index, index + query.length)}\n </mark>\n {text.slice(index + query.length)}\n </>\n );\n}\n\nfunction TreeRow({\n node,\n depth,\n query,\n matchIds,\n selected,\n onSelect,\n status\n}: {\n node: Node;\n depth: number;\n query: string;\n matchIds: Set<string>;\n selected?: SelectedTable;\n onSelect: (schema: string, table: string) => void;\n status: ConnectionStatus;\n}): ReactNode {\n const [manualOpen, setManualOpen] = useState(depth < 2);\n const forceOpen = query.length > 0 && matchIds.has(node.id);\n const open = query.length > 0 ? forceOpen : manualOpen;\n\n if (query.length > 0 && !matchIds.has(node.id)) return null;\n\n const hasChildren = Boolean(node.children && node.children.length > 0);\n const isSelected =\n node.type === \"table\" && selected?.schema === node.schema && selected?.table === node.name;\n\n return (\n <div>\n <div\n role={node.type === \"table\" ? \"button\" : undefined}\n aria-pressed={node.type === \"table\" ? isSelected : undefined}\n className={cn(\n \"mx-1 flex cursor-pointer select-none items-center gap-1.5 rounded-[2px] py-[3px] pr-2 hover:bg-sidebar-accent\",\n isSelected && \"bg-primary/10\"\n )}\n style={{ paddingLeft: `${8 + depth * 14}px` }}\n onClick={() => {\n if (hasChildren) setManualOpen((current) => !current);\n if (node.type === \"table\" && node.schema) onSelect(node.schema, node.name);\n }}\n >\n {hasChildren ? (\n <svg\n viewBox=\"0 0 24 24\"\n className={cn(\n \"h-2.5 w-2.5 shrink-0 text-muted-foreground/60 transition-transform\",\n open && \"rotate-90\"\n )}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n >\n <path d=\"m9 18 6-6-6-6\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n ) : (\n <span className=\"w-2.5 shrink-0\" />\n )}\n\n {node.type === \"connection\" && (\n <Circle\n className=\"h-1.5 w-1.5 shrink-0\"\n fill={STATUS_DOT_COLOR[status]}\n style={{ color: STATUS_DOT_COLOR[status] }}\n />\n )}\n {node.type === \"schema\" && (\n <FolderOpen className=\"h-3 w-3 shrink-0\" style={{ color: \"var(--c-amber)\" }} />\n )}\n {node.type === \"table\" && <Table2 className=\"h-3 w-3 shrink-0 text-muted-foreground\" />}\n\n <span\n className={cn(\n \"truncate font-mono text-[11px] text-foreground/70\",\n isSelected ? \"text-foreground\" : \"hover:text-foreground\"\n )}\n >\n {highlight(node.name, query)}\n </span>\n </div>\n\n {hasChildren && open && (\n <div>\n {node.children?.map((child) => (\n <TreeRow\n key={child.id}\n node={child}\n depth={depth + 1}\n query={query}\n matchIds={matchIds}\n selected={selected}\n onSelect={onSelect}\n status={status}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\n/**\n * A searchable, collapsible navigation tree: connection -> schema -> table, mirroring\n * docs/references/design-system.md's TreeNode pattern. Purely presentational: selection is owned\n * by the caller. Matching a search term force-opens its ancestor path and highlights the match.\n */\nexport function SchemaTree({\n target,\n status,\n schemas,\n selected,\n onSelect\n}: SchemaTreeProps): ReactNode {\n const [query, setQuery] = useState(\"\");\n const tree = useMemo(() => buildTree(target, schemas), [target, schemas]);\n const matchIds = useMemo(\n () => (query.trim().length > 1 ? collectMatchIds(tree, query.trim()) : new Set<string>()),\n [tree, query]\n );\n const trimmedQuery = query.trim();\n\n return (\n <div data-testid=\"schema-tree\" className=\"flex h-full flex-col\">\n <div className=\"shrink-0 border-b border-border px-2 py-2\">\n <div className=\"flex items-center gap-1.5 rounded-[3px] border border-border bg-background px-2 py-1.5\">\n <svg\n viewBox=\"0 0 24 24\"\n className=\"h-2.5 w-2.5 shrink-0 text-muted-foreground/50\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n >\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <path d=\"m21 21-4.35-4.35\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n <input\n type=\"text\"\n value={query}\n onChange={(event) => setQuery(event.target.value)}\n placeholder=\"Search tables, schemas...\"\n aria-label=\"Search tables\"\n className=\"w-full min-w-0 bg-transparent font-mono text-[11px] text-foreground outline-none placeholder:text-muted-foreground/40\"\n />\n </div>\n </div>\n\n <nav className=\"flex-1 overflow-y-auto py-1\">\n {trimmedQuery.length > 1 && matchIds.size === 0 ? (\n <div className=\"px-3 py-4 text-center font-mono text-[11px] text-muted-foreground/40\">\n no results\n </div>\n ) : (\n <TreeRow\n node={tree}\n depth={0}\n query={trimmedQuery.length > 1 ? trimmedQuery : \"\"}\n matchIds={matchIds}\n selected={selected}\n onSelect={onSelect}\n status={status}\n />\n )}\n </nav>\n </div>\n );\n}\n","import type { ConnectionStatus, SchemaMetadata } from \"@humbdb/core\";\nimport { PanelLeftClose, PanelLeftOpen } from \"lucide-react\";\nimport type { ReactNode } from \"react\";\nimport { cn } from \"../cn.js\";\nimport { SchemaTree, type SelectedTable } from \"./schema-tree.js\";\nimport { Spinner } from \"./spinner.js\";\n\nexport interface SidebarProps {\n target: string | null;\n status: ConnectionStatus;\n schemas: SchemaMetadata[];\n selected?: SelectedTable;\n onSelect: (schema: string, table: string) => void;\n isLoading?: boolean;\n isError?: boolean;\n onRetry?: () => void;\n open: boolean;\n onOpenChange: (open: boolean) => void;\n}\n\n/**\n * The app shell's left rail: a searchable schema tree. Desktop collapses to an icon rail; below\n * the `md` breakpoint it becomes an off-canvas overlay drawer (opened via TitleBar's hamburger),\n * both driven by the same `open` state so there is one source of truth for visibility.\n */\nexport function Sidebar({\n target,\n status,\n schemas,\n selected,\n onSelect,\n isLoading,\n isError,\n onRetry,\n open,\n onOpenChange\n}: SidebarProps): ReactNode {\n return (\n <>\n {open && (\n <div\n className=\"fixed inset-0 z-40 bg-black/50 md:hidden\"\n onClick={() => onOpenChange(false)}\n aria-hidden=\"true\"\n />\n )}\n\n <aside\n className={cn(\n \"fixed inset-y-0 left-0 z-50 flex w-64 flex-col border-r border-sidebar-border bg-sidebar transition-transform duration-150\",\n \"md:static md:z-auto md:translate-x-0 md:transition-none\",\n open ? \"translate-x-0\" : \"-translate-x-full\",\n !open && \"md:w-8\"\n )}\n >\n {open ? (\n <>\n <div className=\"flex shrink-0 items-center gap-2 border-b border-border px-3 py-2\">\n <span className=\"font-mono text-[9px] uppercase tracking-widest text-muted-foreground/60\">\n Explorer\n </span>\n <button\n type=\"button\"\n aria-label=\"Collapse sidebar\"\n onClick={() => onOpenChange(false)}\n className=\"ml-auto rounded p-0.5 text-muted-foreground hover:bg-sidebar-accent hover:text-foreground\"\n >\n <PanelLeftClose className=\"h-3 w-3\" />\n </button>\n </div>\n\n <div className=\"min-h-0 flex-1\">\n {isLoading ? (\n <p className=\"flex items-center gap-1.5 px-3 py-2 font-mono text-[11px] text-muted-foreground\">\n <Spinner /> Loading schemas...\n </p>\n ) : isError ? (\n <div className=\"px-3 py-2 font-mono text-[11px] text-muted-foreground\">\n Failed to load schemas.{\" \"}\n <button type=\"button\" onClick={onRetry} className=\"text-primary underline\">\n Retry\n </button>\n </div>\n ) : (\n <SchemaTree\n target={target}\n status={status}\n schemas={schemas}\n selected={selected}\n onSelect={(schema, table) => {\n onSelect(schema, table);\n // Only the mobile off-canvas drawer should auto-close on selection - the\n // desktop rail should stay open, since collapsing it every click is the\n // opposite of useful there.\n if (window.innerWidth < 768) onOpenChange(false);\n }}\n />\n )}\n </div>\n </>\n ) : (\n <div className=\"hidden flex-col items-center gap-2 px-1.5 py-2 md:flex\">\n <button\n type=\"button\"\n aria-label=\"Expand sidebar\"\n onClick={() => onOpenChange(true)}\n className=\"rounded-md p-1 text-muted-foreground hover:bg-sidebar-accent hover:text-foreground\"\n >\n <PanelLeftOpen className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n )}\n </aside>\n </>\n );\n}\n","import type { ConnectionStatus, DatabaseEngine } from \"@humbdb/core\";\nimport { Clock } from \"lucide-react\";\nimport type { ReactNode } from \"react\";\n\nexport interface StatusBarProps {\n status: ConnectionStatus;\n engine?: DatabaseEngine;\n engineVersion?: string | null;\n schema?: string;\n lastQueryMs?: number;\n}\n\nconst STATUS_LABEL: Record<ConnectionStatus, string> = {\n connected: \"connected\",\n disconnected: \"disconnected\",\n unconfigured: \"no database\"\n};\n\nconst STATUS_COLOR: Record<ConnectionStatus, string> = {\n connected: \"var(--c-green)\",\n disconnected: \"var(--c-red)\",\n unconfigured: \"rgb(var(--muted-foreground))\"\n};\n\nfunction Separator(): ReactNode {\n return <span className=\"text-border\">·</span>;\n}\n\n/** Bottom chrome bar: connection status, engine + version, current schema, encoding. */\nexport function StatusBar({\n status,\n engine,\n engineVersion,\n schema,\n lastQueryMs\n}: StatusBarProps): ReactNode {\n const engineLabel = engineVersion ?? engine;\n\n return (\n <footer className=\"flex h-6 shrink-0 items-center justify-between gap-3 border-t border-border bg-sidebar px-3 sm:px-4 font-mono text-[10px]\">\n <div className=\"flex min-w-0 items-center gap-3 text-muted-foreground/60\">\n <span style={{ color: STATUS_COLOR[status] }}>{STATUS_LABEL[status]}</span>\n {engineLabel && (\n <>\n <Separator />\n <span className=\"hidden sm:inline\">{engineLabel}</span>\n </>\n )}\n {schema && (\n <>\n <Separator />\n <span className=\"hidden truncate sm:inline\">{schema}</span>\n </>\n )}\n </div>\n <div className=\"hidden shrink-0 items-center gap-3 text-muted-foreground/40 sm:flex\">\n <span>UTF-8</span>\n {lastQueryMs !== undefined && (\n <>\n <Separator />\n <span className=\"flex items-center gap-1\">\n <Clock className=\"h-2.5 w-2.5\" />\n {lastQueryMs}ms\n </span>\n </>\n )}\n </div>\n </footer>\n );\n}\n","import { FileCode2, FolderOpen, Network, Table2, Terminal, type LucideIcon } from \"lucide-react\";\nimport type { ReactNode } from \"react\";\nimport { cn } from \"../cn.js\";\n\nexport type ShellTab = \"sql-editor\" | \"tables\" | \"schema\" | \"files\" | \"console\";\n\nconst TABS: { id: ShellTab; label: string; icon: LucideIcon }[] = [\n { id: \"sql-editor\", label: \"SQL Editor\", icon: FileCode2 },\n { id: \"tables\", label: \"Tables\", icon: Table2 },\n { id: \"schema\", label: \"Schema\", icon: Network },\n { id: \"files\", label: \"Files\", icon: FolderOpen },\n { id: \"console\", label: \"Console\", icon: Terminal }\n];\n\nexport interface TabBarProps {\n active: ShellTab;\n onChange: (tab: ShellTab) => void;\n}\n\n/** The IDE-style tab strip switching between the shell's five content panes. */\nexport function TabBar({ active, onChange }: TabBarProps): ReactNode {\n return (\n <div\n role=\"tablist\"\n className=\"flex shrink-0 items-end gap-0.5 overflow-x-auto overflow-y-hidden border-b border-border bg-card px-2 pt-1\"\n >\n {TABS.map(({ id, label, icon: Icon }) => {\n const isActive = id === active;\n return (\n <button\n key={id}\n type=\"button\"\n role=\"tab\"\n aria-selected={isActive}\n onClick={() => onChange(id)}\n className={cn(\n \"flex shrink-0 items-center gap-1.5 whitespace-nowrap rounded-t-[3px] px-3 py-1.5 text-[11px] font-medium transition-colors\",\n isActive\n ? \"-mb-px border border-border border-b-background bg-background text-foreground\"\n : \"text-muted-foreground hover:bg-accent/50 hover:text-foreground\"\n )}\n >\n <Icon className=\"h-3 w-3\" />\n {label}\n </button>\n );\n })}\n </div>\n );\n}\n","import type { ConnectionStatus } from \"@humbdb/core\";\nimport { ChevronRight, Menu, Moon, RefreshCw, Settings, Sun } from \"lucide-react\";\nimport type { ReactNode } from \"react\";\nimport { cn } from \"../cn.js\";\n\nexport interface TitleBarProps {\n status: ConnectionStatus;\n target: string | null;\n theme: \"light\" | \"dark\";\n onToggleTheme: () => void;\n onRefresh: () => void;\n isRefreshing?: boolean;\n onToggleSidebar: () => void;\n}\n\nconst STATUS_DOT_COLOR: Record<ConnectionStatus, string> = {\n connected: \"bg-[var(--c-green)]\",\n disconnected: \"bg-[var(--c-red)]\",\n unconfigured: \"bg-muted-foreground\"\n};\n\nconst STATUS_LABEL: Record<ConnectionStatus, string> = {\n connected: \"Connected\",\n disconnected: \"Disconnected\",\n unconfigured: \"No database\"\n};\n\nfunction splitTarget(target: string): { prefix?: string; name: string } {\n const lastSlash = target.lastIndexOf(\"/\");\n if (lastSlash === -1) return { name: target };\n return { prefix: target.slice(0, lastSlash), name: target.slice(lastSlash + 1) };\n}\n\n/** Top chrome bar: wordmark, connection breadcrumb, status dot, and window-level actions. */\nexport function TitleBar({\n status,\n target,\n theme,\n onToggleTheme,\n onRefresh,\n isRefreshing,\n onToggleSidebar\n}: TitleBarProps): ReactNode {\n const breadcrumb = target ? splitTarget(target) : null;\n\n return (\n <header className=\"flex h-9 shrink-0 items-center border-b border-border bg-card px-3 sm:px-4\">\n <button\n type=\"button\"\n onClick={onToggleSidebar}\n aria-label=\"Toggle sidebar\"\n className=\"mr-2 rounded-md p-1 text-muted-foreground hover:bg-accent hover:text-foreground md:hidden\"\n >\n <Menu className=\"h-4 w-4\" />\n </button>\n\n <h1 className=\"m-0 mr-4 shrink-0 font-mono text-[13px] font-semibold tracking-tight text-foreground\">\n Humb\n </h1>\n\n <div className=\"mr-4 hidden h-3.5 w-px shrink-0 bg-border sm:block\" />\n\n <div className=\"flex min-w-0 items-center gap-0 truncate font-mono text-[11px]\">\n {breadcrumb ? (\n <>\n {breadcrumb.prefix && (\n <span className=\"hidden truncate text-muted-foreground/60 sm:inline\">\n {breadcrumb.prefix}\n </span>\n )}\n {breadcrumb.prefix && (\n <ChevronRight className=\"mx-1 hidden h-3 w-3 shrink-0 text-border sm:inline\" />\n )}\n <span className=\"truncate font-medium text-foreground/80\">{breadcrumb.name}</span>\n </>\n ) : (\n <span className=\"text-muted-foreground/60\">not connected</span>\n )}\n </div>\n\n <span\n data-testid=\"status-badge\"\n data-status={status}\n title={STATUS_LABEL[status]}\n className=\"ml-3 flex shrink-0 items-center gap-1.5\"\n >\n <span className={cn(\"h-1.5 w-1.5 rounded-full\", STATUS_DOT_COLOR[status])} />\n <span\n data-testid=\"connection-summary\"\n className=\"font-mono text-[11px] text-muted-foreground\"\n >\n {STATUS_LABEL[status]}\n </span>\n </span>\n\n <div className=\"ml-auto flex shrink-0 items-center gap-0.5\">\n <button\n type=\"button\"\n onClick={onToggleTheme}\n title={theme === \"dark\" ? \"Switch to light\" : \"Switch to dark\"}\n aria-label=\"Toggle theme\"\n className=\"rounded-md p-1.5 text-muted-foreground hover:bg-accent hover:text-foreground\"\n >\n {theme === \"dark\" ? <Sun className=\"h-3.5 w-3.5\" /> : <Moon className=\"h-3.5 w-3.5\" />}\n </button>\n <button\n type=\"button\"\n onClick={onRefresh}\n disabled={isRefreshing}\n aria-label=\"Refresh\"\n className=\"rounded-md p-1.5 text-muted-foreground hover:bg-accent hover:text-foreground disabled:opacity-50\"\n >\n <RefreshCw className={cn(\"h-3.5 w-3.5\", isRefreshing && \"animate-spin\")} />\n </button>\n <button\n type=\"button\"\n aria-label=\"Settings\"\n disabled\n className=\"cursor-not-allowed rounded-md p-1.5 text-muted-foreground opacity-50\"\n >\n <Settings className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n </header>\n );\n}\n","import type { ColumnMetadata, RowPage } from \"@humbdb/core\";\nimport {\n ArrowUpDown,\n ChevronLeft,\n ChevronRight,\n Copy,\n Download,\n RefreshCw,\n Search,\n X\n} from \"lucide-react\";\nimport type { ReactNode } from \"react\";\nimport { useMemo, useState } from \"react\";\nimport { cn } from \"../cn.js\";\nimport { formatCell } from \"../format-cell.js\";\nimport { TypeIcon } from \"./type-icon.js\";\n\nexport interface RowsTableProps {\n rowPage: RowPage;\n columns?: ColumnMetadata[];\n tableName?: string;\n approxRowCount?: number;\n page: number;\n canGoPrevious: boolean;\n canGoNext: boolean;\n onPrevious: () => void;\n onNext: () => void;\n onRefresh?: () => void;\n}\n\ntype SortDir = \"asc\" | \"desc\" | null;\n\nfunction toCsv(columns: string[], rows: Array<Record<string, unknown>>): string {\n const escape = (value: unknown): string => {\n const text = formatCell(value);\n return /[\",\\n]/.test(text) ? `\"${text.replace(/\"/g, '\"\"')}\"` : text;\n };\n const lines = [columns.map(escape).join(\",\")];\n for (const row of rows) lines.push(columns.map((column) => escape(row[column])).join(\",\"));\n return lines.join(\"\\n\");\n}\n\nfunction downloadCsv(filename: string, csv: string): void {\n const blob = new Blob([csv], { type: \"text/csv;charset=utf-8\" });\n const url = URL.createObjectURL(blob);\n const link = document.createElement(\"a\");\n link.href = url;\n link.download = filename;\n link.click();\n URL.revokeObjectURL(url);\n}\n\n/** A page of table rows: client-side search/sort over the fetched page, plus pagination. */\nexport function RowsTable({\n rowPage,\n columns = [],\n tableName,\n approxRowCount,\n page,\n canGoPrevious,\n canGoNext,\n onPrevious,\n onNext,\n onRefresh\n}: RowsTableProps): ReactNode {\n const [search, setSearch] = useState(\"\");\n const [sortCol, setSortCol] = useState<string | null>(null);\n const [sortDir, setSortDir] = useState<SortDir>(null);\n const [selected, setSelected] = useState<Set<number>>(new Set());\n\n const columnByName = useMemo(\n () => new Map(columns.map((column) => [column.name, column])),\n [columns]\n );\n\n const indexed = useMemo(() => rowPage.rows.map((row, index) => ({ row, index })), [rowPage.rows]);\n\n const filtered = useMemo(() => {\n const query = search.trim().toLowerCase();\n if (!query) return indexed;\n return indexed.filter(({ row }) =>\n Object.values(row).some((value) => formatCell(value).toLowerCase().includes(query))\n );\n }, [indexed, search]);\n\n const sorted = useMemo(() => {\n if (!sortCol || !sortDir) return filtered;\n const copy = [...filtered];\n copy.sort((a, b) => {\n const left = formatCell(a.row[sortCol]);\n const right = formatCell(b.row[sortCol]);\n const cmp = left < right ? -1 : left > right ? 1 : 0;\n return sortDir === \"asc\" ? cmp : -cmp;\n });\n return copy;\n }, [filtered, sortCol, sortDir]);\n\n function handleSort(column: string): void {\n if (sortCol !== column) {\n setSortCol(column);\n setSortDir(\"asc\");\n } else if (sortDir === \"asc\") {\n setSortDir(\"desc\");\n } else {\n setSortCol(null);\n setSortDir(null);\n }\n }\n\n function toggleRow(index: number): void {\n setSelected((current) => {\n const next = new Set(current);\n if (next.has(index)) next.delete(index);\n else next.add(index);\n return next;\n });\n }\n\n async function copySelected(): Promise<void> {\n const rows = sorted.filter(({ index }) => selected.has(index)).map(({ row }) => row);\n await navigator.clipboard.writeText(toCsv(rowPage.columns, rows));\n }\n\n function exportCsv(): void {\n downloadCsv(\n `${tableName ?? \"rows\"}.csv`,\n toCsv(\n rowPage.columns,\n sorted.map(({ row }) => row)\n )\n );\n }\n\n return (\n <div className=\"flex h-full flex-col\">\n <div className=\"flex shrink-0 flex-wrap items-center gap-2 border-b border-border px-3 py-2\">\n <div className=\"flex items-center gap-1.5 rounded-[3px] bg-accent px-2 py-1 font-mono text-[11px] text-muted-foreground\">\n <Search className=\"h-2.5 w-2.5\" />\n <input\n value={search}\n onChange={(event) => setSearch(event.target.value)}\n placeholder=\"Filter this page...\"\n aria-label=\"Filter this page\"\n title=\"Filters only the rows currently loaded on this page, not the whole table\"\n className=\"w-28 min-w-0 bg-transparent text-foreground outline-none placeholder:text-muted-foreground sm:w-36\"\n />\n {search && (\n <button type=\"button\" onClick={() => setSearch(\"\")} aria-label=\"Clear filter\">\n <X className=\"h-2.5 w-2.5\" />\n </button>\n )}\n </div>\n\n <div className=\"ml-auto flex items-center gap-2\">\n {selected.size > 0 && (\n <>\n <span className=\"font-mono text-[10px]\" style={{ color: \"var(--c-blue)\" }}>\n {selected.size} selected\n </span>\n <button\n type=\"button\"\n onClick={() => void copySelected()}\n className=\"flex items-center gap-1 rounded-[3px] px-2 py-1 text-[11px] text-muted-foreground hover:bg-accent hover:text-foreground\"\n >\n <Copy className=\"h-3 w-3\" /> Copy as CSV\n </button>\n </>\n )}\n <button\n type=\"button\"\n onClick={exportCsv}\n aria-label=\"Export this page as CSV\"\n title=\"Exports the rows currently loaded on this page, not the whole table\"\n className=\"rounded-[3px] p-1 text-muted-foreground hover:bg-accent hover:text-foreground\"\n >\n <Download className=\"h-3 w-3\" />\n </button>\n {onRefresh && (\n <button\n type=\"button\"\n onClick={onRefresh}\n aria-label=\"Refresh rows\"\n className=\"rounded-[3px] p-1 text-muted-foreground hover:bg-accent hover:text-foreground\"\n >\n <RefreshCw className=\"h-3 w-3\" />\n </button>\n )}\n </div>\n </div>\n\n {columns.length > 0 && (\n <div className=\"flex shrink-0 overflow-x-auto overflow-y-hidden border-b border-border bg-card\">\n <div className=\"w-8 shrink-0 border-r border-border\" />\n <div className=\"w-8 shrink-0 border-r border-border\" />\n {rowPage.columns.map((columnName) => {\n const meta = columnByName.get(columnName);\n return (\n <div\n key={columnName}\n className=\"flex min-w-[120px] shrink-0 items-center gap-1 whitespace-nowrap border-r border-border px-3 py-1 font-mono text-[9px] text-muted-foreground\"\n >\n {meta && <TypeIcon dataType={meta.dataType} />}\n <span>{meta?.dataType ?? \"unknown\"}</span>\n {meta?.isPrimaryKey && (\n <span className=\"ml-1 font-bold\" style={{ color: \"var(--c-amber)\" }}>\n PK\n </span>\n )}\n </div>\n );\n })}\n </div>\n )}\n\n {rowPage.rows.length === 0 ? (\n <div data-testid=\"rows-table\" className=\"flex-1 p-3\">\n <p className=\"font-mono text-[11px] text-muted-foreground\">No rows in this table.</p>\n </div>\n ) : (\n <div data-testid=\"rows-table\" className=\"flex-1 overflow-auto\">\n <table className=\"w-full border-collapse font-mono text-[11px]\">\n <thead className=\"sticky top-0 z-10 bg-card\">\n <tr>\n <th className=\"w-8 border-b border-r border-border px-2 py-2\" />\n <th className=\"w-8 border-b border-r border-border px-2 py-2 text-right font-normal text-muted-foreground/40\">\n #\n </th>\n {rowPage.columns.map((columnName) => (\n <th\n key={columnName}\n onClick={() => handleSort(columnName)}\n className=\"group cursor-pointer whitespace-nowrap border-b border-r border-border px-3 py-2 text-left font-medium text-muted-foreground hover:text-foreground\"\n >\n <div className=\"flex items-center gap-1.5\">\n {columnName}\n <ArrowUpDown\n className={cn(\n \"h-2.5 w-2.5 transition-opacity\",\n sortCol === columnName\n ? \"text-primary opacity-100\"\n : \"opacity-0 group-hover:opacity-40\"\n )}\n />\n </div>\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {sorted.map(({ row, index }, displayIndex) => (\n <tr\n key={index}\n onClick={() => toggleRow(index)}\n className={cn(\n \"cursor-pointer border-b border-border-subtle hover:bg-accent/40\",\n selected.has(index) && \"bg-primary/5\"\n )}\n >\n <td className=\"w-8 border-r border-border-subtle px-2 py-1.5 text-center\">\n <input\n type=\"checkbox\"\n checked={selected.has(index)}\n onChange={() => toggleRow(index)}\n onClick={(event) => event.stopPropagation()}\n className=\"h-3 w-3 accent-primary\"\n aria-label={`Select row ${displayIndex + 1}`}\n />\n </td>\n <td className=\"w-8 border-r border-border-subtle px-2 py-1.5 text-right text-muted-foreground/30\">\n {displayIndex + 1}\n </td>\n {rowPage.columns.map((columnName) => (\n <td\n key={columnName}\n className=\"whitespace-nowrap border-r border-border-subtle px-3 py-1.5 text-foreground/80\"\n >\n {row[columnName] === null || row[columnName] === undefined ? (\n <span className=\"italic text-muted-foreground/30\">null</span>\n ) : (\n formatCell(row[columnName])\n )}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n\n <div className=\"flex shrink-0 items-center justify-between border-t border-border bg-card px-3 py-1.5\">\n <span className=\"font-mono text-[10px] text-muted-foreground\">\n {sorted.length.toLocaleString()} of{\" \"}\n {approxRowCount !== undefined\n ? `~${approxRowCount.toLocaleString()}`\n : sorted.length.toLocaleString()}{\" \"}\n rows\n {tableName && <> · {tableName}</>}\n </span>\n <div className=\"flex items-center gap-1\">\n <button\n type=\"button\"\n disabled={!canGoPrevious}\n onClick={onPrevious}\n aria-label=\"Previous page\"\n className=\"rounded-[2px] p-0.5 text-muted-foreground hover:bg-accent disabled:opacity-30\"\n >\n <ChevronLeft className=\"h-3.5 w-3.5\" />\n </button>\n <span className=\"px-1 font-mono text-[10px] text-muted-foreground\">Page {page + 1}</span>\n <button\n type=\"button\"\n disabled={!canGoNext}\n onClick={onNext}\n aria-label=\"Next page\"\n className=\"rounded-[2px] p-0.5 text-muted-foreground hover:bg-accent disabled:opacity-30\"\n >\n <ChevronRight className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n </div>\n </div>\n );\n}\n","/** Format an arbitrary row cell value for display. Shared by RowsTable and QueryRunner. */\nexport function formatCell(value: unknown): string {\n if (value === null || value === undefined) {\n return \"\";\n }\n return typeof value === \"string\" ? value : JSON.stringify(value);\n}\n","import type { RowPage } from \"@humbdb/core\";\nimport { Play } from \"lucide-react\";\nimport type { KeyboardEvent, ReactNode, UIEvent } from \"react\";\nimport { useRef } from \"react\";\nimport { formatCell } from \"../format-cell.js\";\nimport { Spinner } from \"./spinner.js\";\n\nexport interface QueryRunnerProps {\n sql: string;\n onSqlChange: (sql: string) => void;\n onRun: () => void;\n isRunning: boolean;\n result?: RowPage;\n error?: string;\n}\n\n/** A read-only SQL query box: SELECT-style statements only, enforced server-side. */\nexport function QueryRunner({\n sql,\n onSqlChange,\n onRun,\n isRunning,\n result,\n error\n}: QueryRunnerProps): ReactNode {\n const canRun = !isRunning && sql.trim().length > 0;\n const lineCount = sql.split(\"\\n\").length;\n const gutterRef = useRef<HTMLDivElement>(null);\n\n function handleKeyDown(event: KeyboardEvent<HTMLTextAreaElement>): void {\n if ((event.ctrlKey || event.metaKey) && event.key === \"Enter\") {\n event.preventDefault();\n if (canRun) onRun();\n }\n }\n\n function handleScroll(event: UIEvent<HTMLTextAreaElement>): void {\n if (gutterRef.current) {\n gutterRef.current.scrollTop = event.currentTarget.scrollTop;\n }\n }\n\n return (\n <div\n data-testid=\"query-runner\"\n className=\"flex h-full flex-col overflow-hidden rounded-[3px] border border-border\"\n >\n <div className=\"flex shrink-0 items-center gap-2 border-b border-border px-3 py-2\">\n <button\n type=\"button\"\n onClick={onRun}\n disabled={!canRun}\n className=\"flex items-center gap-1.5 rounded-[3px] bg-primary px-3 py-1 text-[11px] font-medium text-primary-foreground transition-opacity hover:opacity-90 disabled:opacity-50\"\n >\n {isRunning ? (\n <Spinner className=\"h-2.5 w-2.5 text-primary-foreground\" />\n ) : (\n <Play className=\"h-2.5 w-2.5\" />\n )}\n {isRunning ? \"Running...\" : \"Run\"}\n </button>\n <span className=\"hidden font-mono text-[10px] text-muted-foreground sm:inline\">\n ⌘ Enter\n </span>\n <span className=\"ml-auto font-mono text-[10px] text-muted-foreground\">\n {lineCount} line{lineCount === 1 ? \"\" : \"s\"}\n </span>\n </div>\n\n <div className=\"flex min-h-[8rem] flex-1 overflow-hidden\">\n <div\n ref={gutterRef}\n aria-hidden=\"true\"\n className=\"shrink-0 select-none overflow-hidden border-r border-border bg-background pr-3 pt-3 text-right font-mono text-[11px] text-muted-foreground/30\"\n style={{ minWidth: \"44px\" }}\n >\n {Array.from({ length: lineCount }, (_, index) => (\n <div key={index} style={{ lineHeight: \"20px\" }}>\n {index + 1}\n </div>\n ))}\n </div>\n <textarea\n value={sql}\n onChange={(event) => onSqlChange(event.target.value)}\n onKeyDown={handleKeyDown}\n onScroll={handleScroll}\n placeholder=\"SELECT * FROM my_table LIMIT 10\"\n spellCheck={false}\n className=\"flex-1 resize-none overflow-auto bg-background p-3 font-mono text-[12px] leading-5 text-foreground outline-none\"\n style={{ caretColor: \"var(--c-blue)\" }}\n />\n </div>\n\n {error && (\n <p\n data-testid=\"query-error\"\n className=\"border-t border-border px-3 py-2 font-mono text-[11px]\"\n style={{ color: \"var(--c-red)\" }}\n >\n {error}\n </p>\n )}\n\n {result && !error && (\n <div\n data-testid=\"query-result\"\n className=\"max-h-64 shrink-0 overflow-auto border-t border-border\"\n >\n {result.rows.length === 0 ? (\n <p className=\"p-3 font-mono text-[11px] text-muted-foreground\">\n Query returned no rows.\n </p>\n ) : (\n <table className=\"w-full border-collapse font-mono text-[11px]\">\n <thead className=\"sticky top-0 bg-card\">\n <tr>\n {result.columns.map((column) => (\n <th\n key={column}\n className=\"whitespace-nowrap border-b border-r border-border px-3 py-1.5 text-left font-medium text-muted-foreground\"\n >\n {column}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {result.rows.map((row, rowIndex) => (\n <tr key={rowIndex} className=\"border-b border-border-subtle\">\n {result.columns.map((column) => (\n <td\n key={column}\n className=\"whitespace-nowrap border-r border-border-subtle px-3 py-1.5 text-foreground/80\"\n >\n {formatCell(row[column])}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n )}\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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","names":["jsx","jsx","jsxs","jsx","jsx","jsxs","jsx","FolderOpen","Table2","useState","jsx","jsxs","TreeRow","useState","FolderOpen","Table2","Fragment","jsx","jsxs","Fragment","jsx","jsxs","FileCode2","FolderOpen","Table2","jsx","jsxs","FileCode2","Table2","FolderOpen","Fragment","jsx","jsxs","STATUS_DOT_COLOR","STATUS_LABEL","ChevronRight","RefreshCw","useMemo","useState","Fragment","jsx","jsxs","useState","useMemo","RefreshCw","ChevronRight","jsx","jsxs"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@humbdb/ui",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Reusable presentational UI components for Humb.",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"import": "./dist/index.js"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"main": "./dist/index.js",
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"clsx": "^2.1.1",
|
|
20
|
+
"lucide-react": "^1.23.0",
|
|
21
|
+
"tailwind-merge": "^2.6.0",
|
|
22
|
+
"@humbdb/core": "0.0.1"
|
|
23
|
+
},
|
|
24
|
+
"peerDependencies": {
|
|
25
|
+
"react": "^18.3.1",
|
|
26
|
+
"react-dom": "^18.3.1"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@types/react": "^18.3.18",
|
|
30
|
+
"@types/react-dom": "^18.3.5",
|
|
31
|
+
"react": "^18.3.1",
|
|
32
|
+
"react-dom": "^18.3.1",
|
|
33
|
+
"@humbdb/config": "0.0.0"
|
|
34
|
+
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"build": "tsup",
|
|
37
|
+
"dev": "tsup --watch",
|
|
38
|
+
"typecheck": "tsc --noEmit",
|
|
39
|
+
"test": "vitest run",
|
|
40
|
+
"clean": "rimraf dist .turbo"
|
|
41
|
+
}
|
|
42
|
+
}
|