@datum-cloud/datum-ui 2.10.0 → 2.12.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.
- package/dist/components/features/data-table/components/column-header.d.ts +1 -1
- package/dist/components/features/data-table/components/content.d.ts +2 -1
- package/dist/components/features/data-table/components/list-pagination.d.ts +7 -0
- package/dist/components/features/data-table/components/list-panel.d.ts +10 -0
- package/dist/components/features/data-table/data-table.d.ts +4 -0
- package/dist/components/features/data-table/index.d.ts +1 -1
- package/dist/components/features/data-table/types.d.ts +62 -0
- package/dist/data-table/index.mjs +1 -1
- package/dist/{data-table-CW3-xqkg.mjs → data-table-BOe7pdpJ.mjs} +251 -27
- package/dist/grouped-table/index.mjs +1 -1
- package/dist/{grouped-table-DKUsSHpe.mjs → grouped-table-9nyHKSsK.mjs} +1 -1
- package/dist/index.mjs +2 -2
- package/dist/styles/themes/alpha.css +16 -0
- package/package.json +1 -1
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { RowData } from '@tanstack/react-table';
|
|
2
2
|
import type { ColumnHeaderProps } from '../types';
|
|
3
|
-
export declare function DataTableColumnHeader<TData extends RowData, TValue>({ column, title, className, }: ColumnHeaderProps<TData, TValue>): import("react").JSX.Element;
|
|
3
|
+
export declare function DataTableColumnHeader<TData extends RowData, TValue>({ column, title, className, density, }: ColumnHeaderProps<TData, TValue>): import("react").JSX.Element;
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
+
import type { RowData } from '@tanstack/react-table';
|
|
1
2
|
import type { ContentProps } from '../types';
|
|
2
|
-
export declare function DataTableContent({ emptyMessage, className, tableClassName, headerClassName, headerRowClassName, headerCellClassName, bodyClassName, rowClassName, cellClassName, }: ContentProps): import("react").JSX.Element;
|
|
3
|
+
export declare function DataTableContent<TData extends RowData = Record<string, any>>({ emptyMessage, className, tableClassName, headerClassName, headerRowClassName, headerCellClassName, bodyClassName, rowClassName, cellClassName, density, onRowClick, }: ContentProps<TData>): import("react").JSX.Element;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ListPaginationProps } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Compact list-page footer: `[pageSize ▾] Rows per page … 1-100 of N [resource]`
|
|
4
|
+
* + joined prev/next buttons. Pass `labels` to localize — this package ships no
|
|
5
|
+
* i18n of its own.
|
|
6
|
+
*/
|
|
7
|
+
export declare function DataTableListPagination({ pageSizes, resourceLabel, hideWhenSinglePage, labels, className, }: ListPaginationProps): import("react").JSX.Element | null;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { RowData } from '@tanstack/react-table';
|
|
2
|
+
import type { ListPanelProps } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* Compact "list table" card: search row + dense sticky-header table, matching
|
|
5
|
+
* staff-portal's Figma org-list pattern. Renders inside `DataTable.Client` /
|
|
6
|
+
* `DataTable.Server`, same as every other `DataTable.*` part. Pagination is
|
|
7
|
+
* deliberately not included — render `DataTable.ListPagination` as a sibling,
|
|
8
|
+
* below the panel.
|
|
9
|
+
*/
|
|
10
|
+
export declare function DataTableListPanel<TData extends RowData = Record<string, any>>({ search, searchSlot, toolbar, emptyMessage, loading, onRowClick, className, panelClassName, tableClassName, headerClassName, headerRowClassName, headerCellClassName, bodyClassName, rowClassName, cellClassName, }: ListPanelProps<TData>): import("react").JSX.Element;
|
|
@@ -2,6 +2,8 @@ import { DataTableBulkActions } from './components/bulk-actions';
|
|
|
2
2
|
import { DataTableColumnHeader } from './components/column-header';
|
|
3
3
|
import { DataTableContent } from './components/content';
|
|
4
4
|
import { DataTableInlineContent } from './components/inline-content';
|
|
5
|
+
import { DataTableListPagination } from './components/list-pagination';
|
|
6
|
+
import { DataTableListPanel } from './components/list-panel';
|
|
5
7
|
import { DataTableLoading } from './components/loading';
|
|
6
8
|
import { DataTablePagination } from './components/pagination';
|
|
7
9
|
import { DataTableRowActions } from './components/row-actions';
|
|
@@ -19,6 +21,8 @@ export declare const DataTable: {
|
|
|
19
21
|
readonly InlineContent: typeof DataTableInlineContent;
|
|
20
22
|
readonly ColumnHeader: typeof DataTableColumnHeader;
|
|
21
23
|
readonly Pagination: typeof DataTablePagination;
|
|
24
|
+
readonly ListPanel: typeof DataTableListPanel;
|
|
25
|
+
readonly ListPagination: typeof DataTableListPagination;
|
|
22
26
|
readonly Search: typeof DataTableSearch;
|
|
23
27
|
readonly RowActions: typeof DataTableRowActions;
|
|
24
28
|
readonly BulkActions: typeof DataTableBulkActions;
|
|
@@ -11,4 +11,4 @@ export type { SearchConfig } from './core/filter-engine';
|
|
|
11
11
|
export { createDataTableStore } from './core/store';
|
|
12
12
|
export { DataTable } from './data-table';
|
|
13
13
|
export { useDataTableFilters, useDataTableInlineContents, useDataTableLoading, useDataTablePagination, useDataTableRows, useDataTableSearch, useDataTableSelection, useDataTableSorting, } from './hooks/use-selectors';
|
|
14
|
-
export type { ActionItem, ActiveFiltersProps, BulkActionsProps, ClientPaginationControls, ClientPaginationState, ColumnHeaderProps, ContentProps, CreateStoreOptions, DataTableClientProps, DataTableContextValue, DataTableServerProps, DataTableState, DataTableStore, DataTableStoreState, FilterCheckboxProps, FilterDatePickerProps, FilterFn, FilterFnMap, FilterOption, FilterSelectProps, FilterStrategy, FilterValue, InlineContentEntry, InlineContentProps, InlineContentRenderParams, LoadingProps, PaginationProps, PaginationState, RowActionsProps, SearchProps, SelectionColumnOptions, ServerFetchArgs, ServerPaginationControls, ServerPaginationState, ServerTransformResult, StateAdapter, UseDataTableClientOptions, UseDataTableServerOptions, } from './types';
|
|
14
|
+
export type { ActionItem, ActiveFiltersProps, BulkActionsProps, ClientPaginationControls, ClientPaginationState, ColumnHeaderProps, ContentProps, CreateStoreOptions, DataTableClientProps, DataTableContextValue, DataTableServerProps, DataTableState, DataTableStore, DataTableStoreState, FilterCheckboxProps, FilterDatePickerProps, FilterFn, FilterFnMap, FilterOption, FilterSelectProps, FilterStrategy, FilterValue, InlineContentEntry, InlineContentProps, InlineContentRenderParams, ListPaginationProps, ListPanelProps, ListPanelSearchConfig, LoadingProps, PaginationProps, PaginationState, RowActionsProps, SearchProps, SelectionColumnOptions, ServerFetchArgs, ServerPaginationControls, ServerPaginationState, ServerTransformResult, StateAdapter, UseDataTableClientOptions, UseDataTableServerOptions, } from './types';
|
|
@@ -229,6 +229,8 @@ export interface ColumnHeaderProps<TData extends RowData, TValue> {
|
|
|
229
229
|
readonly column: Column<DataTableFeatures, TData, TValue>;
|
|
230
230
|
readonly title: string;
|
|
231
231
|
readonly className?: string;
|
|
232
|
+
/** `'compact'` swaps in the dense uppercase header label + dual-caret sort icon used by list pages. Default `'default'` renders unchanged. */
|
|
233
|
+
readonly density?: 'default' | 'compact';
|
|
232
234
|
}
|
|
233
235
|
export interface RowActionsProps<TData extends RowData> {
|
|
234
236
|
readonly row: Row<DataTableFeatures, TData>;
|
|
@@ -252,6 +254,10 @@ export interface ContentProps<TData extends RowData = Record<string, any>> {
|
|
|
252
254
|
readonly bodyClassName?: string;
|
|
253
255
|
readonly rowClassName?: string | ((row: Row<DataTableFeatures, TData>) => string);
|
|
254
256
|
readonly cellClassName?: string | ((cell: Cell<DataTableFeatures, TData, unknown>) => string);
|
|
257
|
+
/** `'compact'` applies the sticky mist header, dense rows, and borderless dividers used by list pages. Default `'default'` renders unchanged. */
|
|
258
|
+
readonly density?: 'default' | 'compact';
|
|
259
|
+
/** Fires on row click. Skipped when the click lands on a link, button, checkbox, form control, or the row-actions menu, so nested interactive elements keep working. */
|
|
260
|
+
readonly onRowClick?: (row: TData) => void;
|
|
255
261
|
}
|
|
256
262
|
export interface PaginationProps {
|
|
257
263
|
readonly pageSizes?: readonly number[];
|
|
@@ -282,6 +288,62 @@ export interface LoadingProps {
|
|
|
282
288
|
readonly columns?: number;
|
|
283
289
|
readonly className?: string;
|
|
284
290
|
}
|
|
291
|
+
/** Search-row config for {@link ListPanelProps}. */
|
|
292
|
+
export interface ListPanelSearchConfig {
|
|
293
|
+
readonly placeholder?: string;
|
|
294
|
+
/**
|
|
295
|
+
* Set together with `onChange` to drive the search input externally (server-side
|
|
296
|
+
* search). When set, the built-in store search is not read — the panel renders
|
|
297
|
+
* whatever rows the caller already scoped.
|
|
298
|
+
*/
|
|
299
|
+
readonly value?: string;
|
|
300
|
+
readonly onChange?: (value: string) => void;
|
|
301
|
+
}
|
|
302
|
+
export interface ListPanelProps<TData extends RowData = Record<string, any>> {
|
|
303
|
+
/** `false` hides the search row entirely. Defaults to the built-in (client-filtered) search. */
|
|
304
|
+
readonly search?: false | ListPanelSearchConfig;
|
|
305
|
+
/** Rendered to the right of the search input, inside the search row (e.g. a mobile filter trigger). */
|
|
306
|
+
readonly searchSlot?: ReactNode;
|
|
307
|
+
/** Rendered between the search row and the table (e.g. active-filter chips). */
|
|
308
|
+
readonly toolbar?: ReactNode;
|
|
309
|
+
readonly emptyMessage?: ReactNode;
|
|
310
|
+
/** Renders a skeleton in place of the table body. */
|
|
311
|
+
readonly loading?: boolean;
|
|
312
|
+
/** See {@link ContentProps.onRowClick}. */
|
|
313
|
+
readonly onRowClick?: (row: TData) => void;
|
|
314
|
+
/** Class on the panel's outer element. */
|
|
315
|
+
readonly className?: string;
|
|
316
|
+
/** Class on the card container (border/rounding/background) — merges with, and can override, the default chrome. */
|
|
317
|
+
readonly panelClassName?: string;
|
|
318
|
+
/**
|
|
319
|
+
* Forwarded to the underlying `DataTable.Content` (`density="compact"` already
|
|
320
|
+
* applied) — merges with, and can override, the compact preset. Use this for
|
|
321
|
+
* app-specific cell integrations (e.g. sizing a row-actions menu or a
|
|
322
|
+
* copy-button rendered inside a cell) that don't belong in the shared preset.
|
|
323
|
+
*/
|
|
324
|
+
readonly tableClassName?: string;
|
|
325
|
+
readonly headerClassName?: string;
|
|
326
|
+
readonly headerRowClassName?: string;
|
|
327
|
+
readonly headerCellClassName?: string;
|
|
328
|
+
readonly bodyClassName?: string;
|
|
329
|
+
readonly rowClassName?: string | ((row: Row<DataTableFeatures, TData>) => string);
|
|
330
|
+
readonly cellClassName?: string | ((cell: Cell<DataTableFeatures, TData, unknown>) => string);
|
|
331
|
+
}
|
|
332
|
+
export interface ListPaginationProps {
|
|
333
|
+
readonly pageSizes?: readonly number[];
|
|
334
|
+
/** Appended to the row-count summary, e.g. `"1-20 of 42 organizations"`. */
|
|
335
|
+
readonly resourceLabel?: string;
|
|
336
|
+
/** Hides the whole control when there's one page or fewer. */
|
|
337
|
+
readonly hideWhenSinglePage?: boolean;
|
|
338
|
+
/** English defaults; pass translated strings to localize. */
|
|
339
|
+
readonly labels?: {
|
|
340
|
+
readonly rowsPerPage?: string;
|
|
341
|
+
readonly of?: string;
|
|
342
|
+
readonly previousPage?: string;
|
|
343
|
+
readonly nextPage?: string;
|
|
344
|
+
};
|
|
345
|
+
readonly className?: string;
|
|
346
|
+
}
|
|
285
347
|
export type FilterStrategy = 'checkbox' | 'select' | 'date-gte' | 'date-lte' | FilterFn;
|
|
286
348
|
export interface DataTableStoreState<TData extends RowData> {
|
|
287
349
|
readonly data: TData[];
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { _ as useNuqsAdapter, a as useDataTablePagination, b as DEFAULT_PAGE_SIZE, c as useDataTableSelection, d as resolvePath, f as rowMatchesSearch, g as createSelectionColumn, h as DataTableColumnHeader, i as useDataTableLoading, l as useDataTableSorting, m as DataTableRowActions, n as useDataTableFilters, o as useDataTableRows, p as dataTableFeatures, r as useDataTableInlineContents, s as useDataTableSearch, t as DataTable, u as createDataTableStore, v as DEFAULT_DEBOUNCE_MS, x as DEFAULT_PAGE_SIZES, y as DEFAULT_LOADING_ROWS } from "../data-table-
|
|
1
|
+
import { _ as useNuqsAdapter, a as useDataTablePagination, b as DEFAULT_PAGE_SIZE, c as useDataTableSelection, d as resolvePath, f as rowMatchesSearch, g as createSelectionColumn, h as DataTableColumnHeader, i as useDataTableLoading, l as useDataTableSorting, m as DataTableRowActions, n as useDataTableFilters, o as useDataTableRows, p as dataTableFeatures, r as useDataTableInlineContents, s as useDataTableSearch, t as DataTable, u as createDataTableStore, v as DEFAULT_DEBOUNCE_MS, x as DEFAULT_PAGE_SIZES, y as DEFAULT_LOADING_ROWS } from "../data-table-BOe7pdpJ.mjs";
|
|
2
2
|
export { DEFAULT_DEBOUNCE_MS, DEFAULT_LOADING_ROWS, DEFAULT_PAGE_SIZE, DEFAULT_PAGE_SIZES, DataTable, DataTableColumnHeader, DataTableRowActions, createDataTableStore, createSelectionColumn, dataTableFeatures, resolvePath, rowMatchesSearch, useDataTableFilters, useDataTableInlineContents, useDataTableLoading, useDataTablePagination, useDataTableRows, useDataTableSearch, useDataTableSelection, useDataTableSorting, useNuqsAdapter };
|
|
@@ -12,7 +12,7 @@ import { t as CalendarDatePicker } from "./calendar-date-picker-DW31tDSa.mjs";
|
|
|
12
12
|
import { t as ActionRow } from "./action-row-DTvs91_3.mjs";
|
|
13
13
|
import { n as useDebouncedSearchInput } from "./use-debounced-search-input-yu_F0QBt.mjs";
|
|
14
14
|
import { t as MultiSelect } from "./multi-select-CH8KERkt.mjs";
|
|
15
|
-
import { ArrowDown, ArrowUp, ArrowUpDown, ChevronLeft, ChevronRight, MoreHorizontal, X } from "lucide-react";
|
|
15
|
+
import { ArrowDown, ArrowUp, ArrowUpDown, ChevronLeft, ChevronRight, MoreHorizontal, Search, X } from "lucide-react";
|
|
16
16
|
import { createContext, memo, use, useCallback, useContext, useEffect, useId, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
17
17
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
18
18
|
import { parseAsInteger, parseAsString, useQueryStates } from "nuqs";
|
|
@@ -151,13 +151,54 @@ function withSelectionColumn(columns, options = {}) {
|
|
|
151
151
|
}
|
|
152
152
|
//#endregion
|
|
153
153
|
//#region src/components/features/data-table/components/column-header.tsx
|
|
154
|
-
|
|
154
|
+
/** Figma `Datum App UI/Tables/Header/Dropdown` — two carets, one dimmed to show sort direction. */
|
|
155
|
+
function CompactSortIcon({ sorted }) {
|
|
156
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
157
|
+
className: "text-muted-foreground relative h-[15px] w-[5px] shrink-0",
|
|
158
|
+
"aria-hidden": "true",
|
|
159
|
+
children: [/* @__PURE__ */ jsx("svg", {
|
|
160
|
+
viewBox: "0 0 5.28572 3.25",
|
|
161
|
+
fill: "none",
|
|
162
|
+
className: cn("absolute inset-[26.66%_6.67%_58.34%_7.62%] overflow-visible", sorted === "desc" ? "opacity-35" : "opacity-100"),
|
|
163
|
+
children: /* @__PURE__ */ jsx("path", {
|
|
164
|
+
d: "M0.5 2.75L2.64286 0.5L4.78571 2.75",
|
|
165
|
+
stroke: "currentColor",
|
|
166
|
+
strokeLinecap: "round",
|
|
167
|
+
strokeLinejoin: "round"
|
|
168
|
+
})
|
|
169
|
+
}), /* @__PURE__ */ jsx("svg", {
|
|
170
|
+
viewBox: "0 0 5.28572 3.25",
|
|
171
|
+
fill: "none",
|
|
172
|
+
className: cn("absolute inset-[61.66%_6.67%_23.34%_7.62%] overflow-visible", sorted === "asc" ? "opacity-35" : "opacity-100"),
|
|
173
|
+
children: /* @__PURE__ */ jsx("path", {
|
|
174
|
+
d: "M0.5 0.5L2.64286 2.75L4.78571 0.5",
|
|
175
|
+
stroke: "currentColor",
|
|
176
|
+
strokeLinecap: "round",
|
|
177
|
+
strokeLinejoin: "round"
|
|
178
|
+
})
|
|
179
|
+
})]
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
function DataTableColumnHeader({ column, title, className, density = "default" }) {
|
|
183
|
+
const isCompact = density === "compact";
|
|
155
184
|
if (!column.getCanSort()) return /* @__PURE__ */ jsx("div", {
|
|
156
|
-
className: cn(className),
|
|
185
|
+
className: cn(isCompact && "text-xs leading-4 font-normal tracking-normal text-inherit uppercase", className),
|
|
157
186
|
"data-slot": "dt-column-header",
|
|
158
187
|
children: title
|
|
159
188
|
});
|
|
160
189
|
const sorted = column.getIsSorted();
|
|
190
|
+
const sortLabel = `Sort by ${title}${sorted === "asc" ? ", sorted ascending" : sorted === "desc" ? ", sorted descending" : ""}`;
|
|
191
|
+
if (isCompact) return /* @__PURE__ */ jsx("div", {
|
|
192
|
+
className: cn("flex items-center", className),
|
|
193
|
+
"data-slot": "dt-column-header",
|
|
194
|
+
children: /* @__PURE__ */ jsxs("button", {
|
|
195
|
+
type: "button",
|
|
196
|
+
className: "hover:text-foreground inline-flex h-9 cursor-pointer items-center gap-2 text-xs leading-4 font-normal tracking-normal text-inherit uppercase",
|
|
197
|
+
onClick: column.getToggleSortingHandler(),
|
|
198
|
+
"aria-label": sortLabel,
|
|
199
|
+
children: [/* @__PURE__ */ jsx("span", { children: title }), /* @__PURE__ */ jsx(CompactSortIcon, { sorted })]
|
|
200
|
+
})
|
|
201
|
+
});
|
|
161
202
|
return /* @__PURE__ */ jsx("div", {
|
|
162
203
|
className: cn("flex items-center gap-2", className),
|
|
163
204
|
"data-slot": "dt-column-header",
|
|
@@ -165,7 +206,7 @@ function DataTableColumnHeader({ column, title, className }) {
|
|
|
165
206
|
type: "button",
|
|
166
207
|
className: "flex items-center gap-1 hover:text-foreground -ml-3 h-8 px-3 cursor-pointer",
|
|
167
208
|
onClick: column.getToggleSortingHandler(),
|
|
168
|
-
"aria-label":
|
|
209
|
+
"aria-label": sortLabel,
|
|
169
210
|
children: [/* @__PURE__ */ jsx("span", { children: title }), sorted === "desc" ? /* @__PURE__ */ jsx(ArrowDown, { className: "size-4" }) : sorted === "asc" ? /* @__PURE__ */ jsx(ArrowUp, { className: "size-4" }) : /* @__PURE__ */ jsx(ArrowUpDown, { className: "size-4" })]
|
|
170
211
|
})
|
|
171
212
|
});
|
|
@@ -870,10 +911,33 @@ function DataTableBulkActions({ children, className }) {
|
|
|
870
911
|
}
|
|
871
912
|
//#endregion
|
|
872
913
|
//#region src/components/features/data-table/components/content.tsx
|
|
914
|
+
/**
|
|
915
|
+
* Per-slot class presets keyed by `density`. `'default'` is intentionally empty
|
|
916
|
+
* so omitting `density` (or passing `'default'`) renders identically to before
|
|
917
|
+
* this prop existed. Every preset only ever *adds* to what a caller passes via
|
|
918
|
+
* the matching `*ClassName` prop — `cn(preset, callerClassName)` below lets the
|
|
919
|
+
* caller's own classes win on conflict.
|
|
920
|
+
*/
|
|
921
|
+
const DENSITY_PRESETS = {
|
|
922
|
+
default: {},
|
|
923
|
+
compact: {
|
|
924
|
+
className: "overflow-auto [&>div]:overflow-visible",
|
|
925
|
+
headerClassName: "[&_tr]:border-0",
|
|
926
|
+
headerRowClassName: "border-0 hover:bg-transparent",
|
|
927
|
+
headerCellClassName: cn("sticky top-0 z-10 h-9 border-b border-border bg-table-header-background px-4", "text-xs leading-4 font-normal tracking-normal text-table-header-foreground uppercase"),
|
|
928
|
+
bodyClassName: "[&_tr:last-child]:border-b-0",
|
|
929
|
+
rowClassName: "border-0 hover:bg-muted/30",
|
|
930
|
+
cellClassName: "border-b border-border px-4 py-2 text-sm"
|
|
931
|
+
}
|
|
932
|
+
};
|
|
873
933
|
function resolveClassName(value, item) {
|
|
874
934
|
if (typeof value === "function") return value(item);
|
|
875
935
|
return value;
|
|
876
936
|
}
|
|
937
|
+
/** Clicks inside these should drive their own control, not the row's `onRowClick`. */
|
|
938
|
+
function isInteractiveTarget(target) {
|
|
939
|
+
return target instanceof HTMLElement && target.closest("a, button, [role=\"checkbox\"], input, textarea, select, [data-slot=\"dt-row-actions\"]") != null;
|
|
940
|
+
}
|
|
877
941
|
function renderInlineContentRow(entry, colSpan, rows) {
|
|
878
942
|
return /* @__PURE__ */ jsx(TableRow, {
|
|
879
943
|
"data-slot": "dt-inline-content",
|
|
@@ -888,7 +952,7 @@ function renderInlineContentRow(entry, colSpan, rows) {
|
|
|
888
952
|
})
|
|
889
953
|
}, entry.id);
|
|
890
954
|
}
|
|
891
|
-
function DataTableContent({ emptyMessage, className, tableClassName, headerClassName, headerRowClassName, headerCellClassName, bodyClassName, rowClassName, cellClassName }) {
|
|
955
|
+
function DataTableContent({ emptyMessage, className, tableClassName, headerClassName, headerRowClassName, headerCellClassName, bodyClassName, rowClassName, cellClassName, density = "default", onRowClick }) {
|
|
892
956
|
const { rows, headerGroups, totalColumns } = useDataTableRows();
|
|
893
957
|
const { isLoading, columnCount } = useDataTableLoading();
|
|
894
958
|
const { pageSize } = useDataTablePagination();
|
|
@@ -896,38 +960,42 @@ function DataTableContent({ emptyMessage, className, tableClassName, headerClass
|
|
|
896
960
|
const openInlineContents = useMemo(() => inlineContents.filter((e) => e.open), [inlineContents]);
|
|
897
961
|
const colSpan = totalColumns;
|
|
898
962
|
const skeletonColumns = totalColumns || columnCount || 5;
|
|
963
|
+
const preset = DENSITY_PRESETS[density];
|
|
899
964
|
return /* @__PURE__ */ jsx("div", {
|
|
900
|
-
className: cn("datum-ui-data-table", className),
|
|
965
|
+
className: cn("datum-ui-data-table", preset.className, className),
|
|
901
966
|
"data-slot": "dt",
|
|
902
967
|
style: { overflowX: "auto" },
|
|
903
968
|
children: /* @__PURE__ */ jsxs(Table, {
|
|
904
969
|
className: cn(tableClassName),
|
|
905
970
|
"data-slot": "dt-table",
|
|
906
971
|
children: [/* @__PURE__ */ jsx(TableHeader, {
|
|
907
|
-
className: cn(headerClassName),
|
|
972
|
+
className: cn(preset.headerClassName, headerClassName),
|
|
908
973
|
"data-slot": "dt-header",
|
|
909
974
|
children: headerGroups.map((headerGroup) => /* @__PURE__ */ jsx(TableRow, {
|
|
910
|
-
className: cn(headerRowClassName),
|
|
975
|
+
className: cn(preset.headerRowClassName, headerRowClassName),
|
|
911
976
|
"data-slot": "dt-header-row",
|
|
912
977
|
children: headerGroup.headers.map((header) => /* @__PURE__ */ jsx(TableHead, {
|
|
913
|
-
className: cn(headerCellClassName),
|
|
978
|
+
className: cn(preset.headerCellClassName, headerCellClassName),
|
|
914
979
|
"data-slot": "dt-header-cell",
|
|
915
980
|
children: header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())
|
|
916
981
|
}, header.id))
|
|
917
982
|
}, headerGroup.id))
|
|
918
983
|
}), /* @__PURE__ */ jsxs(TableBody, {
|
|
919
|
-
className: cn(bodyClassName),
|
|
984
|
+
className: cn(preset.bodyClassName, bodyClassName),
|
|
920
985
|
"data-slot": "dt-body",
|
|
921
986
|
children: [openInlineContents.filter((e) => e.position === "top").map((entry) => renderInlineContentRow(entry, colSpan, rows)), rows.length > 0 ? rows.map((row) => {
|
|
922
987
|
const rowEntry = openInlineContents.find((e) => e.position === "row" && e.rowId === row.id);
|
|
923
988
|
if (rowEntry) return renderInlineContentRow(rowEntry, colSpan, rows);
|
|
924
989
|
return /* @__PURE__ */ jsx(TableRow, {
|
|
925
|
-
className: cn(resolveClassName(rowClassName, row)),
|
|
990
|
+
className: cn(preset.rowClassName, resolveClassName(rowClassName, row), onRowClick && "cursor-pointer"),
|
|
926
991
|
style: { transitionProperty: "none" },
|
|
927
992
|
"data-slot": "dt-row",
|
|
928
993
|
"data-state": row.getIsSelected() ? "selected" : void 0,
|
|
994
|
+
onClick: onRowClick ? (e) => {
|
|
995
|
+
if (!isInteractiveTarget(e.target)) onRowClick(row.original);
|
|
996
|
+
} : void 0,
|
|
929
997
|
children: row.getVisibleCells().map((cell) => /* @__PURE__ */ jsx(TableCell, {
|
|
930
|
-
className: cn(resolveClassName(cellClassName, cell)),
|
|
998
|
+
className: cn(preset.cellClassName, resolveClassName(cellClassName, cell)),
|
|
931
999
|
"data-slot": "dt-cell",
|
|
932
1000
|
children: flexRender(cell.column.columnDef.cell, cell.getContext())
|
|
933
1001
|
}, cell.id))
|
|
@@ -1002,6 +1070,175 @@ function DataTableInlineContent({ position, rowId, open, onClose, className, chi
|
|
|
1002
1070
|
return null;
|
|
1003
1071
|
}
|
|
1004
1072
|
//#endregion
|
|
1073
|
+
//#region src/components/features/data-table/components/list-pagination.tsx
|
|
1074
|
+
const DEFAULT_LIST_PAGE_SIZES = [
|
|
1075
|
+
10,
|
|
1076
|
+
20,
|
|
1077
|
+
50,
|
|
1078
|
+
100
|
|
1079
|
+
];
|
|
1080
|
+
const DEFAULT_LABELS = {
|
|
1081
|
+
rowsPerPage: "Rows per page",
|
|
1082
|
+
of: "of",
|
|
1083
|
+
previousPage: "Previous page",
|
|
1084
|
+
nextPage: "Next page"
|
|
1085
|
+
};
|
|
1086
|
+
/**
|
|
1087
|
+
* Compact list-page footer: `[pageSize ▾] Rows per page … 1-100 of N [resource]`
|
|
1088
|
+
* + joined prev/next buttons. Pass `labels` to localize — this package ships no
|
|
1089
|
+
* i18n of its own.
|
|
1090
|
+
*/
|
|
1091
|
+
function DataTableListPagination({ pageSizes = DEFAULT_LIST_PAGE_SIZES, resourceLabel, hideWhenSinglePage = false, labels, className }) {
|
|
1092
|
+
const { canNextPage, canPrevPage, nextPage, prevPage, pageIndex, pageCount, pageSize, setPageSize, totalRows } = useDataTablePagination();
|
|
1093
|
+
const t = {
|
|
1094
|
+
...DEFAULT_LABELS,
|
|
1095
|
+
...labels
|
|
1096
|
+
};
|
|
1097
|
+
if (hideWhenSinglePage && pageCount <= 1) return null;
|
|
1098
|
+
const startRow = totalRows === 0 ? 0 : pageIndex * pageSize + 1;
|
|
1099
|
+
const endRow = Math.min((pageIndex + 1) * pageSize, totalRows);
|
|
1100
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
1101
|
+
className: cn("flex h-7 w-full items-center justify-between gap-3", className),
|
|
1102
|
+
"data-slot": "dt-list-pagination",
|
|
1103
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
1104
|
+
className: "flex items-center gap-3",
|
|
1105
|
+
children: [/* @__PURE__ */ jsxs(Select, {
|
|
1106
|
+
value: String(pageSize),
|
|
1107
|
+
onValueChange: (value) => setPageSize(Number(value)),
|
|
1108
|
+
children: [/* @__PURE__ */ jsx(SelectTrigger, {
|
|
1109
|
+
className: cn("border-border text-muted-foreground h-7 w-[4.5rem] gap-1.5 rounded-md px-2.5 py-0", "min-h-0 text-xs font-normal shadow-none"),
|
|
1110
|
+
children: /* @__PURE__ */ jsx(SelectValue, { placeholder: String(pageSize) })
|
|
1111
|
+
}), /* @__PURE__ */ jsx(SelectContent, {
|
|
1112
|
+
side: "top",
|
|
1113
|
+
children: pageSizes.map((size) => /* @__PURE__ */ jsx(SelectItem, {
|
|
1114
|
+
value: String(size),
|
|
1115
|
+
children: size
|
|
1116
|
+
}, size))
|
|
1117
|
+
})]
|
|
1118
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
1119
|
+
className: "text-muted-foreground text-xs leading-4 whitespace-nowrap",
|
|
1120
|
+
children: t.rowsPerPage
|
|
1121
|
+
})]
|
|
1122
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
1123
|
+
className: "flex items-center gap-3",
|
|
1124
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
1125
|
+
className: "text-muted-foreground text-xs leading-4 whitespace-nowrap tabular-nums",
|
|
1126
|
+
children: `${startRow}-${endRow} ${t.of} ${totalRows}${resourceLabel ? ` ${resourceLabel}` : ""}`
|
|
1127
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
1128
|
+
className: "border-border flex items-center overflow-hidden rounded-md border",
|
|
1129
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
1130
|
+
theme: "outline",
|
|
1131
|
+
size: "icon",
|
|
1132
|
+
className: "border-border size-7 rounded-none border-0 border-r shadow-none",
|
|
1133
|
+
onClick: prevPage,
|
|
1134
|
+
disabled: !canPrevPage,
|
|
1135
|
+
"aria-label": t.previousPage,
|
|
1136
|
+
children: /* @__PURE__ */ jsx(ChevronLeft, { className: "size-3.5" })
|
|
1137
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
1138
|
+
theme: "outline",
|
|
1139
|
+
size: "icon",
|
|
1140
|
+
className: "size-7 rounded-none border-0 shadow-none",
|
|
1141
|
+
onClick: nextPage,
|
|
1142
|
+
disabled: !canNextPage,
|
|
1143
|
+
"aria-label": t.nextPage,
|
|
1144
|
+
children: /* @__PURE__ */ jsx(ChevronRight, { className: "size-3.5" })
|
|
1145
|
+
})]
|
|
1146
|
+
})]
|
|
1147
|
+
})]
|
|
1148
|
+
});
|
|
1149
|
+
}
|
|
1150
|
+
//#endregion
|
|
1151
|
+
//#region src/components/features/data-table/components/search.tsx
|
|
1152
|
+
function DataTableSearch({ placeholder = "Search...", debounceMs = 300, className, disabled }) {
|
|
1153
|
+
const { search, setSearch } = useDataTableSearch();
|
|
1154
|
+
const [inputValue, setInputValue] = useDebouncedSearchInput(search, setSearch, debounceMs);
|
|
1155
|
+
return /* @__PURE__ */ jsx(Input, {
|
|
1156
|
+
placeholder,
|
|
1157
|
+
value: inputValue,
|
|
1158
|
+
onChange: (e) => setInputValue(e.target.value),
|
|
1159
|
+
className,
|
|
1160
|
+
disabled,
|
|
1161
|
+
"aria-label": placeholder,
|
|
1162
|
+
"data-slot": "dt-search"
|
|
1163
|
+
});
|
|
1164
|
+
}
|
|
1165
|
+
//#endregion
|
|
1166
|
+
//#region src/components/features/data-table/components/list-panel.tsx
|
|
1167
|
+
const LOADING_SKELETON_ROWS = 8;
|
|
1168
|
+
const SEARCH_INPUT_CLASS = "h-10 border-0 bg-transparent pl-9 shadow-none focus-visible:shadow-none focus-visible:ring-0";
|
|
1169
|
+
function ListPanelSkeleton({ columnCount }) {
|
|
1170
|
+
const cols = Math.max(columnCount, 1);
|
|
1171
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
1172
|
+
className: "min-h-0 flex-1 overflow-hidden",
|
|
1173
|
+
"data-slot": "dt-list-panel-loading",
|
|
1174
|
+
"aria-busy": "true",
|
|
1175
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
1176
|
+
className: "border-border bg-table-header-background flex h-9 items-center border-b px-4",
|
|
1177
|
+
children: Array.from({ length: cols }, (_, i) => /* @__PURE__ */ jsx("div", {
|
|
1178
|
+
className: "min-w-0 flex-1 px-2 first:pl-0 last:pr-0",
|
|
1179
|
+
children: /* @__PURE__ */ jsx(Skeleton, { className: "h-2.5 w-16" })
|
|
1180
|
+
}, i))
|
|
1181
|
+
}), Array.from({ length: LOADING_SKELETON_ROWS }, (_, row) => /* @__PURE__ */ jsx("div", {
|
|
1182
|
+
className: "border-border flex h-8 items-center border-b px-4",
|
|
1183
|
+
"data-slot": "dt-list-panel-skeleton-row",
|
|
1184
|
+
children: Array.from({ length: cols }, (_, col) => /* @__PURE__ */ jsx("div", {
|
|
1185
|
+
className: "min-w-0 flex-1 px-2 first:pl-0 last:pr-0",
|
|
1186
|
+
children: /* @__PURE__ */ jsx(Skeleton, { className: cn("h-3", col % 3 === 0 ? "w-3/4" : col % 3 === 1 ? "w-1/2" : "w-2/3") })
|
|
1187
|
+
}, col))
|
|
1188
|
+
}, row))]
|
|
1189
|
+
});
|
|
1190
|
+
}
|
|
1191
|
+
/**
|
|
1192
|
+
* Compact "list table" card: search row + dense sticky-header table, matching
|
|
1193
|
+
* staff-portal's Figma org-list pattern. Renders inside `DataTable.Client` /
|
|
1194
|
+
* `DataTable.Server`, same as every other `DataTable.*` part. Pagination is
|
|
1195
|
+
* deliberately not included — render `DataTable.ListPagination` as a sibling,
|
|
1196
|
+
* below the panel.
|
|
1197
|
+
*/
|
|
1198
|
+
function DataTableListPanel({ search = {}, searchSlot, toolbar, emptyMessage, loading = false, onRowClick, className, panelClassName, tableClassName, headerClassName, headerRowClassName, headerCellClassName, bodyClassName, rowClassName, cellClassName }) {
|
|
1199
|
+
const { totalColumns } = useDataTableRows();
|
|
1200
|
+
const showSearch = search !== false;
|
|
1201
|
+
const isControlledSearch = showSearch && (search.value !== void 0 || search.onChange !== void 0);
|
|
1202
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
1203
|
+
className: cn("bg-card text-card-foreground border-card-border flex min-h-0 flex-1 flex-col overflow-hidden rounded-xl border", panelClassName, className),
|
|
1204
|
+
"data-slot": "dt-list-panel",
|
|
1205
|
+
children: [
|
|
1206
|
+
showSearch && /* @__PURE__ */ jsxs("div", {
|
|
1207
|
+
className: "flex shrink-0 items-center gap-1 border-b pr-2",
|
|
1208
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
1209
|
+
className: "relative min-w-0 flex-1",
|
|
1210
|
+
children: [/* @__PURE__ */ jsx(Search, {
|
|
1211
|
+
className: "text-muted-foreground absolute top-1/2 left-3 size-4 -translate-y-1/2",
|
|
1212
|
+
"aria-hidden": "true"
|
|
1213
|
+
}), isControlledSearch ? /* @__PURE__ */ jsx(Input, {
|
|
1214
|
+
placeholder: search.placeholder,
|
|
1215
|
+
value: search.value,
|
|
1216
|
+
onChange: (e) => search.onChange?.(e.target.value),
|
|
1217
|
+
className: SEARCH_INPUT_CLASS
|
|
1218
|
+
}) : /* @__PURE__ */ jsx(DataTableSearch, {
|
|
1219
|
+
placeholder: search.placeholder,
|
|
1220
|
+
className: SEARCH_INPUT_CLASS
|
|
1221
|
+
})]
|
|
1222
|
+
}), searchSlot]
|
|
1223
|
+
}),
|
|
1224
|
+
toolbar,
|
|
1225
|
+
loading ? /* @__PURE__ */ jsx(ListPanelSkeleton, { columnCount: totalColumns }) : /* @__PURE__ */ jsx(DataTableContent, {
|
|
1226
|
+
density: "compact",
|
|
1227
|
+
emptyMessage,
|
|
1228
|
+
onRowClick,
|
|
1229
|
+
className: "min-h-0 flex-1",
|
|
1230
|
+
tableClassName,
|
|
1231
|
+
headerClassName,
|
|
1232
|
+
headerRowClassName,
|
|
1233
|
+
headerCellClassName,
|
|
1234
|
+
bodyClassName,
|
|
1235
|
+
rowClassName,
|
|
1236
|
+
cellClassName
|
|
1237
|
+
})
|
|
1238
|
+
]
|
|
1239
|
+
});
|
|
1240
|
+
}
|
|
1241
|
+
//#endregion
|
|
1005
1242
|
//#region src/components/features/data-table/components/loading.tsx
|
|
1006
1243
|
function DataTableLoading({ rows = 5, columns = 4, className }) {
|
|
1007
1244
|
return /* @__PURE__ */ jsx("div", {
|
|
@@ -1135,21 +1372,6 @@ function DataTablePagination({ pageSizes = DEFAULT_PAGE_SIZES, className }) {
|
|
|
1135
1372
|
});
|
|
1136
1373
|
}
|
|
1137
1374
|
//#endregion
|
|
1138
|
-
//#region src/components/features/data-table/components/search.tsx
|
|
1139
|
-
function DataTableSearch({ placeholder = "Search...", debounceMs = 300, className, disabled }) {
|
|
1140
|
-
const { search, setSearch } = useDataTableSearch();
|
|
1141
|
-
const [inputValue, setInputValue] = useDebouncedSearchInput(search, setSearch, debounceMs);
|
|
1142
|
-
return /* @__PURE__ */ jsx(Input, {
|
|
1143
|
-
placeholder,
|
|
1144
|
-
value: inputValue,
|
|
1145
|
-
onChange: (e) => setInputValue(e.target.value),
|
|
1146
|
-
className,
|
|
1147
|
-
disabled,
|
|
1148
|
-
"aria-label": placeholder,
|
|
1149
|
-
"data-slot": "dt-search"
|
|
1150
|
-
});
|
|
1151
|
-
}
|
|
1152
|
-
//#endregion
|
|
1153
1375
|
//#region src/components/features/data-table/hooks/use-data-table-client.ts
|
|
1154
1376
|
/**
|
|
1155
1377
|
* Creates a TanStack Table instance from an existing store.
|
|
@@ -1622,6 +1844,8 @@ const DataTable = {
|
|
|
1622
1844
|
InlineContent: DataTableInlineContent,
|
|
1623
1845
|
ColumnHeader: DataTableColumnHeader,
|
|
1624
1846
|
Pagination: DataTablePagination,
|
|
1847
|
+
ListPanel: DataTableListPanel,
|
|
1848
|
+
ListPagination: DataTableListPagination,
|
|
1625
1849
|
Search: DataTableSearch,
|
|
1626
1850
|
RowActions: DataTableRowActions,
|
|
1627
1851
|
BulkActions: DataTableBulkActions,
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as GroupedTable } from "../grouped-table-
|
|
1
|
+
import { t as GroupedTable } from "../grouped-table-9nyHKSsK.mjs";
|
|
2
2
|
export { GroupedTable };
|
|
@@ -6,7 +6,7 @@ import { t as useControllableState } from "./use-controllable-state-Dna7u3r9.mjs
|
|
|
6
6
|
import { Skeleton } from "./skeleton/index.mjs";
|
|
7
7
|
import { TableBody, TableCell, TableHead, TableHeader, TableRow } from "./table/index.mjs";
|
|
8
8
|
import { n as EASE } from "./motion-DvGRWdsm.mjs";
|
|
9
|
-
import { f as rowMatchesSearch, g as createSelectionColumn, h as DataTableColumnHeader, m as DataTableRowActions, p as dataTableFeatures } from "./data-table-
|
|
9
|
+
import { f as rowMatchesSearch, g as createSelectionColumn, h as DataTableColumnHeader, m as DataTableRowActions, p as dataTableFeatures } from "./data-table-BOe7pdpJ.mjs";
|
|
10
10
|
import { n as useDebouncedSearchInput } from "./use-debounced-search-input-yu_F0QBt.mjs";
|
|
11
11
|
import { InputWithAddons } from "./input-with-addons/index.mjs";
|
|
12
12
|
import { ChevronRight, Search, X } from "lucide-react";
|
package/dist/index.mjs
CHANGED
|
@@ -55,7 +55,7 @@ import { i as ClientOnly, n as useTheme, r as ThemeScript, t as ThemeProvider }
|
|
|
55
55
|
import { a as formatJson, c as isValidYaml, d as CodeEditor, i as CodeEditorTabs, l as jsonToYaml, n as jsonSchema, o as formatYaml, r as yamlSchema, s as isValidJson, t as createCodeEditorSchema, u as yamlToJson } from "./types-agDpVXBG.mjs";
|
|
56
56
|
import { t as toast } from "./toast-BUPlDkN3.mjs";
|
|
57
57
|
import { n as Toaster, t as useToast } from "./use-toast-Bpq0yJIT.mjs";
|
|
58
|
-
import { _ as useNuqsAdapter, a as useDataTablePagination, b as DEFAULT_PAGE_SIZE, c as useDataTableSelection, d as resolvePath, f as rowMatchesSearch, g as createSelectionColumn, h as DataTableColumnHeader, i as useDataTableLoading, l as useDataTableSorting, m as DataTableRowActions, n as useDataTableFilters, o as useDataTableRows, p as dataTableFeatures, r as useDataTableInlineContents, s as useDataTableSearch, t as DataTable, u as createDataTableStore, v as DEFAULT_DEBOUNCE_MS, x as DEFAULT_PAGE_SIZES, y as DEFAULT_LOADING_ROWS } from "./data-table-
|
|
58
|
+
import { _ as useNuqsAdapter, a as useDataTablePagination, b as DEFAULT_PAGE_SIZE, c as useDataTableSelection, d as resolvePath, f as rowMatchesSearch, g as createSelectionColumn, h as DataTableColumnHeader, i as useDataTableLoading, l as useDataTableSorting, m as DataTableRowActions, n as useDataTableFilters, o as useDataTableRows, p as dataTableFeatures, r as useDataTableInlineContents, s as useDataTableSearch, t as DataTable, u as createDataTableStore, v as DEFAULT_DEBOUNCE_MS, x as DEFAULT_PAGE_SIZES, y as DEFAULT_LOADING_ROWS } from "./data-table-BOe7pdpJ.mjs";
|
|
59
59
|
import { t as ActionRow } from "./action-row-DTvs91_3.mjs";
|
|
60
60
|
import { n as useDebouncedSearchInput, t as DEFAULT_SEARCH_DEBOUNCE_MS } from "./use-debounced-search-input-yu_F0QBt.mjs";
|
|
61
61
|
import { t as MultiSelect } from "./multi-select-CH8KERkt.mjs";
|
|
@@ -71,7 +71,7 @@ import { InputWithAddons } from "./input-with-addons/index.mjs";
|
|
|
71
71
|
import { t as TimePicker } from "./time-picker-BzNSUazl.mjs";
|
|
72
72
|
import { t as Transfer } from "./transfer-DsshYgIk.mjs";
|
|
73
73
|
import { a as getResponsiveValue, c as GRID_COLUMNS, d as RESPONSIVE_MAP, i as getGutter, l as GRID_PREFIX, n as Row, o as registerMediaQuery, r as RowContext, s as GRID_BREAKPOINTS, t as Col, u as RESPONSIVE_ARRAY } from "./col-BYGWTB4j.mjs";
|
|
74
|
-
import { t as GroupedTable } from "./grouped-table-
|
|
74
|
+
import { t as GroupedTable } from "./grouped-table-9nyHKSsK.mjs";
|
|
75
75
|
import { t as InputNumber } from "./input-number-TXmW-X9o.mjs";
|
|
76
76
|
import { a as logoStyles, i as LogoFlat, n as LogoStacked, r as LogoIcon, t as LogoText } from "./logo-text-Dpm5O6Kg.mjs";
|
|
77
77
|
import { t as Logo } from "./logo-C3FxD7jb.mjs";
|
|
@@ -118,6 +118,9 @@ Light-mode tokens on :root, dark-mode tokens on .dark
|
|
|
118
118
|
--table-accent: var(--glacier-mist-800);
|
|
119
119
|
--table-cell: hsl(0 0% 100%);
|
|
120
120
|
--table-cell-hover: var(--glacier-mist-700);
|
|
121
|
+
/* Sticky "mist" list-table header (DataTable.Content density="compact" / DataTable.ListPanel) */
|
|
122
|
+
--table-header-background: var(--glacier-mist-700);
|
|
123
|
+
--table-header-foreground: color-mix(in oklch, var(--midnight-fjord) 60%, transparent);
|
|
121
124
|
|
|
122
125
|
/* Badge */
|
|
123
126
|
--badge-primary: var(--primary);
|
|
@@ -320,6 +323,8 @@ Light-mode tokens on :root, dark-mode tokens on .dark
|
|
|
320
323
|
--table-accent: var(--app-dark-utility-1);
|
|
321
324
|
--table-cell: var(--midnight-fjord);
|
|
322
325
|
--table-cell-hover: var(--app-dark-utility-1);
|
|
326
|
+
--table-header-background: var(--muted);
|
|
327
|
+
--table-header-foreground: var(--muted-foreground);
|
|
323
328
|
|
|
324
329
|
/* Badge */
|
|
325
330
|
--badge-primary: var(--primary);
|
|
@@ -425,6 +430,15 @@ TAILWIND CUSTOM UTILITIES FOR THEME
|
|
|
425
430
|
/* Custom base shadow */
|
|
426
431
|
--shadow: 0 2px 4px 2px rgba(12, 29, 49, 0.03);
|
|
427
432
|
--shadow-tooltip: 0 4px 16px 0 rgba(0, 0, 0, 0.05), 1px 8px 8px 0 rgba(0, 0, 0, 0.02);
|
|
433
|
+
/**
|
|
434
|
+
* Section-card shadow (Figma org-overview cards). Aliases the base `--shadow`
|
|
435
|
+
* rather than a standalone value — applies identically in light and dark since
|
|
436
|
+
* `--shadow` itself isn't theme-split. Consumers reference it directly via
|
|
437
|
+
* `shadow-(--section-card-shadow)` (e.g. staff-portal's `SECTION_CARD_CHROME`),
|
|
438
|
+
* which previously pointed at an undefined custom property and rendered no
|
|
439
|
+
* shadow at all.
|
|
440
|
+
*/
|
|
441
|
+
--section-card-shadow: var(--shadow);
|
|
428
442
|
|
|
429
443
|
--color-tertiary: var(--tertiary);
|
|
430
444
|
--color-tertiary-foreground: var(--tertiary-foreground);
|
|
@@ -445,6 +459,8 @@ TAILWIND CUSTOM UTILITIES FOR THEME
|
|
|
445
459
|
--color-table-accent: var(--table-accent);
|
|
446
460
|
--color-table-cell: var(--table-cell);
|
|
447
461
|
--color-table-cell-hover: var(--table-cell-hover);
|
|
462
|
+
--color-table-header-background: var(--table-header-background);
|
|
463
|
+
--color-table-header-foreground: var(--table-header-foreground);
|
|
448
464
|
|
|
449
465
|
--color-dialog-overlay: var(--dialog-overlay);
|
|
450
466
|
--color-dialog-border: var(--dialog-border);
|