@dendelion/paper-camp 0.19.0 → 0.20.0

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.
Files changed (73) hide show
  1. package/dist/app/assets/index-3pzg7Iyw.js +2 -0
  2. package/dist/app/assets/index-3pzg7Iyw.js.map +1 -0
  3. package/dist/app/assets/{index-B6251tL6.js → index-BHmWkgBW.js} +2 -2
  4. package/dist/app/assets/{index-B6251tL6.js.map → index-BHmWkgBW.js.map} +1 -1
  5. package/dist/app/assets/{index-DLkUANCR.js → index-BuzzfADD.js} +2 -2
  6. package/dist/app/assets/{index-DLkUANCR.js.map → index-BuzzfADD.js.map} +1 -1
  7. package/dist/app/assets/{index-D5j1njQR.js → index-CkLeljbk.js} +2 -2
  8. package/dist/app/assets/{index-D5j1njQR.js.map → index-CkLeljbk.js.map} +1 -1
  9. package/dist/app/assets/{index-nuVVSVma.js → index-DMDqfoCe.js} +2 -2
  10. package/dist/app/assets/index-DMDqfoCe.js.map +1 -0
  11. package/dist/app/assets/index-D_Lo8ptS.js +6 -0
  12. package/dist/app/assets/index-D_Lo8ptS.js.map +1 -0
  13. package/dist/app/assets/{index-BNoowtMI.js → index-DfekHwwU.js} +3 -3
  14. package/dist/app/assets/{index-BNoowtMI.js.map → index-DfekHwwU.js.map} +1 -1
  15. package/dist/app/assets/{index-D2iIIpI1.js → index-Gi97Lmex.js} +3 -3
  16. package/dist/app/assets/{index-D2iIIpI1.js.map → index-Gi97Lmex.js.map} +1 -1
  17. package/dist/app/assets/main-Bm0W4ucz.css +1 -0
  18. package/dist/app/assets/main-DP_okYxh.js +215 -0
  19. package/dist/app/assets/main-DP_okYxh.js.map +1 -0
  20. package/dist/app/assets/sidebar-section-B-A20bg9.js +2 -0
  21. package/dist/app/assets/sidebar-section-B-A20bg9.js.map +1 -0
  22. package/dist/app/index.html +2 -2
  23. package/dist/app/toolbar.js +1071 -1049
  24. package/dist/app/toolbar.js.map +1 -1
  25. package/dist/chunks/{phase-progress.CwSKAAZ-.js → phase-progress.DPAZ01Gg.js} +1720 -1594
  26. package/dist/chunks/phase-progress.DPAZ01Gg.js.map +1 -0
  27. package/dist/cli/index.js +6633 -6345
  28. package/dist/cli/index.js.map +1 -1
  29. package/dist/core/corpus-format.d.ts +11 -0
  30. package/dist/core/corpus-format.d.ts.map +1 -0
  31. package/dist/core/corpus-format.test.d.ts +2 -0
  32. package/dist/core/corpus-format.test.d.ts.map +1 -0
  33. package/dist/core/doctor/checks/metadata.d.ts.map +1 -1
  34. package/dist/core/doctor/rules.d.ts +6 -1
  35. package/dist/core/doctor/rules.d.ts.map +1 -1
  36. package/dist/core/git-pr/pr-lookup.d.ts +6 -1
  37. package/dist/core/git-pr/pr-lookup.d.ts.map +1 -1
  38. package/dist/core/git-pr/pr.d.ts +10 -0
  39. package/dist/core/git-pr/pr.d.ts.map +1 -1
  40. package/dist/core/index.js +54 -53
  41. package/dist/core/issues.d.ts +51 -0
  42. package/dist/core/issues.d.ts.map +1 -0
  43. package/dist/core/issues.test.d.ts +2 -0
  44. package/dist/core/issues.test.d.ts.map +1 -0
  45. package/dist/core/parse/parser.d.ts.map +1 -1
  46. package/dist/core/parse/schemas.d.ts +8 -4
  47. package/dist/core/parse/schemas.d.ts.map +1 -1
  48. package/dist/core/readers.d.ts +7 -2
  49. package/dist/core/readers.d.ts.map +1 -1
  50. package/dist/core/run-order.d.ts +1 -1
  51. package/dist/core/run-order.d.ts.map +1 -1
  52. package/dist/core/scaffold/scaffold.d.ts +0 -1
  53. package/dist/core/scaffold/scaffold.d.ts.map +1 -1
  54. package/dist/core/scaffold/templates.d.ts +1 -1
  55. package/dist/core/scaffold/templates.d.ts.map +1 -1
  56. package/dist/core/sections.d.ts.map +1 -1
  57. package/dist/core/serialize/serializer.d.ts +4 -2
  58. package/dist/core/serialize/serializer.d.ts.map +1 -1
  59. package/dist/core/status/status.d.ts +8 -4
  60. package/dist/core/status/status.d.ts.map +1 -1
  61. package/dist/types/index.d.ts +65 -5
  62. package/dist/types/index.d.ts.map +1 -1
  63. package/dist/types/index.js.map +1 -1
  64. package/package.json +2 -2
  65. package/dist/app/assets/index-nuVVSVma.js.map +0 -1
  66. package/dist/app/assets/index-s6CVH54G.js +0 -6
  67. package/dist/app/assets/index-s6CVH54G.js.map +0 -1
  68. package/dist/app/assets/main--EStESJz.js +0 -217
  69. package/dist/app/assets/main--EStESJz.js.map +0 -1
  70. package/dist/app/assets/main-CAJuC1Pz.css +0 -1
  71. package/dist/app/assets/sidebar-section-DTU8Naqm.js +0 -2
  72. package/dist/app/assets/sidebar-section-DTU8Naqm.js.map +0 -1
  73. package/dist/chunks/phase-progress.CwSKAAZ-.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index-BNoowtMI.js","sources":["../../../src/app/features/docs/components/docs-search.tsx","../../../src/app/features/docs/hooks/use-release-notes.ts","../../../src/app/features/docs/components/release-notes-detail.tsx","../../../src/app/features/docs/components/repo-doc-detail.tsx","../../../src/app/features/docs/docs-page.tsx","../../../src/app/features/docs/components/docs-sidebar.tsx"],"sourcesContent":["import { useAppStore } from '@/app/stores/app-store';\nimport { Button } from '@dendelion/paper-ui';\nimport { useNavigate } from '@tanstack/react-router';\n\ninterface SearchMatch {\n title: string;\n snippet: string;\n}\n\ninterface DocsSearchProps {\n query: string;\n}\n\nconst searchIn = (text: string, query: string): boolean =>\n text.toLowerCase().includes(query.toLowerCase());\n\nconst snippet = (text: string, query: string, maxLen = 120): string => {\n const idx = text.toLowerCase().indexOf(query.toLowerCase());\n if (idx === -1) return text.slice(0, maxLen);\n const start = Math.max(0, idx - 40);\n const end = Math.min(text.length, idx + query.length + 40);\n let s = text.slice(start, end);\n if (start > 0) s = `…${s}`;\n if (end < text.length) s = `${s}…`;\n return s;\n};\n\nexport const DocsSearch = ({ query }: DocsSearchProps) => {\n const repoDocs = useAppStore((s) => s.repoDocs);\n const setActiveDocTitle = useAppStore((s) => s.setActiveDocTitle);\n const setDocSearchQuery = useAppStore((s) => s.setDocSearchQuery);\n const navigate = useNavigate();\n\n const results: SearchMatch[] = [];\n\n for (const f of repoDocs) {\n if (searchIn(f.name, query) || searchIn(f.content, query)) {\n results.push({\n title: f.name,\n snippet: snippet(f.content, query),\n });\n }\n }\n\n const handleSelect = (title: string) => {\n navigate({ to: '/docs/$section', params: { section: 'repo-docs' } });\n setActiveDocTitle(title);\n setDocSearchQuery('');\n };\n\n if (results.length === 0) {\n return <p className=\"opacity-50\">No results found for \"{query}\".</p>;\n }\n\n return (\n <div>\n <p className=\"mb-3 text-sm opacity-50\">\n {results.length} result{results.length === 1 ? '' : 's'} for \"{query}\"\n </p>\n <div className=\"flex flex-col gap-1\">\n {results.map((m) => (\n <Button\n key={m.title}\n variant=\"ghost\"\n size=\"small\"\n fullWidth\n onClick={() => handleSelect(m.title)}\n className=\"justify-start px-3 py-2\"\n >\n <span className=\"text-left\">\n <span className=\"mb-[0.2rem] block font-display-luminari text-[0.95rem] font-semibold\">\n {m.title}\n </span>\n <span className=\"text-sm opacity-60\">{m.snippet}</span>\n </span>\n </Button>\n ))}\n </div>\n </div>\n );\n};\n","import { fetchReleaseNotes } from '@/app/services/release-notes-api';\nimport type { ReleaseNoteSection } from '@/types/index';\nimport { useEffect, useState } from 'react';\n\nexport const useReleaseNotes = (version: string | null): ReleaseNoteSection[] | null => {\n const [sections, setSections] = useState<ReleaseNoteSection[] | null>(null);\n\n useEffect(() => {\n setSections(null);\n if (!version) return;\n let cancelled = false;\n fetchReleaseNotes(version)\n .then((result) => {\n if (!cancelled) setSections(result);\n })\n .catch(() => {});\n return () => {\n cancelled = true;\n };\n }, [version]);\n\n return sections;\n};\n","import { detailHeadingClassName } from '@/app/components/detail-heading-style';\nimport { Markdown } from '@/app/components/markdown';\nimport { useAppStore } from '@/app/stores/app-store';\nimport { useReleaseNotes } from '../hooks/use-release-notes';\n\nexport const ReleaseNotesDetail = () => {\n const version = useAppStore((s) => s.activeReleaseVersion);\n const sections = useReleaseNotes(version);\n if (!version) return null;\n\n if (!sections) {\n return (\n <div>\n <h2 className={`${detailHeadingClassName} m-0 mb-4`}>{version}</h2>\n <p className=\"opacity-50\">No release notes found for {version}.</p>\n </div>\n );\n }\n\n if (sections.length === 0) {\n return (\n <div>\n <h2 className={`${detailHeadingClassName} m-0 mb-4`}>{version}</h2>\n <p className=\"opacity-50\">No ideas could be resolved for this release.</p>\n </div>\n );\n }\n\n const markdown = sections\n .map(\n (section) =>\n `### ${section.label}\\n\\n${section.ideas.map((idea) => `- ${idea.title} (${idea.id})`).join('\\n')}`,\n )\n .join('\\n\\n');\n\n return (\n <div>\n <h2 className={`${detailHeadingClassName} m-0 mb-4`}>{version}</h2>\n <div className=\"text-base leading-[1.7] text-ink-900\">\n <Markdown>{markdown}</Markdown>\n </div>\n </div>\n );\n};\n","import { detailHeadingClassName } from '@/app/components/detail-heading-style';\nimport { Markdown } from '@/app/components/markdown';\nimport { useAppStore } from '@/app/stores/app-store';\n\nexport const RepoDocDetail = () => {\n const repoDocs = useAppStore((s) => s.repoDocs);\n const activeDocTitle = useAppStore((s) => s.activeDocTitle);\n\n const file = repoDocs.find((f) => f.name === activeDocTitle);\n if (!file) return null;\n\n const isMarkdown = file.name.endsWith('.md');\n\n return (\n <div>\n <h2 className={`${detailHeadingClassName} m-0 mb-4`}>{file.name}</h2>\n\n {isMarkdown ? (\n <div className=\"text-base leading-[1.7] text-ink-900\">\n <Markdown>{file.content}</Markdown>\n </div>\n ) : (\n <pre className=\"overflow-x-auto whitespace-pre-wrap rounded-md bg-black/[4%] p-4 font-mono text-xs leading-normal\">\n {file.content}\n </pre>\n )}\n </div>\n );\n};\n","import { PageTitle } from '@/app/components/page-title';\nimport { useResolvedDocSection } from '@/app/hooks';\nimport { useAppStore } from '@/app/stores/app-store';\nimport { Breadcrumb } from '@dendelion/paper-ui';\nimport { useNavigate } from '@tanstack/react-router';\nimport { DocsSearch } from './components/docs-search';\nimport { ReleaseNotesDetail } from './components/release-notes-detail';\nimport { RepoDocDetail } from './components/repo-doc-detail';\n\nexport const DocsPage = () => {\n const docSearchQuery = useAppStore((s) => s.docSearchQuery);\n const activeDocTitle = useAppStore((s) => s.activeDocTitle);\n const activeReleaseVersion = useAppStore((s) => s.activeReleaseVersion);\n const navigate = useNavigate();\n const activeDocSection = useResolvedDocSection();\n\n const handleBackToDocs = () => navigate({ to: '/docs' });\n\n if (docSearchQuery.trim()) {\n return (\n <div>\n <DocsSearch query={docSearchQuery} />\n </div>\n );\n }\n\n if (activeDocSection === 'repo-docs' && activeDocTitle) {\n return (\n <div>\n <div className=\"mb-4\">\n <Breadcrumb\n items={[\n { id: 'docs', label: 'Docs', onClick: handleBackToDocs },\n { id: 'repo-doc', label: activeDocTitle },\n ]}\n />\n </div>\n <RepoDocDetail />\n </div>\n );\n }\n\n if (activeDocSection === 'release-notes' && activeReleaseVersion) {\n return (\n <div>\n <div className=\"mb-4\">\n <Breadcrumb\n items={[\n { id: 'docs', label: 'Docs', onClick: handleBackToDocs },\n { id: 'release-notes', label: activeReleaseVersion },\n ]}\n />\n </div>\n <ReleaseNotesDetail />\n </div>\n );\n }\n\n return (\n <div>\n <PageTitle>Docs</PageTitle>\n <p className=\"opacity-50\">\n Pick a doc from the sidebar — start with a repo doc if you're new here.\n </p>\n </div>\n );\n};\n","import { useResolvedDocSection } from '@/app/hooks';\nimport { useAppStore } from '@/app/stores/app-store';\nimport { Input, ListItem } from '@dendelion/paper-ui';\nimport { useNavigate } from '@tanstack/react-router';\nimport { useEffect } from 'react';\nimport { SidebarSection } from '../../plans/components/sidebar-section';\n\nconst simplecaseLabel = (name: string) =>\n name.charAt(0).toUpperCase() + name.slice(1).toLowerCase();\n\nconst EmptyState = ({ children }: { children: React.ReactNode }) => (\n <span className=\"block px-3 py-1 text-sm italic opacity-[0.35]\">{children}</span>\n);\n\nexport const DocsSidebar = () => {\n const repoDocs = useAppStore((s) => s.repoDocs);\n const repoDocsLoading = useAppStore((s) => s.repoDocsLoading);\n const loadRepoDocs = useAppStore((s) => s.loadRepoDocs);\n const activeDocTitle = useAppStore((s) => s.activeDocTitle);\n const setActiveDocTitle = useAppStore((s) => s.setActiveDocTitle);\n const docSearchQuery = useAppStore((s) => s.docSearchQuery);\n const setDocSearchQuery = useAppStore((s) => s.setDocSearchQuery);\n const releaseVersions = useAppStore((s) => s.releaseVersions);\n const releaseVersionsLoading = useAppStore((s) => s.releaseVersionsLoading);\n const loadReleaseVersions = useAppStore((s) => s.loadReleaseVersions);\n const activeReleaseVersion = useAppStore((s) => s.activeReleaseVersion);\n const setActiveReleaseVersion = useAppStore((s) => s.setActiveReleaseVersion);\n const activeDocSection = useResolvedDocSection();\n const navigate = useNavigate();\n\n useEffect(() => {\n loadRepoDocs();\n }, [loadRepoDocs]);\n\n useEffect(() => {\n loadReleaseVersions();\n }, [loadReleaseVersions]);\n\n return (\n <>\n <div className=\"mb-4\">\n <Input\n size=\"small\"\n aria-label=\"Search docs\"\n placeholder=\"Search docs…\"\n value={docSearchQuery}\n onChange={(e) => setDocSearchQuery(e.target.value)}\n />\n </div>\n\n <SidebarSection label=\"Repo Docs\">\n {repoDocsLoading && repoDocs.length === 0 ? (\n <EmptyState>Loading…</EmptyState>\n ) : repoDocs.length > 0 ? (\n repoDocs.map((f) => (\n <ListItem\n key={f.name}\n size=\"small\"\n active={activeDocSection === 'repo-docs' && activeDocTitle === f.name}\n onClick={() => {\n navigate({ to: '/docs/$section', params: { section: 'repo-docs' } });\n setActiveDocTitle(f.name);\n }}\n >\n {simplecaseLabel(f.name)}\n </ListItem>\n ))\n ) : (\n <EmptyState>No repo docs found</EmptyState>\n )}\n </SidebarSection>\n\n <SidebarSection label=\"Releases\">\n {releaseVersionsLoading && releaseVersions.length === 0 ? (\n <EmptyState>Loading…</EmptyState>\n ) : releaseVersions.length > 0 ? (\n releaseVersions.map((version) => (\n <ListItem\n key={version}\n size=\"small\"\n active={activeDocSection === 'release-notes' && activeReleaseVersion === version}\n onClick={() => {\n navigate({ to: '/docs/$section', params: { section: 'release-notes' } });\n setActiveReleaseVersion(version);\n }}\n >\n {version}\n </ListItem>\n ))\n ) : (\n <EmptyState>No releases yet</EmptyState>\n )}\n </SidebarSection>\n </>\n );\n};\n"],"names":["searchIn","text","query","snippet","maxLen","idx","start","end","s","DocsSearch","repoDocs","useAppStore","setActiveDocTitle","setDocSearchQuery","navigate","useNavigate","results","f","handleSelect","title","jsxs","m","jsx","Button","useReleaseNotes","version","sections","setSections","useState","useEffect","cancelled","fetchReleaseNotes","result","ReleaseNotesDetail","detailHeadingClassName","markdown","section","idea","Markdown","RepoDocDetail","activeDocTitle","file","isMarkdown","DocsPage","docSearchQuery","activeReleaseVersion","activeDocSection","useResolvedDocSection","handleBackToDocs","Breadcrumb","PageTitle","simplecaseLabel","name","EmptyState","children","DocsSidebar","repoDocsLoading","loadRepoDocs","releaseVersions","releaseVersionsLoading","loadReleaseVersions","setActiveReleaseVersion","Fragment","Input","e","SidebarSection","ListItem"],"mappings":"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"}
