@agent-native/core 0.61.0 → 0.62.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/dist/agent/engine/translate-anthropic.d.ts.map +1 -1
- package/dist/agent/engine/translate-anthropic.js +47 -1
- package/dist/agent/engine/translate-anthropic.js.map +1 -1
- package/dist/agent-native/index.d.ts +40 -0
- package/dist/agent-native/index.d.ts.map +1 -0
- package/dist/agent-native/index.js +100 -0
- package/dist/agent-native/index.js.map +1 -0
- package/dist/cli/templates-meta.d.ts.map +1 -1
- package/dist/cli/templates-meta.js +1 -0
- package/dist/cli/templates-meta.js.map +1 -1
- package/dist/client/analytics.d.ts.map +1 -1
- package/dist/client/analytics.js +30 -0
- package/dist/client/analytics.js.map +1 -1
- package/dist/client/blocks/SchemaBlockEditor.d.ts.map +1 -1
- package/dist/client/blocks/SchemaBlockEditor.js +2 -1
- package/dist/client/blocks/SchemaBlockEditor.js.map +1 -1
- package/dist/client/blocks/code-block-direction.d.ts +21 -0
- package/dist/client/blocks/code-block-direction.d.ts.map +1 -0
- package/dist/client/blocks/code-block-direction.js +20 -0
- package/dist/client/blocks/code-block-direction.js.map +1 -0
- package/dist/client/blocks/library/AnnotatedCodeBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/AnnotatedCodeBlock.js +2 -1
- package/dist/client/blocks/library/AnnotatedCodeBlock.js.map +1 -1
- package/dist/client/blocks/library/ApiEndpointBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/ApiEndpointBlock.js +2 -1
- package/dist/client/blocks/library/ApiEndpointBlock.js.map +1 -1
- package/dist/client/blocks/library/DataModelBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/DataModelBlock.js +2 -1
- package/dist/client/blocks/library/DataModelBlock.js.map +1 -1
- package/dist/client/blocks/library/DiffBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/DiffBlock.js +2 -1
- package/dist/client/blocks/library/DiffBlock.js.map +1 -1
- package/dist/client/blocks/library/FileTreeBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/FileTreeBlock.js +2 -1
- package/dist/client/blocks/library/FileTreeBlock.js.map +1 -1
- package/dist/client/blocks/library/HighlightedCode.d.ts.map +1 -1
- package/dist/client/blocks/library/HighlightedCode.js +2 -1
- package/dist/client/blocks/library/HighlightedCode.js.map +1 -1
- package/dist/client/blocks/library/JsonExplorerBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/JsonExplorerBlock.js +2 -1
- package/dist/client/blocks/library/JsonExplorerBlock.js.map +1 -1
- package/dist/client/blocks/library/MermaidBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/MermaidBlock.js +2 -1
- package/dist/client/blocks/library/MermaidBlock.js.map +1 -1
- package/dist/client/blocks/library/OpenApiSpecBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/OpenApiSpecBlock.js +2 -1
- package/dist/client/blocks/library/OpenApiSpecBlock.js.map +1 -1
- package/dist/client/blocks/library/annotation-rail.d.ts.map +1 -1
- package/dist/client/blocks/library/annotation-rail.js +2 -1
- package/dist/client/blocks/library/annotation-rail.js.map +1 -1
- package/dist/client/blocks/library/code-tabs.d.ts.map +1 -1
- package/dist/client/blocks/library/code-tabs.js +2 -1
- package/dist/client/blocks/library/code-tabs.js.map +1 -1
- package/dist/client/blocks/library/code.d.ts.map +1 -1
- package/dist/client/blocks/library/code.js +3 -2
- package/dist/client/blocks/library/code.js.map +1 -1
- package/dist/client/blocks/library/diagram.d.ts.map +1 -1
- package/dist/client/blocks/library/diagram.js +2 -1
- package/dist/client/blocks/library/diagram.js.map +1 -1
- package/dist/client/blocks/library/wireframe.d.ts.map +1 -1
- package/dist/client/blocks/library/wireframe.js +2 -1
- package/dist/client/blocks/library/wireframe.js.map +1 -1
- package/dist/db/client.d.ts +3 -3
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +8 -4
- package/dist/db/client.js.map +1 -1
- package/dist/templates/workspace-core/.agents/skills/composable-mini-apps/SKILL.md +26 -0
- package/docs/content/a2a-protocol.md +28 -0
- package/docs/content/agent-surfaces.md +12 -4
- package/docs/content/getting-started.md +136 -37
- package/docs/content/pure-agent-apps.md +25 -9
- package/docs/content/template-dispatch.md +4 -0
- package/package.json +5 -1
- package/src/templates/workspace-core/.agents/skills/composable-mini-apps/SKILL.md +26 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileTreeBlock.js","sourceRoot":"","sources":["../../../../src/client/blocks/library/FileTreeBlock.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useMemo, useRef, useState } from \"react\";\nimport {\n IconChevronRight,\n IconFile,\n IconFolder,\n IconFolderOpen,\n IconPlus,\n IconTrash,\n} from \"@tabler/icons-react\";\nimport { cn } from \"../../utils.js\";\nimport type { BlockEditProps, BlockReadProps } from \"../types.js\";\nimport type {\n FileTreeChange,\n FileTreeData,\n FileTreeEntry,\n} from \"./file-tree.config.js\";\nimport { FILE_TREE_CHANGES } from \"./file-tree.config.js\";\nimport { DevInput, DevTextarea, DevSelect } from \"./dev-doc-ui.js\";\n\n/**\n * Read + Edit renderers for a `file-tree` block — a VS Code / GitHub-explorer\n * file and change tree. Lives in core so any app can register the dev-doc block\n * (no shadcn import; the editor's enum picker is the core `DevSelect`).\n */\n\n/* ── Theme-aware change tokens ─────────────────────────────────────────────── */\n\n/**\n * Change-badge palette. Tinted background + saturated text in BOTH the `.dark`\n * plan theme and light mode (never a dark-only palette). Each entry keeps legible\n * contrast against the plan surface via Tailwind `dark:` variants.\n */\nconst CHANGE_BADGE: Record<FileTreeChange, string> = {\n added:\n \"bg-emerald-100 text-emerald-700 dark:bg-emerald-500/15 dark:text-emerald-300\",\n modified: \"bg-blue-100 text-blue-700 dark:bg-blue-500/15 dark:text-blue-300\",\n removed: \"bg-red-100 text-red-700 dark:bg-red-500/15 dark:text-red-300\",\n renamed:\n \"bg-violet-100 text-violet-700 dark:bg-violet-500/15 dark:text-violet-300\",\n};\n\n/** Single-letter glyph shown in the change badge (VS Code gutter convention). */\nconst CHANGE_GLYPH: Record<FileTreeChange, string> = {\n added: \"A\",\n modified: \"M\",\n removed: \"D\",\n renamed: \"R\",\n};\n\n/** Accent ink for the file name itself, echoing its change color. */\nconst CHANGE_NAME_INK: Record<FileTreeChange, string> = {\n added: \"text-emerald-700 dark:text-emerald-300\",\n modified: \"text-blue-700 dark:text-blue-300\",\n removed: \"text-red-600 line-through dark:text-red-300\",\n renamed: \"text-violet-700 dark:text-violet-300\",\n};\n\nconst CHANGE_LABEL: Record<FileTreeChange, string> = {\n added: \"Added\",\n modified: \"Modified\",\n removed: \"Removed\",\n renamed: \"Renamed\",\n};\n\n/** Infer a fence language for a file's snippet from its `language` or extension. */\nfunction fenceLanguage(entry: FileTreeEntry): string {\n if (entry.language?.trim()) return entry.language.trim();\n const ext = entry.path.split(\".\").pop()?.toLowerCase() ?? \"\";\n const byExt: Record<string, string> = {\n ts: \"ts\",\n tsx: \"tsx\",\n js: \"js\",\n jsx: \"jsx\",\n mjs: \"js\",\n cjs: \"js\",\n json: \"json\",\n css: \"css\",\n scss: \"scss\",\n html: \"html\",\n md: \"md\",\n mdx: \"md\",\n py: \"python\",\n rb: \"ruby\",\n go: \"go\",\n rs: \"rust\",\n sql: \"sql\",\n sh: \"bash\",\n yml: \"yaml\",\n yaml: \"yaml\",\n toml: \"toml\",\n };\n return byExt[ext] ?? \"text\";\n}\n\n/** Wrap a raw snippet in a fenced code block for `ctx.renderMarkdown`. */\nfunction fence(snippet: string, language: string): string {\n // Never let the snippet's own content break out of the fence.\n const safe = snippet.replace(/```/g, \"ʼʼʼ\");\n return `\\`\\`\\`${language}\\n${safe.replace(/\\s+$/, \"\")}\\n\\`\\`\\``;\n}\n\n/* ── Tree construction (flat paths → nested folders) ───────────────────────── */\n\ninterface FileLeaf {\n kind: \"file\";\n /** Last path segment. */\n name: string;\n /** Full slash path, used as a stable key + anchor. */\n path: string;\n entry: FileTreeEntry;\n /** Index in the original flat `entries` (stable per-file disclosure key). */\n index: number;\n}\n\ninterface FolderNode {\n kind: \"folder\";\n name: string;\n /** Full slash path of the folder, used as a stable key. */\n path: string;\n children: TreeNode[];\n}\n\ntype TreeNode = FolderNode | FileLeaf;\n\ninterface VisibleTreeRow {\n node: TreeNode;\n depth: number;\n}\n\n/** A folder being assembled while we walk the paths (children keyed by name). */\ninterface FolderBuild {\n name: string;\n path: string;\n folders: Map<string, FolderBuild>;\n files: FileLeaf[];\n /** Insertion order of child names (folders + files) for stable rendering. */\n order: string[];\n}\n\nfunction makeFolder(name: string, path: string): FolderBuild {\n return { name, path, folders: new Map(), files: [], order: [] };\n}\n\n/**\n * Build a nested folder tree from the flat `entries`. Folders are derived purely\n * from the slash segments of each `path`; a single-segment path is a root file.\n * Insertion order is preserved within each folder, with folders sorted before\n * files at each level (the conventional explorer ordering).\n */\nfunction buildTree(entries: FileTreeEntry[]): TreeNode[] {\n const root = makeFolder(\"\", \"\");\n\n entries.forEach((entry, index) => {\n const segments = entry.path.split(\"/\").filter(Boolean);\n if (segments.length === 0) return;\n const fileName = segments[segments.length - 1] as string;\n const folderSegments = segments.slice(0, -1);\n\n let cursor = root;\n let prefix = \"\";\n for (const segment of folderSegments) {\n prefix = prefix ? `${prefix}/${segment}` : segment;\n let next = cursor.folders.get(segment);\n if (!next) {\n next = makeFolder(segment, prefix);\n cursor.folders.set(segment, next);\n cursor.order.push(`d:${segment}`);\n }\n cursor = next;\n }\n\n cursor.files.push({\n kind: \"file\",\n name: fileName,\n path: entry.path,\n entry,\n index,\n });\n cursor.order.push(`f:${cursor.files.length - 1}`);\n });\n\n const materialize = (folder: FolderBuild): TreeNode[] => {\n const nodes: TreeNode[] = [];\n for (const key of folder.order) {\n if (key.startsWith(\"d:\")) {\n const child = folder.folders.get(key.slice(2));\n if (!child) continue;\n nodes.push({\n kind: \"folder\",\n name: child.name,\n path: child.path,\n children: materialize(child),\n });\n } else {\n const file = folder.files[Number(key.slice(2))];\n if (file) nodes.push(file);\n }\n }\n // Folders before files at this level (standard explorer ordering).\n return [\n ...nodes.filter((node) => node.kind === \"folder\"),\n ...nodes.filter((node) => node.kind === \"file\"),\n ];\n };\n\n return materialize(root);\n}\n\nfunction compactFolderNode(folder: FolderNode): FolderNode {\n const names = [folder.name];\n let path = folder.path;\n let children = folder.children;\n\n while (children.length === 1 && children[0]?.kind === \"folder\") {\n const child = children[0];\n names.push(child.name);\n path = child.path;\n children = child.children;\n }\n\n return {\n kind: \"folder\",\n name: names.join(\"/\"),\n path,\n children: compactTree(children),\n };\n}\n\nfunction compactTree(nodes: TreeNode[]): TreeNode[] {\n return nodes.map((node) =>\n node.kind === \"folder\" ? compactFolderNode(node) : node,\n );\n}\n\nfunction flattenVisibleRows(\n nodes: TreeNode[],\n collapsedFolders: Record<string, boolean>,\n depth = 0,\n): VisibleTreeRow[] {\n const rows: VisibleTreeRow[] = [];\n\n for (const node of nodes) {\n rows.push({ node, depth });\n if (node.kind === \"folder\" && !(collapsedFolders[node.path] ?? false)) {\n rows.push(\n ...flattenVisibleRows(node.children, collapsedFolders, depth + 1),\n );\n }\n }\n\n return rows;\n}\n\n/* ── Read (IDE explorer) ───────────────────────────────────────────────────── */\n\nconst INDENT_STEP = 14; // px per nesting level — the explorer guide spacing.\nconst DEFAULT_VISIBLE_TREE_ROWS = 10;\n\n/**\n * Read-only renderer for a `file-tree` block — a VS Code / GitHub-explorer file\n * and change tree. The flat `entries` are folded into a nested tree of\n * collapsible folders (IconFolder + chevron) and files (IconFile) carrying a\n * single-letter change badge (A/M/D/R). A file with a `note` or `snippet` is\n * itself clickable and expands to show the note plus the snippet rendered as a\n * fenced code block via `ctx.renderMarkdown`. A summary header tallies the change\n * counts (\"+N · ~M · −K\"). Every color is theme-aware via Tailwind `dark:`\n * variants / plan CSS vars, so the tree reads correctly in both modes.\n */\nexport function FileTreeRead({\n data,\n blockId,\n title,\n summary,\n ctx,\n}: BlockReadProps<FileTreeData>) {\n const entries = data.entries ?? [];\n const tree = useMemo(() => compactTree(buildTree(entries)), [entries]);\n\n // Folders default to fully expanded so the tree is useful at a glance.\n const [collapsedFolders, setCollapsedFolders] = useState<\n Record<string, boolean>\n >({});\n const [showAllRows, setShowAllRows] = useState(false);\n // Files with a note/snippet collapse their detail by default (progressive\n // disclosure) — keyed by the flat entry index so duplicate names never clash.\n const [openFiles, setOpenFiles] = useState<Record<number, boolean>>({});\n\n const toggleFolder = (path: string) =>\n setCollapsedFolders((current) => ({\n ...current,\n [path]: !current[path],\n }));\n const toggleFile = (index: number) =>\n setOpenFiles((current) => ({ ...current, [index]: !current[index] }));\n\n // The recap \"Files touched\" left rail (only) widens into the document as a\n // flyout while the tree is the reader's active focus AND a file's detail is\n // open, then collapses back to a slim rail when they click elsewhere or close\n // the last open file. `data-files-expanded` on the root drives the rail width\n // via CSS (`:has()`); it is inert anywhere the tree renders inline.\n const rootRef = useRef<HTMLElement>(null);\n const [active, setActive] = useState(false);\n const anyFileOpen = useMemo(\n () => Object.values(openFiles).some(Boolean),\n [openFiles],\n );\n const railExpanded = active && anyFileOpen;\n\n useEffect(() => {\n if (!railExpanded) return;\n const onPointerDown = (event: PointerEvent) => {\n const root = rootRef.current;\n if (\n root &&\n event.target instanceof Node &&\n !root.contains(event.target)\n ) {\n // Clicking away collapses the rail and closes any open file detail, so\n // it returns to the clean slim state rather than leaving notes open in\n // the cramped width.\n setActive(false);\n setOpenFiles({});\n }\n };\n document.addEventListener(\"pointerdown\", onPointerDown, true);\n return () =>\n document.removeEventListener(\"pointerdown\", onPointerDown, true);\n }, [railExpanded]);\n\n // Change tally for the summary header.\n const counts = useMemo(() => {\n const tally = { added: 0, modified: 0, removed: 0, renamed: 0 };\n for (const entry of entries) {\n if (entry.change) tally[entry.change] += 1;\n }\n return tally;\n }, [entries]);\n const changeTotal =\n counts.added + counts.modified + counts.removed + counts.renamed;\n\n const visibleRows = useMemo(\n () => flattenVisibleRows(tree, collapsedFolders),\n [collapsedFolders, tree],\n );\n const shouldLimitRows = visibleRows.length > DEFAULT_VISIBLE_TREE_ROWS;\n const displayedRows =\n showAllRows || !shouldLimitRows\n ? visibleRows\n : visibleRows.slice(0, DEFAULT_VISIBLE_TREE_ROWS);\n\n const renderRow = ({ node, depth }: VisibleTreeRow): React.ReactNode => {\n const indent = depth * INDENT_STEP;\n if (node.kind === \"folder\") {\n const collapsed = collapsedFolders[node.path] ?? false;\n return (\n <div key={`d:${node.path}`}>\n <button\n type=\"button\"\n data-plan-interactive\n aria-expanded={!collapsed}\n onClick={() => toggleFolder(node.path)}\n style={{ paddingLeft: indent + 8 }}\n className=\"flex w-full items-center gap-1.5 rounded-md py-1 pr-2 text-left text-[13px] transition-colors hover:bg-accent/40\"\n >\n <IconChevronRight\n className={cn(\n \"size-3.5 shrink-0 text-plan-muted transition-transform\",\n !collapsed && \"rotate-90\",\n )}\n />\n {collapsed ? (\n <IconFolder className=\"size-4 shrink-0 text-plan-muted\" />\n ) : (\n <IconFolderOpen className=\"size-4 shrink-0 text-plan-muted\" />\n )}\n <span className=\"min-w-0 truncate font-medium text-plan-text\">\n {node.name}\n </span>\n </button>\n </div>\n );\n }\n\n const { entry } = node;\n const change = entry.change;\n const hasDetail = Boolean(entry.note?.trim() || entry.snippet?.trim());\n const isOpen = openFiles[node.index] ?? false;\n\n return (\n <div key={`f:${node.index}`}>\n <button\n type=\"button\"\n data-plan-interactive\n data-file-path={node.path}\n disabled={!hasDetail}\n aria-expanded={hasDetail ? isOpen : undefined}\n onClick={hasDetail ? () => toggleFile(node.index) : undefined}\n style={{ paddingLeft: indent + 8 }}\n className={cn(\n \"group flex w-full items-center gap-1.5 rounded-md py-1 pr-2 text-left text-[13px] transition-colors\",\n hasDetail ? \"hover:bg-accent/40\" : \"cursor-default\",\n )}\n >\n {/* Chevron slot — present only for files with expandable detail so\n everything stays aligned with the folder rows above. */}\n {hasDetail ? (\n <IconChevronRight\n className={cn(\n \"size-3.5 shrink-0 text-plan-muted transition-transform\",\n isOpen && \"rotate-90\",\n )}\n />\n ) : (\n <span className=\"size-3.5 shrink-0\" aria-hidden />\n )}\n <IconFile\n className={cn(\n \"size-4 shrink-0\",\n change === \"removed\" ? \"text-plan-muted\" : \"text-plan-muted/80\",\n )}\n />\n <span\n className={cn(\n \"min-w-0 truncate font-medium\",\n change ? CHANGE_NAME_INK[change] : \"text-plan-text\",\n )}\n >\n {node.name}\n </span>\n {change && (\n <span\n title={CHANGE_LABEL[change]}\n aria-label={CHANGE_LABEL[change]}\n className={cn(\n \"ml-1 flex size-4 shrink-0 items-center justify-center rounded text-[10px] font-bold leading-none\",\n CHANGE_BADGE[change],\n )}\n >\n {CHANGE_GLYPH[change]}\n </span>\n )}\n {entry.note?.trim() && !isOpen && (\n <span className=\"ml-1 min-w-0 flex-1 truncate text-xs text-plan-muted\">\n {entry.note}\n </span>\n )}\n </button>\n\n {/* Expanded file detail: the note + a fenced snippet. */}\n {hasDetail && isOpen && (\n <div\n style={{ paddingLeft: indent + 8 + 20 }}\n className=\"pb-2 pr-2 pt-0.5\"\n >\n {entry.note?.trim() && (\n <p className=\"text-xs leading-relaxed text-plan-muted\">\n {entry.note}\n </p>\n )}\n {entry.snippet?.trim() && (\n <div className=\"mt-2 an-file-tree-snippet\">\n {ctx.renderMarkdown?.(\n fence(entry.snippet, fenceLanguage(entry)),\n )}\n </div>\n )}\n </div>\n )}\n </div>\n );\n };\n\n return (\n <section\n ref={rootRef}\n className=\"plan-block\"\n data-block-id={blockId}\n data-files-expanded={railExpanded ? \"\" : undefined}\n onPointerDown={() => setActive(true)}\n >\n {title && <div className=\"plan-block-label\">{title}</div>}\n\n <div className=\"overflow-hidden rounded-xl border border-plan-line bg-plan-block\">\n {/* Summary header: file count + change tally. */}\n <div className=\"flex flex-wrap items-center gap-2 border-b border-plan-line bg-accent/20 px-3 py-2\">\n {data.title && (\n <span className=\"text-[13px] font-semibold text-plan-text\">\n {data.title}\n </span>\n )}\n <span className=\"text-xs text-plan-muted\">\n {entries.length} {entries.length === 1 ? \"file\" : \"files\"}\n </span>\n {changeTotal > 0 && (\n <span className=\"ml-auto flex items-center gap-2 font-mono text-xs\">\n {counts.added > 0 && (\n <span className=\"text-emerald-600 dark:text-emerald-300\">\n +{counts.added}\n </span>\n )}\n {counts.modified > 0 && (\n <span className=\"text-blue-600 dark:text-blue-300\">\n ~{counts.modified}\n </span>\n )}\n {counts.removed > 0 && (\n <span className=\"text-red-600 dark:text-red-300\">\n −{counts.removed}\n </span>\n )}\n {counts.renamed > 0 && (\n <span className=\"text-violet-600 dark:text-violet-300\">\n »{counts.renamed}\n </span>\n )}\n </span>\n )}\n </div>\n\n {/* The tree itself. */}\n <div className=\"py-1.5\">\n {tree.length > 0 ? (\n <>\n {displayedRows.map(renderRow)}\n {shouldLimitRows && (\n <div className=\"px-2 pt-1\">\n <button\n type=\"button\"\n data-plan-interactive\n aria-expanded={showAllRows}\n onClick={() => setShowAllRows((current) => !current)}\n className=\"flex h-8 w-full items-center justify-center gap-1.5 rounded-md text-xs font-medium text-plan-muted transition-colors hover:bg-accent/40 hover:text-plan-text\"\n >\n <IconChevronRight\n className={cn(\n \"size-3.5 shrink-0 transition-transform\",\n showAllRows ? \"-rotate-90\" : \"rotate-90\",\n )}\n />\n {showAllRows\n ? \"Show fewer\"\n : `Show all ${visibleRows.length} rows`}\n </button>\n </div>\n )}\n </>\n ) : (\n <p className=\"px-3 py-2 text-xs text-plan-muted\">No files yet.</p>\n )}\n </div>\n </div>\n\n {summary && <p className=\"mt-5 text-plan-muted\">{summary}</p>}\n </section>\n );\n}\n\n/* ── Edit (panel form) ─────────────────────────────────────────────────────── */\n\nconst fieldLabelClass = \"text-xs font-medium text-muted-foreground\";\n\n/**\n * Panel editor for a `file-tree` block. A structured form: an optional title\n * Input plus a list of file rows (add/remove), each carrying a path Input, a\n * change Select, a note Input, an optional language Input, and a snippet\n * Textarea. The folder tree is derived from the paths in the Read render, so the\n * form stays flat and quick to edit. Renders BARE content (no `<section>`); the\n * registry's panel surface supplies the popover chrome.\n */\nexport function FileTreeEdit({\n data,\n onChange,\n editable,\n}: BlockEditProps<FileTreeData>) {\n const entries = data.entries ?? [];\n\n const patchEntries = (next: FileTreeEntry[]) =>\n onChange({ ...data, entries: next });\n\n const updateEntry = (index: number, next: Partial<FileTreeEntry>) =>\n patchEntries(\n entries.map((entry, i) => (i === index ? { ...entry, ...next } : entry)),\n );\n\n const removeEntry = (index: number) =>\n patchEntries(entries.filter((_, i) => i !== index));\n\n const addEntry = () =>\n patchEntries([...entries, { path: \"src/new-file.ts\", change: \"added\" }]);\n\n return (\n <div className=\"flex flex-col gap-4\" data-plan-interactive>\n <label className=\"flex flex-col gap-1.5\">\n <span className={fieldLabelClass}>Title (optional)</span>\n <DevInput\n className=\"h-9\"\n value={data.title ?? \"\"}\n disabled={!editable}\n placeholder=\"e.g. Files touched\"\n onChange={(event) =>\n onChange({ ...data, title: event.target.value || undefined })\n }\n />\n </label>\n\n <div className=\"flex flex-col gap-3\">\n {entries.map((entry, index) => (\n <div\n key={index}\n className=\"flex flex-col gap-2 rounded-lg border border-input p-3\"\n >\n <div className=\"grid grid-cols-[minmax(0,1fr)_120px_auto] gap-2\">\n <DevInput\n className=\"h-8 font-mono text-xs\"\n value={entry.path}\n disabled={!editable}\n placeholder=\"src/routes/git.ts\"\n onChange={(event) =>\n updateEntry(index, { path: event.target.value })\n }\n />\n <DevSelect\n className=\"h-8\"\n value={entry.change ?? \"none\"}\n disabled={!editable}\n onValueChange={(value) =>\n updateEntry(index, {\n change:\n value === \"none\" ? undefined : (value as FileTreeChange),\n })\n }\n options={[\n { value: \"none\", label: \"No change\" },\n ...FILE_TREE_CHANGES.map((change) => ({\n value: change,\n label: CHANGE_LABEL[change],\n })),\n ]}\n />\n {editable && (\n <button\n type=\"button\"\n data-plan-interactive\n aria-label=\"Remove file\"\n className=\"flex size-8 items-center justify-center rounded-md text-muted-foreground hover:bg-accent/60 hover:text-foreground\"\n onClick={() => removeEntry(index)}\n >\n <IconTrash className=\"size-4\" />\n </button>\n )}\n </div>\n <DevInput\n className=\"h-8 text-xs\"\n value={entry.note ?? \"\"}\n disabled={!editable}\n placeholder=\"Why this file changes\"\n onChange={(event) =>\n updateEntry(index, { note: event.target.value || undefined })\n }\n />\n <div className=\"grid grid-cols-[minmax(0,1fr)_120px] gap-2\">\n <DevTextarea\n className=\"min-h-[64px] font-mono text-xs\"\n value={entry.snippet ?? \"\"}\n disabled={!editable}\n placeholder=\"Optional code snippet\"\n onChange={(event) =>\n updateEntry(index, {\n snippet: event.target.value || undefined,\n })\n }\n />\n <DevInput\n className=\"h-8 self-start font-mono text-xs\"\n value={entry.language ?? \"\"}\n disabled={!editable}\n placeholder=\"language\"\n onChange={(event) =>\n updateEntry(index, {\n language: event.target.value || undefined,\n })\n }\n />\n </div>\n </div>\n ))}\n </div>\n\n {editable && (\n <button\n type=\"button\"\n data-plan-interactive\n className=\"flex items-center justify-center gap-1.5 rounded-md border border-dashed border-input py-2 text-sm text-muted-foreground hover:bg-accent/40 hover:text-foreground\"\n onClick={addEntry}\n >\n <IconPlus className=\"size-4\" />\n Add file\n </button>\n )}\n </div>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"FileTreeBlock.js","sourceRoot":"","sources":["../../../../src/client/blocks/library/FileTreeBlock.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useMemo, useRef, useState } from \"react\";\nimport {\n IconChevronRight,\n IconFile,\n IconFolder,\n IconFolderOpen,\n IconPlus,\n IconTrash,\n} from \"@tabler/icons-react\";\nimport { cn } from \"../../utils.js\";\nimport { ltrCodeBlockProps } from \"../code-block-direction.js\";\nimport type { BlockEditProps, BlockReadProps } from \"../types.js\";\nimport type {\n FileTreeChange,\n FileTreeData,\n FileTreeEntry,\n} from \"./file-tree.config.js\";\nimport { FILE_TREE_CHANGES } from \"./file-tree.config.js\";\nimport { DevInput, DevTextarea, DevSelect } from \"./dev-doc-ui.js\";\n\n/**\n * Read + Edit renderers for a `file-tree` block — a VS Code / GitHub-explorer\n * file and change tree. Lives in core so any app can register the dev-doc block\n * (no shadcn import; the editor's enum picker is the core `DevSelect`).\n */\n\n/* ── Theme-aware change tokens ─────────────────────────────────────────────── */\n\n/**\n * Change-badge palette. Tinted background + saturated text in BOTH the `.dark`\n * plan theme and light mode (never a dark-only palette). Each entry keeps legible\n * contrast against the plan surface via Tailwind `dark:` variants.\n */\nconst CHANGE_BADGE: Record<FileTreeChange, string> = {\n added:\n \"bg-emerald-100 text-emerald-700 dark:bg-emerald-500/15 dark:text-emerald-300\",\n modified: \"bg-blue-100 text-blue-700 dark:bg-blue-500/15 dark:text-blue-300\",\n removed: \"bg-red-100 text-red-700 dark:bg-red-500/15 dark:text-red-300\",\n renamed:\n \"bg-violet-100 text-violet-700 dark:bg-violet-500/15 dark:text-violet-300\",\n};\n\n/** Single-letter glyph shown in the change badge (VS Code gutter convention). */\nconst CHANGE_GLYPH: Record<FileTreeChange, string> = {\n added: \"A\",\n modified: \"M\",\n removed: \"D\",\n renamed: \"R\",\n};\n\n/** Accent ink for the file name itself, echoing its change color. */\nconst CHANGE_NAME_INK: Record<FileTreeChange, string> = {\n added: \"text-emerald-700 dark:text-emerald-300\",\n modified: \"text-blue-700 dark:text-blue-300\",\n removed: \"text-red-600 line-through dark:text-red-300\",\n renamed: \"text-violet-700 dark:text-violet-300\",\n};\n\nconst CHANGE_LABEL: Record<FileTreeChange, string> = {\n added: \"Added\",\n modified: \"Modified\",\n removed: \"Removed\",\n renamed: \"Renamed\",\n};\n\n/** Infer a fence language for a file's snippet from its `language` or extension. */\nfunction fenceLanguage(entry: FileTreeEntry): string {\n if (entry.language?.trim()) return entry.language.trim();\n const ext = entry.path.split(\".\").pop()?.toLowerCase() ?? \"\";\n const byExt: Record<string, string> = {\n ts: \"ts\",\n tsx: \"tsx\",\n js: \"js\",\n jsx: \"jsx\",\n mjs: \"js\",\n cjs: \"js\",\n json: \"json\",\n css: \"css\",\n scss: \"scss\",\n html: \"html\",\n md: \"md\",\n mdx: \"md\",\n py: \"python\",\n rb: \"ruby\",\n go: \"go\",\n rs: \"rust\",\n sql: \"sql\",\n sh: \"bash\",\n yml: \"yaml\",\n yaml: \"yaml\",\n toml: \"toml\",\n };\n return byExt[ext] ?? \"text\";\n}\n\n/** Wrap a raw snippet in a fenced code block for `ctx.renderMarkdown`. */\nfunction fence(snippet: string, language: string): string {\n // Never let the snippet's own content break out of the fence.\n const safe = snippet.replace(/```/g, \"ʼʼʼ\");\n return `\\`\\`\\`${language}\\n${safe.replace(/\\s+$/, \"\")}\\n\\`\\`\\``;\n}\n\n/* ── Tree construction (flat paths → nested folders) ───────────────────────── */\n\ninterface FileLeaf {\n kind: \"file\";\n /** Last path segment. */\n name: string;\n /** Full slash path, used as a stable key + anchor. */\n path: string;\n entry: FileTreeEntry;\n /** Index in the original flat `entries` (stable per-file disclosure key). */\n index: number;\n}\n\ninterface FolderNode {\n kind: \"folder\";\n name: string;\n /** Full slash path of the folder, used as a stable key. */\n path: string;\n children: TreeNode[];\n}\n\ntype TreeNode = FolderNode | FileLeaf;\n\ninterface VisibleTreeRow {\n node: TreeNode;\n depth: number;\n}\n\n/** A folder being assembled while we walk the paths (children keyed by name). */\ninterface FolderBuild {\n name: string;\n path: string;\n folders: Map<string, FolderBuild>;\n files: FileLeaf[];\n /** Insertion order of child names (folders + files) for stable rendering. */\n order: string[];\n}\n\nfunction makeFolder(name: string, path: string): FolderBuild {\n return { name, path, folders: new Map(), files: [], order: [] };\n}\n\n/**\n * Build a nested folder tree from the flat `entries`. Folders are derived purely\n * from the slash segments of each `path`; a single-segment path is a root file.\n * Insertion order is preserved within each folder, with folders sorted before\n * files at each level (the conventional explorer ordering).\n */\nfunction buildTree(entries: FileTreeEntry[]): TreeNode[] {\n const root = makeFolder(\"\", \"\");\n\n entries.forEach((entry, index) => {\n const segments = entry.path.split(\"/\").filter(Boolean);\n if (segments.length === 0) return;\n const fileName = segments[segments.length - 1] as string;\n const folderSegments = segments.slice(0, -1);\n\n let cursor = root;\n let prefix = \"\";\n for (const segment of folderSegments) {\n prefix = prefix ? `${prefix}/${segment}` : segment;\n let next = cursor.folders.get(segment);\n if (!next) {\n next = makeFolder(segment, prefix);\n cursor.folders.set(segment, next);\n cursor.order.push(`d:${segment}`);\n }\n cursor = next;\n }\n\n cursor.files.push({\n kind: \"file\",\n name: fileName,\n path: entry.path,\n entry,\n index,\n });\n cursor.order.push(`f:${cursor.files.length - 1}`);\n });\n\n const materialize = (folder: FolderBuild): TreeNode[] => {\n const nodes: TreeNode[] = [];\n for (const key of folder.order) {\n if (key.startsWith(\"d:\")) {\n const child = folder.folders.get(key.slice(2));\n if (!child) continue;\n nodes.push({\n kind: \"folder\",\n name: child.name,\n path: child.path,\n children: materialize(child),\n });\n } else {\n const file = folder.files[Number(key.slice(2))];\n if (file) nodes.push(file);\n }\n }\n // Folders before files at this level (standard explorer ordering).\n return [\n ...nodes.filter((node) => node.kind === \"folder\"),\n ...nodes.filter((node) => node.kind === \"file\"),\n ];\n };\n\n return materialize(root);\n}\n\nfunction compactFolderNode(folder: FolderNode): FolderNode {\n const names = [folder.name];\n let path = folder.path;\n let children = folder.children;\n\n while (children.length === 1 && children[0]?.kind === \"folder\") {\n const child = children[0];\n names.push(child.name);\n path = child.path;\n children = child.children;\n }\n\n return {\n kind: \"folder\",\n name: names.join(\"/\"),\n path,\n children: compactTree(children),\n };\n}\n\nfunction compactTree(nodes: TreeNode[]): TreeNode[] {\n return nodes.map((node) =>\n node.kind === \"folder\" ? compactFolderNode(node) : node,\n );\n}\n\nfunction flattenVisibleRows(\n nodes: TreeNode[],\n collapsedFolders: Record<string, boolean>,\n depth = 0,\n): VisibleTreeRow[] {\n const rows: VisibleTreeRow[] = [];\n\n for (const node of nodes) {\n rows.push({ node, depth });\n if (node.kind === \"folder\" && !(collapsedFolders[node.path] ?? false)) {\n rows.push(\n ...flattenVisibleRows(node.children, collapsedFolders, depth + 1),\n );\n }\n }\n\n return rows;\n}\n\n/* ── Read (IDE explorer) ───────────────────────────────────────────────────── */\n\nconst INDENT_STEP = 14; // px per nesting level — the explorer guide spacing.\nconst DEFAULT_VISIBLE_TREE_ROWS = 10;\n\n/**\n * Read-only renderer for a `file-tree` block — a VS Code / GitHub-explorer file\n * and change tree. The flat `entries` are folded into a nested tree of\n * collapsible folders (IconFolder + chevron) and files (IconFile) carrying a\n * single-letter change badge (A/M/D/R). A file with a `note` or `snippet` is\n * itself clickable and expands to show the note plus the snippet rendered as a\n * fenced code block via `ctx.renderMarkdown`. A summary header tallies the change\n * counts (\"+N · ~M · −K\"). Every color is theme-aware via Tailwind `dark:`\n * variants / plan CSS vars, so the tree reads correctly in both modes.\n */\nexport function FileTreeRead({\n data,\n blockId,\n title,\n summary,\n ctx,\n}: BlockReadProps<FileTreeData>) {\n const entries = data.entries ?? [];\n const tree = useMemo(() => compactTree(buildTree(entries)), [entries]);\n\n // Folders default to fully expanded so the tree is useful at a glance.\n const [collapsedFolders, setCollapsedFolders] = useState<\n Record<string, boolean>\n >({});\n const [showAllRows, setShowAllRows] = useState(false);\n // Files with a note/snippet collapse their detail by default (progressive\n // disclosure) — keyed by the flat entry index so duplicate names never clash.\n const [openFiles, setOpenFiles] = useState<Record<number, boolean>>({});\n\n const toggleFolder = (path: string) =>\n setCollapsedFolders((current) => ({\n ...current,\n [path]: !current[path],\n }));\n const toggleFile = (index: number) =>\n setOpenFiles((current) => ({ ...current, [index]: !current[index] }));\n\n // The recap \"Files touched\" left rail (only) widens into the document as a\n // flyout while the tree is the reader's active focus AND a file's detail is\n // open, then collapses back to a slim rail when they click elsewhere or close\n // the last open file. `data-files-expanded` on the root drives the rail width\n // via CSS (`:has()`); it is inert anywhere the tree renders inline.\n const rootRef = useRef<HTMLElement>(null);\n const [active, setActive] = useState(false);\n const anyFileOpen = useMemo(\n () => Object.values(openFiles).some(Boolean),\n [openFiles],\n );\n const railExpanded = active && anyFileOpen;\n\n useEffect(() => {\n if (!railExpanded) return;\n const onPointerDown = (event: PointerEvent) => {\n const root = rootRef.current;\n if (\n root &&\n event.target instanceof Node &&\n !root.contains(event.target)\n ) {\n // Clicking away collapses the rail and closes any open file detail, so\n // it returns to the clean slim state rather than leaving notes open in\n // the cramped width.\n setActive(false);\n setOpenFiles({});\n }\n };\n document.addEventListener(\"pointerdown\", onPointerDown, true);\n return () =>\n document.removeEventListener(\"pointerdown\", onPointerDown, true);\n }, [railExpanded]);\n\n // Change tally for the summary header.\n const counts = useMemo(() => {\n const tally = { added: 0, modified: 0, removed: 0, renamed: 0 };\n for (const entry of entries) {\n if (entry.change) tally[entry.change] += 1;\n }\n return tally;\n }, [entries]);\n const changeTotal =\n counts.added + counts.modified + counts.removed + counts.renamed;\n\n const visibleRows = useMemo(\n () => flattenVisibleRows(tree, collapsedFolders),\n [collapsedFolders, tree],\n );\n const shouldLimitRows = visibleRows.length > DEFAULT_VISIBLE_TREE_ROWS;\n const displayedRows =\n showAllRows || !shouldLimitRows\n ? visibleRows\n : visibleRows.slice(0, DEFAULT_VISIBLE_TREE_ROWS);\n\n const renderRow = ({ node, depth }: VisibleTreeRow): React.ReactNode => {\n const indent = depth * INDENT_STEP;\n if (node.kind === \"folder\") {\n const collapsed = collapsedFolders[node.path] ?? false;\n return (\n <div key={`d:${node.path}`}>\n <button\n type=\"button\"\n data-plan-interactive\n aria-expanded={!collapsed}\n onClick={() => toggleFolder(node.path)}\n style={{ paddingLeft: indent + 8 }}\n className=\"flex w-full items-center gap-1.5 rounded-md py-1 pr-2 text-left text-[13px] transition-colors hover:bg-accent/40\"\n >\n <IconChevronRight\n className={cn(\n \"size-3.5 shrink-0 text-plan-muted transition-transform\",\n !collapsed && \"rotate-90\",\n )}\n />\n {collapsed ? (\n <IconFolder className=\"size-4 shrink-0 text-plan-muted\" />\n ) : (\n <IconFolderOpen className=\"size-4 shrink-0 text-plan-muted\" />\n )}\n <span className=\"min-w-0 truncate font-medium text-plan-text\">\n {node.name}\n </span>\n </button>\n </div>\n );\n }\n\n const { entry } = node;\n const change = entry.change;\n const hasDetail = Boolean(entry.note?.trim() || entry.snippet?.trim());\n const isOpen = openFiles[node.index] ?? false;\n\n return (\n <div key={`f:${node.index}`}>\n <button\n type=\"button\"\n data-plan-interactive\n data-file-path={node.path}\n disabled={!hasDetail}\n aria-expanded={hasDetail ? isOpen : undefined}\n onClick={hasDetail ? () => toggleFile(node.index) : undefined}\n style={{ paddingLeft: indent + 8 }}\n className={cn(\n \"group flex w-full items-center gap-1.5 rounded-md py-1 pr-2 text-left text-[13px] transition-colors\",\n hasDetail ? \"hover:bg-accent/40\" : \"cursor-default\",\n )}\n >\n {/* Chevron slot — present only for files with expandable detail so\n everything stays aligned with the folder rows above. */}\n {hasDetail ? (\n <IconChevronRight\n className={cn(\n \"size-3.5 shrink-0 text-plan-muted transition-transform\",\n isOpen && \"rotate-90\",\n )}\n />\n ) : (\n <span className=\"size-3.5 shrink-0\" aria-hidden />\n )}\n <IconFile\n className={cn(\n \"size-4 shrink-0\",\n change === \"removed\" ? \"text-plan-muted\" : \"text-plan-muted/80\",\n )}\n />\n <span\n className={cn(\n \"min-w-0 truncate font-medium\",\n change ? CHANGE_NAME_INK[change] : \"text-plan-text\",\n )}\n >\n {node.name}\n </span>\n {change && (\n <span\n title={CHANGE_LABEL[change]}\n aria-label={CHANGE_LABEL[change]}\n className={cn(\n \"ml-1 flex size-4 shrink-0 items-center justify-center rounded text-[10px] font-bold leading-none\",\n CHANGE_BADGE[change],\n )}\n >\n {CHANGE_GLYPH[change]}\n </span>\n )}\n {entry.note?.trim() && !isOpen && (\n <span className=\"ml-1 min-w-0 flex-1 truncate text-xs text-plan-muted\">\n {entry.note}\n </span>\n )}\n </button>\n\n {/* Expanded file detail: the note + a fenced snippet. */}\n {hasDetail && isOpen && (\n <div\n style={{ paddingLeft: indent + 8 + 20 }}\n className=\"pb-2 pr-2 pt-0.5\"\n >\n {entry.note?.trim() && (\n <p className=\"text-xs leading-relaxed text-plan-muted\">\n {entry.note}\n </p>\n )}\n {entry.snippet?.trim() && (\n <div className=\"mt-2 an-file-tree-snippet\">\n {ctx.renderMarkdown?.(\n fence(entry.snippet, fenceLanguage(entry)),\n )}\n </div>\n )}\n </div>\n )}\n </div>\n );\n };\n\n return (\n <section\n {...ltrCodeBlockProps}\n ref={rootRef}\n className=\"plan-block\"\n data-block-id={blockId}\n data-files-expanded={railExpanded ? \"\" : undefined}\n onPointerDown={() => setActive(true)}\n >\n {title && <div className=\"plan-block-label\">{title}</div>}\n\n <div className=\"overflow-hidden rounded-xl border border-plan-line bg-plan-block\">\n {/* Summary header: file count + change tally. */}\n <div className=\"flex flex-wrap items-center gap-2 border-b border-plan-line bg-accent/20 px-3 py-2\">\n {data.title && (\n <span className=\"text-[13px] font-semibold text-plan-text\">\n {data.title}\n </span>\n )}\n <span className=\"text-xs text-plan-muted\">\n {entries.length} {entries.length === 1 ? \"file\" : \"files\"}\n </span>\n {changeTotal > 0 && (\n <span className=\"ml-auto flex items-center gap-2 font-mono text-xs\">\n {counts.added > 0 && (\n <span className=\"text-emerald-600 dark:text-emerald-300\">\n +{counts.added}\n </span>\n )}\n {counts.modified > 0 && (\n <span className=\"text-blue-600 dark:text-blue-300\">\n ~{counts.modified}\n </span>\n )}\n {counts.removed > 0 && (\n <span className=\"text-red-600 dark:text-red-300\">\n −{counts.removed}\n </span>\n )}\n {counts.renamed > 0 && (\n <span className=\"text-violet-600 dark:text-violet-300\">\n »{counts.renamed}\n </span>\n )}\n </span>\n )}\n </div>\n\n {/* The tree itself. */}\n <div className=\"py-1.5\">\n {tree.length > 0 ? (\n <>\n {displayedRows.map(renderRow)}\n {shouldLimitRows && (\n <div className=\"px-2 pt-1\">\n <button\n type=\"button\"\n data-plan-interactive\n aria-expanded={showAllRows}\n onClick={() => setShowAllRows((current) => !current)}\n className=\"flex h-8 w-full items-center justify-center gap-1.5 rounded-md text-xs font-medium text-plan-muted transition-colors hover:bg-accent/40 hover:text-plan-text\"\n >\n <IconChevronRight\n className={cn(\n \"size-3.5 shrink-0 transition-transform\",\n showAllRows ? \"-rotate-90\" : \"rotate-90\",\n )}\n />\n {showAllRows\n ? \"Show fewer\"\n : `Show all ${visibleRows.length} rows`}\n </button>\n </div>\n )}\n </>\n ) : (\n <p className=\"px-3 py-2 text-xs text-plan-muted\">No files yet.</p>\n )}\n </div>\n </div>\n\n {summary && <p className=\"mt-5 text-plan-muted\">{summary}</p>}\n </section>\n );\n}\n\n/* ── Edit (panel form) ─────────────────────────────────────────────────────── */\n\nconst fieldLabelClass = \"text-xs font-medium text-muted-foreground\";\n\n/**\n * Panel editor for a `file-tree` block. A structured form: an optional title\n * Input plus a list of file rows (add/remove), each carrying a path Input, a\n * change Select, a note Input, an optional language Input, and a snippet\n * Textarea. The folder tree is derived from the paths in the Read render, so the\n * form stays flat and quick to edit. Renders BARE content (no `<section>`); the\n * registry's panel surface supplies the popover chrome.\n */\nexport function FileTreeEdit({\n data,\n onChange,\n editable,\n}: BlockEditProps<FileTreeData>) {\n const entries = data.entries ?? [];\n\n const patchEntries = (next: FileTreeEntry[]) =>\n onChange({ ...data, entries: next });\n\n const updateEntry = (index: number, next: Partial<FileTreeEntry>) =>\n patchEntries(\n entries.map((entry, i) => (i === index ? { ...entry, ...next } : entry)),\n );\n\n const removeEntry = (index: number) =>\n patchEntries(entries.filter((_, i) => i !== index));\n\n const addEntry = () =>\n patchEntries([...entries, { path: \"src/new-file.ts\", change: \"added\" }]);\n\n return (\n <div className=\"flex flex-col gap-4\" data-plan-interactive>\n <label className=\"flex flex-col gap-1.5\">\n <span className={fieldLabelClass}>Title (optional)</span>\n <DevInput\n className=\"h-9\"\n value={data.title ?? \"\"}\n disabled={!editable}\n placeholder=\"e.g. Files touched\"\n onChange={(event) =>\n onChange({ ...data, title: event.target.value || undefined })\n }\n />\n </label>\n\n <div className=\"flex flex-col gap-3\">\n {entries.map((entry, index) => (\n <div\n key={index}\n className=\"flex flex-col gap-2 rounded-lg border border-input p-3\"\n >\n <div className=\"grid grid-cols-[minmax(0,1fr)_120px_auto] gap-2\">\n <DevInput\n className=\"h-8 font-mono text-xs\"\n value={entry.path}\n disabled={!editable}\n placeholder=\"src/routes/git.ts\"\n onChange={(event) =>\n updateEntry(index, { path: event.target.value })\n }\n />\n <DevSelect\n className=\"h-8\"\n value={entry.change ?? \"none\"}\n disabled={!editable}\n onValueChange={(value) =>\n updateEntry(index, {\n change:\n value === \"none\" ? undefined : (value as FileTreeChange),\n })\n }\n options={[\n { value: \"none\", label: \"No change\" },\n ...FILE_TREE_CHANGES.map((change) => ({\n value: change,\n label: CHANGE_LABEL[change],\n })),\n ]}\n />\n {editable && (\n <button\n type=\"button\"\n data-plan-interactive\n aria-label=\"Remove file\"\n className=\"flex size-8 items-center justify-center rounded-md text-muted-foreground hover:bg-accent/60 hover:text-foreground\"\n onClick={() => removeEntry(index)}\n >\n <IconTrash className=\"size-4\" />\n </button>\n )}\n </div>\n <DevInput\n className=\"h-8 text-xs\"\n value={entry.note ?? \"\"}\n disabled={!editable}\n placeholder=\"Why this file changes\"\n onChange={(event) =>\n updateEntry(index, { note: event.target.value || undefined })\n }\n />\n <div className=\"grid grid-cols-[minmax(0,1fr)_120px] gap-2\">\n <DevTextarea\n className=\"min-h-[64px] font-mono text-xs\"\n value={entry.snippet ?? \"\"}\n disabled={!editable}\n placeholder=\"Optional code snippet\"\n onChange={(event) =>\n updateEntry(index, {\n snippet: event.target.value || undefined,\n })\n }\n />\n <DevInput\n className=\"h-8 self-start font-mono text-xs\"\n value={entry.language ?? \"\"}\n disabled={!editable}\n placeholder=\"language\"\n onChange={(event) =>\n updateEntry(index, {\n language: event.target.value || undefined,\n })\n }\n />\n </div>\n </div>\n ))}\n </div>\n\n {editable && (\n <button\n type=\"button\"\n data-plan-interactive\n className=\"flex items-center justify-center gap-1.5 rounded-md border border-dashed border-input py-2 text-sm text-muted-foreground hover:bg-accent/40 hover:text-foreground\"\n onClick={addEntry}\n >\n <IconPlus className=\"size-4\" />\n Add file\n </button>\n )}\n </div>\n );\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HighlightedCode.d.ts","sourceRoot":"","sources":["../../../../src/client/blocks/library/HighlightedCode.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"HighlightedCode.d.ts","sourceRoot":"","sources":["../../../../src/client/blocks/library/HighlightedCode.tsx"],"names":[],"mappings":"AAkHA,wBAAgB,kBAAkB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAS1E;AAED,wBAAgB,eAAe,CAAC,EAC9B,IAAI,EACJ,QAAQ,GACT,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,2CA2CA;AAED;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAEzC;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,QAAQ,EACR,QAAiC,EACjC,iBAAwB,EACxB,SAAS,GACV,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,2CAmDA"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useMemo, useState } from "react";
|
|
3
3
|
import { cn } from "../../utils.js";
|
|
4
|
+
import { ltrCodeBlockProps } from "../code-block-direction.js";
|
|
4
5
|
let highlighterLoader = null;
|
|
5
6
|
function loadHighlighter() {
|
|
6
7
|
if (!highlighterLoader) {
|
|
@@ -167,7 +168,7 @@ export function CodeSurface({ code, language, maxLines = DEFAULT_CODE_MAX_LINES,
|
|
|
167
168
|
const collapsed = collapsible && !expanded;
|
|
168
169
|
const hiddenLines = collapsible ? lineCount - cap : 0;
|
|
169
170
|
const label = prettyLanguageName(language);
|
|
170
|
-
return (_jsxs("div", { className: cn("plan-code-surface", className ?? "mt-5"), "data-collapsed": collapsed ? "true" : undefined, children: [showLanguageLabel && label && (_jsx("div", { className: "plan-code-surface-bar", children: _jsx("span", { className: "plan-code-surface-lang", children: label }) })), _jsxs("div", { className: "plan-code-surface-scroll", style: collapsed
|
|
171
|
+
return (_jsxs("div", { ...ltrCodeBlockProps, className: cn("plan-code-surface", className ?? "mt-5"), "data-collapsed": collapsed ? "true" : undefined, children: [showLanguageLabel && label && (_jsx("div", { className: "plan-code-surface-bar", children: _jsx("span", { className: "plan-code-surface-lang", children: label }) })), _jsxs("div", { className: "plan-code-surface-scroll", style: collapsed
|
|
171
172
|
? { "--plan-code-max-lines": cap }
|
|
172
173
|
: undefined, children: [_jsx(HighlightedCode, { code: code, language: language }), collapsed && (_jsx("div", { className: "plan-code-surface-fade", "aria-hidden": "true" }))] }), collapsible && (_jsx("button", { type: "button", "data-plan-interactive": true, className: "plan-code-surface-toggle", onClick: () => setExpanded((value) => !value), children: collapsed
|
|
173
174
|
? `Show ${hiddenLines} more line${hiddenLines === 1 ? "" : "s"}`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HighlightedCode.js","sourceRoot":"","sources":["../../../../src/client/blocks/library/HighlightedCode.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useMemo, useState, type CSSProperties } from \"react\";\nimport { cn } from \"../../utils.js\";\n\ntype ShikiHighlighter = {\n codeToHtml: (\n code: string,\n options: {\n lang: string;\n themes: { light: string; dark: string };\n defaultColor?: false | \"light\" | \"dark\";\n },\n ) => string | Promise<string>;\n getLoadedLanguages: () => string[];\n};\n\nlet highlighterLoader: Promise<ShikiHighlighter> | null = null;\nfunction loadHighlighter(): Promise<ShikiHighlighter> {\n if (!highlighterLoader) {\n highlighterLoader = (async () => {\n // Use the JavaScript regex engine instead of Oniguruma WASM (~608 KB saved).\n // forgiving:true degrades unsupported patterns gracefully instead of throwing.\n const [{ createHighlighterCore }, { createJavaScriptRegexEngine }] =\n await Promise.all([\n import(\"shiki/core\"),\n import(\"shiki/engine/javascript\"),\n ]);\n return createHighlighterCore({\n themes: [\n import(\"shiki/themes/github-light-default.mjs\"),\n import(\"shiki/themes/github-dark-default.mjs\"),\n ],\n langs: [\n import(\"shiki/langs/javascript.mjs\"),\n import(\"shiki/langs/typescript.mjs\"),\n import(\"shiki/langs/jsx.mjs\"),\n import(\"shiki/langs/tsx.mjs\"),\n import(\"shiki/langs/json.mjs\"),\n import(\"shiki/langs/css.mjs\"),\n import(\"shiki/langs/html.mjs\"),\n import(\"shiki/langs/markdown.mjs\"),\n import(\"shiki/langs/bash.mjs\"),\n import(\"shiki/langs/shellscript.mjs\"),\n import(\"shiki/langs/python.mjs\"),\n import(\"shiki/langs/yaml.mjs\"),\n import(\"shiki/langs/sql.mjs\"),\n ],\n engine: createJavaScriptRegexEngine({ forgiving: true }),\n }) as unknown as Promise<ShikiHighlighter>;\n })().catch((error) => {\n highlighterLoader = null;\n throw error;\n });\n }\n return highlighterLoader;\n}\n\nconst LANG_ALIASES: Record<string, string> = {\n js: \"javascript\",\n ts: \"typescript\",\n sh: \"bash\",\n shell: \"bash\",\n zsh: \"bash\",\n py: \"python\",\n yml: \"yaml\",\n md: \"markdown\",\n bq: \"sql\",\n bigquery: \"sql\",\n};\n\n/**\n * Human-facing label for a code language hint (the value stored on a code block\n * / code tab). Returns `null` for empty / unknown / plain hints so callers can\n * keep the surface clean (no \"Plain text\" chrome) when the language is unknown\n * or auto-detected. Web languages lead because plans skew that way.\n */\nconst LANGUAGE_LABELS: Record<string, string> = {\n typescript: \"TypeScript\",\n ts: \"TypeScript\",\n tsx: \"TSX\",\n javascript: \"JavaScript\",\n js: \"JavaScript\",\n jsx: \"JSX\",\n json: \"JSON\",\n html: \"HTML\",\n css: \"CSS\",\n scss: \"SCSS\",\n bash: \"Bash\",\n sh: \"Bash\",\n shell: \"Shell\",\n zsh: \"Bash\",\n python: \"Python\",\n py: \"Python\",\n sql: \"SQL\",\n yaml: \"YAML\",\n yml: \"YAML\",\n markdown: \"Markdown\",\n md: \"Markdown\",\n graphql: \"GraphQL\",\n go: \"Go\",\n rust: \"Rust\",\n ruby: \"Ruby\",\n java: \"Java\",\n c: \"C\",\n cpp: \"C++\",\n csharp: \"C#\",\n php: \"PHP\",\n swift: \"Swift\",\n kotlin: \"Kotlin\",\n diff: \"Diff\",\n dockerfile: \"Dockerfile\",\n xml: \"XML\",\n};\n\nexport function prettyLanguageName(language?: string | null): string | null {\n const raw = language\n ?.trim()\n .toLowerCase()\n .replace(/^language-/, \"\");\n if (!raw || raw === \"text\" || raw === \"plaintext\" || raw === \"plain\") {\n return null;\n }\n return LANGUAGE_LABELS[raw] ?? raw;\n}\n\nexport function HighlightedCode({\n code,\n language,\n}: {\n code: string;\n language?: string;\n}) {\n const [html, setHtml] = useState<string | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n loadHighlighter()\n .then((highlighter) => {\n const requested = (language || \"text\").toLowerCase();\n const resolved = LANG_ALIASES[requested] ?? requested;\n const loaded = highlighter.getLoadedLanguages();\n const lang = loaded.includes(resolved) ? resolved : \"text\";\n return highlighter.codeToHtml(code, {\n lang,\n themes: {\n light: \"github-light-default\",\n dark: \"github-dark-default\",\n },\n defaultColor: false,\n });\n })\n .then((out) => {\n if (!cancelled) setHtml(out as string);\n })\n .catch(() => {\n if (!cancelled) setHtml(null);\n });\n return () => {\n cancelled = true;\n };\n }, [code, language]);\n\n if (html) {\n return (\n <div className=\"plan-shiki\" dangerouslySetInnerHTML={{ __html: html }} />\n );\n }\n return (\n <pre>\n <code className={language ? `language-${language}` : undefined}>\n {code}\n </code>\n </pre>\n );\n}\n\n/**\n * Default number of code lines shown before a code surface collapses behind a\n * \"Show N more lines\" toggle. Long code panes (read view, code tabs, API specs)\n * stay scannable instead of dominating the document, matching the rest of the\n * plan's progressively-disclosed surfaces.\n */\nexport const DEFAULT_CODE_MAX_LINES = 40;\n\n/**\n * Read-only code surface used across the plan blocks (code tabs, API specs) and\n * the markdown read view. Syntax-highlights via {@link HighlightedCode} (Shiki,\n * client-only with a plain `<pre>` SSR fallback), follows the current\n * light/dark `--plan-code` palette, and collapses to `maxLines` with an\n * expand/collapse toggle so long snippets do not run away.\n *\n * `maxLines` of `0` / `null` disables collapsing (show everything). The default\n * is {@link DEFAULT_CODE_MAX_LINES}; the surface only collapses when the code is\n * actually longer than that.\n */\nexport function CodeSurface({\n code,\n language,\n maxLines = DEFAULT_CODE_MAX_LINES,\n showLanguageLabel = true,\n className,\n}: {\n code: string;\n language?: string;\n maxLines?: number | null;\n showLanguageLabel?: boolean;\n className?: string;\n}) {\n const [expanded, setExpanded] = useState(false);\n\n const lineCount = useMemo(\n () => (code ? code.replace(/\\n$/, \"\").split(\"\\n\").length : 0),\n [code],\n );\n const cap = typeof maxLines === \"number\" && maxLines > 0 ? maxLines : null;\n const collapsible = cap != null && lineCount > cap;\n const collapsed = collapsible && !expanded;\n const hiddenLines = collapsible ? lineCount - cap : 0;\n const label = prettyLanguageName(language);\n\n return (\n <div\n className={cn(\"plan-code-surface\", className ?? \"mt-5\")}\n data-collapsed={collapsed ? \"true\" : undefined}\n >\n {showLanguageLabel && label && (\n <div className=\"plan-code-surface-bar\">\n <span className=\"plan-code-surface-lang\">{label}</span>\n </div>\n )}\n <div\n className=\"plan-code-surface-scroll\"\n style={\n collapsed\n ? ({ \"--plan-code-max-lines\": cap } as CSSProperties)\n : undefined\n }\n >\n <HighlightedCode code={code} language={language} />\n {collapsed && (\n <div className=\"plan-code-surface-fade\" aria-hidden=\"true\" />\n )}\n </div>\n {collapsible && (\n <button\n type=\"button\"\n data-plan-interactive\n className=\"plan-code-surface-toggle\"\n onClick={() => setExpanded((value) => !value)}\n >\n {collapsed\n ? `Show ${hiddenLines} more line${hiddenLines === 1 ? \"\" : \"s\"}`\n : \"Show less\"}\n </button>\n )}\n </div>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"HighlightedCode.js","sourceRoot":"","sources":["../../../../src/client/blocks/library/HighlightedCode.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useMemo, useState, type CSSProperties } from \"react\";\nimport { cn } from \"../../utils.js\";\nimport { ltrCodeBlockProps } from \"../code-block-direction.js\";\n\ntype ShikiHighlighter = {\n codeToHtml: (\n code: string,\n options: {\n lang: string;\n themes: { light: string; dark: string };\n defaultColor?: false | \"light\" | \"dark\";\n },\n ) => string | Promise<string>;\n getLoadedLanguages: () => string[];\n};\n\nlet highlighterLoader: Promise<ShikiHighlighter> | null = null;\nfunction loadHighlighter(): Promise<ShikiHighlighter> {\n if (!highlighterLoader) {\n highlighterLoader = (async () => {\n // Use the JavaScript regex engine instead of Oniguruma WASM (~608 KB saved).\n // forgiving:true degrades unsupported patterns gracefully instead of throwing.\n const [{ createHighlighterCore }, { createJavaScriptRegexEngine }] =\n await Promise.all([\n import(\"shiki/core\"),\n import(\"shiki/engine/javascript\"),\n ]);\n return createHighlighterCore({\n themes: [\n import(\"shiki/themes/github-light-default.mjs\"),\n import(\"shiki/themes/github-dark-default.mjs\"),\n ],\n langs: [\n import(\"shiki/langs/javascript.mjs\"),\n import(\"shiki/langs/typescript.mjs\"),\n import(\"shiki/langs/jsx.mjs\"),\n import(\"shiki/langs/tsx.mjs\"),\n import(\"shiki/langs/json.mjs\"),\n import(\"shiki/langs/css.mjs\"),\n import(\"shiki/langs/html.mjs\"),\n import(\"shiki/langs/markdown.mjs\"),\n import(\"shiki/langs/bash.mjs\"),\n import(\"shiki/langs/shellscript.mjs\"),\n import(\"shiki/langs/python.mjs\"),\n import(\"shiki/langs/yaml.mjs\"),\n import(\"shiki/langs/sql.mjs\"),\n ],\n engine: createJavaScriptRegexEngine({ forgiving: true }),\n }) as unknown as Promise<ShikiHighlighter>;\n })().catch((error) => {\n highlighterLoader = null;\n throw error;\n });\n }\n return highlighterLoader;\n}\n\nconst LANG_ALIASES: Record<string, string> = {\n js: \"javascript\",\n ts: \"typescript\",\n sh: \"bash\",\n shell: \"bash\",\n zsh: \"bash\",\n py: \"python\",\n yml: \"yaml\",\n md: \"markdown\",\n bq: \"sql\",\n bigquery: \"sql\",\n};\n\n/**\n * Human-facing label for a code language hint (the value stored on a code block\n * / code tab). Returns `null` for empty / unknown / plain hints so callers can\n * keep the surface clean (no \"Plain text\" chrome) when the language is unknown\n * or auto-detected. Web languages lead because plans skew that way.\n */\nconst LANGUAGE_LABELS: Record<string, string> = {\n typescript: \"TypeScript\",\n ts: \"TypeScript\",\n tsx: \"TSX\",\n javascript: \"JavaScript\",\n js: \"JavaScript\",\n jsx: \"JSX\",\n json: \"JSON\",\n html: \"HTML\",\n css: \"CSS\",\n scss: \"SCSS\",\n bash: \"Bash\",\n sh: \"Bash\",\n shell: \"Shell\",\n zsh: \"Bash\",\n python: \"Python\",\n py: \"Python\",\n sql: \"SQL\",\n yaml: \"YAML\",\n yml: \"YAML\",\n markdown: \"Markdown\",\n md: \"Markdown\",\n graphql: \"GraphQL\",\n go: \"Go\",\n rust: \"Rust\",\n ruby: \"Ruby\",\n java: \"Java\",\n c: \"C\",\n cpp: \"C++\",\n csharp: \"C#\",\n php: \"PHP\",\n swift: \"Swift\",\n kotlin: \"Kotlin\",\n diff: \"Diff\",\n dockerfile: \"Dockerfile\",\n xml: \"XML\",\n};\n\nexport function prettyLanguageName(language?: string | null): string | null {\n const raw = language\n ?.trim()\n .toLowerCase()\n .replace(/^language-/, \"\");\n if (!raw || raw === \"text\" || raw === \"plaintext\" || raw === \"plain\") {\n return null;\n }\n return LANGUAGE_LABELS[raw] ?? raw;\n}\n\nexport function HighlightedCode({\n code,\n language,\n}: {\n code: string;\n language?: string;\n}) {\n const [html, setHtml] = useState<string | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n loadHighlighter()\n .then((highlighter) => {\n const requested = (language || \"text\").toLowerCase();\n const resolved = LANG_ALIASES[requested] ?? requested;\n const loaded = highlighter.getLoadedLanguages();\n const lang = loaded.includes(resolved) ? resolved : \"text\";\n return highlighter.codeToHtml(code, {\n lang,\n themes: {\n light: \"github-light-default\",\n dark: \"github-dark-default\",\n },\n defaultColor: false,\n });\n })\n .then((out) => {\n if (!cancelled) setHtml(out as string);\n })\n .catch(() => {\n if (!cancelled) setHtml(null);\n });\n return () => {\n cancelled = true;\n };\n }, [code, language]);\n\n if (html) {\n return (\n <div className=\"plan-shiki\" dangerouslySetInnerHTML={{ __html: html }} />\n );\n }\n return (\n <pre>\n <code className={language ? `language-${language}` : undefined}>\n {code}\n </code>\n </pre>\n );\n}\n\n/**\n * Default number of code lines shown before a code surface collapses behind a\n * \"Show N more lines\" toggle. Long code panes (read view, code tabs, API specs)\n * stay scannable instead of dominating the document, matching the rest of the\n * plan's progressively-disclosed surfaces.\n */\nexport const DEFAULT_CODE_MAX_LINES = 40;\n\n/**\n * Read-only code surface used across the plan blocks (code tabs, API specs) and\n * the markdown read view. Syntax-highlights via {@link HighlightedCode} (Shiki,\n * client-only with a plain `<pre>` SSR fallback), follows the current\n * light/dark `--plan-code` palette, and collapses to `maxLines` with an\n * expand/collapse toggle so long snippets do not run away.\n *\n * `maxLines` of `0` / `null` disables collapsing (show everything). The default\n * is {@link DEFAULT_CODE_MAX_LINES}; the surface only collapses when the code is\n * actually longer than that.\n */\nexport function CodeSurface({\n code,\n language,\n maxLines = DEFAULT_CODE_MAX_LINES,\n showLanguageLabel = true,\n className,\n}: {\n code: string;\n language?: string;\n maxLines?: number | null;\n showLanguageLabel?: boolean;\n className?: string;\n}) {\n const [expanded, setExpanded] = useState(false);\n\n const lineCount = useMemo(\n () => (code ? code.replace(/\\n$/, \"\").split(\"\\n\").length : 0),\n [code],\n );\n const cap = typeof maxLines === \"number\" && maxLines > 0 ? maxLines : null;\n const collapsible = cap != null && lineCount > cap;\n const collapsed = collapsible && !expanded;\n const hiddenLines = collapsible ? lineCount - cap : 0;\n const label = prettyLanguageName(language);\n\n return (\n <div\n {...ltrCodeBlockProps}\n className={cn(\"plan-code-surface\", className ?? \"mt-5\")}\n data-collapsed={collapsed ? \"true\" : undefined}\n >\n {showLanguageLabel && label && (\n <div className=\"plan-code-surface-bar\">\n <span className=\"plan-code-surface-lang\">{label}</span>\n </div>\n )}\n <div\n className=\"plan-code-surface-scroll\"\n style={\n collapsed\n ? ({ \"--plan-code-max-lines\": cap } as CSSProperties)\n : undefined\n }\n >\n <HighlightedCode code={code} language={language} />\n {collapsed && (\n <div className=\"plan-code-surface-fade\" aria-hidden=\"true\" />\n )}\n </div>\n {collapsible && (\n <button\n type=\"button\"\n data-plan-interactive\n className=\"plan-code-surface-toggle\"\n onClick={() => setExpanded((value) => !value)}\n >\n {collapsed\n ? `Show ${hiddenLines} more line${hiddenLines === 1 ? \"\" : \"s\"}`\n : \"Show less\"}\n </button>\n )}\n </div>\n );\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JsonExplorerBlock.d.ts","sourceRoot":"","sources":["../../../../src/client/blocks/library/JsonExplorerBlock.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"JsonExplorerBlock.d.ts","sourceRoot":"","sources":["../../../../src/client/blocks/library/JsonExplorerBlock.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,2BAA2B,CAAC;AAySnC;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,IAAI,EACJ,OAAO,EACP,KAAK,EACL,OAAO,GACR,EAAE,cAAc,CAAC,gBAAgB,CAAC,2CAclC;AAED,wBAAgB,mBAAmB,CAAC,EAClC,IAAI,EACJ,SAAS,EACT,KAAc,GACf,EAAE;IACD,IAAI,EAAE,IAAI,CAAC,gBAAgB,EAAE,MAAM,GAAG,gBAAgB,CAAC,CAAC;IACxD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,2CAqHA;AAID;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,IAAI,EACJ,QAAQ,EACR,QAAQ,GACT,EAAE,cAAc,CAAC,gBAAgB,CAAC,2CA6HlC"}
|
|
@@ -2,6 +2,7 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
2
2
|
import { useCallback, useEffect, useId, useMemo, useState, } from "react";
|
|
3
3
|
import { IconChevronRight } from "@tabler/icons-react";
|
|
4
4
|
import { cn } from "../../utils.js";
|
|
5
|
+
import { ltrCodeBlockProps } from "../code-block-direction.js";
|
|
5
6
|
import { JSON_EXPLORER_DEFAULT_COLLAPSED_DEPTH, JSON_EXPLORER_MAX_COLLAPSED_DEPTH, } from "./json-explorer.config.js";
|
|
6
7
|
import { DevInput, DevLabel, DevTextarea } from "./dev-doc-ui.js";
|
|
7
8
|
/**
|
|
@@ -159,7 +160,7 @@ function JsonNode({ nodeId, label, value, depth, collapsedDepth, forceOpen, onCo
|
|
|
159
160
|
*/
|
|
160
161
|
export function JsonExplorerRead({ data, blockId, title, summary, }) {
|
|
161
162
|
const heading = data.title ?? title;
|
|
162
|
-
return (_jsxs("section", { className: "plan-block", "data-block-id": blockId, children: [heading && _jsx("div", { className: "plan-block-label", children: heading }), _jsx(JsonExplorerSurface, { data: data }), summary && _jsx("p", { className: "mt-5 text-plan-muted", children: summary })] }));
|
|
163
|
+
return (_jsxs("section", { ...ltrCodeBlockProps, className: "plan-block", "data-block-id": blockId, children: [heading && _jsx("div", { className: "plan-block-label", children: heading }), _jsx(JsonExplorerSurface, { data: data }), summary && _jsx("p", { className: "mt-5 text-plan-muted", children: summary })] }));
|
|
163
164
|
}
|
|
164
165
|
export function JsonExplorerSurface({ data, className, label = "JSON", }) {
|
|
165
166
|
const parsed = useMemo(() => parseJson(data.json), [data.json]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JsonExplorerBlock.js","sourceRoot":"","sources":["../../../../src/client/blocks/library/JsonExplorerBlock.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n useCallback,\n useEffect,\n useId,\n useMemo,\n useState,\n type MouseEvent as ReactMouseEvent,\n} from \"react\";\nimport { IconChevronRight } from \"@tabler/icons-react\";\nimport { cn } from \"../../utils.js\";\nimport type { BlockEditProps, BlockReadProps } from \"../types.js\";\nimport {\n JSON_EXPLORER_DEFAULT_COLLAPSED_DEPTH,\n JSON_EXPLORER_MAX_COLLAPSED_DEPTH,\n type JsonExplorerData,\n} from \"./json-explorer.config.js\";\nimport { DevInput, DevLabel, DevTextarea } from \"./dev-doc-ui.js\";\n\n/**\n * Read + Edit renderers for a `json-explorer` block — a browser-devtools /\n * Postman-style collapsible JSON tree. The raw JSON TEXT (`data.json`) is the\n * source of truth; the Read renderer parses it defensively and, on any parse\n * error, falls back to the raw text plus the error message (it never throws).\n * Lives in core so any app can register the dev-doc block (no shadcn import).\n *\n * Progressive disclosure is the whole point: object/array nodes show a chevron\n * and a one-line summary (\"{…} 3 keys\" / \"[…] 5 items\"); each node tracks its\n * own open/closed state (`useState`) seeded by `collapsedDepth` so deep payloads\n * stay scannable. Leaf values are type-colored (string = green, number = blue,\n * boolean = violet, null = muted); keys use a stable accent color; subtle indent\n * guide lines mark nesting.\n *\n * DARK/LIGHT: the plan editor toggles a `.dark` class on <html>. Every color\n * token — value types, keys, guide lines, chrome — uses Tailwind `dark:` variants\n * or the theme-aware plan CSS-var utilities, so the tree reads correctly in BOTH\n * modes (no hardcoded dark-only palette).\n */\n\n/* ── Theme-aware value-type color tokens ───────────────────────────────────── */\n\n/** String leaves: green in both modes. */\nconst STRING_CLASS = \"text-emerald-700 dark:text-emerald-300\";\n/** Number leaves: blue in both modes. */\nconst NUMBER_CLASS = \"text-blue-700 dark:text-blue-300\";\n/** Boolean leaves: violet in both modes. */\nconst BOOLEAN_CLASS = \"text-violet-700 dark:text-violet-300\";\n/** `null`/`undefined` leaves: muted (theme-aware plan var). */\nconst NULL_CLASS = \"text-plan-muted italic\";\n/** Object keys: a stable, saturated accent that reads in both modes. */\nconst KEY_CLASS = \"text-rose-700 dark:text-rose-300\";\n/** Structural punctuation (braces, brackets, commas, colons). */\nconst PUNCT_CLASS = \"text-plan-muted\";\n\nconst JSON_EXPLORER_DEPTH_PRESETS = [\n { label: \"Off\", value: 0 },\n { label: \"2 levels\", value: JSON_EXPLORER_DEFAULT_COLLAPSED_DEPTH },\n { label: \"3 levels\", value: 3 },\n { label: \"All\", value: JSON_EXPLORER_MAX_COLLAPSED_DEPTH },\n] as const;\n\nfunction clampCollapsedDepth(value: number): number {\n return Math.max(0, Math.min(JSON_EXPLORER_MAX_COLLAPSED_DEPTH, value));\n}\n\ntype JsonValue =\n | string\n | number\n | boolean\n | null\n | JsonValue[]\n | { [key: string]: JsonValue };\ntype JsonObject = { [key: string]: JsonValue };\n\ninterface ParseResult {\n ok: boolean;\n value?: JsonValue;\n error?: string;\n}\n\ninterface JsonTreePulse {\n open: boolean;\n nonce: number;\n}\n\nfunction parseJson(raw: string): ParseResult {\n const trimmed = raw.trim();\n if (!trimmed) {\n return { ok: false, error: \"Empty payload — add some JSON to explore.\" };\n }\n try {\n return { ok: true, value: JSON.parse(trimmed) as JsonValue };\n } catch (error) {\n return {\n ok: false,\n error: error instanceof Error ? error.message : \"Invalid JSON\",\n };\n }\n}\n\nfunction isContainer(value: JsonValue): value is JsonValue[] | JsonObject {\n return value !== null && typeof value === \"object\";\n}\n\nfunction isNonEmptyContainer(\n value: JsonValue,\n): value is JsonValue[] | JsonObject {\n if (!isContainer(value)) return false;\n return Array.isArray(value)\n ? value.length > 0\n : Object.keys(value).length > 0;\n}\n\n/** One-line summary for a collapsed container, devtools style. */\nfunction containerSummary(value: JsonValue[] | JsonObject): string {\n if (Array.isArray(value)) {\n const count = value.length;\n return `[…] ${count} ${count === 1 ? \"item\" : \"items\"}`;\n }\n const count = Object.keys(value).length;\n return `{…} ${count} ${count === 1 ? \"key\" : \"keys\"}`;\n}\n\n/** Render a leaf (primitive) value with its type color. */\nfunction LeafValue({ value }: { value: string | number | boolean | null }) {\n if (value === null) {\n return <span className={NULL_CLASS}>null</span>;\n }\n if (typeof value === \"string\") {\n return <span className={STRING_CLASS}>{JSON.stringify(value)}</span>;\n }\n if (typeof value === \"number\") {\n return <span className={NUMBER_CLASS}>{String(value)}</span>;\n }\n // boolean\n return <span className={BOOLEAN_CLASS}>{String(value)}</span>;\n}\n\ninterface JsonNodeProps {\n /** Stable id used by the root surface to derive aggregate expansion state. */\n nodeId: string;\n /** The object key or array index label for this node (root has none). */\n label?: string | number;\n value: JsonValue;\n depth: number;\n /** Depth beyond which nodes start collapsed. */\n collapsedDepth: number;\n /** Global or parent expand/collapse pulse — overrides per-node seed when changed. */\n forceOpen: JsonTreePulse | null;\n onContainerStateChange?: (nodeId: string, open: boolean | null) => void;\n /** True when this node is followed by a sibling (renders a trailing comma). */\n trailingComma?: boolean;\n}\n\n/**\n * A single tree node. Containers (object/array) get their own collapse state,\n * seeded from `collapsedDepth` and re-seeded whenever the global expand/collapse\n * \"pulse\" (`forceOpen`) flips. Leaves render inline with their type color.\n */\nfunction JsonNode({\n nodeId,\n label,\n value,\n depth,\n collapsedDepth,\n forceOpen,\n onContainerStateChange,\n trailingComma,\n}: JsonNodeProps) {\n const seededOpen = forceOpen?.open ?? depth < collapsedDepth;\n // `forceOpen` is the global pulse: when the user hits expand/collapse all we\n // flip every node, but per-node toggles still win afterward.\n const [openState, setOpenState] = useState<{\n forceOpen: JsonTreePulse | null;\n open: boolean;\n }>({ forceOpen, open: seededOpen });\n const [subtreePulse, setSubtreePulse] = useState<JsonTreePulse | null>(null);\n\n let open = openState.open;\n if (forceOpen !== openState.forceOpen) {\n open = forceOpen?.open ?? openState.open;\n }\n\n useEffect(() => {\n if (forceOpen === openState.forceOpen) return;\n setOpenState({ forceOpen, open });\n }, [forceOpen, open, openState.forceOpen]);\n\n const handleToggle = (event: ReactMouseEvent<HTMLButtonElement>) => {\n const nextOpen = !open;\n setOpenState((prev) => ({ ...prev, open: nextOpen }));\n if (event.altKey) {\n setSubtreePulse((prev) => ({\n open: nextOpen,\n nonce: (prev?.nonce ?? 0) + 1,\n }));\n } else {\n setSubtreePulse(null);\n }\n };\n\n const keyEl =\n label !== undefined ? (\n <>\n <span className={KEY_CLASS}>\n {typeof label === \"number\" ? label : JSON.stringify(label)}\n </span>\n <span className={PUNCT_CLASS}>: </span>\n </>\n ) : null;\n\n const container = isContainer(value);\n const entries: Array<[string | number, JsonValue]> = container\n ? Array.isArray(value)\n ? (value as JsonValue[]).map((item, index) => [index, item])\n : Object.entries(value as JsonObject)\n : [];\n const empty = entries.length === 0;\n\n useEffect(() => {\n if (!container || empty || !onContainerStateChange) return;\n onContainerStateChange(nodeId, open);\n return () => onContainerStateChange(nodeId, null);\n }, [container, empty, nodeId, onContainerStateChange, open]);\n\n if (!container) {\n return (\n <div className=\"flex items-start py-0.5 leading-relaxed\">\n <span className=\"select-none whitespace-pre\">{keyEl}</span>\n <LeafValue value={value} />\n {trailingComma && <span className={PUNCT_CLASS}>,</span>}\n </div>\n );\n }\n\n const isArray = Array.isArray(value);\n const openBrace = isArray ? \"[\" : \"{\";\n const closeBrace = isArray ? \"]\" : \"}\";\n const childForceOpen = subtreePulse ?? forceOpen;\n const childPulseNonce = childForceOpen?.nonce ?? 0;\n\n return (\n <div className=\"leading-relaxed\">\n <button\n type=\"button\"\n data-plan-interactive\n aria-expanded={open}\n disabled={empty}\n onClick={handleToggle}\n className={cn(\n \"group flex w-full items-start gap-1 rounded py-0.5 text-left transition-colors\",\n !empty && \"hover:bg-accent/40\",\n empty && \"cursor-default\",\n )}\n >\n <IconChevronRight\n className={cn(\n \"mt-1 size-3.5 shrink-0 text-plan-muted transition-transform\",\n open && \"rotate-90\",\n empty && \"opacity-0\",\n )}\n />\n <span className=\"min-w-0 whitespace-pre-wrap break-words\">\n {keyEl}\n <span className={PUNCT_CLASS}>{openBrace}</span>\n {!open && !empty && (\n <span className=\"ml-1 text-plan-muted\">\n {containerSummary(value)}\n </span>\n )}\n {(!open || empty) && (\n <span className={PUNCT_CLASS}>\n {empty ? \"\" : \"…\"}\n {closeBrace}\n {trailingComma ? \",\" : \"\"}\n </span>\n )}\n </span>\n </button>\n\n {open && !empty && (\n <>\n {/* Indent guide: a subtle vertical rule marks the nesting level. */}\n <div className=\"ml-[7px] border-l border-plan-line pl-3.5\">\n {entries.map(([entryKey, entryValue], index) => (\n <JsonNode\n key={`${String(entryKey)}:${childPulseNonce}`}\n nodeId={`${nodeId}/${JSON.stringify(entryKey)}`}\n label={entryKey}\n value={entryValue}\n depth={depth + 1}\n collapsedDepth={collapsedDepth}\n forceOpen={childForceOpen}\n onContainerStateChange={onContainerStateChange}\n trailingComma={index < entries.length - 1}\n />\n ))}\n </div>\n <div className=\"flex items-start\">\n {/* Align the closing brace under the chevron column. */}\n <span className=\"ml-[18px] whitespace-pre\">\n <span className={PUNCT_CLASS}>{closeBrace}</span>\n {trailingComma && <span className={PUNCT_CLASS}>,</span>}\n </span>\n </div>\n </>\n )}\n </div>\n );\n}\n\n/* ── Read (collapsible devtools tree) ──────────────────────────────────────── */\n\n/**\n * Read-only renderer for a `json-explorer` block. Parses `data.json` defensively\n * and renders the collapsible tree; on a parse error it shows the raw payload in\n * a monospace block plus the error (never throws). An \"Expand all / Collapse\n * all\" control toggles every node at once via a global pulse counter.\n */\nexport function JsonExplorerRead({\n data,\n blockId,\n title,\n summary,\n}: BlockReadProps<JsonExplorerData>) {\n const heading = data.title ?? title;\n\n return (\n <section className=\"plan-block\" data-block-id={blockId}>\n {heading && <div className=\"plan-block-label\">{heading}</div>}\n <JsonExplorerSurface data={data} />\n {summary && <p className=\"mt-5 text-plan-muted\">{summary}</p>}\n </section>\n );\n}\n\nexport function JsonExplorerSurface({\n data,\n className,\n label = \"JSON\",\n}: {\n data: Pick<JsonExplorerData, \"json\" | \"collapsedDepth\">;\n className?: string;\n label?: string;\n}) {\n const parsed = useMemo(() => parseJson(data.json), [data.json]);\n const collapsedDepth =\n data.collapsedDepth ?? JSON_EXPLORER_DEFAULT_COLLAPSED_DEPTH;\n // `pulse` carries a boolean (expand/collapse) plus a nonce so repeated clicks\n // of the same action still re-fire the reseed in each node.\n const [pulse, setPulse] = useState<{ open: boolean; nonce: number } | null>(\n null,\n );\n const [containerOpenStates, setContainerOpenStates] = useState<\n Record<string, boolean>\n >({});\n const handleContainerStateChange = useCallback(\n (nodeId: string, open: boolean | null) => {\n setContainerOpenStates((prev) => {\n if (open === null) {\n if (!(nodeId in prev)) return prev;\n const next = { ...prev };\n delete next[nodeId];\n return next;\n }\n if (prev[nodeId] === open) return prev;\n return { ...prev, [nodeId]: open };\n });\n },\n [],\n );\n const openStates = Object.values(containerOpenStates);\n const hasRegisteredContainers = openStates.length > 0;\n const fullyExpanded =\n hasRegisteredContainers && openStates.every((open) => open);\n const fullyCollapsed =\n hasRegisteredContainers && openStates.every((open) => !open);\n const parsedValue = parsed.ok ? (parsed.value as JsonValue) : null;\n const showTreeActions = parsedValue\n ? isNonEmptyContainer(parsedValue)\n : false;\n const actionButtonClass =\n \"rounded px-1.5 py-0.5 text-xs text-plan-muted transition-colors hover:bg-accent/60 hover:text-plan-text disabled:pointer-events-none disabled:opacity-40\";\n\n return (\n <div\n className={cn(\n \"group overflow-hidden rounded-xl border border-plan-line bg-plan-code\",\n className,\n )}\n >\n <div className=\"flex items-center justify-between gap-2 border-b border-plan-line px-3 py-1.5\">\n <span className=\"font-mono text-xs uppercase tracking-wide text-plan-muted\">\n {label}\n </span>\n {showTreeActions && (\n <div\n data-json-explorer-actions=\"true\"\n className=\"pointer-events-none flex items-center gap-1 opacity-0 transition-opacity group-hover:pointer-events-auto group-hover:opacity-100 group-focus-within:pointer-events-auto group-focus-within:opacity-100\"\n >\n <button\n type=\"button\"\n data-plan-interactive\n disabled={fullyExpanded}\n onClick={() =>\n setPulse((prev) => ({\n open: true,\n nonce: (prev?.nonce ?? 0) + 1,\n }))\n }\n className={actionButtonClass}\n >\n Expand all\n </button>\n <span className=\"text-plan-muted\">·</span>\n <button\n type=\"button\"\n data-plan-interactive\n disabled={fullyCollapsed}\n onClick={() =>\n setPulse((prev) => ({\n open: false,\n nonce: (prev?.nonce ?? 0) + 1,\n }))\n }\n className={actionButtonClass}\n >\n Collapse all\n </button>\n </div>\n )}\n </div>\n <div\n className=\"overflow-auto px-3 py-2.5 font-mono [font-size:var(--plan-doc-code-size)] text-plan-code-text\"\n data-code-surface\n >\n {parsed.ok ? (\n <JsonNode\n // Remount the whole tree when the global pulse fires so every node\n // re-seeds from the new open/closed state cleanly.\n key={pulse?.nonce ?? 0}\n nodeId=\"$\"\n value={parsed.value as JsonValue}\n depth={0}\n collapsedDepth={collapsedDepth}\n forceOpen={pulse}\n onContainerStateChange={handleContainerStateChange}\n />\n ) : (\n <div className=\"space-y-2\">\n <pre className=\"overflow-auto whitespace-pre-wrap break-words text-plan-code-text\">\n {data.json || \"—\"}\n </pre>\n <p className=\"text-xs text-red-600 dark:text-red-300\">\n Could not parse JSON: {parsed.error}\n </p>\n </div>\n )}\n </div>\n </div>\n );\n}\n\n/* ── Edit (panel form) ─────────────────────────────────────────────────────── */\n\n/**\n * Panel editor for a `json-explorer` block: a monospace textarea bound to the\n * raw `json`, a \"Format\" button that pretty-prints via `JSON.parse` →\n * `JSON.stringify(_, null, 2)` (guarded — shows an INLINE error, never\n * `window.alert`), an auto-expand depth picker/input, and a `title` input.\n * Renders BARE content (no `<section>`); the registry's panel surface supplies\n * the popover chrome.\n */\nexport function JsonExplorerEdit({\n data,\n onChange,\n editable,\n}: BlockEditProps<JsonExplorerData>) {\n const jsonId = useId();\n const titleId = useId();\n const depthId = useId();\n const [formatError, setFormatError] = useState<string | null>(null);\n const collapsedDepth =\n data.collapsedDepth ?? JSON_EXPLORER_DEFAULT_COLLAPSED_DEPTH;\n\n const setCollapsedDepth = (value: number) => {\n onChange({ ...data, collapsedDepth: clampCollapsedDepth(value) });\n };\n\n const handleFormat = () => {\n try {\n const formatted = JSON.stringify(JSON.parse(data.json), null, 2);\n setFormatError(null);\n onChange({ ...data, json: formatted });\n } catch (error) {\n setFormatError(\n error instanceof Error ? error.message : \"Invalid JSON — cannot format\",\n );\n }\n };\n\n return (\n <div className=\"grid gap-3\" data-plan-interactive>\n <div className=\"grid gap-1.5\">\n <DevLabel htmlFor={titleId}>Title</DevLabel>\n <DevInput\n id={titleId}\n value={data.title ?? \"\"}\n readOnly={!editable}\n onChange={(event) =>\n onChange({ ...data, title: event.target.value || undefined })\n }\n placeholder=\"Optional heading\"\n />\n </div>\n\n <div className=\"grid gap-1.5\">\n <div className=\"flex items-center justify-between\">\n <DevLabel htmlFor={jsonId}>JSON payload</DevLabel>\n {editable && (\n <button\n type=\"button\"\n data-plan-interactive\n onClick={handleFormat}\n className=\"inline-flex h-7 cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-md border border-input bg-background px-2 text-xs font-medium ring-offset-background transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50\"\n >\n Format\n </button>\n )}\n </div>\n <DevTextarea\n id={jsonId}\n value={data.json}\n readOnly={!editable}\n spellCheck={false}\n onChange={(event) => {\n setFormatError(null);\n onChange({ ...data, json: event.target.value });\n }}\n className=\"min-h-56 font-mono text-xs\"\n placeholder={'{\\n \"id\": \"abc123\",\\n \"active\": true\\n}'}\n />\n {formatError && (\n <p className=\"text-xs text-red-600 dark:text-red-300\">\n {formatError}\n </p>\n )}\n <p className=\"text-xs text-muted-foreground\">\n Raw JSON text is the source of truth. Use Format to pretty-print it.\n </p>\n </div>\n\n <div className=\"grid gap-1.5\">\n <DevLabel htmlFor={depthId}>Auto expand</DevLabel>\n <div className=\"flex flex-wrap gap-1\">\n {JSON_EXPLORER_DEPTH_PRESETS.map((preset) => {\n const active = collapsedDepth === preset.value;\n return (\n <button\n key={preset.label}\n type=\"button\"\n data-plan-interactive\n aria-pressed={active}\n disabled={!editable}\n onClick={() => setCollapsedDepth(preset.value)}\n className={cn(\n \"inline-flex h-7 items-center justify-center rounded-md border px-2 text-xs font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50\",\n active\n ? \"border-primary bg-primary text-primary-foreground\"\n : \"border-input bg-background text-muted-foreground hover:bg-accent hover:text-accent-foreground\",\n )}\n >\n {preset.label}\n </button>\n );\n })}\n </div>\n <DevInput\n id={depthId}\n type=\"number\"\n min={0}\n max={JSON_EXPLORER_MAX_COLLAPSED_DEPTH}\n value={collapsedDepth}\n readOnly={!editable}\n onChange={(event) => {\n const next = Number.parseInt(event.target.value, 10);\n onChange({\n ...data,\n collapsedDepth: Number.isFinite(next)\n ? clampCollapsedDepth(next)\n : undefined,\n });\n }}\n className=\"w-24\"\n />\n <p className=\"text-xs text-muted-foreground\">\n Levels open automatically. Use 0 to start collapsed,{\" \"}\n {JSON_EXPLORER_MAX_COLLAPSED_DEPTH} for all.\n </p>\n </div>\n </div>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"JsonExplorerBlock.js","sourceRoot":"","sources":["../../../../src/client/blocks/library/JsonExplorerBlock.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n useCallback,\n useEffect,\n useId,\n useMemo,\n useState,\n type MouseEvent as ReactMouseEvent,\n} from \"react\";\nimport { IconChevronRight } from \"@tabler/icons-react\";\nimport { cn } from \"../../utils.js\";\nimport { ltrCodeBlockProps } from \"../code-block-direction.js\";\nimport type { BlockEditProps, BlockReadProps } from \"../types.js\";\nimport {\n JSON_EXPLORER_DEFAULT_COLLAPSED_DEPTH,\n JSON_EXPLORER_MAX_COLLAPSED_DEPTH,\n type JsonExplorerData,\n} from \"./json-explorer.config.js\";\nimport { DevInput, DevLabel, DevTextarea } from \"./dev-doc-ui.js\";\n\n/**\n * Read + Edit renderers for a `json-explorer` block — a browser-devtools /\n * Postman-style collapsible JSON tree. The raw JSON TEXT (`data.json`) is the\n * source of truth; the Read renderer parses it defensively and, on any parse\n * error, falls back to the raw text plus the error message (it never throws).\n * Lives in core so any app can register the dev-doc block (no shadcn import).\n *\n * Progressive disclosure is the whole point: object/array nodes show a chevron\n * and a one-line summary (\"{…} 3 keys\" / \"[…] 5 items\"); each node tracks its\n * own open/closed state (`useState`) seeded by `collapsedDepth` so deep payloads\n * stay scannable. Leaf values are type-colored (string = green, number = blue,\n * boolean = violet, null = muted); keys use a stable accent color; subtle indent\n * guide lines mark nesting.\n *\n * DARK/LIGHT: the plan editor toggles a `.dark` class on <html>. Every color\n * token — value types, keys, guide lines, chrome — uses Tailwind `dark:` variants\n * or the theme-aware plan CSS-var utilities, so the tree reads correctly in BOTH\n * modes (no hardcoded dark-only palette).\n */\n\n/* ── Theme-aware value-type color tokens ───────────────────────────────────── */\n\n/** String leaves: green in both modes. */\nconst STRING_CLASS = \"text-emerald-700 dark:text-emerald-300\";\n/** Number leaves: blue in both modes. */\nconst NUMBER_CLASS = \"text-blue-700 dark:text-blue-300\";\n/** Boolean leaves: violet in both modes. */\nconst BOOLEAN_CLASS = \"text-violet-700 dark:text-violet-300\";\n/** `null`/`undefined` leaves: muted (theme-aware plan var). */\nconst NULL_CLASS = \"text-plan-muted italic\";\n/** Object keys: a stable, saturated accent that reads in both modes. */\nconst KEY_CLASS = \"text-rose-700 dark:text-rose-300\";\n/** Structural punctuation (braces, brackets, commas, colons). */\nconst PUNCT_CLASS = \"text-plan-muted\";\n\nconst JSON_EXPLORER_DEPTH_PRESETS = [\n { label: \"Off\", value: 0 },\n { label: \"2 levels\", value: JSON_EXPLORER_DEFAULT_COLLAPSED_DEPTH },\n { label: \"3 levels\", value: 3 },\n { label: \"All\", value: JSON_EXPLORER_MAX_COLLAPSED_DEPTH },\n] as const;\n\nfunction clampCollapsedDepth(value: number): number {\n return Math.max(0, Math.min(JSON_EXPLORER_MAX_COLLAPSED_DEPTH, value));\n}\n\ntype JsonValue =\n | string\n | number\n | boolean\n | null\n | JsonValue[]\n | { [key: string]: JsonValue };\ntype JsonObject = { [key: string]: JsonValue };\n\ninterface ParseResult {\n ok: boolean;\n value?: JsonValue;\n error?: string;\n}\n\ninterface JsonTreePulse {\n open: boolean;\n nonce: number;\n}\n\nfunction parseJson(raw: string): ParseResult {\n const trimmed = raw.trim();\n if (!trimmed) {\n return { ok: false, error: \"Empty payload — add some JSON to explore.\" };\n }\n try {\n return { ok: true, value: JSON.parse(trimmed) as JsonValue };\n } catch (error) {\n return {\n ok: false,\n error: error instanceof Error ? error.message : \"Invalid JSON\",\n };\n }\n}\n\nfunction isContainer(value: JsonValue): value is JsonValue[] | JsonObject {\n return value !== null && typeof value === \"object\";\n}\n\nfunction isNonEmptyContainer(\n value: JsonValue,\n): value is JsonValue[] | JsonObject {\n if (!isContainer(value)) return false;\n return Array.isArray(value)\n ? value.length > 0\n : Object.keys(value).length > 0;\n}\n\n/** One-line summary for a collapsed container, devtools style. */\nfunction containerSummary(value: JsonValue[] | JsonObject): string {\n if (Array.isArray(value)) {\n const count = value.length;\n return `[…] ${count} ${count === 1 ? \"item\" : \"items\"}`;\n }\n const count = Object.keys(value).length;\n return `{…} ${count} ${count === 1 ? \"key\" : \"keys\"}`;\n}\n\n/** Render a leaf (primitive) value with its type color. */\nfunction LeafValue({ value }: { value: string | number | boolean | null }) {\n if (value === null) {\n return <span className={NULL_CLASS}>null</span>;\n }\n if (typeof value === \"string\") {\n return <span className={STRING_CLASS}>{JSON.stringify(value)}</span>;\n }\n if (typeof value === \"number\") {\n return <span className={NUMBER_CLASS}>{String(value)}</span>;\n }\n // boolean\n return <span className={BOOLEAN_CLASS}>{String(value)}</span>;\n}\n\ninterface JsonNodeProps {\n /** Stable id used by the root surface to derive aggregate expansion state. */\n nodeId: string;\n /** The object key or array index label for this node (root has none). */\n label?: string | number;\n value: JsonValue;\n depth: number;\n /** Depth beyond which nodes start collapsed. */\n collapsedDepth: number;\n /** Global or parent expand/collapse pulse — overrides per-node seed when changed. */\n forceOpen: JsonTreePulse | null;\n onContainerStateChange?: (nodeId: string, open: boolean | null) => void;\n /** True when this node is followed by a sibling (renders a trailing comma). */\n trailingComma?: boolean;\n}\n\n/**\n * A single tree node. Containers (object/array) get their own collapse state,\n * seeded from `collapsedDepth` and re-seeded whenever the global expand/collapse\n * \"pulse\" (`forceOpen`) flips. Leaves render inline with their type color.\n */\nfunction JsonNode({\n nodeId,\n label,\n value,\n depth,\n collapsedDepth,\n forceOpen,\n onContainerStateChange,\n trailingComma,\n}: JsonNodeProps) {\n const seededOpen = forceOpen?.open ?? depth < collapsedDepth;\n // `forceOpen` is the global pulse: when the user hits expand/collapse all we\n // flip every node, but per-node toggles still win afterward.\n const [openState, setOpenState] = useState<{\n forceOpen: JsonTreePulse | null;\n open: boolean;\n }>({ forceOpen, open: seededOpen });\n const [subtreePulse, setSubtreePulse] = useState<JsonTreePulse | null>(null);\n\n let open = openState.open;\n if (forceOpen !== openState.forceOpen) {\n open = forceOpen?.open ?? openState.open;\n }\n\n useEffect(() => {\n if (forceOpen === openState.forceOpen) return;\n setOpenState({ forceOpen, open });\n }, [forceOpen, open, openState.forceOpen]);\n\n const handleToggle = (event: ReactMouseEvent<HTMLButtonElement>) => {\n const nextOpen = !open;\n setOpenState((prev) => ({ ...prev, open: nextOpen }));\n if (event.altKey) {\n setSubtreePulse((prev) => ({\n open: nextOpen,\n nonce: (prev?.nonce ?? 0) + 1,\n }));\n } else {\n setSubtreePulse(null);\n }\n };\n\n const keyEl =\n label !== undefined ? (\n <>\n <span className={KEY_CLASS}>\n {typeof label === \"number\" ? label : JSON.stringify(label)}\n </span>\n <span className={PUNCT_CLASS}>: </span>\n </>\n ) : null;\n\n const container = isContainer(value);\n const entries: Array<[string | number, JsonValue]> = container\n ? Array.isArray(value)\n ? (value as JsonValue[]).map((item, index) => [index, item])\n : Object.entries(value as JsonObject)\n : [];\n const empty = entries.length === 0;\n\n useEffect(() => {\n if (!container || empty || !onContainerStateChange) return;\n onContainerStateChange(nodeId, open);\n return () => onContainerStateChange(nodeId, null);\n }, [container, empty, nodeId, onContainerStateChange, open]);\n\n if (!container) {\n return (\n <div className=\"flex items-start py-0.5 leading-relaxed\">\n <span className=\"select-none whitespace-pre\">{keyEl}</span>\n <LeafValue value={value} />\n {trailingComma && <span className={PUNCT_CLASS}>,</span>}\n </div>\n );\n }\n\n const isArray = Array.isArray(value);\n const openBrace = isArray ? \"[\" : \"{\";\n const closeBrace = isArray ? \"]\" : \"}\";\n const childForceOpen = subtreePulse ?? forceOpen;\n const childPulseNonce = childForceOpen?.nonce ?? 0;\n\n return (\n <div className=\"leading-relaxed\">\n <button\n type=\"button\"\n data-plan-interactive\n aria-expanded={open}\n disabled={empty}\n onClick={handleToggle}\n className={cn(\n \"group flex w-full items-start gap-1 rounded py-0.5 text-left transition-colors\",\n !empty && \"hover:bg-accent/40\",\n empty && \"cursor-default\",\n )}\n >\n <IconChevronRight\n className={cn(\n \"mt-1 size-3.5 shrink-0 text-plan-muted transition-transform\",\n open && \"rotate-90\",\n empty && \"opacity-0\",\n )}\n />\n <span className=\"min-w-0 whitespace-pre-wrap break-words\">\n {keyEl}\n <span className={PUNCT_CLASS}>{openBrace}</span>\n {!open && !empty && (\n <span className=\"ml-1 text-plan-muted\">\n {containerSummary(value)}\n </span>\n )}\n {(!open || empty) && (\n <span className={PUNCT_CLASS}>\n {empty ? \"\" : \"…\"}\n {closeBrace}\n {trailingComma ? \",\" : \"\"}\n </span>\n )}\n </span>\n </button>\n\n {open && !empty && (\n <>\n {/* Indent guide: a subtle vertical rule marks the nesting level. */}\n <div className=\"ml-[7px] border-l border-plan-line pl-3.5\">\n {entries.map(([entryKey, entryValue], index) => (\n <JsonNode\n key={`${String(entryKey)}:${childPulseNonce}`}\n nodeId={`${nodeId}/${JSON.stringify(entryKey)}`}\n label={entryKey}\n value={entryValue}\n depth={depth + 1}\n collapsedDepth={collapsedDepth}\n forceOpen={childForceOpen}\n onContainerStateChange={onContainerStateChange}\n trailingComma={index < entries.length - 1}\n />\n ))}\n </div>\n <div className=\"flex items-start\">\n {/* Align the closing brace under the chevron column. */}\n <span className=\"ml-[18px] whitespace-pre\">\n <span className={PUNCT_CLASS}>{closeBrace}</span>\n {trailingComma && <span className={PUNCT_CLASS}>,</span>}\n </span>\n </div>\n </>\n )}\n </div>\n );\n}\n\n/* ── Read (collapsible devtools tree) ──────────────────────────────────────── */\n\n/**\n * Read-only renderer for a `json-explorer` block. Parses `data.json` defensively\n * and renders the collapsible tree; on a parse error it shows the raw payload in\n * a monospace block plus the error (never throws). An \"Expand all / Collapse\n * all\" control toggles every node at once via a global pulse counter.\n */\nexport function JsonExplorerRead({\n data,\n blockId,\n title,\n summary,\n}: BlockReadProps<JsonExplorerData>) {\n const heading = data.title ?? title;\n\n return (\n <section\n {...ltrCodeBlockProps}\n className=\"plan-block\"\n data-block-id={blockId}\n >\n {heading && <div className=\"plan-block-label\">{heading}</div>}\n <JsonExplorerSurface data={data} />\n {summary && <p className=\"mt-5 text-plan-muted\">{summary}</p>}\n </section>\n );\n}\n\nexport function JsonExplorerSurface({\n data,\n className,\n label = \"JSON\",\n}: {\n data: Pick<JsonExplorerData, \"json\" | \"collapsedDepth\">;\n className?: string;\n label?: string;\n}) {\n const parsed = useMemo(() => parseJson(data.json), [data.json]);\n const collapsedDepth =\n data.collapsedDepth ?? JSON_EXPLORER_DEFAULT_COLLAPSED_DEPTH;\n // `pulse` carries a boolean (expand/collapse) plus a nonce so repeated clicks\n // of the same action still re-fire the reseed in each node.\n const [pulse, setPulse] = useState<{ open: boolean; nonce: number } | null>(\n null,\n );\n const [containerOpenStates, setContainerOpenStates] = useState<\n Record<string, boolean>\n >({});\n const handleContainerStateChange = useCallback(\n (nodeId: string, open: boolean | null) => {\n setContainerOpenStates((prev) => {\n if (open === null) {\n if (!(nodeId in prev)) return prev;\n const next = { ...prev };\n delete next[nodeId];\n return next;\n }\n if (prev[nodeId] === open) return prev;\n return { ...prev, [nodeId]: open };\n });\n },\n [],\n );\n const openStates = Object.values(containerOpenStates);\n const hasRegisteredContainers = openStates.length > 0;\n const fullyExpanded =\n hasRegisteredContainers && openStates.every((open) => open);\n const fullyCollapsed =\n hasRegisteredContainers && openStates.every((open) => !open);\n const parsedValue = parsed.ok ? (parsed.value as JsonValue) : null;\n const showTreeActions = parsedValue\n ? isNonEmptyContainer(parsedValue)\n : false;\n const actionButtonClass =\n \"rounded px-1.5 py-0.5 text-xs text-plan-muted transition-colors hover:bg-accent/60 hover:text-plan-text disabled:pointer-events-none disabled:opacity-40\";\n\n return (\n <div\n className={cn(\n \"group overflow-hidden rounded-xl border border-plan-line bg-plan-code\",\n className,\n )}\n >\n <div className=\"flex items-center justify-between gap-2 border-b border-plan-line px-3 py-1.5\">\n <span className=\"font-mono text-xs uppercase tracking-wide text-plan-muted\">\n {label}\n </span>\n {showTreeActions && (\n <div\n data-json-explorer-actions=\"true\"\n className=\"pointer-events-none flex items-center gap-1 opacity-0 transition-opacity group-hover:pointer-events-auto group-hover:opacity-100 group-focus-within:pointer-events-auto group-focus-within:opacity-100\"\n >\n <button\n type=\"button\"\n data-plan-interactive\n disabled={fullyExpanded}\n onClick={() =>\n setPulse((prev) => ({\n open: true,\n nonce: (prev?.nonce ?? 0) + 1,\n }))\n }\n className={actionButtonClass}\n >\n Expand all\n </button>\n <span className=\"text-plan-muted\">·</span>\n <button\n type=\"button\"\n data-plan-interactive\n disabled={fullyCollapsed}\n onClick={() =>\n setPulse((prev) => ({\n open: false,\n nonce: (prev?.nonce ?? 0) + 1,\n }))\n }\n className={actionButtonClass}\n >\n Collapse all\n </button>\n </div>\n )}\n </div>\n <div\n className=\"overflow-auto px-3 py-2.5 font-mono [font-size:var(--plan-doc-code-size)] text-plan-code-text\"\n data-code-surface\n >\n {parsed.ok ? (\n <JsonNode\n // Remount the whole tree when the global pulse fires so every node\n // re-seeds from the new open/closed state cleanly.\n key={pulse?.nonce ?? 0}\n nodeId=\"$\"\n value={parsed.value as JsonValue}\n depth={0}\n collapsedDepth={collapsedDepth}\n forceOpen={pulse}\n onContainerStateChange={handleContainerStateChange}\n />\n ) : (\n <div className=\"space-y-2\">\n <pre className=\"overflow-auto whitespace-pre-wrap break-words text-plan-code-text\">\n {data.json || \"—\"}\n </pre>\n <p className=\"text-xs text-red-600 dark:text-red-300\">\n Could not parse JSON: {parsed.error}\n </p>\n </div>\n )}\n </div>\n </div>\n );\n}\n\n/* ── Edit (panel form) ─────────────────────────────────────────────────────── */\n\n/**\n * Panel editor for a `json-explorer` block: a monospace textarea bound to the\n * raw `json`, a \"Format\" button that pretty-prints via `JSON.parse` →\n * `JSON.stringify(_, null, 2)` (guarded — shows an INLINE error, never\n * `window.alert`), an auto-expand depth picker/input, and a `title` input.\n * Renders BARE content (no `<section>`); the registry's panel surface supplies\n * the popover chrome.\n */\nexport function JsonExplorerEdit({\n data,\n onChange,\n editable,\n}: BlockEditProps<JsonExplorerData>) {\n const jsonId = useId();\n const titleId = useId();\n const depthId = useId();\n const [formatError, setFormatError] = useState<string | null>(null);\n const collapsedDepth =\n data.collapsedDepth ?? JSON_EXPLORER_DEFAULT_COLLAPSED_DEPTH;\n\n const setCollapsedDepth = (value: number) => {\n onChange({ ...data, collapsedDepth: clampCollapsedDepth(value) });\n };\n\n const handleFormat = () => {\n try {\n const formatted = JSON.stringify(JSON.parse(data.json), null, 2);\n setFormatError(null);\n onChange({ ...data, json: formatted });\n } catch (error) {\n setFormatError(\n error instanceof Error ? error.message : \"Invalid JSON — cannot format\",\n );\n }\n };\n\n return (\n <div className=\"grid gap-3\" data-plan-interactive>\n <div className=\"grid gap-1.5\">\n <DevLabel htmlFor={titleId}>Title</DevLabel>\n <DevInput\n id={titleId}\n value={data.title ?? \"\"}\n readOnly={!editable}\n onChange={(event) =>\n onChange({ ...data, title: event.target.value || undefined })\n }\n placeholder=\"Optional heading\"\n />\n </div>\n\n <div className=\"grid gap-1.5\">\n <div className=\"flex items-center justify-between\">\n <DevLabel htmlFor={jsonId}>JSON payload</DevLabel>\n {editable && (\n <button\n type=\"button\"\n data-plan-interactive\n onClick={handleFormat}\n className=\"inline-flex h-7 cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-md border border-input bg-background px-2 text-xs font-medium ring-offset-background transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50\"\n >\n Format\n </button>\n )}\n </div>\n <DevTextarea\n id={jsonId}\n value={data.json}\n readOnly={!editable}\n spellCheck={false}\n onChange={(event) => {\n setFormatError(null);\n onChange({ ...data, json: event.target.value });\n }}\n className=\"min-h-56 font-mono text-xs\"\n placeholder={'{\\n \"id\": \"abc123\",\\n \"active\": true\\n}'}\n />\n {formatError && (\n <p className=\"text-xs text-red-600 dark:text-red-300\">\n {formatError}\n </p>\n )}\n <p className=\"text-xs text-muted-foreground\">\n Raw JSON text is the source of truth. Use Format to pretty-print it.\n </p>\n </div>\n\n <div className=\"grid gap-1.5\">\n <DevLabel htmlFor={depthId}>Auto expand</DevLabel>\n <div className=\"flex flex-wrap gap-1\">\n {JSON_EXPLORER_DEPTH_PRESETS.map((preset) => {\n const active = collapsedDepth === preset.value;\n return (\n <button\n key={preset.label}\n type=\"button\"\n data-plan-interactive\n aria-pressed={active}\n disabled={!editable}\n onClick={() => setCollapsedDepth(preset.value)}\n className={cn(\n \"inline-flex h-7 items-center justify-center rounded-md border px-2 text-xs font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50\",\n active\n ? \"border-primary bg-primary text-primary-foreground\"\n : \"border-input bg-background text-muted-foreground hover:bg-accent hover:text-accent-foreground\",\n )}\n >\n {preset.label}\n </button>\n );\n })}\n </div>\n <DevInput\n id={depthId}\n type=\"number\"\n min={0}\n max={JSON_EXPLORER_MAX_COLLAPSED_DEPTH}\n value={collapsedDepth}\n readOnly={!editable}\n onChange={(event) => {\n const next = Number.parseInt(event.target.value, 10);\n onChange({\n ...data,\n collapsedDepth: Number.isFinite(next)\n ? clampCollapsedDepth(next)\n : undefined,\n });\n }}\n className=\"w-24\"\n />\n <p className=\"text-xs text-muted-foreground\">\n Levels open automatically. Use 0 to start collapsed,{\" \"}\n {JSON_EXPLORER_MAX_COLLAPSED_DEPTH} for all.\n </p>\n </div>\n </div>\n );\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MermaidBlock.d.ts","sourceRoot":"","sources":["../../../../src/client/blocks/library/MermaidBlock.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"MermaidBlock.d.ts","sourceRoot":"","sources":["../../../../src/client/blocks/library/MermaidBlock.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAoRvD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,OAAO,EACP,KAAK,EACL,OAAO,GACR,EAAE,cAAc,CAAC,WAAW,CAAC,2CAe7B;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,QAAQ,EACR,QAAQ,GACT,EAAE,cAAc,CAAC,WAAW,CAAC,2CAwC7B"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useId, useMemo, useState } from "react";
|
|
3
3
|
import { IconArrowsMaximize } from "@tabler/icons-react";
|
|
4
|
+
import { ltrCodeBlockProps } from "../code-block-direction.js";
|
|
4
5
|
import { DevInput, DevLabel } from "./dev-doc-ui.js";
|
|
5
6
|
import { DiagramLightbox } from "./diagram.js";
|
|
6
7
|
function errorMessage(error) {
|
|
@@ -159,7 +160,7 @@ function MermaidDiagram({ source, idSeed, }) {
|
|
|
159
160
|
* house style.
|
|
160
161
|
*/
|
|
161
162
|
export function MermaidRead({ data, blockId, title, summary, }) {
|
|
162
|
-
return (_jsxs("section", { className: "plan-block", "data-block-id": blockId, children: [title && _jsx("div", { className: "plan-block-label", children: title }), _jsx(MermaidDiagram, { source: data.source, idSeed: blockId }), data.caption && (_jsx("p", { className: "mt-3 text-sm text-plan-muted", children: data.caption })), summary && _jsx("p", { className: "mt-5 text-plan-muted", children: summary })] }));
|
|
163
|
+
return (_jsxs("section", { ...ltrCodeBlockProps, className: "plan-block", "data-block-id": blockId, children: [title && _jsx("div", { className: "plan-block-label", children: title }), _jsx(MermaidDiagram, { source: data.source, idSeed: blockId }), data.caption && (_jsx("p", { className: "mt-3 text-sm text-plan-muted", children: data.caption })), summary && _jsx("p", { className: "mt-5 text-plan-muted", children: summary })] }));
|
|
163
164
|
}
|
|
164
165
|
/**
|
|
165
166
|
* Edit renderer (panel surface) for a `mermaid` block: a monospace textarea for
|