@tradalab/lyra 1.0.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.
@@ -0,0 +1,63 @@
1
+ import * as React from 'react';
2
+ import { ReactNode, HTMLAttributes } from 'react';
3
+ import { Row, Cell, Column, ColumnDef, Table, Header, HeaderGroup } from '@tanstack/react-table';
4
+ export { ColumnDef } from '@tanstack/react-table';
5
+
6
+ declare const TableContext: React.Context<{
7
+ data: unknown[];
8
+ columns: ColumnDef<unknown, unknown>[];
9
+ table: Table<unknown> | null;
10
+ }>;
11
+ type TableProviderProps<TData, TValue> = {
12
+ columns: ColumnDef<TData, TValue>[];
13
+ data: TData[];
14
+ children: ReactNode;
15
+ className?: string;
16
+ };
17
+ declare function TableProvider<TData, TValue>({ columns, data, children, className }: TableProviderProps<TData, TValue>): React.JSX.Element;
18
+ type TableHeadProps = {
19
+ header: Header<unknown, unknown>;
20
+ className?: string;
21
+ };
22
+ declare const TableHead: React.MemoExoticComponent<({ header, className }: TableHeadProps) => React.JSX.Element>;
23
+ type TableHeaderGroupProps = {
24
+ headerGroup: HeaderGroup<unknown>;
25
+ children: (props: {
26
+ header: Header<unknown, unknown>;
27
+ }) => ReactNode;
28
+ };
29
+ declare const TableHeaderGroup: ({ headerGroup, children }: TableHeaderGroupProps) => React.JSX.Element;
30
+ type TableHeaderProps = {
31
+ className?: string;
32
+ children: (props: {
33
+ headerGroup: HeaderGroup<unknown>;
34
+ }) => ReactNode;
35
+ };
36
+ declare const TableHeader: ({ className, children }: TableHeaderProps) => React.JSX.Element;
37
+ interface TableColumnHeaderProps<TData, TValue> extends HTMLAttributes<HTMLDivElement> {
38
+ column: Column<TData, TValue>;
39
+ title: string;
40
+ }
41
+ declare function TableColumnHeader<TData, TValue>({ column, title, className }: TableColumnHeaderProps<TData, TValue>): React.JSX.Element;
42
+ type TableCellProps = {
43
+ cell: Cell<unknown, unknown>;
44
+ className?: string;
45
+ };
46
+ declare const TableCell: ({ cell, className }: TableCellProps) => React.JSX.Element;
47
+ type TableRowProps = {
48
+ row: Row<unknown>;
49
+ children: (props: {
50
+ cell: Cell<unknown, unknown>;
51
+ }) => ReactNode;
52
+ className?: string;
53
+ };
54
+ declare const TableRow: ({ row, children, className }: TableRowProps) => React.JSX.Element;
55
+ type TableBodyProps = {
56
+ children: (props: {
57
+ row: Row<unknown>;
58
+ }) => ReactNode;
59
+ className?: string;
60
+ };
61
+ declare const TableBody: ({ children, className }: TableBodyProps) => React.JSX.Element;
62
+
63
+ export { TableBody, type TableBodyProps, TableCell, type TableCellProps, TableColumnHeader, type TableColumnHeaderProps, TableContext, TableHead, type TableHeadProps, TableHeader, TableHeaderGroup, type TableHeaderGroupProps, type TableHeaderProps, TableProvider, type TableProviderProps, TableRow, type TableRowProps };
@@ -0,0 +1,85 @@
1
+ "use client";
2
+ import { TableHead, Table, TableRow, TableHeader, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, TableCell, TableBody } from '../chunk-X2BCIKOJ.js';
3
+ import { Button } from '../chunk-KFQOYZ64.js';
4
+ import { cn } from '../chunk-XH55BHUU.js';
5
+ import { flexRender, useReactTable, getSortedRowModel, getCoreRowModel } from '@tanstack/react-table';
6
+ import { ArrowDownIcon, ArrowUpIcon, ChevronsUpDownIcon } from 'lucide-react';
7
+ import { createContext, memo, useState, useContext, useCallback } from 'react';
8
+ import { jsx, jsxs } from 'react/jsx-runtime';
9
+
10
+ var TableContext = createContext({
11
+ data: [],
12
+ columns: [],
13
+ table: null
14
+ });
15
+ function TableProvider({ columns, data, children, className }) {
16
+ const [sorting, setSorting] = useState([]);
17
+ const table = useReactTable({
18
+ data,
19
+ columns,
20
+ getCoreRowModel: getCoreRowModel(),
21
+ getSortedRowModel: getSortedRowModel(),
22
+ // useState's setter is itself a valid TanStack OnChangeFn (it accepts a
23
+ // value or an updater fn), so it can be wired directly — type-safe, no cast.
24
+ onSortingChange: setSorting,
25
+ state: {
26
+ sorting
27
+ }
28
+ });
29
+ return /* @__PURE__ */ jsx(
30
+ TableContext.Provider,
31
+ {
32
+ value: {
33
+ data,
34
+ columns,
35
+ table
36
+ },
37
+ children: /* @__PURE__ */ jsx(Table, { className, children })
38
+ }
39
+ );
40
+ }
41
+ var TableHead2 = memo(({ header, className }) => /* @__PURE__ */ jsx(TableHead, { className, children: header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext()) }, header.id));
42
+ TableHead2.displayName = "TableHead";
43
+ var TableHeaderGroup = ({ headerGroup, children }) => /* @__PURE__ */ jsx(TableRow, { children: headerGroup.headers.map((header) => children({ header })) }, headerGroup.id);
44
+ var TableHeader2 = ({ className, children }) => {
45
+ const { table } = useContext(TableContext);
46
+ return /* @__PURE__ */ jsx(TableHeader, { className, children: table?.getHeaderGroups().map((headerGroup) => children({ headerGroup })) });
47
+ };
48
+ function TableColumnHeader({ column, title, className }) {
49
+ const handleSortAsc = useCallback(() => {
50
+ column.toggleSorting(false);
51
+ }, [column]);
52
+ const handleSortDesc = useCallback(() => {
53
+ column.toggleSorting(true);
54
+ }, [column]);
55
+ if (!column.getCanSort()) {
56
+ return /* @__PURE__ */ jsx("div", { className: cn(className), children: title });
57
+ }
58
+ return /* @__PURE__ */ jsx("div", { className: cn("flex items-center space-x-2", className), children: /* @__PURE__ */ jsxs(DropdownMenu, { children: [
59
+ /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(Button, { className: "-ml-3 h-8 data-[state=open]:bg-accent", size: "sm", variant: "ghost", children: [
60
+ /* @__PURE__ */ jsx("span", { children: title }),
61
+ column.getIsSorted() === "desc" ? /* @__PURE__ */ jsx(ArrowDownIcon, { className: "ml-2 h-4 w-4" }) : column.getIsSorted() === "asc" ? /* @__PURE__ */ jsx(ArrowUpIcon, { className: "ml-2 h-4 w-4" }) : /* @__PURE__ */ jsx(ChevronsUpDownIcon, { className: "ml-2 h-4 w-4" })
62
+ ] }) }),
63
+ /* @__PURE__ */ jsxs(DropdownMenuContent, { align: "start", children: [
64
+ /* @__PURE__ */ jsxs(DropdownMenuItem, { onClick: handleSortAsc, children: [
65
+ /* @__PURE__ */ jsx(ArrowUpIcon, { className: "mr-2 h-3.5 w-3.5 text-muted-foreground/70" }),
66
+ "Asc"
67
+ ] }),
68
+ /* @__PURE__ */ jsxs(DropdownMenuItem, { onClick: handleSortDesc, children: [
69
+ /* @__PURE__ */ jsx(ArrowDownIcon, { className: "mr-2 h-3.5 w-3.5 text-muted-foreground/70" }),
70
+ "Desc"
71
+ ] })
72
+ ] })
73
+ ] }) });
74
+ }
75
+ var TableCell2 = ({ cell, className }) => /* @__PURE__ */ jsx(TableCell, { className, children: flexRender(cell.column.columnDef.cell, cell.getContext()) });
76
+ var TableRow2 = ({ row, children, className }) => /* @__PURE__ */ jsx(TableRow, { className, "data-state": row.getIsSelected() && "selected", children: row.getVisibleCells().map((cell) => children({ cell })) }, row.id);
77
+ var TableBody2 = ({ children, className }) => {
78
+ const { columns, table } = useContext(TableContext);
79
+ const rows = table?.getRowModel().rows;
80
+ return /* @__PURE__ */ jsx(TableBody, { className, children: rows?.length ? rows.map((row) => children({ row })) : /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { className: "h-24 text-center", colSpan: columns.length, children: "No results." }) }) });
81
+ };
82
+
83
+ export { TableBody2 as TableBody, TableCell2 as TableCell, TableColumnHeader, TableContext, TableHead2 as TableHead, TableHeader2 as TableHeader, TableHeaderGroup, TableProvider, TableRow2 as TableRow };
84
+ //# sourceMappingURL=index.js.map
85
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/data-table/index.tsx"],"names":["TableHead","TableHeader","TableCell","TableRow","TableBody"],"mappings":"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","file":"index.js","sourcesContent":["import type { Cell, Column, ColumnDef, Header, HeaderGroup, Row, SortingState, Table } from \"@tanstack/react-table\"\nimport { flexRender, getCoreRowModel, getSortedRowModel, useReactTable } from \"@tanstack/react-table\"\nimport { ArrowDownIcon, ArrowUpIcon, ChevronsUpDownIcon } from \"lucide-react\"\nimport type { HTMLAttributes, ReactNode } from \"react\"\nimport { createContext, memo, useCallback, useContext, useState } from \"react\"\nimport { Button } from \"~/ui/primitives/button.js\"\nimport { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from \"~/ui/primitives/dropdown-menu.js\"\nimport {\n TableBody as TableBodyRaw,\n TableCell as TableCellRaw,\n TableHeader as TableHeaderRaw,\n TableHead as TableHeadRaw,\n Table as TableRaw,\n TableRow as TableRowRaw,\n} from \"~/ui/primitives/table.js\"\nimport { cn } from \"~/utils/cn.js\"\n\nexport type { ColumnDef } from \"@tanstack/react-table\"\n\n\nexport const TableContext = createContext<{\n data: unknown[]\n columns: ColumnDef<unknown, unknown>[]\n table: Table<unknown> | null\n}>({\n data: [],\n columns: [],\n table: null,\n})\n\nexport type TableProviderProps<TData, TValue> = {\n columns: ColumnDef<TData, TValue>[]\n data: TData[]\n children: ReactNode\n className?: string\n}\n\nexport function TableProvider<TData, TValue>({ columns, data, children, className }: TableProviderProps<TData, TValue>) {\n const [sorting, setSorting] = useState<SortingState>([])\n const table = useReactTable({\n data,\n columns,\n getCoreRowModel: getCoreRowModel(),\n getSortedRowModel: getSortedRowModel(),\n // useState's setter is itself a valid TanStack OnChangeFn (it accepts a\n // value or an updater fn), so it can be wired directly — type-safe, no cast.\n onSortingChange: setSorting,\n state: {\n sorting,\n },\n })\n\n return (\n <TableContext.Provider\n value={{\n data,\n columns: columns as never,\n table: table as never,\n }}\n >\n <TableRaw className={className}>{children}</TableRaw>\n </TableContext.Provider>\n )\n}\n\nexport type TableHeadProps = {\n header: Header<unknown, unknown>\n className?: string\n}\n\nexport const TableHead = memo(({ header, className }: TableHeadProps) => (\n <TableHeadRaw className={className} key={header.id}>\n {header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}\n </TableHeadRaw>\n))\n\nTableHead.displayName = \"TableHead\"\n\nexport type TableHeaderGroupProps = {\n headerGroup: HeaderGroup<unknown>\n children: (props: { header: Header<unknown, unknown> }) => ReactNode\n}\n\nexport const TableHeaderGroup = ({ headerGroup, children }: TableHeaderGroupProps) => (\n <TableRowRaw key={headerGroup.id}>{headerGroup.headers.map(header => children({ header }))}</TableRowRaw>\n)\n\nexport type TableHeaderProps = {\n className?: string\n children: (props: { headerGroup: HeaderGroup<unknown> }) => ReactNode\n}\n\nexport const TableHeader = ({ className, children }: TableHeaderProps) => {\n const { table } = useContext(TableContext)\n\n return <TableHeaderRaw className={className}>{table?.getHeaderGroups().map(headerGroup => children({ headerGroup }))}</TableHeaderRaw>\n}\n\nexport interface TableColumnHeaderProps<TData, TValue> extends HTMLAttributes<HTMLDivElement> {\n column: Column<TData, TValue>\n title: string\n}\n\nexport function TableColumnHeader<TData, TValue>({ column, title, className }: TableColumnHeaderProps<TData, TValue>) {\n // Extract inline event handlers to prevent unnecessary re-renders\n const handleSortAsc = useCallback(() => {\n column.toggleSorting(false)\n }, [column])\n\n const handleSortDesc = useCallback(() => {\n column.toggleSorting(true)\n }, [column])\n\n if (!column.getCanSort()) {\n return <div className={cn(className)}>{title}</div>\n }\n\n return (\n <div className={cn(\"flex items-center space-x-2\", className)}>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button className=\"-ml-3 h-8 data-[state=open]:bg-accent\" size=\"sm\" variant=\"ghost\">\n <span>{title}</span>\n {column.getIsSorted() === \"desc\" ? (\n <ArrowDownIcon className=\"ml-2 h-4 w-4\" />\n ) : column.getIsSorted() === \"asc\" ? (\n <ArrowUpIcon className=\"ml-2 h-4 w-4\" />\n ) : (\n <ChevronsUpDownIcon className=\"ml-2 h-4 w-4\" />\n )}\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\">\n <DropdownMenuItem onClick={handleSortAsc}>\n <ArrowUpIcon className=\"mr-2 h-3.5 w-3.5 text-muted-foreground/70\" />\n Asc\n </DropdownMenuItem>\n <DropdownMenuItem onClick={handleSortDesc}>\n <ArrowDownIcon className=\"mr-2 h-3.5 w-3.5 text-muted-foreground/70\" />\n Desc\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n )\n}\n\nexport type TableCellProps = {\n cell: Cell<unknown, unknown>\n className?: string\n}\n\nexport const TableCell = ({ cell, className }: TableCellProps) => (\n <TableCellRaw className={className}>{flexRender(cell.column.columnDef.cell, cell.getContext())}</TableCellRaw>\n)\n\nexport type TableRowProps = {\n row: Row<unknown>\n children: (props: { cell: Cell<unknown, unknown> }) => ReactNode\n className?: string\n}\n\nexport const TableRow = ({ row, children, className }: TableRowProps) => (\n <TableRowRaw className={className} data-state={row.getIsSelected() && \"selected\"} key={row.id}>\n {row.getVisibleCells().map(cell => children({ cell }))}\n </TableRowRaw>\n)\n\nexport type TableBodyProps = {\n children: (props: { row: Row<unknown> }) => ReactNode\n className?: string\n}\n\nexport const TableBody = ({ children, className }: TableBodyProps) => {\n const { columns, table } = useContext(TableContext)\n const rows = table?.getRowModel().rows\n\n return (\n <TableBodyRaw className={className}>\n {rows?.length ? (\n rows.map(row => children({ row }))\n ) : (\n <TableRowRaw>\n <TableCellRaw className=\"h-24 text-center\" colSpan={columns.length}>\n No results.\n </TableCellRaw>\n </TableRowRaw>\n )}\n </TableBodyRaw>\n )\n}\n"]}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Returns `true` when viewport width is below the given mobile breakpoint.
3
+ *
4
+ * SSR-safe: returns `false` on the server / initial render, then updates after
5
+ * mount. Listens to `matchMedia` change events for live updates.
6
+ */
7
+ declare function useMobile(breakpointPx?: number): boolean;
8
+
9
+ export { useMobile };
@@ -0,0 +1,4 @@
1
+ "use client";
2
+ export { useMobile } from '../chunk-QYA2HGKW.js';
3
+ //# sourceMappingURL=index.js.map
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
@@ -0,0 +1,2 @@
1
+
2
+ export { }
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+
2
+ //# sourceMappingURL=index.js.map
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
@@ -0,0 +1,84 @@
1
+ import * as React from 'react';
2
+ import { ComponentProps, ReactNode } from 'react';
3
+ import { S as SidebarProvider, a as SidebarInset, B as Breadcrumb } from '../breadcrumb-CGzHbSCd.js';
4
+ import 'class-variance-authority/types';
5
+ import 'class-variance-authority';
6
+ import 'radix-ui';
7
+
8
+ interface AppShellProps extends Omit<ComponentProps<typeof SidebarProvider>, "children"> {
9
+ children: ReactNode;
10
+ }
11
+ /**
12
+ * App shell composition root. Wires `SidebarProvider`. Pair with
13
+ * `<Sidebar>` from `@tradalab/lyra/ui` and `<AppShellMain>` for the
14
+ * right-hand pane.
15
+ *
16
+ * @example
17
+ * import { AppShell, AppShellMain, AppShellHeader, AppShellBody, NavGroup, NavItem, Breadcrumbs } from "@tradalab/lyra/shell"
18
+ * import { Sidebar, SidebarHeader, SidebarContent, SidebarFooter, SidebarTrigger } from "@tradalab/lyra/ui"
19
+ *
20
+ * <AppShell>
21
+ * <Sidebar collapsible="icon">
22
+ * <SidebarHeader>{logo}</SidebarHeader>
23
+ * <SidebarContent>
24
+ * <NavGroup label="Primitives">{...}</NavGroup>
25
+ * </SidebarContent>
26
+ * <SidebarFooter>{user}</SidebarFooter>
27
+ * </Sidebar>
28
+ * <AppShellMain>
29
+ * <AppShellHeader><SidebarTrigger /><Breadcrumbs /></AppShellHeader>
30
+ * <AppShellBody>{children}</AppShellBody>
31
+ * </AppShellMain>
32
+ * </AppShell>
33
+ */
34
+ declare function AppShell({ children, ...rest }: AppShellProps): React.JSX.Element;
35
+ /** Right-hand pane container. Alias for `SidebarInset`. */
36
+ declare const AppShellMain: typeof SidebarInset;
37
+ /** Top bar inside `<AppShellMain>`. Standardizes h-12 + border-b + flex row. */
38
+ declare function AppShellHeader({ className, children, ...rest }: ComponentProps<"header">): React.JSX.Element;
39
+ /** Scroll body inside `<AppShellMain>`. Sibling of `<AppShellHeader>`. */
40
+ declare function AppShellBody({ className, children, ...rest }: ComponentProps<"div">): React.JSX.Element;
41
+
42
+ interface NavGroupProps {
43
+ label?: ReactNode;
44
+ children: ReactNode;
45
+ }
46
+ declare function NavGroup({ label, children }: NavGroupProps): React.JSX.Element;
47
+
48
+ type MatchMode = "exact" | "prefix";
49
+ interface UseActiveRoute {
50
+ pathname: string;
51
+ isActive: (href: string, mode?: MatchMode) => boolean;
52
+ }
53
+ /**
54
+ * App-Router pathname helper. Default `mode` is `"prefix"`.
55
+ *
56
+ * Root (`/`) is always exact-matched regardless of `mode` — otherwise the
57
+ * root nav item would light up on every nested page.
58
+ */
59
+ declare function useActiveRoute(): UseActiveRoute;
60
+
61
+ type NavIcon = ReactNode;
62
+ interface NavItemProps {
63
+ href: string;
64
+ label: string;
65
+ /** Pre-rendered icon element, e.g. `<Globe />`. Element form so the prop is serializable across the RSC boundary. */
66
+ icon?: NavIcon;
67
+ /** Sidebar tooltip; visible in collapsed icon mode. */
68
+ tooltip?: string;
69
+ /** Default `"prefix"` — matches `href` and any nested path. */
70
+ matchMode?: MatchMode;
71
+ }
72
+ /** Sidebar nav row. Must be rendered inside a {@link NavGroup}. */
73
+ declare function NavItem({ href, label, icon, tooltip, matchMode, }: NavItemProps): React.JSX.Element;
74
+
75
+ interface BreadcrumbsProps extends ComponentProps<typeof Breadcrumb> {
76
+ /** Separator content. Falls back to shadcn's chevron when omitted. */
77
+ separator?: ReactNode;
78
+ /** Segment-id → display-label map. Unmapped segments render raw. */
79
+ labels?: Record<string, string>;
80
+ }
81
+ /** Pathname-derived breadcrumbs. Renders nothing on the root route. */
82
+ declare function Breadcrumbs({ separator, labels, ...rest }: BreadcrumbsProps): React.JSX.Element | null;
83
+
84
+ export { AppShell, AppShellBody, AppShellHeader, AppShellMain, type AppShellProps, Breadcrumbs, type BreadcrumbsProps, type MatchMode, NavGroup, type NavGroupProps, type NavIcon, NavItem, type NavItemProps, type UseActiveRoute, useActiveRoute };
@@ -0,0 +1,93 @@
1
+ "use client";
2
+ import { SidebarInset, SidebarProvider, SidebarGroup, SidebarGroupLabel, SidebarGroupContent, SidebarMenu, SidebarMenuItem, SidebarMenuButton, Breadcrumb, BreadcrumbList, BreadcrumbSeparator, BreadcrumbItem, BreadcrumbPage, BreadcrumbLink } from '../chunk-E2QCV5QI.js';
3
+ import '../chunk-QYA2HGKW.js';
4
+ import '../chunk-KFQOYZ64.js';
5
+ import { cn } from '../chunk-XH55BHUU.js';
6
+ import { jsx, jsxs } from 'react/jsx-runtime';
7
+ import Link from 'next/link';
8
+ import { usePathname } from 'next/navigation';
9
+ import { Fragment } from 'react';
10
+
11
+ function AppShell({ children, ...rest }) {
12
+ return /* @__PURE__ */ jsx(SidebarProvider, { ...rest, children });
13
+ }
14
+ var AppShellMain = SidebarInset;
15
+ function AppShellHeader({
16
+ className,
17
+ children,
18
+ ...rest
19
+ }) {
20
+ return /* @__PURE__ */ jsx(
21
+ "header",
22
+ {
23
+ className: cn(
24
+ "flex h-12 shrink-0 items-center gap-2 border-b px-3",
25
+ className
26
+ ),
27
+ ...rest,
28
+ children
29
+ }
30
+ );
31
+ }
32
+ function AppShellBody({
33
+ className,
34
+ children,
35
+ ...rest
36
+ }) {
37
+ return /* @__PURE__ */ jsx("div", { className: cn("flex-1 overflow-auto", className), ...rest, children });
38
+ }
39
+ function NavGroup({ label, children }) {
40
+ return /* @__PURE__ */ jsxs(SidebarGroup, { children: [
41
+ label != null ? /* @__PURE__ */ jsx(SidebarGroupLabel, { children: label }) : null,
42
+ /* @__PURE__ */ jsx(SidebarGroupContent, { children: /* @__PURE__ */ jsx(SidebarMenu, { children }) })
43
+ ] });
44
+ }
45
+ function useActiveRoute() {
46
+ const pathname = usePathname() ?? "/";
47
+ return {
48
+ pathname,
49
+ isActive: (href, mode = "prefix") => {
50
+ if (mode === "exact" || href === "/") return pathname === href;
51
+ return pathname === href || pathname.startsWith(`${href}/`);
52
+ }
53
+ };
54
+ }
55
+ function NavItem({
56
+ href,
57
+ label,
58
+ icon,
59
+ tooltip,
60
+ matchMode = "prefix"
61
+ }) {
62
+ const { isActive } = useActiveRoute();
63
+ return /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsx(
64
+ SidebarMenuButton,
65
+ {
66
+ asChild: true,
67
+ isActive: isActive(href, matchMode),
68
+ tooltip,
69
+ children: /* @__PURE__ */ jsxs(Link, { href, children: [
70
+ icon,
71
+ /* @__PURE__ */ jsx("span", { children: label })
72
+ ] })
73
+ }
74
+ ) });
75
+ }
76
+ function Breadcrumbs({ separator, labels, ...rest }) {
77
+ const { pathname } = useActiveRoute();
78
+ const segments = pathname.split("/").filter(Boolean);
79
+ if (segments.length === 0) return null;
80
+ const last = segments.length - 1;
81
+ return /* @__PURE__ */ jsx(Breadcrumb, { ...rest, children: /* @__PURE__ */ jsx(BreadcrumbList, { children: segments.map((seg, i) => {
82
+ const href = "/" + segments.slice(0, i + 1).join("/");
83
+ const label = labels?.[seg] ?? seg;
84
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
85
+ i > 0 ? /* @__PURE__ */ jsx(BreadcrumbSeparator, { children: separator }) : null,
86
+ /* @__PURE__ */ jsx(BreadcrumbItem, { children: i === last ? /* @__PURE__ */ jsx(BreadcrumbPage, { children: label }) : /* @__PURE__ */ jsx(BreadcrumbLink, { asChild: true, children: /* @__PURE__ */ jsx(Link, { href, children: label }) }) })
87
+ ] }, href);
88
+ }) }) });
89
+ }
90
+
91
+ export { AppShell, AppShellBody, AppShellHeader, AppShellMain, Breadcrumbs, NavGroup, NavItem, useActiveRoute };
92
+ //# sourceMappingURL=index.js.map
93
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/shell/app-shell.tsx","../../src/shell/nav-group.tsx","../../src/shell/use-active-route.ts","../../src/shell/nav-item.tsx","../../src/shell/breadcrumbs.tsx"],"names":["jsx","jsxs","Link"],"mappings":"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","file":"index.js","sourcesContent":["\"use client\"\n\nimport type { ComponentProps, ReactNode } from \"react\"\nimport {\n SidebarInset,\n SidebarProvider,\n} from \"~/ui/primitives/sidebar.js\"\nimport { cn } from \"~/utils/cn.js\"\n\nexport interface AppShellProps\n extends Omit<ComponentProps<typeof SidebarProvider>, \"children\"> {\n children: ReactNode\n}\n\n/**\n * App shell composition root. Wires `SidebarProvider`. Pair with\n * `<Sidebar>` from `@tradalab/lyra/ui` and `<AppShellMain>` for the\n * right-hand pane.\n *\n * @example\n * import { AppShell, AppShellMain, AppShellHeader, AppShellBody, NavGroup, NavItem, Breadcrumbs } from \"@tradalab/lyra/shell\"\n * import { Sidebar, SidebarHeader, SidebarContent, SidebarFooter, SidebarTrigger } from \"@tradalab/lyra/ui\"\n *\n * <AppShell>\n * <Sidebar collapsible=\"icon\">\n * <SidebarHeader>{logo}</SidebarHeader>\n * <SidebarContent>\n * <NavGroup label=\"Primitives\">{...}</NavGroup>\n * </SidebarContent>\n * <SidebarFooter>{user}</SidebarFooter>\n * </Sidebar>\n * <AppShellMain>\n * <AppShellHeader><SidebarTrigger /><Breadcrumbs /></AppShellHeader>\n * <AppShellBody>{children}</AppShellBody>\n * </AppShellMain>\n * </AppShell>\n */\nexport function AppShell({ children, ...rest }: AppShellProps) {\n return <SidebarProvider {...rest}>{children}</SidebarProvider>\n}\n\n/** Right-hand pane container. Alias for `SidebarInset`. */\nexport const AppShellMain = SidebarInset\n\n/** Top bar inside `<AppShellMain>`. Standardizes h-12 + border-b + flex row. */\nexport function AppShellHeader({\n className,\n children,\n ...rest\n}: ComponentProps<\"header\">) {\n return (\n <header\n className={cn(\n \"flex h-12 shrink-0 items-center gap-2 border-b px-3\",\n className,\n )}\n {...rest}\n >\n {children}\n </header>\n )\n}\n\n/** Scroll body inside `<AppShellMain>`. Sibling of `<AppShellHeader>`. */\nexport function AppShellBody({\n className,\n children,\n ...rest\n}: ComponentProps<\"div\">) {\n return (\n <div className={cn(\"flex-1 overflow-auto\", className)} {...rest}>\n {children}\n </div>\n )\n}\n","\"use client\"\n\nimport type { ReactNode } from \"react\"\nimport {\n SidebarGroup,\n SidebarGroupContent,\n SidebarGroupLabel,\n SidebarMenu,\n} from \"~/ui/primitives/sidebar.js\"\n\nexport interface NavGroupProps {\n label?: ReactNode\n children: ReactNode\n}\n\nexport function NavGroup({ label, children }: NavGroupProps) {\n return (\n <SidebarGroup>\n {label != null ? <SidebarGroupLabel>{label}</SidebarGroupLabel> : null}\n <SidebarGroupContent>\n <SidebarMenu>{children}</SidebarMenu>\n </SidebarGroupContent>\n </SidebarGroup>\n )\n}\n","\"use client\"\n\nimport { usePathname } from \"next/navigation\"\n\nexport type MatchMode = \"exact\" | \"prefix\"\n\nexport interface UseActiveRoute {\n pathname: string\n isActive: (href: string, mode?: MatchMode) => boolean\n}\n\n/**\n * App-Router pathname helper. Default `mode` is `\"prefix\"`.\n *\n * Root (`/`) is always exact-matched regardless of `mode` — otherwise the\n * root nav item would light up on every nested page.\n */\nexport function useActiveRoute(): UseActiveRoute {\n const pathname = usePathname() ?? \"/\"\n return {\n pathname,\n isActive: (href, mode = \"prefix\") => {\n if (mode === \"exact\" || href === \"/\") return pathname === href\n return pathname === href || pathname.startsWith(`${href}/`)\n },\n }\n}\n","\"use client\"\n\nimport Link from \"next/link\"\nimport type { ReactNode } from \"react\"\nimport {\n SidebarMenuButton,\n SidebarMenuItem,\n} from \"~/ui/primitives/sidebar.js\"\nimport { useActiveRoute, type MatchMode } from \"./use-active-route.js\"\n\nexport type NavIcon = ReactNode\n\nexport interface NavItemProps {\n href: string\n label: string\n /** Pre-rendered icon element, e.g. `<Globe />`. Element form so the prop is serializable across the RSC boundary. */\n icon?: NavIcon\n /** Sidebar tooltip; visible in collapsed icon mode. */\n tooltip?: string\n /** Default `\"prefix\"` — matches `href` and any nested path. */\n matchMode?: MatchMode\n}\n\n/** Sidebar nav row. Must be rendered inside a {@link NavGroup}. */\nexport function NavItem({\n href,\n label,\n icon,\n tooltip,\n matchMode = \"prefix\",\n}: NavItemProps) {\n const { isActive } = useActiveRoute()\n return (\n <SidebarMenuItem>\n <SidebarMenuButton\n asChild\n isActive={isActive(href, matchMode)}\n tooltip={tooltip}\n >\n <Link href={href}>\n {icon}\n <span>{label}</span>\n </Link>\n </SidebarMenuButton>\n </SidebarMenuItem>\n )\n}\n","\"use client\"\n\nimport { Fragment, type ComponentProps, type ReactNode } from \"react\"\nimport Link from \"next/link\"\nimport {\n Breadcrumb,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbList,\n BreadcrumbPage,\n BreadcrumbSeparator,\n} from \"~/ui/primitives/breadcrumb.js\"\nimport { useActiveRoute } from \"./use-active-route.js\"\n\nexport interface BreadcrumbsProps extends ComponentProps<typeof Breadcrumb> {\n /** Separator content. Falls back to shadcn's chevron when omitted. */\n separator?: ReactNode\n /** Segment-id → display-label map. Unmapped segments render raw. */\n labels?: Record<string, string>\n}\n\n/** Pathname-derived breadcrumbs. Renders nothing on the root route. */\nexport function Breadcrumbs({ separator, labels, ...rest }: BreadcrumbsProps) {\n const { pathname } = useActiveRoute()\n const segments = pathname.split(\"/\").filter(Boolean)\n if (segments.length === 0) return null\n const last = segments.length - 1\n return (\n <Breadcrumb {...rest}>\n <BreadcrumbList>\n {segments.map((seg, i) => {\n const href = \"/\" + segments.slice(0, i + 1).join(\"/\")\n const label = labels?.[seg] ?? seg\n return (\n <Fragment key={href}>\n {i > 0 ? (\n <BreadcrumbSeparator>{separator}</BreadcrumbSeparator>\n ) : null}\n <BreadcrumbItem>\n {i === last ? (\n <BreadcrumbPage>{label}</BreadcrumbPage>\n ) : (\n <BreadcrumbLink asChild>\n <Link href={href}>{label}</Link>\n </BreadcrumbLink>\n )}\n </BreadcrumbItem>\n </Fragment>\n )\n })}\n </BreadcrumbList>\n </Breadcrumb>\n )\n}\n"]}