@acronis-platform/ui-react 0.56.1 → 0.57.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/ui/avatar/avatar.js +7 -7
- package/dist/components/ui/avatar/avatar.js.map +1 -1
- package/dist/components/ui/bar-chart/bar-chart.js +104 -0
- package/dist/components/ui/bar-chart/bar-chart.js.map +1 -0
- package/dist/components/ui/chart/chart.js +49 -49
- package/dist/components/ui/chart/chart.js.map +1 -1
- package/dist/components/ui/checkbox/checkbox.js +1 -1
- package/dist/components/ui/checkbox/checkbox.js.map +1 -1
- package/dist/components/ui/chip/chip.js +28 -28
- package/dist/components/ui/chip/chip.js.map +1 -1
- package/dist/components/ui/data-table/data-table.js +223 -155
- package/dist/components/ui/data-table/data-table.js.map +1 -1
- package/dist/components/ui/input-text/input-text.js +8 -8
- package/dist/components/ui/input-text/input-text.js.map +1 -1
- package/dist/components/ui/link/link.js +16 -16
- package/dist/components/ui/link/link.js.map +1 -1
- package/dist/components/ui/page-header/page-header.js +159 -49
- package/dist/components/ui/page-header/page-header.js.map +1 -1
- package/dist/components/ui/search/search.js +6 -6
- package/dist/components/ui/search/search.js.map +1 -1
- package/dist/components/ui/table/table.js +32 -32
- package/dist/components/ui/table/table.js.map +1 -1
- package/dist/components/ui/toolbar/toolbar.js +214 -0
- package/dist/components/ui/toolbar/toolbar.js.map +1 -0
- package/dist/hooks/use-intersection-observer.js +26 -0
- package/dist/hooks/use-intersection-observer.js.map +1 -0
- package/dist/index.js +356 -343
- package/dist/index.js.map +1 -1
- package/dist/react.js +356 -343
- package/dist/react.js.map +1 -1
- package/dist/src/components/ui/bar-chart/bar-chart.d.ts +28 -0
- package/dist/src/components/ui/bar-chart/index.d.ts +1 -0
- package/dist/src/components/ui/data-table/data-table.d.ts +107 -4
- package/dist/src/components/ui/data-table/data-table.docs.d.ts +88 -4
- package/dist/src/components/ui/data-table/index.d.ts +1 -1
- package/dist/src/components/ui/page-header/index.d.ts +1 -1
- package/dist/src/components/ui/page-header/page-header.d.ts +9 -3
- package/dist/src/components/ui/toolbar/index.d.ts +1 -0
- package/dist/src/components/ui/toolbar/toolbar.d.ts +23 -0
- package/dist/src/hooks/index.d.ts +1 -0
- package/dist/src/hooks/use-intersection-observer.d.ts +26 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/ui-react.css +1 -1
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-table.js","sources":["../../../../src/components/ui/data-table/data-table.tsx"],"sourcesContent":["import {\n type CSSProperties,\n Fragment,\n type KeyboardEvent,\n type ReactNode,\n useEffect,\n useState,\n} from 'react';\nimport {\n type Cell,\n type Column,\n type ColumnDef,\n type ColumnFiltersState,\n type ColumnSizingState,\n type ExpandedState,\n type Header,\n type OnChangeFn,\n type Row,\n type RowData,\n type SortingState,\n type VisibilityState,\n flexRender,\n getCoreRowModel,\n getExpandedRowModel,\n getFilteredRowModel,\n getPaginationRowModel,\n getSortedRowModel,\n useReactTable,\n} from '@tanstack/react-table';\n\nimport { cn } from '@/lib/utils';\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from '../table';\n\n// Ported from `@acronis-platform/shadcn-uikit`'s `data-table`\n// (packages/ui-legacy/src/components/ui/data-table/). A TanStack-react-table v8\n// data grid composed over the ui-react Table primitives — sorting, filtering,\n// column visibility, row selection, pagination, and optional row expansion. The\n// presentational flags (`striped`, `bordered`, `skeleton`, `highlightCurrentRow`)\n// are borrowed from the Vue `AvTable`; behavioral features come from TanStack.\n// Pair with DataTableToolbar / DataTablePagination / DataTableColumnHeader, which\n// take the `table` instance returned to column cells via TanStack context.\n// The grid cells/rows/headers are themed by the Table primitives' `--ui-table-*`\n// tier; DataTable's own chrome reuses that tier too — the wrapper border matches\n// the cell borders (`--ui-table-global-cell-border-color`), the empty-state uses\n// the muted table-value color, the current row the active-row color, and stripes\n// the secondary surface.\n//\n// Advanced-grid opt-ins built on native TanStack features:\n// • Column resizing -> `enableColumnResizing` + `columnResizing` state, with a\n// drag handle rendered from `header.getResizeHandler()`.\n// • Sticky columns -> `ColumnDef.meta.pin: 'left' | 'right'` drives TanStack's\n// native column-pinning API (`column.pin()` / `getStart()` / `getAfter()`),\n// surfaced as `position: sticky` cells with an opaque row-token background.\n\n// Extend TanStack's per-column `meta` with the flags DataTable reads. Augmenting\n// the module keeps `ColumnDef.meta.pin` type-safe at the call site.\ndeclare module '@tanstack/react-table' {\n // Type params must match TanStack's `ColumnMeta<TData, TValue>` arity/names for\n // declaration merging, even though this augmentation doesn't reference them.\n // eslint-disable-next-line unused-imports/no-unused-vars\n interface ColumnMeta<TData extends RowData, TValue> {\n /** Pin the column to a table edge (sticky while the grid scrolls horizontally). */\n pin?: 'left' | 'right';\n /**\n * Let the column's header + cells wrap onto multiple lines (drops the fixed\n * row height); mirrors the `Table` primitives' `wrap` prop on TableHead/TableCell.\n */\n wrap?: boolean;\n }\n}\n\n// Sticky offset + stacking for a pinned column, computed from TanStack's own\n// pinning geometry rather than hand-rolled CSS math. A subtle edge shadow (facing\n// the scrollable columns) separates the pinned column from content sliding\n// underneath it — the opaque background that actually hides that content lives\n// in the caller's className (see `headerPinnedBg`/`rowBg` below), not here.\nfunction getPinnedStyle<TData>(\n column: Column<TData, unknown>\n): CSSProperties | undefined {\n const pinned = column.getIsPinned();\n if (!pinned) return undefined;\n return {\n position: 'sticky',\n left: pinned === 'left' ? column.getStart('left') : undefined,\n right: pinned === 'right' ? column.getAfter('right') : undefined,\n zIndex: 1,\n // Derived from the same border token every other table divider uses (not a\n // hardcoded color), so the separator theme-adapts automatically.\n boxShadow:\n pinned === 'left'\n ? '4px 0 4px -4px var(--ui-table-global-cell-border-color)'\n : '-4px 0 4px -4px var(--ui-table-global-cell-border-color)',\n };\n}\n\n// A column's rendered width tracks TanStack's size model once the consumer has\n// opted in — either explicitly (a `size` set on the `ColumnDef`) or implicitly\n// (column resizing enabled, which needs every column's width to be deterministic\n// for the drag math to work). Without either, columns stay in native `<table>`\n// auto-layout so `size`'s internal default (TanStack falls back to 150) never\n// forces every untouched column to a fixed width.\nfunction getColumnWidth<TData>(\n column: Column<TData, unknown>,\n enableColumnResizing: boolean\n): number | undefined {\n if (enableColumnResizing || column.columnDef.size !== undefined) {\n return column.getSize();\n }\n return undefined;\n}\n\nfunction getHeaderStyle<TData>(\n header: Header<TData, unknown>,\n enableColumnResizing: boolean\n): CSSProperties | undefined {\n const pin = getPinnedStyle(header.column);\n const width = getColumnWidth(header.column, enableColumnResizing);\n if (!pin && width === undefined) return undefined;\n return { ...pin, width };\n}\n\nfunction getCellStyle<TData>(\n cell: Cell<TData, unknown>,\n enableColumnResizing: boolean\n): CSSProperties | undefined {\n const pin = getPinnedStyle(cell.column);\n const width = getColumnWidth(cell.column, enableColumnResizing);\n if (!pin && width === undefined) return undefined;\n return { ...pin, width };\n}\n\n// Matches TanStack's own `defaultColumnSizing` fallback bounds — the same\n// range `column.getSize()` already clamps to internally when a column\n// doesn't set its own `minSize`/`maxSize`.\nconst DEFAULT_MIN_COLUMN_SIZE = 20;\nconst DEFAULT_MAX_COLUMN_SIZE = Number.MAX_SAFE_INTEGER;\n\n/**\n * Computes the next column width for an Arrow-key resize step (Shift = larger\n * step), clamped to `[min, max]` regardless of which bound `currentSize`\n * started outside of. Returns `undefined` for any other key, so the caller\n * knows not to `preventDefault()`/resize.\n */\nexport function getResizeKeyboardStep(\n key: string,\n currentSize: number,\n { shiftKey, min, max }: { shiftKey: boolean; min: number; max: number }\n): number | undefined {\n const step = shiftKey ? 50 : 10;\n if (key === 'ArrowLeft') return Math.min(max, Math.max(min, currentSize - step));\n if (key === 'ArrowRight') return Math.max(min, Math.min(max, currentSize + step));\n return undefined;\n}\n\nexport interface DataTableProps<TData, TValue> {\n columns: ColumnDef<TData, TValue>[];\n data: TData[];\n /** Enables row expansion for rows that return true. Pair with `renderExpandedRow`. */\n getRowCanExpand?: (row: Row<TData>) => boolean;\n /**\n * Renders expanded content for an expanded row. Used together with\n * `getRowCanExpand`.\n */\n renderExpandedRow?: (row: Row<TData>) => ReactNode;\n /** Alternating row backgrounds. */\n striped?: boolean;\n /** Vertical borders between columns (rows already have horizontal borders). */\n bordered?: boolean;\n /** Highlight the row the user last clicked (the \"current\" row). */\n highlightCurrentRow?: boolean;\n /** Render placeholder skeleton rows instead of data (loading state). */\n skeleton?: boolean;\n /** Number of skeleton rows to render when `skeleton` is set. */\n skeletonRows?: number;\n /**\n * Opt in to interactive column resizing. Renders a drag handle at the trailing\n * edge of each resizable header cell (TanStack's native `columnResizing`).\n */\n enableColumnResizing?: boolean;\n /** Passthrough for the `columnSizing` state so a consumer can persist widths. */\n onColumnSizingChange?: OnChangeFn<ColumnSizingState>;\n /**\n * Controlled column-visibility state — pass this (with\n * `onColumnVisibilityChange`) to share one visibility state with an\n * external `useReactTable` instance (e.g. a composed toolbar). Uncontrolled\n * (internal state) when omitted.\n */\n columnVisibility?: VisibilityState;\n /** Passthrough for the `columnVisibility` state; pairs with `columnVisibility`. */\n onColumnVisibilityChange?: OnChangeFn<VisibilityState>;\n}\n\nexport function DataTable<TData, TValue>({\n columns,\n data,\n getRowCanExpand,\n renderExpandedRow,\n striped = false,\n bordered = false,\n highlightCurrentRow = false,\n skeleton = false,\n skeletonRows = 5,\n enableColumnResizing = false,\n onColumnSizingChange,\n columnVisibility: controlledColumnVisibility,\n onColumnVisibilityChange,\n}: DataTableProps<TData, TValue>) {\n const [sorting, setSorting] = useState<SortingState>([]);\n const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);\n const [internalColumnVisibility, setInternalColumnVisibility] =\n useState<VisibilityState>({});\n const columnVisibility = controlledColumnVisibility ?? internalColumnVisibility;\n const [rowSelection, setRowSelection] = useState({});\n const [expanded, setExpanded] = useState<ExpandedState>({});\n const [columnSizing, setColumnSizing] = useState<ColumnSizingState>({});\n const [currentRowId, setCurrentRowId] = useState<string>();\n\n const handleColumnSizingChange: OnChangeFn<ColumnSizingState> = (updater) => {\n setColumnSizing(updater);\n onColumnSizingChange?.(updater);\n };\n\n const handleColumnVisibilityChange: OnChangeFn<VisibilityState> = (updater) => {\n setInternalColumnVisibility(updater);\n onColumnVisibilityChange?.(updater);\n };\n\n const table = useReactTable({\n data,\n columns,\n enableColumnResizing,\n columnResizeMode: 'onChange',\n getCoreRowModel: getCoreRowModel(),\n getExpandedRowModel: getExpandedRowModel(),\n getPaginationRowModel: getPaginationRowModel(),\n getRowCanExpand,\n onExpandedChange: setExpanded,\n onSortingChange: setSorting,\n getSortedRowModel: getSortedRowModel(),\n onColumnFiltersChange: setColumnFilters,\n getFilteredRowModel: getFilteredRowModel(),\n onColumnVisibilityChange: handleColumnVisibilityChange,\n onRowSelectionChange: setRowSelection,\n onColumnSizingChange: handleColumnSizingChange,\n state: {\n sorting,\n columnFilters,\n columnVisibility,\n rowSelection,\n expanded,\n columnSizing,\n },\n });\n\n // Arrow-key resize on the drag handle (see `canResize` below). Ignores any\n // modifier besides Shift so it doesn't hijack browser/OS shortcuts bound to\n // Ctrl/Alt/Cmd+Arrow (e.g. back navigation) while the handle has focus.\n const handleResizeKeyDown = (\n event: KeyboardEvent<HTMLDivElement>,\n header: Header<TData, unknown>\n ) => {\n if (event.ctrlKey || event.altKey || event.metaKey) return;\n const nextSize = getResizeKeyboardStep(event.key, header.column.getSize(), {\n shiftKey: event.shiftKey,\n min: header.column.columnDef.minSize ?? DEFAULT_MIN_COLUMN_SIZE,\n max: header.column.columnDef.maxSize ?? DEFAULT_MAX_COLUMN_SIZE,\n });\n if (nextSize === undefined) return;\n event.preventDefault();\n table.setColumnSizing((old) => ({ ...old, [header.column.id]: nextSize }));\n };\n\n // Read each column's `meta.pin` and drive TanStack's native pinning state.\n // Always calls `pin()` (rather than only when truthy) so a column whose\n // `meta.pin` is removed dynamically actually un-pins.\n useEffect(() => {\n table.getAllLeafColumns().forEach((column) => {\n column.pin(column.columnDef.meta?.pin ?? false);\n });\n }, [table, columns]);\n\n const rows = table.getRowModel().rows;\n // Vertical borders are opt-in; a trailing border on the last cell would\n // double up with the wrapper, so suppress it.\n const borderedClass = bordered\n ? '[&_th:not(:last-child)]:border-e [&_td:not(:last-child)]:border-e [&_th]:border-[var(--ui-table-global-cell-border-color)] [&_td]:border-[var(--ui-table-global-cell-border-color)]'\n : undefined;\n\n // A pinned header/body cell must be opaque so the cells scrolling under it\n // (same row) aren't visible. `--ui-table-global-row-color-idle` is\n // *transparent by design* (an idle row shows the page/card surface through\n // it), so it can't be reused here — pinned idle cells need the actual\n // resolved surface color instead (`--ui-background-surface-primary`, bridged\n // to `bg-background`). Non-idle states (selected/current/striped) already use\n // real opaque tokens and are safe to mirror as-is (see `rowBg` below).\n const headerPinnedBg = 'bg-background';\n\n return (\n <div\n className={cn(\n 'rounded-md border border-[var(--ui-table-global-cell-border-color)]',\n borderedClass\n )}\n >\n <Table\n style={\n enableColumnResizing\n ? { width: table.getCenterTotalSize() }\n : undefined\n }\n >\n <TableHeader>\n {table.getHeaderGroups().map((headerGroup) => (\n <TableRow key={headerGroup.id}>\n {headerGroup.headers.map((header) => {\n const isPinned = header.column.getIsPinned();\n const canResize =\n enableColumnResizing && header.column.getCanResize();\n return (\n <TableHead\n key={header.id}\n wrap={header.column.columnDef.meta?.wrap}\n style={getHeaderStyle(header, enableColumnResizing)}\n className={cn(\n canResize && 'relative',\n isPinned && headerPinnedBg\n )}\n >\n {header.isPlaceholder\n ? null\n : flexRender(\n header.column.columnDef.header,\n header.getContext()\n )}\n {canResize && (\n <div\n role=\"separator\"\n aria-orientation=\"vertical\"\n aria-label=\"Resize column\"\n aria-valuenow={header.column.getSize()}\n aria-valuemin={\n header.column.columnDef.minSize ?? DEFAULT_MIN_COLUMN_SIZE\n }\n aria-valuemax={\n header.column.columnDef.maxSize ?? DEFAULT_MAX_COLUMN_SIZE\n }\n tabIndex={0}\n onMouseDown={header.getResizeHandler()}\n onTouchStart={header.getResizeHandler()}\n onKeyDown={(event) => handleResizeKeyDown(event, header)}\n className={cn(\n 'absolute end-0 top-0 h-full w-1 cursor-(--ui-resizable-cursor) touch-none select-none bg-[var(--ui-table-global-cell-border-color)] opacity-0 transition-opacity hover:opacity-100 focus-visible:opacity-100 focus-visible:outline-2 focus-visible:outline-(--ui-focus-primary)',\n header.column.getIsResizing() && 'opacity-100'\n )}\n />\n )}\n </TableHead>\n );\n })}\n </TableRow>\n ))}\n </TableHeader>\n <TableBody>\n {skeleton ? (\n Array.from({ length: skeletonRows }).map((_, rowIndex) => (\n <TableRow key={`skeleton-${rowIndex}`} className=\"hover:bg-transparent\">\n {table.getVisibleLeafColumns().map((column) => (\n <TableCell key={column.id}>\n <div className=\"h-4 w-full animate-pulse rounded bg-[var(--ui-background-surface-secondary)]\" />\n </TableCell>\n ))}\n </TableRow>\n ))\n ) : rows?.length ? (\n rows.map((row, rowIndex) => {\n const isSelected = row.getIsSelected();\n const isCurrent = highlightCurrentRow && currentRowId === row.id;\n // Opaque background applied to pinned cells so sibling cells don't\n // show through while the grid scrolls horizontally. Mirrors the\n // row's own resolved background across selection/current/stripe —\n // the idle case falls back to the real surface color\n // (`bg-background`) since the row's own idle token is transparent\n // by design (see `headerPinnedBg` above).\n const rowBg =\n isSelected || isCurrent\n ? 'bg-[var(--ui-table-global-row-color-active)]'\n : striped && rowIndex % 2 === 1\n ? 'bg-[var(--ui-background-surface-secondary)]'\n : 'bg-background';\n return (\n <Fragment key={row.id}>\n <TableRow\n selected={isSelected}\n onClick={\n highlightCurrentRow\n ? () => setCurrentRowId(row.id)\n : undefined\n }\n className={cn(\n highlightCurrentRow && 'cursor-pointer',\n striped &&\n rowIndex % 2 === 1 &&\n !isSelected &&\n !isCurrent &&\n 'bg-[var(--ui-background-surface-secondary)]',\n isCurrent &&\n !isSelected &&\n 'bg-[var(--ui-table-global-row-color-active)]'\n )}\n >\n {row.getVisibleCells().map((cell) => {\n const isPinned = cell.column.getIsPinned();\n return (\n <TableCell\n key={cell.id}\n wrap={cell.column.columnDef.meta?.wrap}\n style={getCellStyle(cell, enableColumnResizing)}\n className={cn(isPinned && rowBg)}\n >\n {flexRender(\n cell.column.columnDef.cell,\n cell.getContext()\n )}\n </TableCell>\n );\n })}\n </TableRow>\n {renderExpandedRow && row.getIsExpanded() && (\n <TableRow className=\"hover:bg-transparent\">\n <TableCell\n className=\"h-auto py-3\"\n colSpan={row.getVisibleCells().length}\n >\n {renderExpandedRow(row)}\n </TableCell>\n </TableRow>\n )}\n </Fragment>\n );\n })\n ) : (\n <TableRow>\n <TableCell\n colSpan={columns.length}\n className=\"h-24 text-center text-[var(--ui-table-data-value-color-disabled)]\"\n >\n No results.\n </TableCell>\n </TableRow>\n )}\n </TableBody>\n </Table>\n </div>\n );\n}\n"],"names":["getPinnedStyle","column","pinned","getColumnWidth","enableColumnResizing","getHeaderStyle","header","pin","width","getCellStyle","cell","DEFAULT_MIN_COLUMN_SIZE","DEFAULT_MAX_COLUMN_SIZE","getResizeKeyboardStep","key","currentSize","shiftKey","min","max","step","DataTable","columns","data","getRowCanExpand","renderExpandedRow","striped","bordered","highlightCurrentRow","skeleton","skeletonRows","onColumnSizingChange","controlledColumnVisibility","onColumnVisibilityChange","sorting","setSorting","useState","columnFilters","setColumnFilters","internalColumnVisibility","setInternalColumnVisibility","columnVisibility","rowSelection","setRowSelection","expanded","setExpanded","columnSizing","setColumnSizing","currentRowId","setCurrentRowId","handleColumnSizingChange","updater","handleColumnVisibilityChange","table","useReactTable","getCoreRowModel","getExpandedRowModel","getPaginationRowModel","getSortedRowModel","getFilteredRowModel","handleResizeKeyDown","event","nextSize","old","useEffect","_a","rows","borderedClass","headerPinnedBg","jsx","cn","jsxs","Table","TableHeader","headerGroup","TableRow","isPinned","canResize","TableHead","flexRender","TableBody","_","rowIndex","TableCell","row","isSelected","isCurrent","rowBg","Fragment"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"data-table.js","sources":["../../../../src/components/ui/data-table/data-table.tsx"],"sourcesContent":["import {\n type CSSProperties,\n Fragment,\n type KeyboardEvent,\n type ReactNode,\n useEffect,\n useState,\n} from 'react';\nimport {\n type Cell,\n type Column,\n type ColumnDef,\n type ColumnFiltersState,\n type ColumnSizingState,\n type ExpandedState,\n type Header,\n type OnChangeFn,\n type Row,\n type RowData,\n type SortingState,\n type Table as TanstackTable,\n type VisibilityState,\n flexRender,\n getCoreRowModel,\n getExpandedRowModel,\n getFilteredRowModel,\n getPaginationRowModel,\n getSortedRowModel,\n useReactTable,\n} from '@tanstack/react-table';\n\nimport { useIntersectionObserver } from '@/hooks';\nimport { cn } from '@/lib/utils';\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from '../table';\n\n// Ported from `@acronis-platform/shadcn-uikit`'s `data-table`\n// (packages/ui-legacy/src/components/ui/data-table/). A TanStack-react-table v8\n// data grid composed over the ui-react Table primitives — sorting, filtering,\n// column visibility, row selection, pagination, and optional row expansion. The\n// presentational flags (`striped`, `bordered`, `skeleton`, `highlightCurrentRow`)\n// are borrowed from the Vue `AvTable`; behavioral features come from TanStack.\n// Pair with DataTableToolbar / DataTablePagination / DataTableColumnHeader, which\n// take the `table` instance returned to column cells via TanStack context.\n// The grid cells/rows/headers are themed by the Table primitives' `--ui-table-*`\n// tier; DataTable's own chrome reuses that tier too — the wrapper border matches\n// the cell borders (`--ui-table-global-row-border-color`), the empty-state uses\n// the muted table-value color, the current row the active-row color, and stripes\n// the secondary surface.\n//\n// Advanced-grid opt-ins built on native TanStack features:\n// • Column resizing -> `enableColumnResizing` + `columnResizing` state, with a\n// drag handle rendered from `header.getResizeHandler()`.\n// • Sticky columns -> `ColumnDef.meta.pin: 'left' | 'right'` drives TanStack's\n// native column-pinning API (`column.pin()` / `getStart()` / `getAfter()`),\n// surfaced as `position: sticky` cells with an opaque row-token background.\n\n// Extend TanStack's per-column `meta` with the flags DataTable reads. Augmenting\n// the module keeps `ColumnDef.meta.pin` type-safe at the call site.\ndeclare module '@tanstack/react-table' {\n // Type params must match TanStack's `ColumnMeta<TData, TValue>` arity/names for\n // declaration merging, even though this augmentation doesn't reference them.\n // eslint-disable-next-line unused-imports/no-unused-vars\n interface ColumnMeta<TData extends RowData, TValue> {\n /** Pin the column to a table edge (sticky while the grid scrolls horizontally). */\n pin?: 'left' | 'right';\n /**\n * Let the column's header + cells wrap onto multiple lines (drops the fixed\n * row height); mirrors the `Table` primitives' `wrap` prop on TableHead/TableCell.\n */\n wrap?: boolean;\n }\n}\n\n// Sticky offset + stacking for a pinned column, computed from TanStack's own\n// pinning geometry rather than hand-rolled CSS math. A subtle edge shadow (facing\n// the scrollable columns) separates the pinned column from content sliding\n// underneath it — the opaque background that actually hides that content lives\n// in the caller's className (see `headerPinnedBg`/`rowBg` below), not here.\nexport function getPinnedStyle<TData>(\n column: Column<TData, unknown>\n): CSSProperties | undefined {\n const pinned = column.getIsPinned();\n if (!pinned) return undefined;\n return {\n position: 'sticky',\n left: pinned === 'left' ? column.getStart('left') : undefined,\n right: pinned === 'right' ? column.getAfter('right') : undefined,\n zIndex: 1,\n // Derived from the same border token every other table divider uses (not a\n // hardcoded color), so the separator theme-adapts automatically.\n boxShadow:\n pinned === 'left'\n ? '4px 0 4px -4px var(--ui-table-global-row-border-color)'\n : '-4px 0 4px -4px var(--ui-table-global-row-border-color)',\n };\n}\n\n// A column's rendered width tracks TanStack's size model once the consumer has\n// opted in — either explicitly (a `size` set on the `ColumnDef`) or implicitly\n// (column resizing enabled, which needs every column's width to be deterministic\n// for the drag math to work). Without either, columns stay in native `<table>`\n// auto-layout so `size`'s internal default (TanStack falls back to 150) never\n// forces every untouched column to a fixed width.\nexport function getColumnWidth<TData>(\n column: Column<TData, unknown>,\n enableColumnResizing: boolean\n): number | undefined {\n if (enableColumnResizing || column.columnDef.size !== undefined) {\n return column.getSize();\n }\n return undefined;\n}\n\nfunction getHeaderStyle<TData>(\n header: Header<TData, unknown>,\n enableColumnResizing: boolean\n): CSSProperties | undefined {\n const pin = getPinnedStyle(header.column);\n const width = getColumnWidth(header.column, enableColumnResizing);\n if (!pin && width === undefined) return undefined;\n return { ...pin, width };\n}\n\nexport function getCellStyle<TData>(\n cell: Cell<TData, unknown>,\n enableColumnResizing: boolean\n): CSSProperties | undefined {\n const pin = getPinnedStyle(cell.column);\n const width = getColumnWidth(cell.column, enableColumnResizing);\n if (!pin && width === undefined) return undefined;\n return { ...pin, width };\n}\n\n// Matches TanStack's own `defaultColumnSizing` fallback bounds — the same\n// range `column.getSize()` already clamps to internally when a column\n// doesn't set its own `minSize`/`maxSize`.\nconst DEFAULT_MIN_COLUMN_SIZE = 20;\nconst DEFAULT_MAX_COLUMN_SIZE = Number.MAX_SAFE_INTEGER;\n\n/**\n * Computes the next column width for an Arrow-key resize step (Shift = larger\n * step), clamped to `[min, max]` regardless of which bound `currentSize`\n * started outside of. Returns `undefined` for any other key, so the caller\n * knows not to `preventDefault()`/resize.\n */\nexport function getResizeKeyboardStep(\n key: string,\n currentSize: number,\n { shiftKey, min, max }: { shiftKey: boolean; min: number; max: number }\n): number | undefined {\n const step = shiftKey ? 50 : 10;\n if (key === 'ArrowLeft')\n return Math.min(max, Math.max(min, currentSize - step));\n if (key === 'ArrowRight')\n return Math.max(min, Math.min(max, currentSize + step));\n return undefined;\n}\n\n// `columns`/`data` build DataTable's own table instance; `table` renders an\n// externally-built one instead. At least one of the two forms is required —\n// omitting both would otherwise silently render an empty table — but `table`\n// may still be passed alongside `columns`/`data` (e.g. to also drive a\n// composed toolbar/pagination from the same instance DataTable renders).\ntype DataTableDataSourceProps<TData, TValue> =\n | {\n columns: ColumnDef<TData, TValue>[];\n data: TData[];\n /**\n * Also drive an externally-built TanStack `table` instance (e.g. a\n * composed toolbar/pagination) from the same state as this DataTable.\n */\n table?: TanstackTable<TData>;\n }\n | {\n columns?: ColumnDef<TData, TValue>[];\n data?: TData[];\n /**\n * Render from an externally-built TanStack `table` instance instead of\n * DataTable's own — DataTable then owns no state and renders the caller's\n * instance as-is (sorting, filtering, pagination, row models, etc. are all\n * configured on that instance). Makes `columns`/`data` unnecessary (they're\n * only used to build DataTable's own instance) and the following props\n * no-ops (configure the equivalent directly on the external instance\n * instead): `columnVisibility`, `onColumnVisibilityChange`,\n * `onColumnSizingChange`, `enableColumnResizing`, `getRowCanExpand`,\n * `manualSorting`, `sorting`, `onSortingChange`, `paginationMode`,\n * `onLoadMore`, `loadMoreRootMargin`, `hasNextPage`, `isLoadingMore`.\n * `meta.pin`-driven column pinning is also skipped — pin/unpin the\n * caller's own instance via TanStack's `column.pin()` directly.\n */\n table: TanstackTable<TData>;\n };\n\ninterface DataTableOwnProps<TData> {\n /** Enables row expansion for rows that return true. Pair with `renderExpandedRow`. */\n getRowCanExpand?: (row: Row<TData>) => boolean;\n /**\n * Renders expanded content for an expanded row. Used together with\n * `getRowCanExpand`.\n */\n renderExpandedRow?: (row: Row<TData>) => ReactNode;\n /** Alternating row backgrounds. */\n striped?: boolean;\n /** Vertical borders between columns (rows already have horizontal borders). */\n bordered?: boolean;\n /** Highlight the row the user last clicked (the \"current\" row). */\n highlightCurrentRow?: boolean;\n /** Render placeholder skeleton rows instead of data (loading state). */\n skeleton?: boolean;\n /** Number of skeleton rows to render when `skeleton` is set. */\n skeletonRows?: number;\n /**\n * Opt in to interactive column resizing. Renders a drag handle at the trailing\n * edge of each resizable header cell (TanStack's native `columnResizing`).\n */\n enableColumnResizing?: boolean;\n /** Passthrough for the `columnSizing` state so a consumer can persist widths. */\n onColumnSizingChange?: OnChangeFn<ColumnSizingState>;\n /**\n * Controlled column-visibility state — pass this (with\n * `onColumnVisibilityChange`) to share one visibility state with an\n * external `useReactTable` instance (e.g. a composed toolbar). Uncontrolled\n * (internal state) when omitted.\n */\n columnVisibility?: VisibilityState;\n /** Passthrough for the `columnVisibility` state; pairs with `columnVisibility`. */\n onColumnVisibilityChange?: OnChangeFn<VisibilityState>;\n /**\n * Opt out of client-side sorting — pass already-sorted `data` and drive\n * sorting via `sorting`/`onSortingChange` (e.g. mapped to a server query by\n * the caller). Mapping sort state to a query and refetching stays the\n * caller's job; DataTable only skips its own comparator.\n */\n manualSorting?: boolean;\n /**\n * Controlled sorting state — pass this (with `onSortingChange`) to drive\n * sorting externally. Uncontrolled (internal state) when omitted.\n */\n sorting?: SortingState;\n /** Passthrough for the `sorting` state; pairs with `sorting`. */\n onSortingChange?: OnChangeFn<SortingState>;\n /**\n * Renders a full row, bypassing DataTable's default per-cell `flexRender`\n * path entirely (no `<TableRow>`/cell-styling/pinning of DataTable's own).\n * Use to swap in a custom, independently memoizable row component. The\n * caller owns the row's markup and equality semantics — reuse the exported\n * `getCellStyle`/`getPinnedStyle`/`getColumnWidth` helpers to match\n * DataTable's default cell styling if desired.\n *\n * Also bypasses DataTable's `renderExpandedRow` handling — a row rendered\n * via `renderRow` never gets an expanded-content row appended, even when\n * `getRowCanExpand` returns true for it. Read `row.getIsExpanded()` and\n * render the expanded content yourself if you need both.\n */\n renderRow?: (row: Row<TData>, rowIndex: number) => ReactNode;\n /**\n * Renders a custom empty state instead of the default \"No results.\" row.\n * Receives `hasFilters` (whether any column filter is currently applied) so\n * the caller can distinguish \"no data at all\" from \"no matches\" — the\n * actual copy/wording/localization stays the caller's job.\n */\n renderEmptyState?: (context: { hasFilters: boolean }) => ReactNode;\n /**\n * `'page'` (default) keeps today's client-paginated behavior. `'infinite'`\n * omits the paginated row model — `data` is assumed to be the full\n * accumulated array the caller appends to on each `onLoadMore` — and\n * renders a sentinel row that calls `onLoadMore` once it scrolls into view.\n * Does not compose with virtualization; for a large accumulated list, use\n * the `VirtualScrolling` recipe over the raw `Table` primitives instead.\n */\n paginationMode?: 'page' | 'infinite';\n /**\n * Called when the infinite-scroll sentinel intersects the viewport.\n * `paginationMode=\"infinite\"` only. The fetch-more call, cursor/offset\n * tracking, dedup, and accumulating `data` stay the caller's job. Requires\n * at least one row already rendered — an empty table with `data={[]}`\n * cannot use the sentinel to drive its very first fetch; seed the first\n * page yourself (e.g. on mount) and use `onLoadMore` for subsequent pages.\n */\n onLoadMore?: () => void;\n /**\n * Expands the sentinel's `IntersectionObserver` root margin (native CSS\n * margin syntax, e.g. `'400px'`) so `onLoadMore` fires before the sentinel\n * is literally visible — the closer the caller's fetch is to finishing by\n * the time the user actually scrolls there, the less often the trailing\n * loading row is seen. `paginationMode=\"infinite\"` only; no-op when `table`\n * is passed. How far this actually prefetches also depends on page size —\n * a large margin with small pages can trigger several `onLoadMore` calls\n * back-to-back as the user scrolls normally, which is expected.\n */\n loadMoreRootMargin?: string;\n /** Whether more rows are available to load. `paginationMode=\"infinite\"` only. */\n hasNextPage?: boolean;\n /**\n * Whether a load is in flight — suppresses further `onLoadMore` calls and\n * renders a trailing loading row. `paginationMode=\"infinite\"` only.\n */\n isLoadingMore?: boolean;\n}\n\nexport type DataTableProps<TData, TValue = unknown> = DataTableOwnProps<TData> &\n DataTableDataSourceProps<TData, TValue>;\n\nexport function DataTable<TData, TValue = unknown>({\n columns = [],\n data = [],\n table: externalTable,\n getRowCanExpand,\n renderExpandedRow,\n striped = false,\n bordered = false,\n highlightCurrentRow = false,\n skeleton = false,\n skeletonRows = 5,\n enableColumnResizing = false,\n onColumnSizingChange,\n columnVisibility: controlledColumnVisibility,\n onColumnVisibilityChange,\n manualSorting = false,\n sorting: controlledSorting,\n onSortingChange,\n renderRow,\n renderEmptyState,\n paginationMode = 'page',\n onLoadMore,\n loadMoreRootMargin,\n hasNextPage = false,\n isLoadingMore = false,\n}: DataTableProps<TData, TValue>) {\n const [internalSorting, setInternalSorting] = useState<SortingState>([]);\n const sorting = controlledSorting ?? internalSorting;\n const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);\n const [internalColumnVisibility, setInternalColumnVisibility] =\n useState<VisibilityState>({});\n const columnVisibility =\n controlledColumnVisibility ?? internalColumnVisibility;\n const [rowSelection, setRowSelection] = useState({});\n const [expanded, setExpanded] = useState<ExpandedState>({});\n const [columnSizing, setColumnSizing] = useState<ColumnSizingState>({});\n const [currentRowId, setCurrentRowId] = useState<string>();\n\n const handleColumnSizingChange: OnChangeFn<ColumnSizingState> = (updater) => {\n setColumnSizing(updater);\n onColumnSizingChange?.(updater);\n };\n\n const handleColumnVisibilityChange: OnChangeFn<VisibilityState> = (\n updater\n ) => {\n setInternalColumnVisibility(updater);\n onColumnVisibilityChange?.(updater);\n };\n\n const handleSortingChange: OnChangeFn<SortingState> = (updater) => {\n if (controlledSorting === undefined) {\n setInternalSorting(updater);\n }\n onSortingChange?.(updater);\n };\n\n // Built unconditionally — hooks can't be conditionally called — but only\n // feeds the render path below when no external `table` is passed (see\n // `table` below).\n const internalTable = useReactTable({\n data,\n columns,\n enableColumnResizing,\n columnResizeMode: 'onChange',\n getCoreRowModel: getCoreRowModel(),\n getExpandedRowModel: getExpandedRowModel(),\n ...(paginationMode === 'page'\n ? { getPaginationRowModel: getPaginationRowModel() }\n : {}),\n getRowCanExpand,\n onExpandedChange: setExpanded,\n manualSorting,\n onSortingChange: handleSortingChange,\n ...(manualSorting ? {} : { getSortedRowModel: getSortedRowModel() }),\n onColumnFiltersChange: setColumnFilters,\n getFilteredRowModel: getFilteredRowModel(),\n onColumnVisibilityChange: handleColumnVisibilityChange,\n onRowSelectionChange: setRowSelection,\n onColumnSizingChange: handleColumnSizingChange,\n state: {\n sorting,\n columnFilters,\n columnVisibility,\n rowSelection,\n expanded,\n columnSizing,\n },\n });\n\n // The caller's instance is the single source of truth when passed — it\n // configures its own row models/state, so DataTable just renders from it.\n const table = externalTable ?? internalTable;\n const isInfiniteScroll = !externalTable && paginationMode === 'infinite';\n // `enableColumnResizing` is documented as a no-op with an external `table`\n // (the caller owns that instance's ColumnSizing state), but ColumnSizing is\n // a built-in TanStack feature present on any instance — reading the raw\n // prop below would still render live resize handles that mutate the\n // caller's own instance. Gate it the same way as `isInfiniteScroll`.\n const resizingEnabled = enableColumnResizing && !externalTable;\n const sentinelRef = useIntersectionObserver<HTMLTableRowElement>({\n onIntersect: () => onLoadMore?.(),\n disabled: !isInfiniteScroll || !hasNextPage || isLoadingMore,\n rootMargin: loadMoreRootMargin,\n });\n\n // Arrow-key resize on the drag handle (see `canResize` below). Ignores any\n // modifier besides Shift so it doesn't hijack browser/OS shortcuts bound to\n // Ctrl/Alt/Cmd+Arrow (e.g. back navigation) while the handle has focus.\n const handleResizeKeyDown = (\n event: KeyboardEvent<HTMLDivElement>,\n header: Header<TData, unknown>\n ) => {\n if (event.ctrlKey || event.altKey || event.metaKey) return;\n const nextSize = getResizeKeyboardStep(event.key, header.column.getSize(), {\n shiftKey: event.shiftKey,\n min: header.column.columnDef.minSize ?? DEFAULT_MIN_COLUMN_SIZE,\n max: header.column.columnDef.maxSize ?? DEFAULT_MAX_COLUMN_SIZE,\n });\n if (nextSize === undefined) return;\n event.preventDefault();\n table.setColumnSizing((old) => ({ ...old, [header.column.id]: nextSize }));\n };\n\n // Read each column's `meta.pin` and drive TanStack's native pinning state.\n // Always calls `pin()` (rather than only when truthy) so a column whose\n // `meta.pin` is removed dynamically actually un-pins. Skipped for an\n // external `table` — DataTable owns no state in that mode (see the `table`\n // prop's tsdoc), so the caller's own pinning setup is left alone.\n useEffect(() => {\n if (externalTable) return;\n table.getAllLeafColumns().forEach((column) => {\n column.pin(column.columnDef.meta?.pin ?? false);\n });\n }, [table, columns, externalTable]);\n\n const rows = table.getRowModel().rows;\n // Vertical borders are opt-in; a trailing border on the last cell would\n // double up with the wrapper, so suppress it.\n const borderedClass = bordered\n ? '[&_th:not(:last-child)]:border-e [&_td:not(:last-child)]:border-e [&_th]:border-[var(--ui-table-global-row-border-color)] [&_td]:border-[var(--ui-table-global-row-border-color)]'\n : undefined;\n\n // A pinned header/body cell must be opaque so the cells scrolling under it\n // (same row) aren't visible. `--ui-table-data-row-color-idle` is\n // *transparent by design* (an idle row shows the page/card surface through\n // it), so it can't be reused here — pinned idle cells need the actual\n // resolved surface color instead (`--ui-background-surface-primary`, bridged\n // to `bg-background`). Non-idle states (selected/current/striped) already use\n // real opaque tokens and are safe to mirror as-is (see `rowBg` below).\n const headerPinnedBg = 'bg-background';\n\n return (\n <div\n className={cn(\n 'rounded-md border border-[var(--ui-table-global-row-border-color)]',\n borderedClass\n )}\n >\n <Table\n style={\n resizingEnabled ? { width: table.getCenterTotalSize() } : undefined\n }\n >\n <TableHeader>\n {table.getHeaderGroups().map((headerGroup) => (\n <TableRow key={headerGroup.id}>\n {headerGroup.headers.map((header) => {\n const isPinned = header.column.getIsPinned();\n const canResize =\n resizingEnabled && header.column.getCanResize();\n return (\n <TableHead\n key={header.id}\n wrap={header.column.columnDef.meta?.wrap}\n style={getHeaderStyle(header, resizingEnabled)}\n className={cn(\n canResize && 'relative',\n isPinned && headerPinnedBg\n )}\n >\n {header.isPlaceholder\n ? null\n : flexRender(\n header.column.columnDef.header,\n header.getContext()\n )}\n {canResize && (\n <div\n role=\"separator\"\n aria-orientation=\"vertical\"\n aria-label=\"Resize column\"\n aria-valuenow={header.column.getSize()}\n aria-valuemin={\n header.column.columnDef.minSize ??\n DEFAULT_MIN_COLUMN_SIZE\n }\n aria-valuemax={\n header.column.columnDef.maxSize ??\n DEFAULT_MAX_COLUMN_SIZE\n }\n tabIndex={0}\n onMouseDown={header.getResizeHandler()}\n onTouchStart={header.getResizeHandler()}\n onKeyDown={(event) =>\n handleResizeKeyDown(event, header)\n }\n className={cn(\n 'absolute end-0 top-0 h-full w-1 cursor-(--ui-resizable-cursor) touch-none select-none bg-[var(--ui-table-global-row-border-color)] opacity-0 transition-opacity hover:opacity-100 focus-visible:opacity-100 focus-visible:outline-2 focus-visible:outline-(--ui-focus-primary)',\n header.column.getIsResizing() && 'opacity-100'\n )}\n />\n )}\n </TableHead>\n );\n })}\n </TableRow>\n ))}\n </TableHeader>\n <TableBody>\n {skeleton ? (\n Array.from({ length: skeletonRows }).map((_, rowIndex) => (\n <TableRow\n key={`skeleton-${rowIndex}`}\n className=\"hover:bg-transparent\"\n >\n {table.getVisibleLeafColumns().map((column) => (\n <TableCell key={column.id}>\n <div className=\"h-4 w-full animate-pulse rounded bg-[var(--ui-background-surface-secondary)]\" />\n </TableCell>\n ))}\n </TableRow>\n ))\n ) : rows?.length ? (\n rows.map((row, rowIndex) => {\n if (renderRow) {\n return (\n <Fragment key={row.id}>{renderRow(row, rowIndex)}</Fragment>\n );\n }\n const isSelected = row.getIsSelected();\n const isCurrent = highlightCurrentRow && currentRowId === row.id;\n // Opaque background applied to pinned cells so sibling cells don't\n // show through while the grid scrolls horizontally. Mirrors the\n // row's own resolved background across selection/current/stripe —\n // the idle case falls back to the real surface color\n // (`bg-background`) since the row's own idle token is transparent\n // by design (see `headerPinnedBg` above).\n const rowBg =\n isSelected || isCurrent\n ? 'bg-[var(--ui-table-data-row-color-active)]'\n : striped && rowIndex % 2 === 1\n ? 'bg-[var(--ui-background-surface-secondary)]'\n : 'bg-background';\n return (\n <Fragment key={row.id}>\n <TableRow\n selected={isSelected}\n onClick={\n highlightCurrentRow\n ? () => setCurrentRowId(row.id)\n : undefined\n }\n className={cn(\n highlightCurrentRow && 'cursor-pointer',\n striped &&\n rowIndex % 2 === 1 &&\n !isSelected &&\n !isCurrent &&\n 'bg-[var(--ui-background-surface-secondary)]',\n isCurrent &&\n !isSelected &&\n 'bg-[var(--ui-table-data-row-color-active)]'\n )}\n >\n {row.getVisibleCells().map((cell) => {\n const isPinned = cell.column.getIsPinned();\n return (\n <TableCell\n key={cell.id}\n wrap={cell.column.columnDef.meta?.wrap}\n style={getCellStyle(cell, resizingEnabled)}\n className={cn(isPinned && rowBg)}\n >\n {flexRender(\n cell.column.columnDef.cell,\n cell.getContext()\n )}\n </TableCell>\n );\n })}\n </TableRow>\n {renderExpandedRow && row.getIsExpanded() && (\n <TableRow className=\"hover:bg-transparent\">\n <TableCell\n className=\"h-auto py-3\"\n colSpan={row.getVisibleCells().length}\n >\n {renderExpandedRow(row)}\n </TableCell>\n </TableRow>\n )}\n </Fragment>\n );\n })\n ) : renderEmptyState ? (\n <TableRow>\n <TableCell\n colSpan={table.getVisibleLeafColumns().length}\n className=\"h-24 text-center\"\n >\n {renderEmptyState({\n hasFilters: table.getState().columnFilters.length > 0,\n })}\n </TableCell>\n </TableRow>\n ) : (\n <TableRow>\n <TableCell\n colSpan={table.getVisibleLeafColumns().length}\n className=\"h-24 text-center text-[var(--ui-table-data-value-color-disabled)]\"\n >\n No results.\n </TableCell>\n </TableRow>\n )}\n {isInfiniteScroll && !skeleton && rows.length > 0 && hasNextPage && (\n <TableRow\n ref={sentinelRef}\n aria-hidden\n className=\"hover:bg-transparent\"\n >\n <TableCell\n colSpan={table.getVisibleLeafColumns().length}\n className=\"h-1 p-0\"\n />\n </TableRow>\n )}\n {isInfiniteScroll &&\n !skeleton &&\n rows.length > 0 &&\n isLoadingMore && (\n <TableRow className=\"hover:bg-transparent\">\n <TableCell colSpan={table.getVisibleLeafColumns().length}>\n <div\n role=\"status\"\n aria-live=\"polite\"\n className=\"h-4 w-full animate-pulse rounded bg-[var(--ui-background-surface-secondary)]\"\n >\n <span className=\"sr-only\">Loading more rows…</span>\n </div>\n </TableCell>\n </TableRow>\n )}\n </TableBody>\n </Table>\n </div>\n );\n}\n"],"names":["getPinnedStyle","column","pinned","getColumnWidth","enableColumnResizing","getHeaderStyle","header","pin","width","getCellStyle","cell","DEFAULT_MIN_COLUMN_SIZE","DEFAULT_MAX_COLUMN_SIZE","getResizeKeyboardStep","key","currentSize","shiftKey","min","max","step","DataTable","columns","data","externalTable","getRowCanExpand","renderExpandedRow","striped","bordered","highlightCurrentRow","skeleton","skeletonRows","onColumnSizingChange","controlledColumnVisibility","onColumnVisibilityChange","manualSorting","controlledSorting","onSortingChange","renderRow","renderEmptyState","paginationMode","onLoadMore","loadMoreRootMargin","hasNextPage","isLoadingMore","internalSorting","setInternalSorting","useState","sorting","columnFilters","setColumnFilters","internalColumnVisibility","setInternalColumnVisibility","columnVisibility","rowSelection","setRowSelection","expanded","setExpanded","columnSizing","setColumnSizing","currentRowId","setCurrentRowId","handleColumnSizingChange","updater","handleColumnVisibilityChange","handleSortingChange","internalTable","useReactTable","getCoreRowModel","getExpandedRowModel","getPaginationRowModel","getSortedRowModel","getFilteredRowModel","table","isInfiniteScroll","resizingEnabled","sentinelRef","useIntersectionObserver","handleResizeKeyDown","event","nextSize","old","useEffect","_a","rows","borderedClass","headerPinnedBg","jsx","cn","jsxs","Table","TableHeader","headerGroup","TableRow","isPinned","canResize","TableHead","flexRender","TableBody","_","rowIndex","TableCell","row","Fragment","isSelected","isCurrent","rowBg"],"mappings":"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"}
|
|
@@ -6,18 +6,18 @@ import { InputBox as C } from "../input/input.js";
|
|
|
6
6
|
const T = m.forwardRef(
|
|
7
7
|
({
|
|
8
8
|
className: g,
|
|
9
|
-
id:
|
|
9
|
+
id: b,
|
|
10
10
|
label: i,
|
|
11
11
|
required: u,
|
|
12
|
-
description:
|
|
12
|
+
description: v,
|
|
13
13
|
error: a,
|
|
14
14
|
clearable: f,
|
|
15
15
|
onClear: h,
|
|
16
16
|
disabled: e,
|
|
17
|
-
value:
|
|
17
|
+
value: o,
|
|
18
18
|
...I
|
|
19
19
|
}, N) => {
|
|
20
|
-
const y = m.useId(), l =
|
|
20
|
+
const y = m.useId(), l = b ?? y, d = `${l}-message`, r = a != null && a !== "", w = o != null && o !== "", p = !!f && w && !e, n = r ? a : v, x = n != null && n !== "";
|
|
21
21
|
return /* @__PURE__ */ s("div", { className: "flex w-full min-w-[var(--ui-input-text-global-container-width-min)] flex-col gap-[var(--ui-input-text-global-container-gap)]", children: [
|
|
22
22
|
i != null && i !== "" && /* @__PURE__ */ s(
|
|
23
23
|
"label",
|
|
@@ -47,8 +47,8 @@ const T = m.forwardRef(
|
|
|
47
47
|
ref: N,
|
|
48
48
|
id: l,
|
|
49
49
|
disabled: e,
|
|
50
|
-
value:
|
|
51
|
-
"aria-invalid":
|
|
50
|
+
value: o,
|
|
51
|
+
"aria-invalid": r || void 0,
|
|
52
52
|
"aria-required": u || void 0,
|
|
53
53
|
"aria-describedby": x ? d : void 0,
|
|
54
54
|
className: c(p && "pe-9", g),
|
|
@@ -61,7 +61,7 @@ const T = m.forwardRef(
|
|
|
61
61
|
type: "button",
|
|
62
62
|
onClick: h,
|
|
63
63
|
"aria-label": "Clear",
|
|
64
|
-
className: "absolute end-[var(--ui-input-text-global-box-padding-x)] top-1/2 flex size-4 -translate-y-1/2 items-center justify-center rounded-[var(--ui-input-text-global-box-border-radius)] text-[var(--ui-
|
|
64
|
+
className: "absolute end-[var(--ui-input-text-global-box-padding-x)] top-1/2 flex size-4 -translate-y-1/2 items-center justify-center rounded-[var(--ui-input-text-global-box-border-radius)] text-[var(--ui-button-icon-global-icon-color-idle)] outline-none focus-visible:ring-[3px] focus-visible:ring-[var(--ui-focus-primary)] [&_svg]:size-4 [&_svg]:shrink-0",
|
|
65
65
|
children: /* @__PURE__ */ t(j, {})
|
|
66
66
|
}
|
|
67
67
|
)
|
|
@@ -72,7 +72,7 @@ const T = m.forwardRef(
|
|
|
72
72
|
id: d,
|
|
73
73
|
className: c(
|
|
74
74
|
"text-xs leading-4",
|
|
75
|
-
|
|
75
|
+
r ? "text-[var(--ui-input-text-error-msg-error-color)]" : e ? "text-[var(--ui-input-text-normal-description-color-disabled)]" : "text-[var(--ui-input-text-normal-description-color-idle)]"
|
|
76
76
|
),
|
|
77
77
|
children: n
|
|
78
78
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"input-text.js","sources":["../../../../src/components/ui/input-text/input-text.tsx"],"sourcesContent":["import * as React from 'react';\nimport { TimesIcon } from '@acronis-platform/icons-react/stroke-mono';\n\nimport { cn } from '@/lib/utils';\nimport { InputBox } from '../input';\n\n// Mirrors the Figma \"InputText\" component: a full single-line text field built\n// around the bare `InputBox` primitive (themed by the `--ui-input-text-*` tier). It\n// adds the field furniture: an optional `label` (with an optional `required` `*`),\n// an optional clear (✕) button, and an optional `description` or `error` message\n// below. Passing `error` switches the field to its error treatment — the box gets\n// the red error border (via the input's `aria-invalid` styling) and the red error\n// message replaces the description. The clear button appears only while `clearable`\n// is set and the (controlled) field has a value, and calls `onClear`. Colors come\n// from the `--ui-input-text-*` tokens — label/required/description/error
|
|
1
|
+
{"version":3,"file":"input-text.js","sources":["../../../../src/components/ui/input-text/input-text.tsx"],"sourcesContent":["import * as React from 'react';\nimport { TimesIcon } from '@acronis-platform/icons-react/stroke-mono';\n\nimport { cn } from '@/lib/utils';\nimport { InputBox } from '../input';\n\n// Mirrors the Figma \"InputText\" component: a full single-line text field built\n// around the bare `InputBox` primitive (themed by the `--ui-input-text-*` tier). It\n// adds the field furniture: an optional `label` (with an optional `required` `*`),\n// an optional clear (✕) button, and an optional `description` or `error` message\n// below. Passing `error` switches the field to its error treatment — the box gets\n// the red error border (via the input's `aria-invalid` styling) and the red error\n// message replaces the description. The clear button appears only while `clearable`\n// is set and the (controlled) field has a value, and calls `onClear`. Colors come\n// from the `--ui-input-text-*` tokens — label/required/description/error — so brand\n// overrides are honored; the clear button is a ghost ButtonIcon (glyph\n// `--ui-button-icon-global-icon-color-idle`, since the input-text tier dropped its\n// own clear-icon token in the Figma sync) with a 3px `--ui-focus-primary` ring.\nexport interface InputTextProps\n extends Omit<React.ComponentPropsWithoutRef<'input'>, 'children'> {\n /** Field label, rendered above the input. */\n label?: React.ReactNode;\n /** Marks the field required — appends a `*` after the label. */\n required?: boolean;\n /** Helper text below the input. Hidden while `error` is set. */\n description?: React.ReactNode;\n /**\n * Error message below the input. Its presence switches the field to the error\n * treatment (red box border + red message).\n */\n error?: React.ReactNode;\n /** Show a clear (✕) button while the (controlled) field has a value. */\n clearable?: boolean;\n /** Called when the clear button is activated. */\n onClear?: () => void;\n}\n\nconst InputText = React.forwardRef<HTMLInputElement, InputTextProps>(\n (\n {\n className,\n id,\n label,\n required,\n description,\n error,\n clearable,\n onClear,\n disabled,\n value,\n ...props\n },\n ref\n ) => {\n const reactId = React.useId();\n const inputId = id ?? reactId;\n const messageId = `${inputId}-message`;\n\n const hasError = error != null && error !== '';\n const hasValue = value != null && value !== '';\n const showClear = Boolean(clearable) && hasValue && !disabled;\n const message = hasError ? error : description;\n const hasMessage = message != null && message !== '';\n\n return (\n <div className=\"flex w-full min-w-[var(--ui-input-text-global-container-width-min)] flex-col gap-[var(--ui-input-text-global-container-gap)]\">\n {label != null && label !== '' && (\n <label\n htmlFor={inputId}\n className={cn(\n 'flex gap-[var(--ui-input-text-global-container-label-gap)] text-sm leading-4',\n disabled\n ? 'text-[var(--ui-input-text-global-label-color-disabled)]'\n : 'text-[var(--ui-input-text-global-label-color-idle)]'\n )}\n >\n {label}\n {required && (\n <span\n aria-hidden=\"true\"\n className=\"text-[var(--ui-input-text-global-required-color)]\"\n >\n *\n </span>\n )}\n </label>\n )}\n\n <div className=\"relative\">\n <InputBox\n ref={ref}\n id={inputId}\n disabled={disabled}\n value={value}\n aria-invalid={hasError || undefined}\n aria-required={required || undefined}\n aria-describedby={hasMessage ? messageId : undefined}\n className={cn(showClear && 'pe-9', className)}\n {...props}\n />\n {showClear && (\n <button\n type=\"button\"\n onClick={onClear}\n aria-label=\"Clear\"\n className=\"absolute end-[var(--ui-input-text-global-box-padding-x)] top-1/2 flex size-4 -translate-y-1/2 items-center justify-center rounded-[var(--ui-input-text-global-box-border-radius)] text-[var(--ui-button-icon-global-icon-color-idle)] outline-none focus-visible:ring-[3px] focus-visible:ring-[var(--ui-focus-primary)] [&_svg]:size-4 [&_svg]:shrink-0\"\n >\n <TimesIcon />\n </button>\n )}\n </div>\n\n {hasMessage && (\n <p\n id={messageId}\n className={cn(\n 'text-xs leading-4',\n hasError\n ? 'text-[var(--ui-input-text-error-msg-error-color)]'\n : disabled\n ? 'text-[var(--ui-input-text-normal-description-color-disabled)]'\n : 'text-[var(--ui-input-text-normal-description-color-idle)]'\n )}\n >\n {message}\n </p>\n )}\n </div>\n );\n }\n);\nInputText.displayName = 'InputText';\n\nexport { InputText };\n"],"names":["InputText","React","className","id","label","required","description","error","clearable","onClear","disabled","value","props","ref","reactId","inputId","messageId","hasError","hasValue","showClear","message","hasMessage","jsxs","cn","jsx","InputBox","TimesIcon"],"mappings":";;;;;AAqCA,MAAMA,IAAYC,EAAM;AAAA,EACtB,CACE;AAAA,IACE,WAAAC;AAAA,IACA,IAAAC;AAAA,IACA,OAAAC;AAAA,IACA,UAAAC;AAAA,IACA,aAAAC;AAAA,IACA,OAAAC;AAAA,IACA,WAAAC;AAAA,IACA,SAAAC;AAAA,IACA,UAAAC;AAAA,IACA,OAAAC;AAAA,IACA,GAAGC;AAAA,EAAA,GAELC,MACG;AACH,UAAMC,IAAUb,EAAM,MAAA,GAChBc,IAAUZ,KAAMW,GAChBE,IAAY,GAAGD,CAAO,YAEtBE,IAAWV,KAAS,QAAQA,MAAU,IACtCW,IAAWP,KAAS,QAAQA,MAAU,IACtCQ,IAAY,EAAQX,KAAcU,KAAY,CAACR,GAC/CU,IAAUH,IAAWV,IAAQD,GAC7Be,IAAaD,KAAW,QAAQA,MAAY;AAElD,WACE,gBAAAE,EAAC,OAAA,EAAI,WAAU,gIACZ,UAAA;AAAA,MAAAlB,KAAS,QAAQA,MAAU,MAC1B,gBAAAkB;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,SAASP;AAAA,UACT,WAAWQ;AAAA,YACT;AAAA,YACAb,IACI,4DACA;AAAA,UAAA;AAAA,UAGL,UAAA;AAAA,YAAAN;AAAA,YACAC,KACC,gBAAAmB;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,eAAY;AAAA,gBACZ,WAAU;AAAA,gBACX,UAAA;AAAA,cAAA;AAAA,YAAA;AAAA,UAED;AAAA,QAAA;AAAA,MAAA;AAAA,MAKN,gBAAAF,EAAC,OAAA,EAAI,WAAU,YACb,UAAA;AAAA,QAAA,gBAAAE;AAAA,UAACC;AAAA,UAAA;AAAA,YACC,KAAAZ;AAAA,YACA,IAAIE;AAAA,YACJ,UAAAL;AAAA,YACA,OAAAC;AAAA,YACA,gBAAcM,KAAY;AAAA,YAC1B,iBAAeZ,KAAY;AAAA,YAC3B,oBAAkBgB,IAAaL,IAAY;AAAA,YAC3C,WAAWO,EAAGJ,KAAa,QAAQjB,CAAS;AAAA,YAC3C,GAAGU;AAAA,UAAA;AAAA,QAAA;AAAA,QAELO,KACC,gBAAAK;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,SAASf;AAAA,YACT,cAAW;AAAA,YACX,WAAU;AAAA,YAEV,4BAACiB,GAAA,CAAA,CAAU;AAAA,UAAA;AAAA,QAAA;AAAA,MACb,GAEJ;AAAA,MAECL,KACC,gBAAAG;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,IAAIR;AAAA,UACJ,WAAWO;AAAA,YACT;AAAA,YACAN,IACI,sDACAP,IACE,kEACA;AAAA,UAAA;AAAA,UAGP,UAAAU;AAAA,QAAA;AAAA,MAAA;AAAA,IACH,GAEJ;AAAA,EAEJ;AACF;AACApB,EAAU,cAAc;"}
|
|
@@ -3,37 +3,37 @@ import * as v from "react";
|
|
|
3
3
|
import { mergeProps as x } from "@base-ui/react/merge-props";
|
|
4
4
|
import { useRender as m } from "@base-ui/react/use-render";
|
|
5
5
|
import { SquareArrowUpRightIcon as u } from "@acronis-platform/icons-react/stroke-mono";
|
|
6
|
-
import { cn as
|
|
7
|
-
const
|
|
8
|
-
({ className:
|
|
6
|
+
import { cn as g } from "../../../lib/utils.js";
|
|
7
|
+
const p = v.forwardRef(
|
|
8
|
+
({ className: i, external: o, disabled: e, href: r, children: t, render: a, ...n }, l) => m({
|
|
9
9
|
render: a,
|
|
10
10
|
ref: l,
|
|
11
11
|
defaultTagName: "a",
|
|
12
12
|
props: x(
|
|
13
13
|
{
|
|
14
|
-
className:
|
|
15
|
-
"inline-flex items-center gap-[var(--ui-link-container-gap)] rounded-sm text-sm font-semibold leading-6 outline-none transition-colors [text-underline-position:from-font] [&_svg]:size-4 [&_svg]:shrink-0",
|
|
16
|
-
"text-[var(--ui-link-color-idle)] [text-decoration:var(--ui-link-text-decoration-idle)] [&_svg]:text-[var(--ui-link-external-icon-color-idle)]",
|
|
17
|
-
"hover:text-[var(--ui-link-color-hover)] hover:[text-decoration:var(--ui-link-text-decoration-hover)] hover:[&_svg]:text-[var(--ui-link-external-icon-color-hover)]",
|
|
18
|
-
"active:text-[var(--ui-link-color-active)] active:[text-decoration:var(--ui-link-text-decoration-active)] active:[&_svg]:text-[var(--ui-link-external-icon-color-active)]",
|
|
14
|
+
className: g(
|
|
15
|
+
"inline-flex items-center gap-[var(--ui-link-global-container-gap)] rounded-sm text-sm font-semibold leading-6 outline-none transition-colors [text-underline-position:from-font] [&_svg]:size-4 [&_svg]:shrink-0",
|
|
16
|
+
"text-[var(--ui-link-normal-text-color-idle)] [text-decoration:var(--ui-link-global-text-decoration-idle)] [&_svg]:text-[var(--ui-link-normal-external-icon-color-idle)]",
|
|
17
|
+
"hover:text-[var(--ui-link-normal-text-color-hover)] hover:[text-decoration:var(--ui-link-global-text-decoration-hover)] hover:[&_svg]:text-[var(--ui-link-normal-external-icon-color-hover)]",
|
|
18
|
+
"active:text-[var(--ui-link-normal-text-color-active)] active:[text-decoration:var(--ui-link-global-text-decoration-active)] active:[&_svg]:text-[var(--ui-link-normal-external-icon-color-active)]",
|
|
19
19
|
"focus-visible:ring-[3px] focus-visible:ring-[var(--ui-focus-primary)]",
|
|
20
|
-
"aria-disabled:pointer-events-none aria-disabled:text-[var(--ui-link-color-disabled)] aria-disabled:[text-decoration:var(--ui-link-text-decoration-disabled)] aria-disabled:[&_svg]:text-[var(--ui-link-external-icon-color-disabled)]",
|
|
21
|
-
|
|
20
|
+
"aria-disabled:pointer-events-none aria-disabled:text-[var(--ui-link-normal-text-color-disabled)] aria-disabled:[text-decoration:var(--ui-link-global-text-decoration-disabled)] aria-disabled:[&_svg]:text-[var(--ui-link-normal-external-icon-color-disabled)]",
|
|
21
|
+
i
|
|
22
22
|
),
|
|
23
|
-
href:
|
|
24
|
-
"aria-disabled":
|
|
25
|
-
tabIndex:
|
|
23
|
+
href: e ? void 0 : r,
|
|
24
|
+
"aria-disabled": e || void 0,
|
|
25
|
+
tabIndex: e ? -1 : void 0,
|
|
26
26
|
children: /* @__PURE__ */ c(s, { children: [
|
|
27
27
|
t,
|
|
28
|
-
|
|
28
|
+
o && /* @__PURE__ */ d(u, { size: 16 })
|
|
29
29
|
] })
|
|
30
30
|
},
|
|
31
31
|
n
|
|
32
32
|
)
|
|
33
33
|
})
|
|
34
34
|
);
|
|
35
|
-
|
|
35
|
+
p.displayName = "Link";
|
|
36
36
|
export {
|
|
37
|
-
|
|
37
|
+
p as Link
|
|
38
38
|
};
|
|
39
39
|
//# sourceMappingURL=link.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"link.js","sources":["../../../../src/components/ui/link/link.tsx"],"sourcesContent":["import * as React from 'react';\nimport { mergeProps } from '@base-ui/react/merge-props';\nimport { useRender } from '@base-ui/react/use-render';\nimport { SquareArrowUpRightIcon } from '@acronis-platform/icons-react/stroke-mono';\n\nimport { cn } from '@/lib/utils';\n\n// Mirrors the Figma \"Link\" component: an inline text link (semibold, 14/24) with an\n// optional trailing external-link icon (`external`). Themed by the `--ui-link-*`\n// tier — each state wires its own text color (`--ui-link-color-*`), text
|
|
1
|
+
{"version":3,"file":"link.js","sources":["../../../../src/components/ui/link/link.tsx"],"sourcesContent":["import * as React from 'react';\nimport { mergeProps } from '@base-ui/react/merge-props';\nimport { useRender } from '@base-ui/react/use-render';\nimport { SquareArrowUpRightIcon } from '@acronis-platform/icons-react/stroke-mono';\n\nimport { cn } from '@/lib/utils';\n\n// Mirrors the Figma \"Link\" component: an inline text link (semibold, 14/24) with an\n// optional trailing external-link icon (`external`). Themed by the `--ui-link-*`\n// tier — each state wires its own text color (`--ui-link-normal-text-color-*`), text\n// decoration (`--ui-link-global-text-decoration-*`; underline on hover only) and\n// external-icon color (`--ui-link-normal-external-icon-color-*`, kept separate from\n// the text per the tier). The tier also exposes an `inverse` set\n// (`--ui-link-inverse-*`) for links on dark/brand surfaces; it is not wired here yet.\n// Focus paints a 3px `--ui-focus-primary` ring. Polymorphic via Base UI `useRender`\n// — pass `render` to render a router `Link` instead of the default `<a>`. `disabled`\n// makes it inert: disabled color, removed from the tab order, no navigation.\n//\n// The Figma container has a fixed 32px height for grid alignment\n// (`--ui-link-global-container-height`); it is intentionally NOT applied here so the\n// link flows inline within prose.\nexport interface LinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {\n /** Append a trailing external-link icon (e.g. for links that leave the app). */\n external?: boolean;\n /** Render the link inert: disabled color, removed from the tab order, no navigation. */\n disabled?: boolean;\n /**\n * Replace the rendered `<a>` with another element or component (Base UI\n * composition) — e.g. a router `Link`. Props and class names are merged onto it.\n */\n render?: useRender.RenderProp;\n}\n\nconst Link = React.forwardRef<HTMLAnchorElement, LinkProps>(\n ({ className, external, disabled, href, children, render, ...props }, ref) =>\n useRender({\n render,\n ref,\n defaultTagName: 'a',\n props: mergeProps<'a'>(\n {\n className: cn(\n 'inline-flex items-center gap-[var(--ui-link-global-container-gap)] rounded-sm text-sm font-semibold leading-6 outline-none transition-colors [text-underline-position:from-font] [&_svg]:size-4 [&_svg]:shrink-0',\n 'text-[var(--ui-link-normal-text-color-idle)] [text-decoration:var(--ui-link-global-text-decoration-idle)] [&_svg]:text-[var(--ui-link-normal-external-icon-color-idle)]',\n 'hover:text-[var(--ui-link-normal-text-color-hover)] hover:[text-decoration:var(--ui-link-global-text-decoration-hover)] hover:[&_svg]:text-[var(--ui-link-normal-external-icon-color-hover)]',\n 'active:text-[var(--ui-link-normal-text-color-active)] active:[text-decoration:var(--ui-link-global-text-decoration-active)] active:[&_svg]:text-[var(--ui-link-normal-external-icon-color-active)]',\n 'focus-visible:ring-[3px] focus-visible:ring-[var(--ui-focus-primary)]',\n 'aria-disabled:pointer-events-none aria-disabled:text-[var(--ui-link-normal-text-color-disabled)] aria-disabled:[text-decoration:var(--ui-link-global-text-decoration-disabled)] aria-disabled:[&_svg]:text-[var(--ui-link-normal-external-icon-color-disabled)]',\n className\n ),\n href: disabled ? undefined : href,\n 'aria-disabled': disabled || undefined,\n tabIndex: disabled ? -1 : undefined,\n children: (\n <>\n {children}\n {external && <SquareArrowUpRightIcon size={16} />}\n </>\n ),\n },\n props\n ),\n })\n);\nLink.displayName = 'Link';\n\nexport { Link };\n"],"names":["Link","React","className","external","disabled","href","children","render","props","ref","useRender","mergeProps","cn","jsxs","Fragment","jsx","SquareArrowUpRightIcon"],"mappings":";;;;;;AAiCA,MAAMA,IAAOC,EAAM;AAAA,EACjB,CAAC,EAAE,WAAAC,GAAW,UAAAC,GAAU,UAAAC,GAAU,MAAAC,GAAM,UAAAC,GAAU,QAAAC,GAAQ,GAAGC,KAASC,MACpEC,EAAU;AAAA,IACR,QAAAH;AAAA,IACA,KAAAE;AAAA,IACA,gBAAgB;AAAA,IAChB,OAAOE;AAAA,MACL;AAAA,QACE,WAAWC;AAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACAV;AAAA,QAAA;AAAA,QAEF,MAAME,IAAW,SAAYC;AAAA,QAC7B,iBAAiBD,KAAY;AAAA,QAC7B,UAAUA,IAAW,KAAK;AAAA,QAC1B,UACE,gBAAAS,EAAAC,GAAA,EACG,UAAA;AAAA,UAAAR;AAAA,UACAH,KAAY,gBAAAY,EAACC,GAAA,EAAuB,MAAM,GAAA,CAAI;AAAA,QAAA,EAAA,CACjD;AAAA,MAAA;AAAA,MAGJR;AAAA,IAAA;AAAA,EACF,CACD;AACL;AACAR,EAAK,cAAc;"}
|
|
@@ -1,74 +1,184 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import * as
|
|
3
|
-
import {
|
|
4
|
-
|
|
1
|
+
import { jsx as a, jsxs as p, Fragment as v } from "react/jsx-runtime";
|
|
2
|
+
import * as n from "react";
|
|
3
|
+
import { mergeProps as N } from "@base-ui/react/merge-props";
|
|
4
|
+
import { useRender as P } from "@base-ui/react/use-render";
|
|
5
|
+
import { EllipsisIcon as A, CircleInfoIcon as C } from "@acronis-platform/icons-react/stroke-mono";
|
|
6
|
+
import { cn as i } from "../../../lib/utils.js";
|
|
7
|
+
import { DropdownMenu as D, DropdownMenuTrigger as I, DropdownMenuContent as M, DropdownMenuItem as S } from "../dropdown-menu/dropdown-menu.js";
|
|
8
|
+
import { ButtonIcon as O } from "../button-icon/button-icon.js";
|
|
9
|
+
import { Tooltip as j, TooltipTrigger as z, TooltipContent as B } from "../tooltip/tooltip.js";
|
|
10
|
+
import { Tag as F } from "../tag/tag.js";
|
|
11
|
+
import { Button as E } from "../button/button.js";
|
|
12
|
+
function H() {
|
|
13
|
+
const e = n.useRef(null), r = n.useRef(null), [t, c] = n.useState(!1);
|
|
14
|
+
return n.useEffect(() => {
|
|
15
|
+
const o = e.current, s = r.current;
|
|
16
|
+
if (!o || !s) return;
|
|
17
|
+
const l = () => c(s.scrollWidth > o.clientWidth);
|
|
18
|
+
l();
|
|
19
|
+
const d = new ResizeObserver(l);
|
|
20
|
+
return d.observe(o), () => d.disconnect();
|
|
21
|
+
}), { containerRef: e, measureRef: r, collapsed: t };
|
|
22
|
+
}
|
|
23
|
+
const W = n.forwardRef(({ className: e, ...r }, t) => /* @__PURE__ */ a(
|
|
5
24
|
"div",
|
|
6
25
|
{
|
|
7
|
-
ref:
|
|
26
|
+
ref: t,
|
|
8
27
|
"data-slot": "page-header",
|
|
9
28
|
role: "banner",
|
|
10
|
-
className:
|
|
11
|
-
...
|
|
29
|
+
className: i("flex w-full flex-col items-start gap-1", e),
|
|
30
|
+
...r
|
|
12
31
|
}
|
|
13
32
|
));
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
"nav",
|
|
17
|
-
{
|
|
18
|
-
ref: r,
|
|
19
|
-
"data-slot": "page-header-breadcrumb",
|
|
20
|
-
"aria-label": "Breadcrumb",
|
|
21
|
-
className: s("text-sm text-muted-foreground", e),
|
|
22
|
-
...a
|
|
23
|
-
}
|
|
24
|
-
));
|
|
25
|
-
i.displayName = "PageHeaderBreadcrumb";
|
|
26
|
-
const l = d.forwardRef(({ className: e, ...a }, r) => /* @__PURE__ */ t(
|
|
33
|
+
W.displayName = "PageHeader";
|
|
34
|
+
const k = n.forwardRef(({ className: e, ...r }, t) => /* @__PURE__ */ a(
|
|
27
35
|
"div",
|
|
28
36
|
{
|
|
29
|
-
ref:
|
|
37
|
+
ref: t,
|
|
30
38
|
"data-slot": "page-header-row",
|
|
31
|
-
className:
|
|
32
|
-
...
|
|
39
|
+
className: i("flex w-full items-center gap-2", e),
|
|
40
|
+
...r
|
|
33
41
|
}
|
|
34
42
|
));
|
|
35
|
-
|
|
36
|
-
const
|
|
43
|
+
k.displayName = "PageHeaderRow";
|
|
44
|
+
const $ = n.forwardRef(({ className: e, ...r }, t) => /* @__PURE__ */ a(
|
|
37
45
|
"h1",
|
|
38
46
|
{
|
|
39
|
-
ref:
|
|
47
|
+
ref: t,
|
|
40
48
|
"data-slot": "page-header-title",
|
|
41
|
-
className:
|
|
42
|
-
|
|
49
|
+
className: i(
|
|
50
|
+
"shrink-0 whitespace-nowrap text-2xl font-normal leading-8 text-foreground",
|
|
51
|
+
e
|
|
52
|
+
),
|
|
53
|
+
...r
|
|
43
54
|
}
|
|
44
55
|
));
|
|
45
|
-
|
|
46
|
-
const
|
|
47
|
-
|
|
56
|
+
$.displayName = "PageHeaderTitle";
|
|
57
|
+
const q = n.forwardRef(({ className: e, children: r, ...t }, c) => {
|
|
58
|
+
const o = n.Children.toArray(r), { containerRef: s, measureRef: l, collapsed: d } = H(), m = d && o.length > 1, g = m ? o.slice(1) : [], u = /* @__PURE__ */ p(v, { children: [
|
|
59
|
+
m ? /* @__PURE__ */ p(v, { children: [
|
|
60
|
+
o[0],
|
|
61
|
+
/* @__PURE__ */ p(j, { children: [
|
|
62
|
+
/* @__PURE__ */ a(z, { render: /* @__PURE__ */ a(F, { icon: /* @__PURE__ */ a(C, { size: 16 }) }), children: `+${g.length}` }),
|
|
63
|
+
/* @__PURE__ */ a(B, { children: /* @__PURE__ */ a("ul", { children: g.map((w, R) => {
|
|
64
|
+
var h;
|
|
65
|
+
return /* @__PURE__ */ a("li", { children: (h = w.props) == null ? void 0 : h.children }, R);
|
|
66
|
+
}) }) })
|
|
67
|
+
] })
|
|
68
|
+
] }) : o,
|
|
69
|
+
o.length > 1 && /* @__PURE__ */ a(
|
|
70
|
+
"div",
|
|
71
|
+
{
|
|
72
|
+
ref: l,
|
|
73
|
+
"aria-hidden": !0,
|
|
74
|
+
className: "invisible absolute flex items-center gap-2",
|
|
75
|
+
children: o
|
|
76
|
+
}
|
|
77
|
+
)
|
|
78
|
+
] });
|
|
79
|
+
return P({
|
|
80
|
+
ref: [c, s],
|
|
81
|
+
defaultTagName: "div",
|
|
82
|
+
props: {
|
|
83
|
+
"data-slot": "page-header-tags",
|
|
84
|
+
...N(
|
|
85
|
+
{
|
|
86
|
+
className: i(
|
|
87
|
+
"flex min-w-0 flex-1 items-center gap-2 overflow-hidden",
|
|
88
|
+
e
|
|
89
|
+
),
|
|
90
|
+
children: u
|
|
91
|
+
},
|
|
92
|
+
t
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
q.displayName = "PageHeaderTags";
|
|
98
|
+
const y = (e) => {
|
|
99
|
+
var r;
|
|
100
|
+
return e.type === E && ((r = e.props) == null ? void 0 : r.variant) === "secondary";
|
|
101
|
+
}, G = n.forwardRef(({ className: e, children: r, ...t }, c) => {
|
|
102
|
+
const o = n.Children.toArray(r), s = o.filter(y), { containerRef: l, measureRef: d, collapsed: m } = H(), g = m && s.length > 0, u = /* @__PURE__ */ p(D, { children: [
|
|
103
|
+
/* @__PURE__ */ a(
|
|
104
|
+
I,
|
|
105
|
+
{
|
|
106
|
+
render: /* @__PURE__ */ a(O, { variant: "secondary", "aria-label": "More actions", children: /* @__PURE__ */ a(A, { size: 16 }) })
|
|
107
|
+
}
|
|
108
|
+
),
|
|
109
|
+
/* @__PURE__ */ a(M, { align: "end", children: s.map((f, x) => {
|
|
110
|
+
const { variant: L, children: T, ...b } = f.props;
|
|
111
|
+
return /* @__PURE__ */ a(
|
|
112
|
+
S,
|
|
113
|
+
{
|
|
114
|
+
...b,
|
|
115
|
+
children: T
|
|
116
|
+
},
|
|
117
|
+
x
|
|
118
|
+
);
|
|
119
|
+
}) })
|
|
120
|
+
] }, "page-header-actions-more"), w = (f) => y(f) ? f === s[0] ? [u] : [] : [f], R = g ? o.flatMap(w) : o, h = /* @__PURE__ */ p(v, { children: [
|
|
121
|
+
R,
|
|
122
|
+
s.length > 0 && /* @__PURE__ */ a(
|
|
123
|
+
"div",
|
|
124
|
+
{
|
|
125
|
+
ref: d,
|
|
126
|
+
"aria-hidden": !0,
|
|
127
|
+
className: "invisible absolute flex items-center gap-4",
|
|
128
|
+
children: o
|
|
129
|
+
}
|
|
130
|
+
)
|
|
131
|
+
] });
|
|
132
|
+
return P({
|
|
133
|
+
ref: [c, l],
|
|
134
|
+
defaultTagName: "div",
|
|
135
|
+
props: {
|
|
136
|
+
"data-slot": "page-header-actions",
|
|
137
|
+
...N(
|
|
138
|
+
{
|
|
139
|
+
className: i(
|
|
140
|
+
"flex min-w-0 flex-1 items-center justify-end gap-4 overflow-hidden",
|
|
141
|
+
e
|
|
142
|
+
),
|
|
143
|
+
children: h
|
|
144
|
+
},
|
|
145
|
+
t
|
|
146
|
+
)
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
G.displayName = "PageHeaderActions";
|
|
151
|
+
const J = n.forwardRef(({ className: e, ...r }, t) => /* @__PURE__ */ a(
|
|
152
|
+
"div",
|
|
48
153
|
{
|
|
49
|
-
ref:
|
|
50
|
-
"data-slot": "page-header-description",
|
|
51
|
-
className:
|
|
52
|
-
...
|
|
154
|
+
ref: t,
|
|
155
|
+
"data-slot": "page-header-description-row",
|
|
156
|
+
className: i("flex max-w-lg items-start gap-2", e),
|
|
157
|
+
...r
|
|
53
158
|
}
|
|
54
159
|
));
|
|
55
|
-
|
|
56
|
-
const
|
|
57
|
-
"
|
|
160
|
+
J.displayName = "PageHeaderDescriptionRow";
|
|
161
|
+
const K = n.forwardRef(({ className: e, ...r }, t) => /* @__PURE__ */ a(
|
|
162
|
+
"p",
|
|
58
163
|
{
|
|
59
|
-
ref:
|
|
60
|
-
"data-slot": "page-header-
|
|
61
|
-
className:
|
|
62
|
-
|
|
164
|
+
ref: t,
|
|
165
|
+
"data-slot": "page-header-description",
|
|
166
|
+
className: i(
|
|
167
|
+
"min-w-0 flex-1 text-sm font-normal leading-6 text-muted-foreground",
|
|
168
|
+
e
|
|
169
|
+
),
|
|
170
|
+
...r
|
|
63
171
|
}
|
|
64
172
|
));
|
|
65
|
-
|
|
173
|
+
K.displayName = "PageHeaderDescription";
|
|
66
174
|
export {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
175
|
+
W as PageHeader,
|
|
176
|
+
G as PageHeaderActions,
|
|
177
|
+
K as PageHeaderDescription,
|
|
178
|
+
J as PageHeaderDescriptionRow,
|
|
179
|
+
k as PageHeaderRow,
|
|
180
|
+
q as PageHeaderTags,
|
|
181
|
+
$ as PageHeaderTitle,
|
|
182
|
+
H as useRowOverflow
|
|
73
183
|
};
|
|
74
184
|
//# sourceMappingURL=page-header.js.map
|