1
+ {"version":3,"file":"index-DfekHwwU.js","sources":["../../../src/app/features/docs/components/docs-search.tsx","../../../src/app/features/docs/hooks/use-release-notes.ts","../../../src/app/features/docs/components/release-notes-detail.tsx","../../../src/app/features/docs/components/repo-doc-detail.tsx","../../../src/app/features/docs/docs-page.tsx","../../../src/app/features/docs/components/docs-sidebar.tsx"],"sourcesContent":["import { useAppStore } from '@/app/stores/app-store';\nimport { Button } from '@dendelion/paper-ui';\nimport { useNavigate } from '@tanstack/react-router';\n\ninterface SearchMatch {\n title: string;\n snippet: string;\n}\n\ninterface DocsSearchProps {\n query: string;\n}\n\nconst searchIn = (text: string, query: string): boolean =>\n text.toLowerCase().includes(query.toLowerCase());\n\nconst snippet = (text: string, query: string, maxLen = 120): string => {\n const idx = text.toLowerCase().indexOf(query.toLowerCase());\n if (idx === -1) return text.slice(0, maxLen);\n const start = Math.max(0, idx - 40);\n const end = Math.min(text.length, idx + query.length + 40);\n let s = text.slice(start, end);\n if (start > 0) s = `…${s}`;\n if (end < text.length) s = `${s}…`;\n return s;\n};\n\nexport const DocsSearch = ({ query }: DocsSearchProps) => {\n const repoDocs = useAppStore((s) => s.repoDocs);\n const setActiveDocTitle = useAppStore((s) => s.setActiveDocTitle);\n const setDocSearchQuery = useAppStore((s) => s.setDocSearchQuery);\n const navigate = useNavigate();\n\n const results: SearchMatch[] = [];\n\n for (const f of repoDocs) {\n if (searchIn(f.name, query) || searchIn(f.content, query)) {\n results.push({\n title: f.name,\n snippet: snippet(f.content, query),\n });\n }\n }\n\n const handleSelect = (title: string) => {\n navigate({ to: '/docs/$section', params: { section: 'repo-docs' } });\n setActiveDocTitle(title);\n setDocSearchQuery('');\n };\n\n if (results.length === 0) {\n return <p className=\"opacity-50\">No results found for \"{query}\".</p>;\n }\n\n return (\n <div>\n <p className=\"mb-3 text-sm opacity-50\">\n {results.length} result{results.length === 1 ? '' : 's'} for \"{query}\"\n </p>\n <div className=\"flex flex-col gap-1\">\n {results.map((m) => (\n <Button\n key={m.title}\n variant=\"ghost\"\n size=\"small\"\n fullWidth\n onClick={() => handleSelect(m.title)}\n className=\"justify-start px-3 py-2\"\n >\n <span className=\"text-left\">\n <span className=\"mb-[0.2rem] block font-display-luminari text-[0.95rem] font-semibold\">\n {m.title}\n </span>\n <span className=\"text-sm opacity-60\">{m.snippet}</span>\n </span>\n </Button>\n ))}\n </div>\n </div>\n );\n};\n","import { fetchReleaseNotes } from '@/app/services/release-notes-api';\nimport type { ReleaseNoteSection } from '@/types/index';\nimport { useEffect, useState } from 'react';\n\nexport const useReleaseNotes = (version: string | null): ReleaseNoteSection[] | null => {\n const [sections, setSections] = useState<ReleaseNoteSection[] | null>(null);\n\n useEffect(() => {\n setSections(null);\n if (!version) return;\n let cancelled = false;\n fetchReleaseNotes(version)\n .then((result) => {\n if (!cancelled) setSections(result);\n })\n .catch(() => {});\n return () => {\n cancelled = true;\n };\n }, [version]);\n\n return sections;\n};\n","import { detailHeadingClassName } from '@/app/components/detail-heading-style';\nimport { Markdown } from '@/app/components/markdown';\nimport { useAppStore } from '@/app/stores/app-store';\nimport { useReleaseNotes } from '../hooks/use-release-notes';\n\nexport const ReleaseNotesDetail = () => {\n const version = useAppStore((s) => s.activeReleaseVersion);\n const sections = useReleaseNotes(version);\n if (!version) return null;\n\n if (!sections) {\n return (\n <div>\n <h2 className={`${detailHeadingClassName} m-0 mb-4`}>{version}</h2>\n <p className=\"opacity-50\">No release notes found for {version}.</p>\n </div>\n );\n }\n\n if (sections.length === 0) {\n return (\n <div>\n <h2 className={`${detailHeadingClassName} m-0 mb-4`}>{version}</h2>\n <p className=\"opacity-50\">No ideas could be resolved for this release.</p>\n </div>\n );\n }\n\n const markdown = sections\n .map(\n (section) =>\n `### ${section.label}\\n\\n${section.ideas.map((idea) => `- ${idea.title} (${idea.id})`).join('\\n')}`,\n )\n .join('\\n\\n');\n\n return (\n <div>\n <h2 className={`${detailHeadingClassName} m-0 mb-4`}>{version}</h2>\n <div className=\"text-base leading-[1.7] text-ink-900\">\n <Markdown>{markdown}</Markdown>\n </div>\n </div>\n );\n};\n","import { detailHeadingClassName } from '@/app/components/detail-heading-style';\nimport { Markdown } from '@/app/components/markdown';\nimport { useAppStore } from '@/app/stores/app-store';\n\nexport const RepoDocDetail = () => {\n const repoDocs = useAppStore((s) => s.repoDocs);\n const activeDocTitle = useAppStore((s) => s.activeDocTitle);\n\n const file = repoDocs.find((f) => f.name === activeDocTitle);\n if (!file) return null;\n\n const isMarkdown = file.name.endsWith('.md');\n\n return (\n <div>\n <h2 className={`${detailHeadingClassName} m-0 mb-4`}>{file.name}</h2>\n\n {isMarkdown ? (\n <div className=\"text-base leading-[1.7] text-ink-900\">\n <Markdown>{file.content}</Markdown>\n </div>\n ) : (\n <pre className=\"overflow-x-auto whitespace-pre-wrap rounded-md bg-black/[4%] p-4 font-mono text-xs leading-normal\">\n {file.content}\n </pre>\n )}\n </div>\n );\n};\n","import { PageTitle } from '@/app/components/page-title';\nimport { useResolvedDocSection } from '@/app/hooks';\nimport { useAppStore } from '@/app/stores/app-store';\nimport { Breadcrumb } from '@dendelion/paper-ui';\nimport { useNavigate } from '@tanstack/react-router';\nimport { DocsSearch } from './components/docs-search';\nimport { ReleaseNotesDetail } from './components/release-notes-detail';\nimport { RepoDocDetail } from './components/repo-doc-detail';\n\nexport const DocsPage = () => {\n const docSearchQuery = useAppStore((s) => s.docSearchQuery);\n const activeDocTitle = useAppStore((s) => s.activeDocTitle);\n const activeReleaseVersion = useAppStore((s) => s.activeReleaseVersion);\n const navigate = useNavigate();\n const activeDocSection = useResolvedDocSection();\n\n const handleBackToDocs = () => navigate({ to: '/docs' });\n\n if (docSearchQuery.trim()) {\n return (\n <div>\n <DocsSearch query={docSearchQuery} />\n </div>\n );\n }\n\n if (activeDocSection === 'repo-docs' && activeDocTitle) {\n return (\n <div>\n <div className=\"mb-4\">\n <Breadcrumb\n items={[\n { id: 'docs', label: 'Docs', onClick: handleBackToDocs },\n { id: 'repo-doc', label: activeDocTitle },\n ]}\n />\n </div>\n <RepoDocDetail />\n </div>\n );\n }\n\n if (activeDocSection === 'release-notes' && activeReleaseVersion) {\n return (\n <div>\n <div className=\"mb-4\">\n <Breadcrumb\n items={[\n { id: 'docs', label: 'Docs', onClick: handleBackToDocs },\n { id: 'release-notes', label: activeReleaseVersion },\n ]}\n />\n </div>\n <ReleaseNotesDetail />\n </div>\n );\n }\n\n return (\n <div>\n <PageTitle>Docs</PageTitle>\n <p className=\"opacity-50\">\n Pick a doc from the sidebar — start with a repo doc if you're new here.\n </p>\n </div>\n );\n};\n","import { useResolvedDocSection } from '@/app/hooks';\nimport { useAppStore } from '@/app/stores/app-store';\nimport { Input, ListItem } from '@dendelion/paper-ui';\nimport { useNavigate } from '@tanstack/react-router';\nimport { useEffect } from 'react';\nimport { SidebarSection } from '../../plans/components/sidebar-section';\n\nconst simplecaseLabel = (name: string) =>\n name.charAt(0).toUpperCase() + name.slice(1).toLowerCase();\n\nconst EmptyState = ({ children }: { children: React.ReactNode }) => (\n <span className=\"block px-3 py-1 text-sm italic opacity-[0.35]\">{children}</span>\n);\n\nexport const DocsSidebar = () => {\n const repoDocs = useAppStore((s) => s.repoDocs);\n const repoDocsLoading = useAppStore((s) => s.repoDocsLoading);\n const loadRepoDocs = useAppStore((s) => s.loadRepoDocs);\n const activeDocTitle = useAppStore((s) => s.activeDocTitle);\n const setActiveDocTitle = useAppStore((s) => s.setActiveDocTitle);\n const docSearchQuery = useAppStore((s) => s.docSearchQuery);\n const setDocSearchQuery = useAppStore((s) => s.setDocSearchQuery);\n const releaseVersions = useAppStore((s) => s.releaseVersions);\n const releaseVersionsLoading = useAppStore((s) => s.releaseVersionsLoading);\n const loadReleaseVersions = useAppStore((s) => s.loadReleaseVersions);\n const activeReleaseVersion = useAppStore((s) => s.activeReleaseVersion);\n const setActiveReleaseVersion = useAppStore((s) => s.setActiveReleaseVersion);\n const activeDocSection = useResolvedDocSection();\n const navigate = useNavigate();\n\n useEffect(() => {\n loadRepoDocs();\n }, [loadRepoDocs]);\n\n useEffect(() => {\n loadReleaseVersions();\n }, [loadReleaseVersions]);\n\n return (\n <>\n <div className=\"flex h-[64px] items-center\">\n <Input\n size=\"small\"\n aria-label=\"Search docs\"\n placeholder=\"Search docs…\"\n value={docSearchQuery}\n onChange={(e) => setDocSearchQuery(e.target.value)}\n />\n </div>\n\n <SidebarSection label=\"Repo Docs\">\n {repoDocsLoading && repoDocs.length === 0 ? (\n <EmptyState>Loading…</EmptyState>\n ) : repoDocs.length > 0 ? (\n repoDocs.map((f) => (\n <ListItem\n key={f.name}\n size=\"small\"\n className=\"pc-row text-xs\"\n active={activeDocSection === 'repo-docs' && activeDocTitle === f.name}\n onClick={() => {\n navigate({ to: '/docs/$section', params: { section: 'repo-docs' } });\n setActiveDocTitle(f.name);\n }}\n >\n {simplecaseLabel(f.name)}\n </ListItem>\n ))\n ) : (\n <EmptyState>No repo docs found</EmptyState>\n )}\n </SidebarSection>\n\n <SidebarSection label=\"Releases\">\n {releaseVersionsLoading && releaseVersions.length === 0 ? (\n <EmptyState>Loading…</EmptyState>\n ) : releaseVersions.length > 0 ? (\n releaseVersions.map((version) => (\n <ListItem\n key={version}\n size=\"small\"\n className=\"pc-row text-xs\"\n active={activeDocSection === 'release-notes' && activeReleaseVersion === version}\n onClick={() => {\n navigate({ to: '/docs/$section', params: { section: 'release-notes' } });\n setActiveReleaseVersion(version);\n }}\n >\n {version}\n </ListItem>\n ))\n ) : (\n <EmptyState>No releases yet</EmptyState>\n )}\n </SidebarSection>\n </>\n );\n};\n"],"names":["searchIn","text","query","snippet","maxLen","idx","start","end","s","DocsSearch","repoDocs","useAppStore","setActiveDocTitle","setDocSearchQuery","navigate","useNavigate","results","f","handleSelect","title","jsxs","m","jsx","Button","useReleaseNotes","version","sections","setSections","useState","useEffect","cancelled","fetchReleaseNotes","result","ReleaseNotesDetail","detailHeadingClassName","markdown","section","idea","Markdown","RepoDocDetail","activeDocTitle","file","isMarkdown","DocsPage","docSearchQuery","activeReleaseVersion","activeDocSection","useResolvedDocSection","handleBackToDocs","Breadcrumb","PageTitle","simplecaseLabel","name","EmptyState","children","DocsSidebar","repoDocsLoading","loadRepoDocs","releaseVersions","releaseVersionsLoading","loadReleaseVersions","setActiveReleaseVersion","Fragment","Input","e","SidebarSection","ListItem"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import{u as g,m as L,r as c,C as O,j as e,H as P,x as T,J as y,I as M,K as B,a as D,F,P as k,L as U,N as $,M as A,g as w,S as N,O as q,R as _,Q as V,T as H,i as z,U as J,V as K,W as G,p as I}from"./main--EStESJz.js";import{X as xe}from"./main--EStESJz.js";const C="__no-subject__",W=({horizonTitle:s,item:t,candidateName:o,onClose:d,onPromoted:a})=>{const m=g(x=>x.promoteRoadmapItem),i=g(x=>x.launchIdeaExtend),{subjects:b,available:j}=L(),[u,h]=c.useState(C),[f,n]=c.useState(!1),[p,v]=c.useState(null),{toast:l}=O();c.useEffect(()=>{t&&(h(o?t.name:C),n(!1),v(null))},[t,o]);const r=async()=>{if(!(!t||!s)){n(!0),v(null);try{const x=await m(s,t,u===C?void 0:u,o??void 0),S=g.getState().ideaEntries.find(R=>R.id===x);if(S)try{await i(x,M(S,s))}catch(R){l({title:"Idea created, but the refine agent failed to launch",description:B(R.message),variant:"error"})}a(),d()}catch(x){v(x.message)}finally{n(!1)}}};return e.jsx(P,{open:t!==null,onClose:d,title:o??(t==null?void 0:t.name)??"",size:"small",children:e.jsxs("div",{className:"flex flex-col gap-4",children:[!o&&e.jsx("p",{className:"m-0 opacity-80",children:t==null?void 0:t.description}),e.jsx("div",{children:e.jsx(T,{size:"small",value:u,onChange:h,disabled:f||!j,options:[{value:C,label:"No subject"},...!j&&u!==C?[{value:u,label:u}]:[],...b.map(x=>({value:x,label:x}))]})}),p&&e.jsx("p",{className:"m-0 text-watercolor-rose-dark text-sm",children:p}),e.jsxs("div",{className:"flex justify-end gap-2",children:[e.jsx(y,{type:"button",variant:"ghost",onClick:d,disabled:f,children:"Cancel"}),e.jsx(y,{type:"button",variant:"primary",onClick:r,disabled:f,children:f?"Promoting…":"Promote to idea"})]})]})})},Q=s=>({shipped:s.filter(t=>t.status==="done").length,queued:s.filter(t=>t.status!=="done"&&t.status!=="dropped").length}),X="font-handwritten text-md font-semibold opacity-70 leading-none pt-2 px-1 pb-0",Z=({size:s=14})=>e.jsx("svg",{width:s,height:s,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:e.jsx("polyline",{points:"9 18 15 12 9 6"})}),Y=({name:s,onPromote:t})=>e.jsx(_,{size:"small",texture:"kraft",className:"plan-row-card",children:e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("span",{className:"flex-1",children:s}),e.jsx(y,{type:"button",variant:"ghost",size:"small",onClick:t,children:"Promote to idea"})]})}),ee=({onAdd:s})=>{const[t,o]=c.useState(""),[d,a]=c.useState(!1),m=async()=>{if(t.trim()){a(!0);try{await s(t.trim()),o("")}finally{a(!1)}}};return e.jsxs("div",{className:"flex gap-2",children:[e.jsx(z,{size:"small",value:t,onChange:i=>o(i.target.value),onKeyDown:i=>{i.key==="Enter"&&m()},placeholder:"Add option…",disabled:d,className:"flex-1"}),e.jsx(y,{type:"button",variant:"ghost",size:"small",onClick:m,disabled:d||!t.trim(),children:"Add"})]})},se=(s,t)=>{const o=new Set,d=t.map(a=>(a.id&&o.add(a.id),a.idea&&o.add(a.idea),{key:a.title,label:a.title,status:a.status,pr:a.pr,planId:a.id,planTitle:a.title}));for(const a of s)o.has(a.id)||d.push({key:a.id,label:a.id,status:a.status,pr:a.pr});return d},te=({idea:s,onOpen:t})=>e.jsx(_,{size:"small",texture:"kraft",className:"plan-row-card",children:e.jsxs("div",{className:"flex items-center gap-3",children:[t?e.jsx("button",{type:"button",onClick:t,className:"flex-1 min-w-0 overflow-hidden text-ellipsis whitespace-nowrap bg-transparent border-none p-0 cursor-pointer [font:inherit] text-inherit text-left",children:s.label}):e.jsx("span",{className:"flex-1 min-w-0 overflow-hidden text-ellipsis whitespace-nowrap",children:s.label}),s.pr&&e.jsx(V,{pr:s.pr}),e.jsx(w,{size:"small",fillColor:N[s.status].fill,textColor:N[s.status].text,children:H[s.status]})]})}),ae=({done:s,total:t})=>{const o=t>0?Math.round(s/t*100):0;return e.jsx("div",{className:"w-24 h-1.5 rounded-full bg-black/[0.08] overflow-hidden shrink-0",children:e.jsx("div",{className:`h-full rounded-full ${t>0?"bg-watercolor-green":"bg-transparent"}`,style:{width:`${o}%`}})})},ne=({item:s,graduated:t,highlighted:o,onPromote:d,onPromoteCandidate:a,onAddCandidate:m,onOpenGraduated:i})=>{const[b,j]=c.useState(o),{shipped:u,queued:h}=Q(t),f=s.candidates.length,n=se(s.links,t);return c.useEffect(()=>{o&&j(!0)},[o]),e.jsxs("div",{className:`border-b border-black/10 last:border-b-0 ${o?"roadmap-item-highlighted outline outline-2 outline-offset-[-2px] outline-[rgba(200,154,90,0.5)]":""}`,children:[e.jsxs("button",{type:"button","aria-expanded":b,onClick:()=>j(p=>!p),className:"flex w-full items-center gap-3 py-2.5 px-0 bg-transparent border-none cursor-pointer text-left [font:inherit] text-inherit",children:[e.jsx("span",{className:`inline-flex items-center opacity-50 shrink-0 ${b?"rotate-90":""}`,children:e.jsx(Z,{})}),e.jsx("span",{className:"font-semibold flex-1 min-w-0 truncate",children:s.name}),e.jsx(ae,{done:s.rollup.done,total:s.rollup.total}),h>0&&e.jsxs(w,{size:"small",fillColor:N.planned.fill,textColor:N.planned.text,children:[h," in queue"]}),u>0&&e.jsxs(w,{size:"small",fillColor:N.done.fill,textColor:N.done.text,children:[u," shipped"]}),f>0&&e.jsxs(w,{size:"small",fillColor:"rgba(0, 0, 0, 0.06)",textColor:"rgba(0, 0, 0, 0.55)",children:[f," candidate",f===1?"":"s"]})]}),b&&e.jsxs("div",{className:"flex flex-col gap-1 pl-6 pb-4",children:[e.jsx("span",{className:"text-sm opacity-70",children:s.description}),n.map(p=>e.jsx(te,{idea:p,onOpen:p.planTitle?()=>i(p.planId,p.planTitle):void 0},p.key)),s.candidates.map(p=>e.jsx(Y,{name:p,onPromote:()=>a(p)},p)),e.jsx(ee,{onAdd:m}),e.jsx(y,{type:"button",variant:"ghost",size:"small",onClick:d,className:"self-start",children:"Promote to idea"})]})]})},le=({goal:s})=>{const[t,o]=c.useState(!1),[d,...a]=s.split(/\n{2,}/),m=a.length>0;return e.jsxs("div",{className:"mb-6 pb-4 border-b border-black/[8%]",children:[e.jsx("span",{className:"font-handwritten text-xs font-semibold opacity-[0.55]",children:"The goal"}),e.jsxs("div",{className:"text-sm leading-relaxed opacity-80 mt-2",children:[e.jsx(A,{children:d}),t&&m&&e.jsx(A,{children:a.join(`
1
+ import{u as g,m as L,r as c,C as O,j as e,H as P,x as T,J as y,I as M,K as B,a as D,F,P as S,L as U,N as $,M as A,g as k,S as N,O as q,R as _,Q as V,T as H,i as z,U as J,V as K,W as G,p as I}from"./main-DP_okYxh.js";import{X as xe}from"./main-DP_okYxh.js";const w="__no-subject__",W=({horizonTitle:s,item:t,candidateName:o,onClose:d,onPromoted:a})=>{const m=g(x=>x.promoteRoadmapItem),i=g(x=>x.launchIdeaExtend),{subjects:b,available:j}=L(),[u,h]=c.useState(w),[f,n]=c.useState(!1),[p,v]=c.useState(null),{toast:l}=O();c.useEffect(()=>{t&&(h(o?t.name:w),n(!1),v(null))},[t,o]);const r=async()=>{if(!(!t||!s)){n(!0),v(null);try{const x=await m(s,t,u===w?void 0:u,o??void 0),C=g.getState().ideaEntries.find(R=>R.id===x);if(C)try{await i(x,M(C,s))}catch(R){l({title:"Idea created, but the refine agent failed to launch",description:B(R.message),variant:"error"})}a(),d()}catch(x){v(x.message)}finally{n(!1)}}};return e.jsx(P,{open:t!==null,onClose:d,title:o??(t==null?void 0:t.name)??"",size:"small",children:e.jsxs("div",{className:"flex flex-col gap-4",children:[!o&&e.jsx("p",{className:"m-0 opacity-80",children:t==null?void 0:t.description}),e.jsx("div",{children:e.jsx(T,{size:"small",value:u,onChange:h,disabled:f||!j,options:[{value:w,label:"No subject"},...!j&&u!==w?[{value:u,label:u}]:[],...b.map(x=>({value:x,label:x}))]})}),p&&e.jsx("p",{className:"m-0 text-watercolor-rose-dark text-sm",children:p}),e.jsxs("div",{className:"flex justify-end gap-2",children:[e.jsx(y,{type:"button",variant:"ghost",onClick:d,disabled:f,children:"Cancel"}),e.jsx(y,{type:"button",variant:"primary",onClick:r,disabled:f,children:f?"Promoting…":"Promote to idea"})]})]})})},Q=s=>({shipped:s.filter(t=>t.status==="done").length,queued:s.filter(t=>t.status!=="done"&&t.status!=="dropped").length}),X="font-handwritten text-md font-semibold opacity-70 leading-none pt-2 px-1 pb-0",Z=({size:s=14})=>e.jsx("svg",{width:s,height:s,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:e.jsx("polyline",{points:"9 18 15 12 9 6"})}),Y=({name:s,onPromote:t})=>e.jsx(_,{size:"small",texture:"kraft",className:"plan-row-card",children:e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("span",{className:"flex-1",children:s}),e.jsx(y,{type:"button",variant:"ghost",size:"small",onClick:t,children:"Promote to idea"})]})}),ee=({onAdd:s})=>{const[t,o]=c.useState(""),[d,a]=c.useState(!1),m=async()=>{if(t.trim()){a(!0);try{await s(t.trim()),o("")}finally{a(!1)}}};return e.jsxs("div",{className:"flex gap-2",children:[e.jsx(z,{size:"small",value:t,onChange:i=>o(i.target.value),onKeyDown:i=>{i.key==="Enter"&&m()},placeholder:"Add option…",disabled:d,className:"flex-1"}),e.jsx(y,{type:"button",variant:"ghost",size:"small",onClick:m,disabled:d||!t.trim(),children:"Add"})]})},se=(s,t)=>{const o=new Set,d=t.map(a=>(a.id&&o.add(a.id),a.idea&&o.add(a.idea),{key:a.title,label:a.title,status:a.status,pr:a.pr,planId:a.id,planTitle:a.title}));for(const a of s)o.has(a.id)||d.push({key:a.id,label:a.id,status:a.status,pr:a.pr});return d},te=({idea:s,onOpen:t})=>e.jsx(_,{size:"small",texture:"kraft",className:"plan-row-card",children:e.jsxs("div",{className:"flex items-center gap-3",children:[t?e.jsx("button",{type:"button",onClick:t,className:"flex-1 min-w-0 overflow-hidden text-ellipsis whitespace-nowrap bg-transparent border-none p-0 cursor-pointer [font:inherit] text-inherit text-left",children:s.label}):e.jsx("span",{className:"flex-1 min-w-0 overflow-hidden text-ellipsis whitespace-nowrap",children:s.label}),s.pr&&e.jsx(V,{pr:s.pr}),e.jsx(k,{size:"small",fillColor:N[s.status].fill,textColor:N[s.status].text,children:H[s.status]})]})}),ae=({done:s,total:t})=>{const o=t>0?Math.round(s/t*100):0;return e.jsx("div",{className:"w-24 h-1.5 rounded-full bg-black/[0.08] overflow-hidden shrink-0",children:e.jsx("div",{className:`h-full rounded-full ${t>0?"bg-watercolor-green":"bg-transparent"}`,style:{width:`${o}%`}})})},ne=({item:s,graduated:t,highlighted:o,onPromote:d,onPromoteCandidate:a,onAddCandidate:m,onOpenGraduated:i})=>{const[b,j]=c.useState(o),{shipped:u,queued:h}=Q(t),f=s.candidates.length,n=se(s.links,t);return c.useEffect(()=>{o&&j(!0)},[o]),e.jsxs("div",{className:`border-b border-black/10 last:border-b-0 ${o?"roadmap-item-highlighted outline outline-2 outline-offset-[-2px] outline-[rgba(200,154,90,0.5)]":""}`,children:[e.jsxs("button",{type:"button","aria-expanded":b,onClick:()=>j(p=>!p),className:"flex w-full items-center gap-3 py-2.5 px-0 bg-transparent border-none cursor-pointer text-left [font:inherit] text-inherit",children:[e.jsx("span",{className:`inline-flex items-center opacity-50 shrink-0 ${b?"rotate-90":""}`,children:e.jsx(Z,{})}),e.jsx("span",{className:"font-semibold flex-1 min-w-0 truncate",children:s.name}),e.jsx(ae,{done:s.rollup.done,total:s.rollup.total}),h>0&&e.jsxs(k,{size:"small",fillColor:N.planned.fill,textColor:N.planned.text,children:[h," in queue"]}),u>0&&e.jsxs(k,{size:"small",fillColor:N.done.fill,textColor:N.done.text,children:[u," shipped"]}),f>0&&e.jsxs(k,{size:"small",fillColor:"rgba(0, 0, 0, 0.06)",textColor:"rgba(0, 0, 0, 0.55)",children:[f," candidate",f===1?"":"s"]})]}),b&&e.jsxs("div",{className:"flex flex-col gap-1 pl-6 pb-4",children:[e.jsx("span",{className:"text-sm opacity-70",children:s.description}),n.map(p=>e.jsx(te,{idea:p,onOpen:p.planTitle?()=>i(p.planId,p.planTitle):void 0},p.key)),s.candidates.map(p=>e.jsx(Y,{name:p,onPromote:()=>a(p)},p)),e.jsx(ee,{onAdd:m}),e.jsx(y,{type:"button",variant:"ghost",size:"small",onClick:d,className:"self-start",children:"Promote to idea"})]})]})},le=({goal:s})=>{const[t,o]=c.useState(!1),[d,...a]=s.split(/\n{2,}/),m=a.length>0;return e.jsxs("div",{className:"mb-6 pb-4 border-b border-black/[8%]",children:[e.jsx("span",{className:"font-handwritten text-xs font-semibold opacity-[0.55]",children:"The goal"}),e.jsxs("div",{className:"text-sm leading-relaxed opacity-80 mt-2",children:[e.jsx(A,{children:d}),t&&m&&e.jsx(A,{children:a.join(`
2
2
 
3
- `)})]}),m&&e.jsx("button",{type:"button",onClick:()=>o(i=>!i),className:"bg-transparent border-none p-0 mt-2 cursor-pointer text-2xs opacity-[0.65] underline",children:t?"Show less":"Show more"})]})},de=()=>{const s=g(l=>l.roadmap),t=g(l=>l.roadmapError),o=g(l=>l.loadRoadmap),d=g(l=>l.roadmapFilters),[a,m]=c.useState(null),i=g(l=>l.plans),b=D(),{item:j}=F({from:"/roadmap"}),u=c.useRef(null);if(c.useEffect(()=>{o()},[o]),c.useEffect(()=>{var r;if(!j||!s)return;const l=(r=u.current)==null?void 0:r.querySelector(".roadmap-item-highlighted");l==null||l.scrollIntoView({behavior:"smooth",block:"center"})},[j,s]),t)return e.jsxs("div",{children:[e.jsx(k,{children:"Roadmap"}),e.jsx("p",{className:"opacity-50",children:"Couldn't load the roadmap — the server may need a restart to pick up new routes."})]});if(!s)return e.jsxs("div",{children:[e.jsx(k,{children:"Roadmap"}),e.jsx("p",{className:"opacity-50",children:"Loading…"})]});if(s.horizons.length===0)return e.jsxs("div",{children:[e.jsx(k,{children:"Roadmap"}),e.jsx("p",{className:"opacity-50",children:"No `ROADMAP.md` found at the project root."})]});const h=l=>(i==null?void 0:i.entries.filter(r=>r.subject===l.name))??[],f=async(l,r,x)=>{await q(l,r,x),await o()},n=U(s,d),p=n.reduce((l,r)=>l+r.items.length,0),v=d.horizons.length>0||d.statuses.length>0;return e.jsxs("div",{ref:u,children:[e.jsx(k,{children:"Roadmap"}),e.jsx(le,{goal:s.goal}),p===0?e.jsx("p",{className:"opacity-50 py-6 px-0 text-center",children:v?"Nothing matches these filters — clear one from the sidebar to see more.":"No roadmap items yet — add one from the sidebar."}):e.jsx("div",{className:"flex flex-col gap-6",children:n.filter(l=>l.items.length>0).map(l=>e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx("div",{className:X,children:l.title}),e.jsx("div",{className:"flex flex-col",children:l.items.map(r=>e.jsx(ne,{item:r,graduated:h(r),highlighted:r.name===j,onPromote:()=>m({horizonTitle:l.title,item:r}),onPromoteCandidate:x=>m({horizonTitle:l.title,item:r,candidateName:x}),onAddCandidate:x=>f(l.title,r.name,x),onOpenGraduated:(x,S)=>b({to:"/plans/$planId",params:{planId:$(x,S)}})},r.name))})]},l.title))}),e.jsx(W,{horizonTitle:(a==null?void 0:a.horizonTitle)??null,item:(a==null?void 0:a.item)??null,candidateName:a==null?void 0:a.candidateName,onClose:()=>m(null),onPromoted:o})]})},oe=({open:s,horizonTitles:t,onClose:o})=>{const d=g(r=>r.loadRoadmap),[a,m]=c.useState(t[0]??""),[i,b]=c.useState(""),[j,u]=c.useState(""),[h,f]=c.useState(!1),[n,p]=c.useState(null),v=c.useRef(t);v.current=t,c.useEffect(()=>{s&&(m(v.current[0]??""),b(""),u(""),p(null),f(!1))},[s]);const l=async()=>{if(!(!i.trim()||!a)){f(!0),p(null);try{await J(a,i.trim(),j.trim()),await d(),o()}catch(r){p(r.message)}finally{f(!1)}}};return e.jsx(P,{open:s,onClose:o,title:"Add roadmap item",size:"small",children:e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsx(T,{size:"small",value:a,onChange:m,disabled:h,options:t.map(r=>({value:r,label:r}))}),e.jsx(z,{size:"small",value:i,onChange:r=>b(r.target.value),placeholder:"Item name…",disabled:h,autoFocus:!0}),e.jsx(z,{size:"small",value:j,onChange:r=>u(r.target.value),onKeyDown:r=>{r.key==="Enter"&&l()},placeholder:"Description…",disabled:h}),n&&e.jsx("p",{className:"m-0 text-watercolor-rose-dark text-sm",children:n}),e.jsxs("div",{className:"flex justify-end gap-2",children:[e.jsx(y,{type:"button",variant:"ghost",onClick:o,disabled:h,children:"Cancel"}),e.jsx(y,{type:"button",variant:"primary",onClick:l,disabled:h||!i.trim()||!a,children:h?"Adding…":"Add item"})]})]})})},re=["in-progress","review","planned","idea","done","dropped"],E="text-2xs font-semibold tracking-[0.08em] uppercase text-ink-300 mb-2",ce=()=>{const s=g(n=>n.roadmap),t=g(n=>n.roadmapFilters),o=g(n=>n.toggleRoadmapHorizon),d=g(n=>n.toggleRoadmapStatus),[a,m]=c.useState(!1);if(!s)return null;const i=s.horizons.map(n=>n.title),b=K(s,t),j=G(s,t),u=new Set(t.horizons),h=new Set(t.statuses),f=re.filter(n=>(j[n]??0)>0||h.has(n));return e.jsxs("div",{className:"flex flex-col gap-8 -mt-5",children:[e.jsx(y,{type:"button",variant:"primary",size:"small",onClick:()=>m(!0),disabled:i.length===0,children:"+ Add item"}),e.jsxs("div",{children:[e.jsx("div",{className:E,children:"Horizon"}),e.jsx("div",{className:"flex flex-col gap-1",children:i.map(n=>e.jsx(I,{size:"small",active:u.has(n),onClick:()=>o(n),className:"text-xs leading-4 py-2",action:e.jsx("span",{className:"text-2xs text-ink-500",children:b[n]??0}),children:n},n))})]}),e.jsxs("div",{children:[e.jsx("div",{className:E,children:"Status"}),e.jsxs("div",{className:"flex flex-col gap-1",children:[f.length===0&&e.jsx("span",{className:"opacity-50 text-2xs",children:"No linked ideas"}),f.map(n=>e.jsx(I,{size:"small",active:h.has(n),onClick:()=>d(n),className:"text-xs leading-4 py-2",icon:e.jsx("span",{className:"w-[9px] h-[9px] rounded-full shrink-0",style:{background:N[n].text}}),action:e.jsx("span",{className:"text-2xs text-ink-500",children:j[n]??0}),children:H[n]},n))]})]}),e.jsx(oe,{open:a,horizonTitles:i,onClose:()=>m(!1)})]})};export{de as RoadmapPage,ce as RoadmapSidebar,xe as useRoadmapItemNames};
4
- //# sourceMappingURL=index-D2iIIpI1.js.map
3
+ `)})]}),m&&e.jsx("button",{type:"button",onClick:()=>o(i=>!i),className:"bg-transparent border-none p-0 mt-2 cursor-pointer text-2xs opacity-[0.65] underline",children:t?"Show less":"Show more"})]})},de=()=>{const s=g(l=>l.roadmap),t=g(l=>l.roadmapError),o=g(l=>l.loadRoadmap),d=g(l=>l.roadmapFilters),[a,m]=c.useState(null),i=g(l=>l.plans),b=D(),{item:j}=F({from:"/roadmap"}),u=c.useRef(null);if(c.useEffect(()=>{o()},[o]),c.useEffect(()=>{var r;if(!j||!s)return;const l=(r=u.current)==null?void 0:r.querySelector(".roadmap-item-highlighted");l==null||l.scrollIntoView({behavior:"smooth",block:"center"})},[j,s]),t)return e.jsxs("div",{children:[e.jsx(S,{children:"Roadmap"}),e.jsx("p",{className:"opacity-50",children:"Couldn't load the roadmap — the server may need a restart to pick up new routes."})]});if(!s)return e.jsxs("div",{children:[e.jsx(S,{children:"Roadmap"}),e.jsx("p",{className:"opacity-50",children:"Loading…"})]});if(s.horizons.length===0)return e.jsxs("div",{children:[e.jsx(S,{children:"Roadmap"}),e.jsx("p",{className:"opacity-50",children:"No `ROADMAP.md` found at the project root."})]});const h=l=>(i==null?void 0:i.entries.filter(r=>r.subject===l.name))??[],f=async(l,r,x)=>{await q(l,r,x),await o()},n=U(s,d),p=n.reduce((l,r)=>l+r.items.length,0),v=d.horizons.length>0||d.statuses.length>0;return e.jsxs("div",{ref:u,children:[e.jsx(S,{children:"Roadmap"}),e.jsx(le,{goal:s.goal}),p===0?e.jsx("p",{className:"opacity-50 py-6 px-0 text-center",children:v?"Nothing matches these filters — clear one from the sidebar to see more.":"No roadmap items yet — add one from the sidebar."}):e.jsx("div",{className:"flex flex-col gap-6",children:n.filter(l=>l.items.length>0).map(l=>e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx("div",{className:X,children:l.title}),e.jsx("div",{className:"flex flex-col",children:l.items.map(r=>e.jsx(ne,{item:r,graduated:h(r),highlighted:r.name===j,onPromote:()=>m({horizonTitle:l.title,item:r}),onPromoteCandidate:x=>m({horizonTitle:l.title,item:r,candidateName:x}),onAddCandidate:x=>f(l.title,r.name,x),onOpenGraduated:(x,C)=>b({to:"/plans/$planId",params:{planId:$(x,C)}})},r.name))})]},l.title))}),e.jsx(W,{horizonTitle:(a==null?void 0:a.horizonTitle)??null,item:(a==null?void 0:a.item)??null,candidateName:a==null?void 0:a.candidateName,onClose:()=>m(null),onPromoted:o})]})},oe=({open:s,horizonTitles:t,onClose:o})=>{const d=g(r=>r.loadRoadmap),[a,m]=c.useState(t[0]??""),[i,b]=c.useState(""),[j,u]=c.useState(""),[h,f]=c.useState(!1),[n,p]=c.useState(null),v=c.useRef(t);v.current=t,c.useEffect(()=>{s&&(m(v.current[0]??""),b(""),u(""),p(null),f(!1))},[s]);const l=async()=>{if(!(!i.trim()||!a)){f(!0),p(null);try{await J(a,i.trim(),j.trim()),await d(),o()}catch(r){p(r.message)}finally{f(!1)}}};return e.jsx(P,{open:s,onClose:o,title:"Add roadmap item",size:"small",children:e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsx(T,{size:"small",value:a,onChange:m,disabled:h,options:t.map(r=>({value:r,label:r}))}),e.jsx(z,{size:"small",value:i,onChange:r=>b(r.target.value),placeholder:"Item name…",disabled:h,autoFocus:!0}),e.jsx(z,{size:"small",value:j,onChange:r=>u(r.target.value),onKeyDown:r=>{r.key==="Enter"&&l()},placeholder:"Description…",disabled:h}),n&&e.jsx("p",{className:"m-0 text-watercolor-rose-dark text-sm",children:n}),e.jsxs("div",{className:"flex justify-end gap-2",children:[e.jsx(y,{type:"button",variant:"ghost",onClick:o,disabled:h,children:"Cancel"}),e.jsx(y,{type:"button",variant:"primary",onClick:l,disabled:h||!i.trim()||!a,children:h?"Adding…":"Add item"})]})]})})},re=["in-progress","review","planned","idea","done","dropped"],E="pc-row-label font-handwritten text-xs font-semibold opacity-[0.45]",ce=()=>{const s=g(n=>n.roadmap),t=g(n=>n.roadmapFilters),o=g(n=>n.toggleRoadmapHorizon),d=g(n=>n.toggleRoadmapStatus),[a,m]=c.useState(!1);if(!s)return null;const i=s.horizons.map(n=>n.title),b=K(s,t),j=G(s,t),u=new Set(t.horizons),h=new Set(t.statuses),f=re.filter(n=>(j[n]??0)>0||h.has(n));return e.jsxs("div",{className:"flex flex-col",children:[e.jsx("div",{className:"flex h-[64px] items-center",children:e.jsx(y,{type:"button",variant:"primary",size:"small",onClick:()=>m(!0),disabled:i.length===0,children:"+ Add item"})}),e.jsxs("div",{children:[e.jsx("div",{className:E,children:"Horizon"}),e.jsx("div",{className:"flex flex-col",children:i.map(n=>e.jsx(I,{size:"small",active:u.has(n),onClick:()=>o(n),className:"pc-row text-xs",action:e.jsx("span",{className:"text-2xs text-ink-500",children:b[n]??0}),children:n},n))})]}),e.jsxs("div",{children:[e.jsx("div",{className:E,children:"Status"}),e.jsxs("div",{className:"flex flex-col",children:[f.length===0&&e.jsx("span",{className:"opacity-50 text-2xs",children:"No linked ideas"}),f.map(n=>e.jsx(I,{size:"small",active:h.has(n),onClick:()=>d(n),className:"pc-row text-xs",icon:e.jsx("span",{className:"w-[9px] h-[9px] rounded-full shrink-0",style:{background:N[n].text}}),action:e.jsx("span",{className:"text-2xs text-ink-500",children:j[n]??0}),children:H[n]},n))]})]}),e.jsx(oe,{open:a,horizonTitles:i,onClose:()=>m(!1)})]})};export{de as RoadmapPage,ce as RoadmapSidebar,xe as useRoadmapItemNames};
4
+ //# sourceMappingURL=index-Gi97Lmex.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index-D2iIIpI1.js","sources":["../../../src/app/features/roadmap/promote-roadmap-item-modal.tsx","../../../src/app/features/roadmap/roadmap-page.tsx","../../../src/app/features/roadmap/add-roadmap-item-modal.tsx","../../../src/app/features/roadmap/roadmap-sidebar.tsx"],"sourcesContent":["import { buildRoadmapPromotePrompt } from '@/app/features/plans/prompts';\nimport { useSubjectVocabulary } from '@/app/hooks/use-subject-vocabulary';\nimport { useAppStore } from '@/app/stores/app-store';\nimport { oneLineErrorSummary } from '@/app/utils/error-summary';\nimport type { RoadmapItem } from '@/types/index';\nimport { Button, Modal, Select, useToast } from '@dendelion/paper-ui';\nimport { useEffect, useState } from 'react';\n\nconst NO_SUBJECT = '__no-subject__';\n\ninterface PromoteRoadmapItemModalProps {\n horizonTitle: string | null;\n item: RoadmapItem | null;\n candidateName?: string | null;\n onClose: () => void;\n onPromoted: () => void;\n}\n\nexport const PromoteRoadmapItemModal = ({\n horizonTitle,\n item,\n candidateName,\n onClose,\n onPromoted,\n}: PromoteRoadmapItemModalProps) => {\n const promoteRoadmapItem = useAppStore((s) => s.promoteRoadmapItem);\n const launchIdeaExtend = useAppStore((s) => s.launchIdeaExtend);\n const { subjects, available: subjectsAvailable } = useSubjectVocabulary();\n const [subject, setSubject] = useState(NO_SUBJECT);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const { toast } = useToast();\n\n useEffect(() => {\n if (item) {\n // A candidate defaults to its parent item's name — the \"big bet becomes a\n // Subject\" rule — but the picker still lets the user override it.\n setSubject(candidateName ? item.name : NO_SUBJECT);\n setLoading(false);\n setError(null);\n }\n }, [item, candidateName]);\n\n const handlePromote = async () => {\n if (!item || !horizonTitle) return;\n setLoading(true);\n setError(null);\n try {\n const id = await promoteRoadmapItem(\n horizonTitle,\n item,\n subject === NO_SUBJECT ? undefined : subject,\n candidateName ?? undefined,\n );\n const idea = useAppStore.getState().ideaEntries.find((e) => e.id === id);\n if (idea) {\n try {\n await launchIdeaExtend(id, buildRoadmapPromotePrompt(idea, horizonTitle));\n } catch (err) {\n // The idea was created either way — a failed refine launch just means\n // no background research ran, not that the promotion itself failed.\n toast({\n title: 'Idea created, but the refine agent failed to launch',\n description: oneLineErrorSummary((err as Error).message),\n variant: 'error',\n });\n }\n }\n onPromoted();\n onClose();\n } catch (err) {\n setError((err as Error).message);\n } finally {\n setLoading(false);\n }\n };\n\n return (\n <Modal\n open={item !== null}\n onClose={onClose}\n title={candidateName ?? item?.name ?? ''}\n size=\"small\"\n >\n <div className=\"flex flex-col gap-4\">\n {!candidateName && <p className=\"m-0 opacity-80\">{item?.description}</p>}\n <div>\n <Select\n size=\"small\"\n value={subject}\n onChange={setSubject}\n disabled={loading || !subjectsAvailable}\n options={[\n { value: NO_SUBJECT, label: 'No subject' },\n ...(!subjectsAvailable && subject !== NO_SUBJECT\n ? [{ value: subject, label: subject }]\n : []),\n ...subjects.map((s) => ({ value: s, label: s })),\n ]}\n />\n </div>\n {error && <p className=\"m-0 text-watercolor-rose-dark text-sm\">{error}</p>}\n <div className=\"flex justify-end gap-2\">\n <Button type=\"button\" variant=\"ghost\" onClick={onClose} disabled={loading}>\n Cancel\n </Button>\n <Button type=\"button\" variant=\"primary\" onClick={handlePromote} disabled={loading}>\n {loading ? 'Promoting…' : 'Promote to idea'}\n </Button>\n </div>\n </div>\n </Modal>\n );\n};\n","import { Markdown } from '@/app/components/markdown';\nimport { PageTitle } from '@/app/components/page-title';\nimport { PrBadge } from '@/app/features/plans/components/pr-badge';\nimport { STATUS_LABEL, STATUS_STAMP } from '@/app/features/plans/constants';\nimport { entityRouteParam } from '@/app/hooks';\nimport { addRoadmapCandidate } from '@/app/services/content/docs-api';\nimport { useAppStore } from '@/app/stores/app-store';\nimport type {\n PlanEntry,\n PlanStatus,\n PrInfo,\n ResolvedRoadmapItem,\n RoadmapLink,\n} from '@/types/index';\nimport { Button, Card, Input, Stamp } from '@dendelion/paper-ui';\nimport { useNavigate, useSearch } from '@tanstack/react-router';\nimport { useEffect, useRef, useState } from 'react';\nimport { PromoteRoadmapItemModal } from './promote-roadmap-item-modal';\nimport { filterHorizons } from './roadmap-filters';\n\nconst graduationCounts = (graduated: PlanEntry[]) => ({\n shipped: graduated.filter((p) => p.status === 'done').length,\n queued: graduated.filter((p) => p.status !== 'done' && p.status !== 'dropped').length,\n});\n\nconst HORIZON_HEADER_CLASSES =\n 'font-handwritten text-md font-semibold opacity-70 leading-none pt-2 px-1 pb-0';\n\nconst ChevronRightIcon = ({ size = 14 }: { size?: number }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"9 18 15 12 9 6\" />\n </svg>\n);\n\nconst CandidateRow = ({\n name,\n onPromote,\n}: {\n name: string;\n onPromote: () => void;\n}) => (\n <Card size=\"small\" texture=\"kraft\" className=\"plan-row-card\">\n <div className=\"flex items-center gap-3\">\n <span className=\"flex-1\">{name}</span>\n <Button type=\"button\" variant=\"ghost\" size=\"small\" onClick={onPromote}>\n Promote to idea\n </Button>\n </div>\n </Card>\n);\n\nconst AddCandidateForm = ({ onAdd }: { onAdd: (name: string) => Promise<void> }) => {\n const [name, setName] = useState('');\n const [saving, setSaving] = useState(false);\n\n const handleAdd = async () => {\n if (!name.trim()) return;\n setSaving(true);\n try {\n await onAdd(name.trim());\n setName('');\n } finally {\n setSaving(false);\n }\n };\n\n return (\n <div className=\"flex gap-2\">\n <Input\n size=\"small\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') handleAdd();\n }}\n placeholder=\"Add option…\"\n disabled={saving}\n className=\"flex-1\"\n />\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"small\"\n onClick={handleAdd}\n disabled={saving || !name.trim()}\n >\n Add\n </Button>\n </div>\n );\n};\n\ninterface MergedIdea {\n key: string;\n label: string;\n status: PlanStatus;\n pr?: PrInfo;\n planId?: string;\n planTitle?: string;\n}\n\nconst mergeIdeas = (links: RoadmapLink[], graduated: PlanEntry[]): MergedIdea[] => {\n const represented = new Set<string>();\n const merged: MergedIdea[] = graduated.map((plan) => {\n if (plan.id) represented.add(plan.id);\n if (plan.idea) represented.add(plan.idea);\n return {\n key: plan.title,\n label: plan.title,\n status: plan.status,\n pr: plan.pr,\n planId: plan.id,\n planTitle: plan.title,\n };\n });\n for (const link of links) {\n if (represented.has(link.id)) continue;\n merged.push({ key: link.id, label: link.id, status: link.status, pr: link.pr });\n }\n return merged;\n};\n\nconst IdeaRow = ({ idea, onOpen }: { idea: MergedIdea; onOpen?: () => void }) => (\n <Card size=\"small\" texture=\"kraft\" className=\"plan-row-card\">\n <div className=\"flex items-center gap-3\">\n {onOpen ? (\n <button\n type=\"button\"\n onClick={onOpen}\n className=\"flex-1 min-w-0 overflow-hidden text-ellipsis whitespace-nowrap bg-transparent border-none p-0 cursor-pointer [font:inherit] text-inherit text-left\"\n >\n {idea.label}\n </button>\n ) : (\n <span className=\"flex-1 min-w-0 overflow-hidden text-ellipsis whitespace-nowrap\">\n {idea.label}\n </span>\n )}\n {idea.pr && <PrBadge pr={idea.pr} />}\n <Stamp\n size=\"small\"\n fillColor={STATUS_STAMP[idea.status].fill}\n textColor={STATUS_STAMP[idea.status].text}\n >\n {STATUS_LABEL[idea.status]}\n </Stamp>\n </div>\n </Card>\n);\n\nconst ProgressBar = ({ done, total }: { done: number; total: number }) => {\n const percent = total > 0 ? Math.round((done / total) * 100) : 0;\n return (\n <div className=\"w-24 h-1.5 rounded-full bg-black/[0.08] overflow-hidden shrink-0\">\n <div\n className={`h-full rounded-full ${total > 0 ? 'bg-watercolor-green' : 'bg-transparent'}`}\n style={{ width: `${percent}%` }}\n />\n </div>\n );\n};\n\nconst RoadmapItemRow = ({\n item,\n graduated,\n highlighted,\n onPromote,\n onPromoteCandidate,\n onAddCandidate,\n onOpenGraduated,\n}: {\n item: ResolvedRoadmapItem;\n graduated: PlanEntry[];\n highlighted: boolean;\n onPromote: () => void;\n onPromoteCandidate: (candidateName: string) => void;\n onAddCandidate: (name: string) => Promise<void>;\n onOpenGraduated: (id: string | undefined, title: string) => void;\n}) => {\n const [expanded, setExpanded] = useState(highlighted);\n const { shipped, queued } = graduationCounts(graduated);\n const candidates = item.candidates.length;\n const ideas = mergeIdeas(item.links, graduated);\n\n useEffect(() => {\n if (highlighted) setExpanded(true);\n }, [highlighted]);\n\n return (\n <div\n className={`border-b border-black/10 last:border-b-0 ${highlighted ? 'roadmap-item-highlighted outline outline-2 outline-offset-[-2px] outline-[rgba(200,154,90,0.5)]' : ''}`}\n >\n <button\n type=\"button\"\n aria-expanded={expanded}\n onClick={() => setExpanded((v) => !v)}\n className=\"flex w-full items-center gap-3 py-2.5 px-0 bg-transparent border-none cursor-pointer text-left [font:inherit] text-inherit\"\n >\n <span\n className={`inline-flex items-center opacity-50 shrink-0 ${expanded ? 'rotate-90' : ''}`}\n >\n <ChevronRightIcon />\n </span>\n <span className=\"font-semibold flex-1 min-w-0 truncate\">{item.name}</span>\n <ProgressBar done={item.rollup.done} total={item.rollup.total} />\n {queued > 0 && (\n <Stamp\n size=\"small\"\n fillColor={STATUS_STAMP.planned.fill}\n textColor={STATUS_STAMP.planned.text}\n >\n {queued} in queue\n </Stamp>\n )}\n {shipped > 0 && (\n <Stamp size=\"small\" fillColor={STATUS_STAMP.done.fill} textColor={STATUS_STAMP.done.text}>\n {shipped} shipped\n </Stamp>\n )}\n {candidates > 0 && (\n <Stamp size=\"small\" fillColor=\"rgba(0, 0, 0, 0.06)\" textColor=\"rgba(0, 0, 0, 0.55)\">\n {candidates} candidate{candidates === 1 ? '' : 's'}\n </Stamp>\n )}\n </button>\n {expanded && (\n <div className=\"flex flex-col gap-1 pl-6 pb-4\">\n <span className=\"text-sm opacity-70\">{item.description}</span>\n {ideas.map((idea) => (\n <IdeaRow\n key={idea.key}\n idea={idea}\n onOpen={\n idea.planTitle\n ? () => onOpenGraduated(idea.planId, idea.planTitle as string)\n : undefined\n }\n />\n ))}\n {item.candidates.map((candidateName) => (\n <CandidateRow\n key={candidateName}\n name={candidateName}\n onPromote={() => onPromoteCandidate(candidateName)}\n />\n ))}\n <AddCandidateForm onAdd={onAddCandidate} />\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"small\"\n onClick={onPromote}\n className=\"self-start\"\n >\n Promote to idea\n </Button>\n </div>\n )}\n </div>\n );\n};\n\nconst GoalBanner = ({ goal }: { goal: string }) => {\n const [expanded, setExpanded] = useState(false);\n const [firstParagraph, ...restParagraphs] = goal.split(/\\n{2,}/);\n const hasMore = restParagraphs.length > 0;\n\n return (\n <div className=\"mb-6 pb-4 border-b border-black/[8%]\">\n <span className=\"font-handwritten text-xs font-semibold opacity-[0.55]\">The goal</span>\n <div className=\"text-sm leading-relaxed opacity-80 mt-2\">\n <Markdown>{firstParagraph}</Markdown>\n {expanded && hasMore && <Markdown>{restParagraphs.join('\\n\\n')}</Markdown>}\n </div>\n {hasMore && (\n <button\n type=\"button\"\n onClick={() => setExpanded((v) => !v)}\n className=\"bg-transparent border-none p-0 mt-2 cursor-pointer text-2xs opacity-[0.65] underline\"\n >\n {expanded ? 'Show less' : 'Show more'}\n </button>\n )}\n </div>\n );\n};\n\nexport const RoadmapPage = () => {\n const roadmap = useAppStore((s) => s.roadmap);\n const roadmapError = useAppStore((s) => s.roadmapError);\n const loadRoadmap = useAppStore((s) => s.loadRoadmap);\n const filters = useAppStore((s) => s.roadmapFilters);\n const [promoting, setPromoting] = useState<{\n horizonTitle: string;\n item: ResolvedRoadmapItem;\n candidateName?: string;\n } | null>(null);\n const plans = useAppStore((s) => s.plans);\n const navigate = useNavigate();\n const { item: highlightedItem } = useSearch({ from: '/roadmap' });\n const containerRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n loadRoadmap();\n }, [loadRoadmap]);\n\n useEffect(() => {\n if (!highlightedItem || !roadmap) return;\n const row = containerRef.current?.querySelector('.roadmap-item-highlighted');\n row?.scrollIntoView({ behavior: 'smooth', block: 'center' });\n }, [highlightedItem, roadmap]);\n\n if (roadmapError) {\n return (\n <div>\n <PageTitle>Roadmap</PageTitle>\n <p className=\"opacity-50\">\n Couldn't load the roadmap — the server may need a restart to pick up new routes.\n </p>\n </div>\n );\n }\n\n if (!roadmap) {\n return (\n <div>\n <PageTitle>Roadmap</PageTitle>\n <p className=\"opacity-50\">Loading…</p>\n </div>\n );\n }\n\n if (roadmap.horizons.length === 0) {\n return (\n <div>\n <PageTitle>Roadmap</PageTitle>\n <p className=\"opacity-50\">No `ROADMAP.md` found at the project root.</p>\n </div>\n );\n }\n\n const graduatedByItem = (item: ResolvedRoadmapItem) =>\n plans?.entries.filter((p) => p.subject === item.name) ?? [];\n\n const handleAddCandidate = async (horizonTitle: string, itemName: string, name: string) => {\n await addRoadmapCandidate(horizonTitle, itemName, name);\n await loadRoadmap();\n };\n\n const horizons = filterHorizons(roadmap, filters);\n const totalVisible = horizons.reduce((count, horizon) => count + horizon.items.length, 0);\n const hasActiveFilters = filters.horizons.length > 0 || filters.statuses.length > 0;\n\n return (\n <div ref={containerRef}>\n <PageTitle>Roadmap</PageTitle>\n <GoalBanner goal={roadmap.goal} />\n {totalVisible === 0 ? (\n <p className=\"opacity-50 py-6 px-0 text-center\">\n {hasActiveFilters\n ? 'Nothing matches these filters — clear one from the sidebar to see more.'\n : 'No roadmap items yet — add one from the sidebar.'}\n </p>\n ) : (\n <div className=\"flex flex-col gap-6\">\n {horizons\n .filter((horizon) => horizon.items.length > 0)\n .map((horizon) => (\n <div key={horizon.title} className=\"flex flex-col gap-1\">\n <div className={HORIZON_HEADER_CLASSES}>{horizon.title}</div>\n <div className=\"flex flex-col\">\n {horizon.items.map((item) => (\n <RoadmapItemRow\n key={item.name}\n item={item}\n graduated={graduatedByItem(item)}\n highlighted={item.name === highlightedItem}\n onPromote={() => setPromoting({ horizonTitle: horizon.title, item })}\n onPromoteCandidate={(candidateName) =>\n setPromoting({ horizonTitle: horizon.title, item, candidateName })\n }\n onAddCandidate={(name) => handleAddCandidate(horizon.title, item.name, name)}\n onOpenGraduated={(id, title) =>\n navigate({\n to: '/plans/$planId',\n params: { planId: entityRouteParam(id, title) },\n })\n }\n />\n ))}\n </div>\n </div>\n ))}\n </div>\n )}\n <PromoteRoadmapItemModal\n horizonTitle={promoting?.horizonTitle ?? null}\n item={promoting?.item ?? null}\n candidateName={promoting?.candidateName}\n onClose={() => setPromoting(null)}\n onPromoted={loadRoadmap}\n />\n </div>\n );\n};\n","import { addRoadmapItem } from '@/app/services/content/docs-api';\nimport { useAppStore } from '@/app/stores/app-store';\nimport { Button, Input, Modal, Select } from '@dendelion/paper-ui';\nimport { useEffect, useRef, useState } from 'react';\n\ninterface AddRoadmapItemModalProps {\n open: boolean;\n horizonTitles: string[];\n onClose: () => void;\n}\n\nexport const AddRoadmapItemModal = ({ open, horizonTitles, onClose }: AddRoadmapItemModalProps) => {\n const loadRoadmap = useAppStore((s) => s.loadRoadmap);\n const [horizon, setHorizon] = useState(horizonTitles[0] ?? '');\n const [name, setName] = useState('');\n const [description, setDescription] = useState('');\n const [saving, setSaving] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const horizonTitlesRef = useRef(horizonTitles);\n horizonTitlesRef.current = horizonTitles;\n\n useEffect(() => {\n if (open) {\n setHorizon(horizonTitlesRef.current[0] ?? '');\n setName('');\n setDescription('');\n setError(null);\n setSaving(false);\n }\n }, [open]);\n\n const handleAdd = async () => {\n if (!name.trim() || !horizon) return;\n setSaving(true);\n setError(null);\n try {\n await addRoadmapItem(horizon, name.trim(), description.trim());\n await loadRoadmap();\n onClose();\n } catch (err) {\n setError((err as Error).message);\n } finally {\n setSaving(false);\n }\n };\n\n return (\n <Modal open={open} onClose={onClose} title=\"Add roadmap item\" size=\"small\">\n <div className=\"flex flex-col gap-4\">\n <Select\n size=\"small\"\n value={horizon}\n onChange={setHorizon}\n disabled={saving}\n options={horizonTitles.map((title) => ({ value: title, label: title }))}\n />\n <Input\n size=\"small\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n placeholder=\"Item name…\"\n disabled={saving}\n autoFocus\n />\n <Input\n size=\"small\"\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') handleAdd();\n }}\n placeholder=\"Description…\"\n disabled={saving}\n />\n {error && <p className=\"m-0 text-watercolor-rose-dark text-sm\">{error}</p>}\n <div className=\"flex justify-end gap-2\">\n <Button type=\"button\" variant=\"ghost\" onClick={onClose} disabled={saving}>\n Cancel\n </Button>\n <Button\n type=\"button\"\n variant=\"primary\"\n onClick={handleAdd}\n disabled={saving || !name.trim() || !horizon}\n >\n {saving ? 'Adding…' : 'Add item'}\n </Button>\n </div>\n </div>\n </Modal>\n );\n};\n","import { STATUS_LABEL, STATUS_STAMP } from '@/app/features/plans/constants';\nimport { useAppStore } from '@/app/stores/app-store';\nimport type { PlanStatus } from '@/types/index';\nimport { Button, ListItem } from '@dendelion/paper-ui';\nimport { useState } from 'react';\nimport { AddRoadmapItemModal } from './add-roadmap-item-modal';\nimport { horizonItemCounts, statusItemCounts } from './roadmap-filters';\n\nconst STATUS_CHIP_ORDER: PlanStatus[] = [\n 'in-progress',\n 'review',\n 'planned',\n 'idea',\n 'done',\n 'dropped',\n];\n\nconst sectionLabelClass = 'text-2xs font-semibold tracking-[0.08em] uppercase text-ink-300 mb-2';\n\nexport const RoadmapSidebar = () => {\n const roadmap = useAppStore((s) => s.roadmap);\n const filters = useAppStore((s) => s.roadmapFilters);\n const toggleRoadmapHorizon = useAppStore((s) => s.toggleRoadmapHorizon);\n const toggleRoadmapStatus = useAppStore((s) => s.toggleRoadmapStatus);\n const [addOpen, setAddOpen] = useState(false);\n\n if (!roadmap) return null;\n\n const horizonTitles = roadmap.horizons.map((horizon) => horizon.title);\n const horizonCounts = horizonItemCounts(roadmap, filters);\n const statusCounts = statusItemCounts(roadmap, filters);\n const activeHorizons = new Set(filters.horizons);\n const activeStatuses = new Set(filters.statuses);\n const visibleStatuses = STATUS_CHIP_ORDER.filter(\n (status) => (statusCounts[status] ?? 0) > 0 || activeStatuses.has(status),\n );\n\n return (\n <div className=\"flex flex-col gap-8 -mt-5\">\n <Button\n type=\"button\"\n variant=\"primary\"\n size=\"small\"\n onClick={() => setAddOpen(true)}\n disabled={horizonTitles.length === 0}\n >\n + Add item\n </Button>\n\n <div>\n <div className={sectionLabelClass}>Horizon</div>\n <div className=\"flex flex-col gap-1\">\n {horizonTitles.map((title) => (\n <ListItem\n key={title}\n size=\"small\"\n active={activeHorizons.has(title)}\n onClick={() => toggleRoadmapHorizon(title)}\n className=\"text-xs leading-4 py-2\"\n action={<span className=\"text-2xs text-ink-500\">{horizonCounts[title] ?? 0}</span>}\n >\n {title}\n </ListItem>\n ))}\n </div>\n </div>\n\n <div>\n <div className={sectionLabelClass}>Status</div>\n <div className=\"flex flex-col gap-1\">\n {visibleStatuses.length === 0 && (\n <span className=\"opacity-50 text-2xs\">No linked ideas</span>\n )}\n {visibleStatuses.map((status) => (\n <ListItem\n key={status}\n size=\"small\"\n active={activeStatuses.has(status)}\n onClick={() => toggleRoadmapStatus(status)}\n className=\"text-xs leading-4 py-2\"\n icon={\n <span\n className=\"w-[9px] h-[9px] rounded-full shrink-0\"\n style={{ background: STATUS_STAMP[status].text }}\n />\n }\n action={<span className=\"text-2xs text-ink-500\">{statusCounts[status] ?? 0}</span>}\n >\n {STATUS_LABEL[status]}\n </ListItem>\n ))}\n </div>\n </div>\n\n <AddRoadmapItemModal\n open={addOpen}\n horizonTitles={horizonTitles}\n onClose={() => setAddOpen(false)}\n />\n </div>\n );\n};\n"],"names":["NO_SUBJECT","PromoteRoadmapItemModal","horizonTitle","item","candidateName","onClose","onPromoted","promoteRoadmapItem","useAppStore","s","launchIdeaExtend","subjects","subjectsAvailable","useSubjectVocabulary","subject","setSubject","useState","loading","setLoading","error","setError","toast","useToast","useEffect","handlePromote","id","idea","e","buildRoadmapPromotePrompt","err","oneLineErrorSummary","jsx","Modal","jsxs","Select","Button","graduationCounts","graduated","p","HORIZON_HEADER_CLASSES","ChevronRightIcon","size","CandidateRow","name","onPromote","Card","AddCandidateForm","onAdd","setName","saving","setSaving","handleAdd","Input","mergeIdeas","links","represented","merged","plan","link","IdeaRow","onOpen","PrBadge","Stamp","STATUS_STAMP","STATUS_LABEL","ProgressBar","done","total","percent","RoadmapItemRow","highlighted","onPromoteCandidate","onAddCandidate","onOpenGraduated","expanded","setExpanded","shipped","queued","candidates","ideas","v","GoalBanner","goal","firstParagraph","restParagraphs","hasMore","Markdown","RoadmapPage","roadmap","roadmapError","loadRoadmap","filters","promoting","setPromoting","plans","navigate","useNavigate","highlightedItem","useSearch","containerRef","useRef","row","_a","PageTitle","graduatedByItem","handleAddCandidate","itemName","addRoadmapCandidate","horizons","filterHorizons","totalVisible","count","horizon","hasActiveFilters","title","entityRouteParam","AddRoadmapItemModal","open","horizonTitles","setHorizon","description","setDescription","horizonTitlesRef","addRoadmapItem","STATUS_CHIP_ORDER","sectionLabelClass","RoadmapSidebar","toggleRoadmapHorizon","toggleRoadmapStatus","addOpen","setAddOpen","horizonCounts","horizonItemCounts","statusCounts","statusItemCounts","activeHorizons","activeStatuses","visibleStatuses","status","ListItem"],"mappings":"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"}
1
+ {"version":3,"file":"index-Gi97Lmex.js","sources":["../../../src/app/features/roadmap/promote-roadmap-item-modal.tsx","../../../src/app/features/roadmap/roadmap-page.tsx","../../../src/app/features/roadmap/add-roadmap-item-modal.tsx","../../../src/app/features/roadmap/roadmap-sidebar.tsx"],"sourcesContent":["import { buildRoadmapPromotePrompt } from '@/app/features/plans/prompts';\nimport { useSubjectVocabulary } from '@/app/hooks/use-subject-vocabulary';\nimport { useAppStore } from '@/app/stores/app-store';\nimport { oneLineErrorSummary } from '@/app/utils/error-summary';\nimport type { RoadmapItem } from '@/types/index';\nimport { Button, Modal, Select, useToast } from '@dendelion/paper-ui';\nimport { useEffect, useState } from 'react';\n\nconst NO_SUBJECT = '__no-subject__';\n\ninterface PromoteRoadmapItemModalProps {\n horizonTitle: string | null;\n item: RoadmapItem | null;\n candidateName?: string | null;\n onClose: () => void;\n onPromoted: () => void;\n}\n\nexport const PromoteRoadmapItemModal = ({\n horizonTitle,\n item,\n candidateName,\n onClose,\n onPromoted,\n}: PromoteRoadmapItemModalProps) => {\n const promoteRoadmapItem = useAppStore((s) => s.promoteRoadmapItem);\n const launchIdeaExtend = useAppStore((s) => s.launchIdeaExtend);\n const { subjects, available: subjectsAvailable } = useSubjectVocabulary();\n const [subject, setSubject] = useState(NO_SUBJECT);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const { toast } = useToast();\n\n useEffect(() => {\n if (item) {\n // A candidate defaults to its parent item's name — the \"big bet becomes a\n // Subject\" rule — but the picker still lets the user override it.\n setSubject(candidateName ? item.name : NO_SUBJECT);\n setLoading(false);\n setError(null);\n }\n }, [item, candidateName]);\n\n const handlePromote = async () => {\n if (!item || !horizonTitle) return;\n setLoading(true);\n setError(null);\n try {\n const id = await promoteRoadmapItem(\n horizonTitle,\n item,\n subject === NO_SUBJECT ? undefined : subject,\n candidateName ?? undefined,\n );\n const idea = useAppStore.getState().ideaEntries.find((e) => e.id === id);\n if (idea) {\n try {\n await launchIdeaExtend(id, buildRoadmapPromotePrompt(idea, horizonTitle));\n } catch (err) {\n // The idea was created either way — a failed refine launch just means\n // no background research ran, not that the promotion itself failed.\n toast({\n title: 'Idea created, but the refine agent failed to launch',\n description: oneLineErrorSummary((err as Error).message),\n variant: 'error',\n });\n }\n }\n onPromoted();\n onClose();\n } catch (err) {\n setError((err as Error).message);\n } finally {\n setLoading(false);\n }\n };\n\n return (\n <Modal\n open={item !== null}\n onClose={onClose}\n title={candidateName ?? item?.name ?? ''}\n size=\"small\"\n >\n <div className=\"flex flex-col gap-4\">\n {!candidateName && <p className=\"m-0 opacity-80\">{item?.description}</p>}\n <div>\n <Select\n size=\"small\"\n value={subject}\n onChange={setSubject}\n disabled={loading || !subjectsAvailable}\n options={[\n { value: NO_SUBJECT, label: 'No subject' },\n ...(!subjectsAvailable && subject !== NO_SUBJECT\n ? [{ value: subject, label: subject }]\n : []),\n ...subjects.map((s) => ({ value: s, label: s })),\n ]}\n />\n </div>\n {error && <p className=\"m-0 text-watercolor-rose-dark text-sm\">{error}</p>}\n <div className=\"flex justify-end gap-2\">\n <Button type=\"button\" variant=\"ghost\" onClick={onClose} disabled={loading}>\n Cancel\n </Button>\n <Button type=\"button\" variant=\"primary\" onClick={handlePromote} disabled={loading}>\n {loading ? 'Promoting…' : 'Promote to idea'}\n </Button>\n </div>\n </div>\n </Modal>\n );\n};\n","import { Markdown } from '@/app/components/markdown';\nimport { PageTitle } from '@/app/components/page-title';\nimport { PrBadge } from '@/app/features/plans/components/pr-badge';\nimport { STATUS_LABEL, STATUS_STAMP } from '@/app/features/plans/constants';\nimport { entityRouteParam } from '@/app/hooks';\nimport { addRoadmapCandidate } from '@/app/services/content/docs-api';\nimport { useAppStore } from '@/app/stores/app-store';\nimport type {\n PlanEntry,\n PlanStatus,\n PrInfo,\n ResolvedRoadmapItem,\n RoadmapLink,\n} from '@/types/index';\nimport { Button, Card, Input, Stamp } from '@dendelion/paper-ui';\nimport { useNavigate, useSearch } from '@tanstack/react-router';\nimport { useEffect, useRef, useState } from 'react';\nimport { PromoteRoadmapItemModal } from './promote-roadmap-item-modal';\nimport { filterHorizons } from './roadmap-filters';\n\nconst graduationCounts = (graduated: PlanEntry[]) => ({\n shipped: graduated.filter((p) => p.status === 'done').length,\n queued: graduated.filter((p) => p.status !== 'done' && p.status !== 'dropped').length,\n});\n\nconst HORIZON_HEADER_CLASSES =\n 'font-handwritten text-md font-semibold opacity-70 leading-none pt-2 px-1 pb-0';\n\nconst ChevronRightIcon = ({ size = 14 }: { size?: number }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"9 18 15 12 9 6\" />\n </svg>\n);\n\nconst CandidateRow = ({\n name,\n onPromote,\n}: {\n name: string;\n onPromote: () => void;\n}) => (\n <Card size=\"small\" texture=\"kraft\" className=\"plan-row-card\">\n <div className=\"flex items-center gap-3\">\n <span className=\"flex-1\">{name}</span>\n <Button type=\"button\" variant=\"ghost\" size=\"small\" onClick={onPromote}>\n Promote to idea\n </Button>\n </div>\n </Card>\n);\n\nconst AddCandidateForm = ({ onAdd }: { onAdd: (name: string) => Promise<void> }) => {\n const [name, setName] = useState('');\n const [saving, setSaving] = useState(false);\n\n const handleAdd = async () => {\n if (!name.trim()) return;\n setSaving(true);\n try {\n await onAdd(name.trim());\n setName('');\n } finally {\n setSaving(false);\n }\n };\n\n return (\n <div className=\"flex gap-2\">\n <Input\n size=\"small\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') handleAdd();\n }}\n placeholder=\"Add option…\"\n disabled={saving}\n className=\"flex-1\"\n />\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"small\"\n onClick={handleAdd}\n disabled={saving || !name.trim()}\n >\n Add\n </Button>\n </div>\n );\n};\n\ninterface MergedIdea {\n key: string;\n label: string;\n status: PlanStatus;\n pr?: PrInfo;\n planId?: string;\n planTitle?: string;\n}\n\nconst mergeIdeas = (links: RoadmapLink[], graduated: PlanEntry[]): MergedIdea[] => {\n const represented = new Set<string>();\n const merged: MergedIdea[] = graduated.map((plan) => {\n if (plan.id) represented.add(plan.id);\n if (plan.idea) represented.add(plan.idea);\n return {\n key: plan.title,\n label: plan.title,\n status: plan.status,\n pr: plan.pr,\n planId: plan.id,\n planTitle: plan.title,\n };\n });\n for (const link of links) {\n if (represented.has(link.id)) continue;\n merged.push({ key: link.id, label: link.id, status: link.status, pr: link.pr });\n }\n return merged;\n};\n\nconst IdeaRow = ({ idea, onOpen }: { idea: MergedIdea; onOpen?: () => void }) => (\n <Card size=\"small\" texture=\"kraft\" className=\"plan-row-card\">\n <div className=\"flex items-center gap-3\">\n {onOpen ? (\n <button\n type=\"button\"\n onClick={onOpen}\n className=\"flex-1 min-w-0 overflow-hidden text-ellipsis whitespace-nowrap bg-transparent border-none p-0 cursor-pointer [font:inherit] text-inherit text-left\"\n >\n {idea.label}\n </button>\n ) : (\n <span className=\"flex-1 min-w-0 overflow-hidden text-ellipsis whitespace-nowrap\">\n {idea.label}\n </span>\n )}\n {idea.pr && <PrBadge pr={idea.pr} />}\n <Stamp\n size=\"small\"\n fillColor={STATUS_STAMP[idea.status].fill}\n textColor={STATUS_STAMP[idea.status].text}\n >\n {STATUS_LABEL[idea.status]}\n </Stamp>\n </div>\n </Card>\n);\n\nconst ProgressBar = ({ done, total }: { done: number; total: number }) => {\n const percent = total > 0 ? Math.round((done / total) * 100) : 0;\n return (\n <div className=\"w-24 h-1.5 rounded-full bg-black/[0.08] overflow-hidden shrink-0\">\n <div\n className={`h-full rounded-full ${total > 0 ? 'bg-watercolor-green' : 'bg-transparent'}`}\n style={{ width: `${percent}%` }}\n />\n </div>\n );\n};\n\nconst RoadmapItemRow = ({\n item,\n graduated,\n highlighted,\n onPromote,\n onPromoteCandidate,\n onAddCandidate,\n onOpenGraduated,\n}: {\n item: ResolvedRoadmapItem;\n graduated: PlanEntry[];\n highlighted: boolean;\n onPromote: () => void;\n onPromoteCandidate: (candidateName: string) => void;\n onAddCandidate: (name: string) => Promise<void>;\n onOpenGraduated: (id: string | undefined, title: string) => void;\n}) => {\n const [expanded, setExpanded] = useState(highlighted);\n const { shipped, queued } = graduationCounts(graduated);\n const candidates = item.candidates.length;\n const ideas = mergeIdeas(item.links, graduated);\n\n useEffect(() => {\n if (highlighted) setExpanded(true);\n }, [highlighted]);\n\n return (\n <div\n className={`border-b border-black/10 last:border-b-0 ${highlighted ? 'roadmap-item-highlighted outline outline-2 outline-offset-[-2px] outline-[rgba(200,154,90,0.5)]' : ''}`}\n >\n <button\n type=\"button\"\n aria-expanded={expanded}\n onClick={() => setExpanded((v) => !v)}\n className=\"flex w-full items-center gap-3 py-2.5 px-0 bg-transparent border-none cursor-pointer text-left [font:inherit] text-inherit\"\n >\n <span\n className={`inline-flex items-center opacity-50 shrink-0 ${expanded ? 'rotate-90' : ''}`}\n >\n <ChevronRightIcon />\n </span>\n <span className=\"font-semibold flex-1 min-w-0 truncate\">{item.name}</span>\n <ProgressBar done={item.rollup.done} total={item.rollup.total} />\n {queued > 0 && (\n <Stamp\n size=\"small\"\n fillColor={STATUS_STAMP.planned.fill}\n textColor={STATUS_STAMP.planned.text}\n >\n {queued} in queue\n </Stamp>\n )}\n {shipped > 0 && (\n <Stamp size=\"small\" fillColor={STATUS_STAMP.done.fill} textColor={STATUS_STAMP.done.text}>\n {shipped} shipped\n </Stamp>\n )}\n {candidates > 0 && (\n <Stamp size=\"small\" fillColor=\"rgba(0, 0, 0, 0.06)\" textColor=\"rgba(0, 0, 0, 0.55)\">\n {candidates} candidate{candidates === 1 ? '' : 's'}\n </Stamp>\n )}\n </button>\n {expanded && (\n <div className=\"flex flex-col gap-1 pl-6 pb-4\">\n <span className=\"text-sm opacity-70\">{item.description}</span>\n {ideas.map((idea) => (\n <IdeaRow\n key={idea.key}\n idea={idea}\n onOpen={\n idea.planTitle\n ? () => onOpenGraduated(idea.planId, idea.planTitle as string)\n : undefined\n }\n />\n ))}\n {item.candidates.map((candidateName) => (\n <CandidateRow\n key={candidateName}\n name={candidateName}\n onPromote={() => onPromoteCandidate(candidateName)}\n />\n ))}\n <AddCandidateForm onAdd={onAddCandidate} />\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"small\"\n onClick={onPromote}\n className=\"self-start\"\n >\n Promote to idea\n </Button>\n </div>\n )}\n </div>\n );\n};\n\nconst GoalBanner = ({ goal }: { goal: string }) => {\n const [expanded, setExpanded] = useState(false);\n const [firstParagraph, ...restParagraphs] = goal.split(/\\n{2,}/);\n const hasMore = restParagraphs.length > 0;\n\n return (\n <div className=\"mb-6 pb-4 border-b border-black/[8%]\">\n <span className=\"font-handwritten text-xs font-semibold opacity-[0.55]\">The goal</span>\n <div className=\"text-sm leading-relaxed opacity-80 mt-2\">\n <Markdown>{firstParagraph}</Markdown>\n {expanded && hasMore && <Markdown>{restParagraphs.join('\\n\\n')}</Markdown>}\n </div>\n {hasMore && (\n <button\n type=\"button\"\n onClick={() => setExpanded((v) => !v)}\n className=\"bg-transparent border-none p-0 mt-2 cursor-pointer text-2xs opacity-[0.65] underline\"\n >\n {expanded ? 'Show less' : 'Show more'}\n </button>\n )}\n </div>\n );\n};\n\nexport const RoadmapPage = () => {\n const roadmap = useAppStore((s) => s.roadmap);\n const roadmapError = useAppStore((s) => s.roadmapError);\n const loadRoadmap = useAppStore((s) => s.loadRoadmap);\n const filters = useAppStore((s) => s.roadmapFilters);\n const [promoting, setPromoting] = useState<{\n horizonTitle: string;\n item: ResolvedRoadmapItem;\n candidateName?: string;\n } | null>(null);\n const plans = useAppStore((s) => s.plans);\n const navigate = useNavigate();\n const { item: highlightedItem } = useSearch({ from: '/roadmap' });\n const containerRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n loadRoadmap();\n }, [loadRoadmap]);\n\n useEffect(() => {\n if (!highlightedItem || !roadmap) return;\n const row = containerRef.current?.querySelector('.roadmap-item-highlighted');\n row?.scrollIntoView({ behavior: 'smooth', block: 'center' });\n }, [highlightedItem, roadmap]);\n\n if (roadmapError) {\n return (\n <div>\n <PageTitle>Roadmap</PageTitle>\n <p className=\"opacity-50\">\n Couldn't load the roadmap — the server may need a restart to pick up new routes.\n </p>\n </div>\n );\n }\n\n if (!roadmap) {\n return (\n <div>\n <PageTitle>Roadmap</PageTitle>\n <p className=\"opacity-50\">Loading…</p>\n </div>\n );\n }\n\n if (roadmap.horizons.length === 0) {\n return (\n <div>\n <PageTitle>Roadmap</PageTitle>\n <p className=\"opacity-50\">No `ROADMAP.md` found at the project root.</p>\n </div>\n );\n }\n\n const graduatedByItem = (item: ResolvedRoadmapItem) =>\n plans?.entries.filter((p) => p.subject === item.name) ?? [];\n\n const handleAddCandidate = async (horizonTitle: string, itemName: string, name: string) => {\n await addRoadmapCandidate(horizonTitle, itemName, name);\n await loadRoadmap();\n };\n\n const horizons = filterHorizons(roadmap, filters);\n const totalVisible = horizons.reduce((count, horizon) => count + horizon.items.length, 0);\n const hasActiveFilters = filters.horizons.length > 0 || filters.statuses.length > 0;\n\n return (\n <div ref={containerRef}>\n <PageTitle>Roadmap</PageTitle>\n <GoalBanner goal={roadmap.goal} />\n {totalVisible === 0 ? (\n <p className=\"opacity-50 py-6 px-0 text-center\">\n {hasActiveFilters\n ? 'Nothing matches these filters — clear one from the sidebar to see more.'\n : 'No roadmap items yet — add one from the sidebar.'}\n </p>\n ) : (\n <div className=\"flex flex-col gap-6\">\n {horizons\n .filter((horizon) => horizon.items.length > 0)\n .map((horizon) => (\n <div key={horizon.title} className=\"flex flex-col gap-1\">\n <div className={HORIZON_HEADER_CLASSES}>{horizon.title}</div>\n <div className=\"flex flex-col\">\n {horizon.items.map((item) => (\n <RoadmapItemRow\n key={item.name}\n item={item}\n graduated={graduatedByItem(item)}\n highlighted={item.name === highlightedItem}\n onPromote={() => setPromoting({ horizonTitle: horizon.title, item })}\n onPromoteCandidate={(candidateName) =>\n setPromoting({ horizonTitle: horizon.title, item, candidateName })\n }\n onAddCandidate={(name) => handleAddCandidate(horizon.title, item.name, name)}\n onOpenGraduated={(id, title) =>\n navigate({\n to: '/plans/$planId',\n params: { planId: entityRouteParam(id, title) },\n })\n }\n />\n ))}\n </div>\n </div>\n ))}\n </div>\n )}\n <PromoteRoadmapItemModal\n horizonTitle={promoting?.horizonTitle ?? null}\n item={promoting?.item ?? null}\n candidateName={promoting?.candidateName}\n onClose={() => setPromoting(null)}\n onPromoted={loadRoadmap}\n />\n </div>\n );\n};\n","import { addRoadmapItem } from '@/app/services/content/docs-api';\nimport { useAppStore } from '@/app/stores/app-store';\nimport { Button, Input, Modal, Select } from '@dendelion/paper-ui';\nimport { useEffect, useRef, useState } from 'react';\n\ninterface AddRoadmapItemModalProps {\n open: boolean;\n horizonTitles: string[];\n onClose: () => void;\n}\n\nexport const AddRoadmapItemModal = ({ open, horizonTitles, onClose }: AddRoadmapItemModalProps) => {\n const loadRoadmap = useAppStore((s) => s.loadRoadmap);\n const [horizon, setHorizon] = useState(horizonTitles[0] ?? '');\n const [name, setName] = useState('');\n const [description, setDescription] = useState('');\n const [saving, setSaving] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const horizonTitlesRef = useRef(horizonTitles);\n horizonTitlesRef.current = horizonTitles;\n\n useEffect(() => {\n if (open) {\n setHorizon(horizonTitlesRef.current[0] ?? '');\n setName('');\n setDescription('');\n setError(null);\n setSaving(false);\n }\n }, [open]);\n\n const handleAdd = async () => {\n if (!name.trim() || !horizon) return;\n setSaving(true);\n setError(null);\n try {\n await addRoadmapItem(horizon, name.trim(), description.trim());\n await loadRoadmap();\n onClose();\n } catch (err) {\n setError((err as Error).message);\n } finally {\n setSaving(false);\n }\n };\n\n return (\n <Modal open={open} onClose={onClose} title=\"Add roadmap item\" size=\"small\">\n <div className=\"flex flex-col gap-4\">\n <Select\n size=\"small\"\n value={horizon}\n onChange={setHorizon}\n disabled={saving}\n options={horizonTitles.map((title) => ({ value: title, label: title }))}\n />\n <Input\n size=\"small\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n placeholder=\"Item name…\"\n disabled={saving}\n autoFocus\n />\n <Input\n size=\"small\"\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') handleAdd();\n }}\n placeholder=\"Description…\"\n disabled={saving}\n />\n {error && <p className=\"m-0 text-watercolor-rose-dark text-sm\">{error}</p>}\n <div className=\"flex justify-end gap-2\">\n <Button type=\"button\" variant=\"ghost\" onClick={onClose} disabled={saving}>\n Cancel\n </Button>\n <Button\n type=\"button\"\n variant=\"primary\"\n onClick={handleAdd}\n disabled={saving || !name.trim() || !horizon}\n >\n {saving ? 'Adding…' : 'Add item'}\n </Button>\n </div>\n </div>\n </Modal>\n );\n};\n","import { STATUS_LABEL, STATUS_STAMP } from '@/app/features/plans/constants';\nimport { useAppStore } from '@/app/stores/app-store';\nimport type { PlanStatus } from '@/types/index';\nimport { Button, ListItem } from '@dendelion/paper-ui';\nimport { useState } from 'react';\nimport { AddRoadmapItemModal } from './add-roadmap-item-modal';\nimport { horizonItemCounts, statusItemCounts } from './roadmap-filters';\n\nconst STATUS_CHIP_ORDER: PlanStatus[] = [\n 'in-progress',\n 'review',\n 'planned',\n 'idea',\n 'done',\n 'dropped',\n];\n\n// Matches SidebarSection — handwritten, no caps, one grid cell.\nconst sectionLabelClass = 'pc-row-label font-handwritten text-xs font-semibold opacity-[0.45]';\n\nexport const RoadmapSidebar = () => {\n const roadmap = useAppStore((s) => s.roadmap);\n const filters = useAppStore((s) => s.roadmapFilters);\n const toggleRoadmapHorizon = useAppStore((s) => s.toggleRoadmapHorizon);\n const toggleRoadmapStatus = useAppStore((s) => s.toggleRoadmapStatus);\n const [addOpen, setAddOpen] = useState(false);\n\n if (!roadmap) return null;\n\n const horizonTitles = roadmap.horizons.map((horizon) => horizon.title);\n const horizonCounts = horizonItemCounts(roadmap, filters);\n const statusCounts = statusItemCounts(roadmap, filters);\n const activeHorizons = new Set(filters.horizons);\n const activeStatuses = new Set(filters.statuses);\n const visibleStatuses = STATUS_CHIP_ORDER.filter(\n (status) => (statusCounts[status] ?? 0) > 0 || activeStatuses.has(status),\n );\n\n return (\n <div className=\"flex flex-col\">\n <div className=\"flex h-[64px] items-center\">\n <Button\n type=\"button\"\n variant=\"primary\"\n size=\"small\"\n onClick={() => setAddOpen(true)}\n disabled={horizonTitles.length === 0}\n >\n + Add item\n </Button>\n </div>\n\n <div>\n <div className={sectionLabelClass}>Horizon</div>\n <div className=\"flex flex-col\">\n {horizonTitles.map((title) => (\n <ListItem\n key={title}\n size=\"small\"\n active={activeHorizons.has(title)}\n onClick={() => toggleRoadmapHorizon(title)}\n className=\"pc-row text-xs\"\n action={<span className=\"text-2xs text-ink-500\">{horizonCounts[title] ?? 0}</span>}\n >\n {title}\n </ListItem>\n ))}\n </div>\n </div>\n\n <div>\n <div className={sectionLabelClass}>Status</div>\n <div className=\"flex flex-col\">\n {visibleStatuses.length === 0 && (\n <span className=\"opacity-50 text-2xs\">No linked ideas</span>\n )}\n {visibleStatuses.map((status) => (\n <ListItem\n key={status}\n size=\"small\"\n active={activeStatuses.has(status)}\n onClick={() => toggleRoadmapStatus(status)}\n className=\"pc-row text-xs\"\n icon={\n <span\n className=\"w-[9px] h-[9px] rounded-full shrink-0\"\n style={{ background: STATUS_STAMP[status].text }}\n />\n }\n action={<span className=\"text-2xs text-ink-500\">{statusCounts[status] ?? 0}</span>}\n >\n {STATUS_LABEL[status]}\n </ListItem>\n ))}\n </div>\n </div>\n\n <AddRoadmapItemModal\n open={addOpen}\n horizonTitles={horizonTitles}\n onClose={() => setAddOpen(false)}\n />\n </div>\n );\n};\n"],"names":["NO_SUBJECT","PromoteRoadmapItemModal","horizonTitle","item","candidateName","onClose","onPromoted","promoteRoadmapItem","useAppStore","s","launchIdeaExtend","subjects","subjectsAvailable","useSubjectVocabulary","subject","setSubject","useState","loading","setLoading","error","setError","toast","useToast","useEffect","handlePromote","id","idea","e","buildRoadmapPromotePrompt","err","oneLineErrorSummary","jsx","Modal","jsxs","Select","Button","graduationCounts","graduated","p","HORIZON_HEADER_CLASSES","ChevronRightIcon","size","CandidateRow","name","onPromote","Card","AddCandidateForm","onAdd","setName","saving","setSaving","handleAdd","Input","mergeIdeas","links","represented","merged","plan","link","IdeaRow","onOpen","PrBadge","Stamp","STATUS_STAMP","STATUS_LABEL","ProgressBar","done","total","percent","RoadmapItemRow","highlighted","onPromoteCandidate","onAddCandidate","onOpenGraduated","expanded","setExpanded","shipped","queued","candidates","ideas","v","GoalBanner","goal","firstParagraph","restParagraphs","hasMore","Markdown","RoadmapPage","roadmap","roadmapError","loadRoadmap","filters","promoting","setPromoting","plans","navigate","useNavigate","highlightedItem","useSearch","containerRef","useRef","row","_a","PageTitle","graduatedByItem","handleAddCandidate","itemName","addRoadmapCandidate","horizons","filterHorizons","totalVisible","count","horizon","hasActiveFilters","title","entityRouteParam","AddRoadmapItemModal","open","horizonTitles","setHorizon","description","setDescription","horizonTitlesRef","addRoadmapItem","STATUS_CHIP_ORDER","sectionLabelClass","RoadmapSidebar","toggleRoadmapHorizon","toggleRoadmapStatus","addOpen","setAddOpen","horizonCounts","horizonItemCounts","statusCounts","statusItemCounts","activeHorizons","activeStatuses","visibleStatuses","status","ListItem"],"mappings":"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"}