@tradalab/lyra 1.10.0 → 2.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.
@@ -1 +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, getFilteredRowModel, getPaginationRowModel, getSortedRowModel, useReactTable } from \"@tanstack/react-table\"\nimport { ArrowDownIcon, ArrowUpIcon, ChevronsUpDownIcon, RefreshCwIcon, SearchIcon } 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 { Input } from \"~/ui/primitives/input.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\n// ---------------------------------------------------------------------------\n// DataTable — a batteries-included, self-contained paginated table. Unlike the\n// composition primitives above (TableProvider + render-prop parts), this is a\n// drop-in: pass `columns` + `data` and get header, body, empty/loading states\n// and Prev/Next pagination. All user-facing labels are props (English\n// defaults) so apps can feed i18n strings; the component itself ships no copy.\n// ---------------------------------------------------------------------------\n\nexport interface DataTableProps<TData, TValue> {\n columns: ColumnDef<TData, TValue>[]\n data: TData[]\n /** Show a single-row loading state instead of the body. */\n loading?: boolean\n /** Row shown when there are no results. */\n emptyText?: string\n /** Row shown while `loading`. */\n loadingText?: string\n /** Previous-page button label. */\n previousLabel?: string\n /** Next-page button label. */\n nextLabel?: string\n /** Rows per page (default 10). Pagination controls appear only when needed. */\n pageSize?: number\n /** Extra classes on the bordered table wrapper. */\n className?: string\n // --- control bar (all optional; the bar renders only when one is set) ---\n /** Show a search box that globally filters rows across all accessor columns. */\n searchable?: boolean\n /** Placeholder for the search box. */\n searchPlaceholder?: string\n /** Show a reload button; called on click. Its icon spins while `loading`. */\n onReload?: () => void\n /** Accessible label / tooltip for the reload button. */\n reloadLabel?: string\n /** Custom controls rendered on the right of the bar (e.g. a \"New\" button). */\n toolbar?: ReactNode\n}\n\nexport function DataTable<TData, TValue>({\n columns,\n data,\n loading,\n emptyText = \"No results.\",\n loadingText = \"Loading…\",\n previousLabel = \"Previous\",\n nextLabel = \"Next\",\n pageSize = 10,\n className,\n searchable,\n searchPlaceholder = \"Search…\",\n onReload,\n reloadLabel = \"Reload\",\n toolbar,\n}: DataTableProps<TData, TValue>) {\n const [globalFilter, setGlobalFilter] = useState(\"\")\n const table = useReactTable({\n data,\n columns,\n state: { globalFilter },\n onGlobalFilterChange: setGlobalFilter,\n getCoreRowModel: getCoreRowModel(),\n getFilteredRowModel: getFilteredRowModel(),\n getPaginationRowModel: getPaginationRowModel(),\n initialState: { pagination: { pageSize } },\n })\n\n const rows = table.getRowModel().rows\n const showBar = Boolean(searchable || onReload || toolbar)\n\n return (\n <div>\n {showBar ? (\n <div className=\"flex items-center gap-2 pb-4\">\n {searchable ? (\n <div className=\"relative w-full max-w-xs\">\n <SearchIcon className=\"text-muted-foreground pointer-events-none absolute top-1/2 left-2.5 size-4 -translate-y-1/2\" />\n <Input\n value={globalFilter}\n onChange={e => table.setGlobalFilter(e.target.value)}\n placeholder={searchPlaceholder}\n className=\"pl-8\"\n />\n </div>\n ) : null}\n {onReload || toolbar ? (\n <div className=\"ml-auto flex items-center gap-2\">\n {toolbar}\n {onReload ? (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"icon-sm\"\n onClick={onReload}\n disabled={loading}\n aria-label={reloadLabel}\n title={reloadLabel}\n >\n <RefreshCwIcon className={cn(\"size-4\", loading && \"animate-spin\")} />\n </Button>\n ) : null}\n </div>\n ) : null}\n </div>\n ) : null}\n <div className={cn(\"overflow-hidden border\", className)}>\n <TableRaw>\n <TableHeaderRaw>\n {table.getHeaderGroups().map(hg => (\n <TableRowRaw key={hg.id}>\n {hg.headers.map(header => (\n <TableHeadRaw key={header.id}>\n {header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}\n </TableHeadRaw>\n ))}\n </TableRowRaw>\n ))}\n </TableHeaderRaw>\n <TableBodyRaw>\n {loading && rows.length === 0 ? (\n // Only replace the body with a loading row on the FIRST load; on a\n // refetch keep the (stale) rows visible while the reload icon spins.\n <TableRowRaw>\n <TableCellRaw className=\"h-24 text-center\" colSpan={columns.length}>\n {loadingText}\n </TableCellRaw>\n </TableRowRaw>\n ) : rows.length ? (\n rows.map(row => (\n <TableRowRaw key={row.id} data-state={row.getIsSelected() && \"selected\"}>\n {row.getVisibleCells().map(cell => (\n <TableCellRaw key={cell.id}>{flexRender(cell.column.columnDef.cell, cell.getContext())}</TableCellRaw>\n ))}\n </TableRowRaw>\n ))\n ) : (\n <TableRowRaw>\n <TableCellRaw className=\"text-muted-foreground h-24 text-center\" colSpan={columns.length}>\n {emptyText}\n </TableCellRaw>\n </TableRowRaw>\n )}\n </TableBodyRaw>\n </TableRaw>\n </div>\n {table.getPageCount() > 1 ? (\n <div className=\"flex items-center justify-end gap-2 py-4\">\n <Button variant=\"outline\" size=\"sm\" onClick={() => table.previousPage()} disabled={!table.getCanPreviousPage()}>\n {previousLabel}\n </Button>\n <Button variant=\"outline\" size=\"sm\" onClick={() => table.nextPage()} disabled={!table.getCanNextPage()}>\n {nextLabel}\n </Button>\n </div>\n ) : null}\n </div>\n )\n}\n"]}
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, getFilteredRowModel, getPaginationRowModel, getSortedRowModel, useReactTable } from \"@tanstack/react-table\"\nimport { ArrowDownIcon, ArrowUpIcon, ChevronsUpDownIcon, Loader2Icon, RefreshCwIcon, SearchIcon } from \"lucide-react\"\nimport type { HTMLAttributes, ReactNode } from \"react\"\nimport { createContext, memo, useCallback, useContext, useEffect, useRef, useState } from \"react\"\nimport { Button } from \"~/ui/primitives/button.js\"\nimport { Input } from \"~/ui/primitives/input.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\n// ---------------------------------------------------------------------------\n// DataTable — a batteries-included, self-contained paginated table. Unlike the\n// composition primitives above (TableProvider + render-prop parts), this is a\n// drop-in: pass `columns` + `data` and get header, body, empty/loading states\n// and Prev/Next pagination. All user-facing labels are props (English\n// defaults) so apps can feed i18n strings; the component itself ships no copy.\n// ---------------------------------------------------------------------------\n\nexport interface DataTableProps<TData, TValue> {\n columns: ColumnDef<TData, TValue>[]\n data: TData[]\n /** Show a single-row loading state instead of the body. */\n loading?: boolean\n /** Row shown when there are no results. */\n emptyText?: string\n /** Row shown while `loading`. */\n loadingText?: string\n /** Previous-page button label. */\n previousLabel?: string\n /** Next-page button label. */\n nextLabel?: string\n /** Rows per page (default 10). Pagination controls appear only when needed. */\n pageSize?: number\n /** Extra classes on the bordered table wrapper. */\n className?: string\n // --- control bar (all optional; the bar renders only when one is set) ---\n /** Show a search box that globally filters rows across all accessor columns. */\n searchable?: boolean\n /** Placeholder for the search box. */\n searchPlaceholder?: string\n /** Show a reload button; called on click. Its icon spins while `loading`. */\n onReload?: () => void\n /** Accessible label / tooltip for the reload button. */\n reloadLabel?: string\n /** Custom controls rendered on the right of the bar (e.g. a \"New\" button). */\n toolbar?: ReactNode\n // --- infinite scroll (opt-in; providing `onLoadMore` switches the table from\n // Prev/Next pagination to rendering every accumulated row and requesting more\n // as a bottom sentinel scrolls into view). Data fetching stays with the caller\n // (e.g. react-query useInfiniteQuery); the table only owns the sentinel. ---\n /** Called when the bottom sentinel becomes visible and more rows can load. */\n onLoadMore?: () => void\n /** Whether another page is available; the sentinel is ignored once false. */\n hasMore?: boolean\n /** True while the next page is loading — shows a spinner row and de-dupes calls. */\n loadingMore?: boolean\n /** Label beside the bottom spinner. */\n loadingMoreText?: string\n}\n\nexport function DataTable<TData, TValue>({\n columns,\n data,\n loading,\n emptyText = \"No results.\",\n loadingText = \"Loading…\",\n previousLabel = \"Previous\",\n nextLabel = \"Next\",\n pageSize = 10,\n className,\n searchable,\n searchPlaceholder = \"Search…\",\n onReload,\n reloadLabel = \"Reload\",\n toolbar,\n onLoadMore,\n hasMore,\n loadingMore,\n loadingMoreText = \"Loading more…\",\n}: DataTableProps<TData, TValue>) {\n const [globalFilter, setGlobalFilter] = useState(\"\")\n const infinite = Boolean(onLoadMore)\n const table = useReactTable({\n data,\n columns,\n state: { globalFilter },\n onGlobalFilterChange: setGlobalFilter,\n getCoreRowModel: getCoreRowModel(),\n getFilteredRowModel: getFilteredRowModel(),\n // Infinite mode renders every accumulated row; pagination is only wired for\n // the default finite table.\n ...(infinite ? {} : { getPaginationRowModel: getPaginationRowModel(), initialState: { pagination: { pageSize } } }),\n })\n\n const rows = table.getRowModel().rows\n const showBar = Boolean(searchable || onReload || toolbar)\n\n // --- infinite scroll: observe a bottom sentinel and ask the caller for more.\n // Latest callback/flags are kept in refs so the observer subscribes once. ---\n const sentinelRef = useRef<HTMLDivElement | null>(null)\n const onLoadMoreRef = useRef(onLoadMore)\n onLoadMoreRef.current = onLoadMore\n const flags = useRef({ hasMore, loadingMore })\n flags.current = { hasMore, loadingMore }\n const intersecting = useRef(false)\n\n const maybeLoadMore = useCallback(() => {\n if (intersecting.current && flags.current.hasMore && !flags.current.loadingMore) {\n onLoadMoreRef.current?.()\n }\n }, [])\n\n useEffect(() => {\n if (!infinite) return\n const el = sentinelRef.current\n if (!el) return\n const io = new IntersectionObserver(\n entries => {\n intersecting.current = entries[0]?.isIntersecting ?? false\n maybeLoadMore()\n },\n { rootMargin: \"200px\" },\n )\n io.observe(el)\n return () => {\n io.disconnect()\n }\n }, [infinite, maybeLoadMore])\n\n // A freshly loaded page can leave the sentinel still on-screen; the observer\n // won't re-fire on its own, so re-check whenever the rows or flags change.\n useEffect(() => {\n if (infinite) maybeLoadMore()\n }, [infinite, rows.length, loadingMore, hasMore, maybeLoadMore])\n\n return (\n <div>\n {showBar ? (\n <div className=\"flex items-center gap-2 pb-4\">\n {searchable ? (\n <div className=\"relative w-full max-w-xs\">\n <SearchIcon className=\"text-muted-foreground pointer-events-none absolute top-1/2 left-2.5 size-4 -translate-y-1/2\" />\n <Input\n value={globalFilter}\n onChange={e => table.setGlobalFilter(e.target.value)}\n placeholder={searchPlaceholder}\n className=\"pl-8\"\n />\n </div>\n ) : null}\n {onReload || toolbar ? (\n <div className=\"ml-auto flex items-center gap-2\">\n {toolbar}\n {onReload ? (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"icon-sm\"\n onClick={onReload}\n disabled={loading}\n aria-label={reloadLabel}\n title={reloadLabel}\n >\n <RefreshCwIcon className={cn(\"size-4\", loading && \"animate-spin\")} />\n </Button>\n ) : null}\n </div>\n ) : null}\n </div>\n ) : null}\n <div className={cn(\"overflow-hidden border\", className)}>\n <TableRaw>\n <TableHeaderRaw>\n {table.getHeaderGroups().map(hg => (\n <TableRowRaw key={hg.id}>\n {hg.headers.map(header => (\n <TableHeadRaw key={header.id}>\n {header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}\n </TableHeadRaw>\n ))}\n </TableRowRaw>\n ))}\n </TableHeaderRaw>\n <TableBodyRaw>\n {loading && rows.length === 0 ? (\n // Only replace the body with a loading row on the FIRST load; on a\n // refetch keep the (stale) rows visible while the reload icon spins.\n <TableRowRaw>\n <TableCellRaw className=\"h-24 text-center\" colSpan={columns.length}>\n {loadingText}\n </TableCellRaw>\n </TableRowRaw>\n ) : rows.length ? (\n rows.map(row => (\n <TableRowRaw key={row.id} data-state={row.getIsSelected() && \"selected\"}>\n {row.getVisibleCells().map(cell => (\n <TableCellRaw key={cell.id}>{flexRender(cell.column.columnDef.cell, cell.getContext())}</TableCellRaw>\n ))}\n </TableRowRaw>\n ))\n ) : (\n <TableRowRaw>\n <TableCellRaw className=\"text-muted-foreground h-24 text-center\" colSpan={columns.length}>\n {emptyText}\n </TableCellRaw>\n </TableRowRaw>\n )}\n </TableBodyRaw>\n </TableRaw>\n {infinite && loadingMore ? (\n <div className=\"text-muted-foreground flex items-center justify-center gap-2 py-3 text-sm\">\n <Loader2Icon className=\"size-4 animate-spin\" />\n {loadingMoreText}\n </div>\n ) : null}\n {infinite ? <div ref={sentinelRef} aria-hidden className=\"h-px w-full\" /> : null}\n </div>\n {!infinite && table.getPageCount() > 1 ? (\n <div className=\"flex items-center justify-end gap-2 py-4\">\n <Button variant=\"outline\" size=\"sm\" onClick={() => table.previousPage()} disabled={!table.getCanPreviousPage()}>\n {previousLabel}\n </Button>\n <Button variant=\"outline\" size=\"sm\" onClick={() => table.nextPage()} disabled={!table.getCanNextPage()}>\n {nextLabel}\n </Button>\n </div>\n ) : null}\n </div>\n )\n}\n"]}
@@ -110,9 +110,15 @@ interface NavItemProps {
110
110
  tooltip?: string;
111
111
  /** Default `"prefix"` — matches `href` and any nested path. */
112
112
  matchMode?: MatchMode;
113
+ /**
114
+ * Render a new-tab anchor instead of a `next/link`, and never mark the row
115
+ * active. Defaults to auto-detection: absolute (`https://…`), protocol-
116
+ * relative, `mailto:` and `tel:` hrefs count as external.
117
+ */
118
+ external?: boolean;
113
119
  }
