@@ -7,30 +7,26 @@ import type {
77} from '@/app/workspace/[workspaceId]/components/resource/components/resource-header'
88
99/**
10- * The only thing a breadcrumb trail needs from a folder tree node. Structural rather than
11- * `WorkflowFolder` so the Files tree builds its trail through this same code path instead of
12- * forking one: file folders live in the same `folder` table, but they are served by their own
13- * routes and carry their own row type (see the `servedFolderResourceTypeSchema` docs in
14- * `@/lib/api/contracts/folders` for why that split exists and is staying).
10+ * Structural rather than `WorkflowFolder` so the Files tree — same `folder` table, own routes
11+ * and row type (see `servedFolderResourceTypeSchema` in `@/lib/api/contracts/folders`) — shares
12+ * this code path instead of forking it.
1513 */
1614export interface BreadcrumbFolder {
1715 id : string
1816 name : string
1917 parentId : string | null
2018}
2119
20+ const EMPTY_CHAIN : never [ ] = [ ]
21+
2222/**
23- * Root-first ancestor chain for a breadcrumb trail, that folder last. Empty at the workspace
24- * root — and empty for a chain that does not reach the root, where {@link folderAncestorChain}
25- * would hand back the part it walked.
26- *
27- * A header falls back to the root title rather than rendering a trail that silently skips a
28- * level: a partial path is not a shorter path, it is a wrong one, claiming the deepest folder
29- * it resolved sits at the workspace root. A chain is complete exactly when its first element
30- * has no parent, which also rejects a cycle (the DB permits one between constraint checks).
23+ * Root-first ancestor chain, that folder last, or empty when it does not reach the root —
24+ * where {@link folderAncestorChain} would hand back the part it walked.
3125 *
32- * `folderById` must therefore be the complete tree — see `FolderAncestors.foldersResolved`;
33- * a partially loaded map reads as an orphan and collapses.
26+ * A partial path is not a shorter path, it is a wrong one: it claims the deepest folder it
27+ * resolved sits at the workspace root. Falling back to the root title is the honest render.
28+ * Completeness is `chain[0].parentId === null`, which also rejects a cycle. Callers must pass
29+ * the complete tree — see `FolderAncestors.foldersResolved`.
3430 */
3531export function breadcrumbFolderChain < T extends BreadcrumbFolder > (
3632 folderId : string | null | undefined ,
@@ -40,10 +36,8 @@ export function breadcrumbFolderChain<T extends BreadcrumbFolder>(
4036 return chain . length === 0 || chain [ 0 ] . parentId === null ? chain : EMPTY_CHAIN
4137}
4238
43- const EMPTY_CHAIN : never [ ] = [ ]
44-
4539interface FolderBreadcrumbItemsBase {
46- /** Root crumb label — the page's own name ("Knowledge Base ", "Tables"). */
40+ /** Root crumb label — the page's own name ("Knowledge bases ", "Tables"). */
4741 rootLabel : string
4842 rootIcon ?: ElementType
4943 /** Root-first ancestor chain, from {@link folderAncestorChain}. */
@@ -84,17 +78,13 @@ export type FolderBreadcrumbItemsOptions =
8478const NO_TRAILING_CRUMBS : BreadcrumbItem [ ] = [ ]
8579
8680/**
87- * Converts a folder ancestor chain into the `BreadcrumbItem[]` that `Resource.Header`
88- * renders, for a list page (`Tables / Reports`) or a detail page (`Tables / Reports / Q3`).
81+ * Builds the `BreadcrumbItem[]` for a list page (`Tables / Reports`) or a detail page
82+ * (`Tables / Reports / Q3`).
8983 *
9084 * A plain builder rather than a component: `Resource.Header` already owns every piece of
9185 * breadcrumb chrome — the root-crumb "Path" popover, segment width allocation, overflow
92- * tooltips, and the rule that a single-element trail renders as a plain page title. A
93- * sibling crumb component would have to fork all of it, which is exactly what this shared
94- * directory exists to prevent.
95- *
96- * The trail always starts with the root crumb, so a list page at the workspace root returns
97- * length 1 and the header renders the page title unchanged.
86+ * tooltips, and the rule that a single-element trail renders as a plain page title. A sibling
87+ * crumb component would have to fork all of it, which is what this directory exists to prevent.
9888 */
9989export function folderBreadcrumbItems ( options : FolderBreadcrumbItemsOptions ) : BreadcrumbItem [ ] {
10090 const { rootLabel, rootIcon, breadcrumbs, onNavigate } = options
0 commit comments