114
120
  /** Sidebar nav row. Must be rendered inside a {@link NavGroup}. */
115
- declare function NavItem({ href, label, icon, tooltip, matchMode, }: NavItemProps): React.JSX.Element;
121
+ declare function NavItem({ href, label, icon, tooltip, matchMode, external, }: NavItemProps): React.JSX.Element;
116
122
 
117
123
  interface NavSectionProps {
118
124
  /** Optional group heading. */
@@ -361,14 +367,27 @@ interface TabBarProps {
361
367
  */
362
368
  declare function TabBar({ tabs, activeId, onSelect, onClose, onTogglePin, onCloseOthers, onCloseAll, labels, }: TabBarProps): React.JSX.Element | null;
363
369
 
370
+ interface LeadingCrumb {
371
+ /** Where the crumb links. Omit to render it as plain text. */
372
+ href?: string;
373
+ label: ReactNode;
374
+ /** Hide on small screens, as app-name crumbs usually should. Default `true`. */
375
+ hideOnMobile?: boolean;
376
+ }
364
377
  interface BreadcrumbsProps extends ComponentProps<typeof Breadcrumb> {
365
378
  /** Separator content. Falls back to shadcn's chevron when omitted. */
366
379
  separator?: ReactNode;
367
380
  /** Segment-id → display-label map. Unmapped segments render raw. */
368
381
  labels?: Record<string, string>;
382
+ /**
383
+ * Crumb rendered before the path segments — typically the app name linking
384
+ * home. With it set the trail also renders on the root route (as the current
385
+ * page); without it the root route renders nothing.
386
+ */
387
+ leading?: LeadingCrumb;
369
388
  }
370
- /** Pathname-derived breadcrumbs. Renders nothing on the root route. */
371
- declare function Breadcrumbs({ separator, labels, ...rest }: BreadcrumbsProps): React.JSX.Element | null;
389
+ /** Pathname-derived breadcrumbs. Renders nothing on the root route unless `leading` is set. */
390
+ declare function Breadcrumbs({ separator, labels, leading, ...rest }: BreadcrumbsProps): React.JSX.Element | null;
372
391
 
373
392
  /** One application in the {@link AppGrid} — rendered as an {@link AppTile}. */
374
393
  interface AppGridItem {
@@ -478,4 +497,4 @@ interface AppGlyphProps {
478
497
  /** The colored glyph for an app: image (URL), lucide icon (name), or monogram. */
479
498
  declare function AppGlyph({ icon, color, name, className }: AppGlyphProps): React.JSX.Element;
480
499
 
481
- export { APP_COLORS, APP_ICON_NAMES, AppGlyph, type AppGlyphProps, AppGrid, type AppGridGroup, type AppGridItem, type AppGridProps, AppShell, AppShellBody, AppShellHeader, AppShellMain, type AppShellProps, AppSwitcher, type AppSwitcherApp, type AppSwitcherProps, type AppSwitcherSection, AppTile, Breadcrumbs, type BreadcrumbsProps, type MatchMode, NavBrand, type NavBrandApp, type NavBrandGroup, type NavBrandProps, NavGroup, type NavGroupProps, type NavIcon, NavItem, type NavItemProps, NavSection, type NavSectionProps, NavUser, type NavUserProps, type NavUserThemeLabels, SidebarDock, SidebarPanel, StackedSidebar, TabBar, type TabBarLabels, type TabBarProps, type TabItem, type UseActiveRoute, defaultAppGridLabels, defaultNavBrandAppsLabel, defaultNavUserThemeLabels, defaultTabBarLabels, isIconUrl, isLucideIcon, toIconName, useActiveRoute };
500
+ export { APP_COLORS, APP_ICON_NAMES, AppGlyph, type AppGlyphProps, AppGrid, type AppGridGroup, type AppGridItem, type AppGridProps, AppShell, AppShellBody, AppShellHeader, AppShellMain, type AppShellProps, AppSwitcher, type AppSwitcherApp, type AppSwitcherProps, type AppSwitcherSection, AppTile, Breadcrumbs, type BreadcrumbsProps, type LeadingCrumb, type MatchMode, NavBrand, type NavBrandApp, type NavBrandGroup, type NavBrandProps, NavGroup, type NavGroupProps, type NavIcon, NavItem, type NavItemProps, NavSection, type NavSectionProps, NavUser, type NavUserProps, type NavUserThemeLabels, SidebarDock, SidebarPanel, StackedSidebar, TabBar, type TabBarLabels, type TabBarProps, type TabItem, type UseActiveRoute, defaultAppGridLabels, defaultNavBrandAppsLabel, defaultNavUserThemeLabels, defaultTabBarLabels, isIconUrl, isLucideIcon, toIconName, useActiveRoute };
@@ -1,12 +1,12 @@
1
1
  "use client";
2
- import { SidebarInset, SidebarProvider, Sidebar, SidebarGroup, SidebarGroupLabel, SidebarGroupContent, SidebarMenu, SidebarMenuItem, SidebarMenuButton, useSidebar, defaultAccountMenuLabels, Avatar, AvatarImage, AvatarFallback, initialsOf, ScrollArea, ContextMenu, ContextMenuTrigger, ContextMenuContent, ContextMenuItem, ContextMenuSeparator, ScrollBar, Breadcrumb, BreadcrumbList, BreadcrumbSeparator, BreadcrumbItem, BreadcrumbPage, BreadcrumbLink, InputGroup, InputGroupAddon, InputGroupInput } from '../chunk-V6TVUMAU.js';
2
+ import { SidebarInset, SidebarProvider, Sidebar, SidebarGroup, SidebarGroupLabel, SidebarGroupContent, SidebarMenu, SidebarMenuItem, SidebarMenuButton, useSidebar, defaultAccountMenuLabels, Avatar, AvatarImage, AvatarFallback, initialsOf, ScrollArea, ContextMenu, ContextMenuTrigger, ContextMenuContent, ContextMenuItem, ContextMenuSeparator, ScrollBar, Breadcrumb, BreadcrumbList, BreadcrumbItem, BreadcrumbPage, BreadcrumbLink, BreadcrumbSeparator, InputGroup, InputGroupAddon, InputGroupInput } from '../chunk-2PHVSGAE.js';
3
3
  import '../chunk-QYA2HGKW.js';
4
- import { Card, CardTitle, CardDescription } from '../chunk-ZG5ZPKFL.js';
4
+ import { Card, CardTitle, CardDescription } from '../chunk-LZZ3UOPT.js';
5
5
  import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuSeparator, DropdownMenuLabel, DropdownMenuSub, DropdownMenuSubTrigger, DropdownMenuSubContent, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuItem } from '../chunk-SQA4ILAK.js';
6
- import { Button } from '../chunk-KFQOYZ64.js';
6
+ import { Button } from '../chunk-5Q4UTRYU.js';
7
7
  import { cn } from '../chunk-XH55BHUU.js';
8
8
  import { jsx, jsxs, Fragment as Fragment$1 } from 'react/jsx-runtime';
9
- import Link from 'next/link';
9
+ import Link2 from 'next/link';
10
10
  import { usePathname } from 'next/navigation';
11
11
  import { Fragment, useRef, useEffect } from 'react';
12
12
  import { ChevronsUpDown, CircleUser, Palette, Sun, Moon, Monitor, UserRoundCog, LogOut, LogIn, Pin, X, PinOff, ListX, Trash2, ChevronDown, Search } from 'lucide-react';
@@ -103,21 +103,27 @@ function useActiveRoute() {
103
103
  }
104
104
  };
105
105
  }
106
+ var looksExternal = (href) => /^([a-z][a-z0-9+.-]*:)?\/\//i.test(href) || /^(mailto|tel):/i.test(href);
106
107
  function NavItem({
107
108
  href,
108
109
  label,
109
110
  icon,
110
111
  tooltip,
111
- matchMode = "prefix"
112
+ matchMode = "prefix",
113
+ external
112
114
  }) {
113
115
  const { isActive } = useActiveRoute();
116
+ const isExternal = external ?? looksExternal(href);
114
117
  return /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsx(
115
118
  SidebarMenuButton,
116
119
  {
117
120
  asChild: true,
118
- isActive: isActive(href, matchMode),
121
+ isActive: !isExternal && isActive(href, matchMode),
119
122
  tooltip,
120
- children: /* @__PURE__ */ jsxs(Link, { href, children: [
123
+ children: isExternal ? /* @__PURE__ */ jsxs("a", { href, target: "_blank", rel: "noopener noreferrer", children: [
124
+ icon,
125
+ /* @__PURE__ */ jsx("span", { children: label })
126
+ ] }) : /* @__PURE__ */ jsxs(Link2, { href, children: [
121
127
  icon,
122
128
  /* @__PURE__ */ jsx("span", { children: label })
123
129
  ] })
@@ -593,19 +599,23 @@ function TabBar({
593
599
  }
594
600
  );
595
601
  }
596
- function Breadcrumbs({ separator, labels, ...rest }) {
602
+ function Breadcrumbs({ separator, labels, leading, ...rest }) {
597
603
  const { pathname } = useActiveRoute();
598
604
  const segments = pathname.split("/").filter(Boolean);
599
- if (segments.length === 0) return null;
605
+ if (segments.length === 0 && !leading) return null;
600
606
  const last = segments.length - 1;
601
- return /* @__PURE__ */ jsx(Breadcrumb, { ...rest, children: /* @__PURE__ */ jsx(BreadcrumbList, { children: segments.map((seg, i) => {
602
- const href = "/" + segments.slice(0, i + 1).join("/");
603
- const label = labels?.[seg] ?? seg;
604
- return /* @__PURE__ */ jsxs(Fragment, { children: [
605
- i > 0 ? /* @__PURE__ */ jsx(BreadcrumbSeparator, { children: separator }) : null,
606
- /* @__PURE__ */ jsx(BreadcrumbItem, { children: i === last ? /* @__PURE__ */ jsx(BreadcrumbPage, { children: label }) : /* @__PURE__ */ jsx(BreadcrumbLink, { asChild: true, children: /* @__PURE__ */ jsx(Link, { href, children: label }) }) })
607
- ] }, href);
608
- }) }) });
607
+ const hideLeading = leading?.hideOnMobile ?? true;
608
+ return /* @__PURE__ */ jsx(Breadcrumb, { ...rest, children: /* @__PURE__ */ jsxs(BreadcrumbList, { children: [
609
+ leading ? /* @__PURE__ */ jsx(BreadcrumbItem, { className: hideLeading ? "hidden md:block" : void 0, children: segments.length === 0 ? /* @__PURE__ */ jsx(BreadcrumbPage, { children: leading.label }) : leading.href ? /* @__PURE__ */ jsx(BreadcrumbLink, { asChild: true, children: /* @__PURE__ */ jsx(Link2, { href: leading.href, children: leading.label }) }) : leading.label }) : null,
610
+ segments.map((seg, i) => {
611
+ const href = "/" + segments.slice(0, i + 1).join("/");
612
+ const label = labels?.[seg] ?? seg;
613
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
614
+ i > 0 || leading ? /* @__PURE__ */ jsx(BreadcrumbSeparator, { className: i === 0 && hideLeading && leading ? "hidden md:block" : void 0, children: separator }) : null,
615
+ /* @__PURE__ */ jsx(BreadcrumbItem, { children: i === last ? /* @__PURE__ */ jsx(BreadcrumbPage, { children: label }) : /* @__PURE__ */ jsx(BreadcrumbLink, { asChild: true, children: /* @__PURE__ */ jsx(Link2, { href, children: label }) }) })
616
+ ] }, href);
617
+ })
618
+ ] }) });
609
619
  }
610
620
  var defaultAppGridLabels = {
611
621
  searchPlaceholder: "Search apps\u2026",