@jinaan/uikit 0.1.45 → 0.1.47
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/data-table.d.ts +6 -1
- package/dist/data-table.d.ts.map +1 -1
- package/dist/index.js +893 -842
- package/dist/index.js.map +1 -1
- package/dist/table-surface.d.ts +5 -1
- package/dist/table-surface.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/data-table.tsx +89 -33
- package/src/table-surface.tsx +16 -0
package/dist/table-surface.d.ts
CHANGED
|
@@ -27,6 +27,10 @@ interface TableSurfaceProps {
|
|
|
27
27
|
headerClassName?: string;
|
|
28
28
|
/** Inner panel overrides (background, border color, …). */
|
|
29
29
|
panelClassName?: string;
|
|
30
|
+
/** Optional footer strip in the outer shell, below the panel (hairline top border). */
|
|
31
|
+
footer?: ReactNode;
|
|
32
|
+
/** Footer strip overrides (padding, colors, …). */
|
|
33
|
+
footerClassName?: string;
|
|
30
34
|
/** Minimum panel height; keeps empty states from collapsing. */
|
|
31
35
|
minHeight?: string;
|
|
32
36
|
/**
|
|
@@ -46,6 +50,6 @@ interface TableSurfaceProps {
|
|
|
46
50
|
* Colors come from the `--table-*` tokens and can be adjusted per surface with
|
|
47
51
|
* `tone` plus `headerClassName` / `panelClassName`.
|
|
48
52
|
*/
|
|
49
|
-
export declare function TableSurface({ title, description, header, children, action, tone, className, headerClassName, panelClassName, minHeight, scrollMode, headerContentRef, }: TableSurfaceProps): import("react").JSX.Element;
|
|
53
|
+
export declare function TableSurface({ title, description, header, children, action, tone, className, headerClassName, panelClassName, footer, footerClassName, minHeight, scrollMode, headerContentRef, }: TableSurfaceProps): import("react").JSX.Element;
|
|
50
54
|
export {};
|
|
51
55
|
//# sourceMappingURL=table-surface.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"table-surface.d.ts","sourceRoot":"","sources":["../src/table-surface.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAM5C,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,OAAO,GAAG,aAAa,CAAC;AAEnE,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,aAAa,CAAC;IAC1D,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,UAAU,iBAAiB;IACzB,kCAAkC;IAClC,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,uCAAuC;IACvC,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,yDAAyD;IACzD,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,0EAA0E;IAC1E,QAAQ,EAAE,SAAS,CAAC;IACpB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,SAAS,GAAG,kBAAkB,CAAC;IACxC,8EAA8E;IAC9E,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gEAAgE;IAChE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC;IACjC,qEAAqE;IACrE,gBAAgB,CAAC,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;CACxC;AAyBD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,WAAW,EACX,MAAM,EACN,QAAQ,EACR,MAAM,EACN,IAAgB,EAChB,SAAS,EACT,eAAe,EACf,cAAc,EACd,SAAS,EACT,UAAsB,EACtB,gBAAgB,GACjB,EAAE,iBAAiB,+
|
|
1
|
+
{"version":3,"file":"table-surface.d.ts","sourceRoot":"","sources":["../src/table-surface.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAM5C,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,OAAO,GAAG,aAAa,CAAC;AAEnE,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,aAAa,CAAC;IAC1D,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,UAAU,iBAAiB;IACzB,kCAAkC;IAClC,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,uCAAuC;IACvC,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,yDAAyD;IACzD,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,0EAA0E;IAC1E,QAAQ,EAAE,SAAS,CAAC;IACpB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,SAAS,GAAG,kBAAkB,CAAC;IACxC,8EAA8E;IAC9E,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,uFAAuF;IACvF,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,mDAAmD;IACnD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gEAAgE;IAChE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC;IACjC,qEAAqE;IACrE,gBAAgB,CAAC,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;CACxC;AAyBD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,WAAW,EACX,MAAM,EACN,QAAQ,EACR,MAAM,EACN,IAAgB,EAChB,SAAS,EACT,eAAe,EACf,cAAc,EACd,MAAM,EACN,eAAe,EACf,SAAS,EACT,UAAsB,EACtB,gBAAgB,GACjB,EAAE,iBAAiB,+BAiGnB"}
|
package/package.json
CHANGED
package/src/data-table.tsx
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
X,
|
|
14
14
|
} from "@phosphor-icons/react";
|
|
15
15
|
import {
|
|
16
|
+
Fragment,
|
|
16
17
|
useCallback,
|
|
17
18
|
useEffect,
|
|
18
19
|
useLayoutEffect,
|
|
@@ -138,6 +139,11 @@ interface DataTableProps<T> {
|
|
|
138
139
|
bulkActions?: BulkAction<T>[];
|
|
139
140
|
|
|
140
141
|
rowActions?: (row: T) => ReactNode;
|
|
142
|
+
/**
|
|
143
|
+
* Expanding rows: renders a chevron toggle cell at the row start and the
|
|
144
|
+
* returned content in a full-width muted band beneath the row.
|
|
145
|
+
*/
|
|
146
|
+
renderExpanded?: (row: T) => ReactNode;
|
|
141
147
|
onRowClick?: (row: T) => void;
|
|
142
148
|
|
|
143
149
|
defaultSort?: { id: string; dir: "asc" | "desc" };
|
|
@@ -233,6 +239,7 @@ export function DataTable<T>({
|
|
|
233
239
|
selectable = false,
|
|
234
240
|
bulkActions,
|
|
235
241
|
rowActions,
|
|
242
|
+
renderExpanded,
|
|
236
243
|
onRowClick,
|
|
237
244
|
defaultSort,
|
|
238
245
|
sort: sortProp,
|
|
@@ -268,6 +275,15 @@ export function DataTable<T>({
|
|
|
268
275
|
const [page, setPage] = useState(0);
|
|
269
276
|
const [pageSize, setPageSize] = useState(initialPageSize);
|
|
270
277
|
const [selected, setSelected] = useState<Set<string>>(new Set());
|
|
278
|
+
const [expanded, setExpanded] = useState<Set<string>>(new Set());
|
|
279
|
+
const toggleExpanded = (id: string) => {
|
|
280
|
+
setExpanded((prev) => {
|
|
281
|
+
const next = new Set(prev);
|
|
282
|
+
if (next.has(id)) next.delete(id);
|
|
283
|
+
else next.add(id);
|
|
284
|
+
return next;
|
|
285
|
+
});
|
|
286
|
+
};
|
|
271
287
|
const [activeFilterIds, setActiveFilterIds] = useState<string[]>([]);
|
|
272
288
|
|
|
273
289
|
const propOrder = columns.map((c) => c.id);
|
|
@@ -398,7 +414,7 @@ export function DataTable<T>({
|
|
|
398
414
|
// order). The pinned colgroup maps positionally onto the columns, so any
|
|
399
415
|
// structural change invalidates the measured widths — otherwise the new
|
|
400
416
|
// column steals its neighbor's width and every column shifts by one.
|
|
401
|
-
const structureKey = `${selectable ? "s" : "-"}|${rowActions ? "a" : "-"}|${columnKey}`;
|
|
417
|
+
const structureKey = `${selectable ? "s" : "-"}|${rowActions ? "a" : "-"}|${renderExpanded ? "e" : "-"}|${columnKey}`;
|
|
402
418
|
const structureRef = useRef(structureKey);
|
|
403
419
|
const pinned = columnWidths.length > 0;
|
|
404
420
|
|
|
@@ -772,6 +788,7 @@ export function DataTable<T>({
|
|
|
772
788
|
/>
|
|
773
789
|
</th>
|
|
774
790
|
)}
|
|
791
|
+
{renderExpanded && <th className="h-(--table-header-h) w-11 px-(--table-pad-x)" />}
|
|
775
792
|
{visibleColumns.map((c) => (
|
|
776
793
|
<th
|
|
777
794
|
key={c.id}
|
|
@@ -886,6 +903,7 @@ export function DataTable<T>({
|
|
|
886
903
|
<thead className="sr-only">
|
|
887
904
|
<tr>
|
|
888
905
|
{selectable && <th scope="col">Select</th>}
|
|
906
|
+
{renderExpanded && <th scope="col">Details</th>}
|
|
889
907
|
{visibleColumns.map((c) => (
|
|
890
908
|
<th key={c.id} scope="col" aria-sort={ariaSort(c)}>
|
|
891
909
|
{c.header}
|
|
@@ -898,22 +916,49 @@ export function DataTable<T>({
|
|
|
898
916
|
{pageRows.map((row) => {
|
|
899
917
|
const id = getRowId(row);
|
|
900
918
|
const isSelected = selected.has(id);
|
|
919
|
+
const isExpanded = expanded.has(id);
|
|
920
|
+
const columnCount =
|
|
921
|
+
visibleColumns.length +
|
|
922
|
+
(selectable ? 1 : 0) +
|
|
923
|
+
(renderExpanded ? 1 : 0) +
|
|
924
|
+
(rowActions ? 1 : 0);
|
|
901
925
|
return (
|
|
902
|
-
<
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
926
|
+
<Fragment key={id}>
|
|
927
|
+
<TableRow
|
|
928
|
+
data-state={isSelected ? "selected" : undefined}
|
|
929
|
+
onClick={onRowClick ? () => onRowClick(row) : undefined}
|
|
930
|
+
className={onRowClick ? "cursor-pointer" : undefined}
|
|
931
|
+
>
|
|
932
|
+
{selectable && (
|
|
933
|
+
<TableCell className="w-11" onClick={(e) => e.stopPropagation()}>
|
|
934
|
+
<Checkbox
|
|
935
|
+
aria-label="Select row"
|
|
936
|
+
checked={isSelected}
|
|
937
|
+
onCheckedChange={() => toggleOne(id)}
|
|
938
|
+
/>
|
|
939
|
+
</TableCell>
|
|
940
|
+
)}
|
|
941
|
+
{renderExpanded && (
|
|
942
|
+
<TableCell className="w-11" onClick={(e) => e.stopPropagation()}>
|
|
943
|
+
<Button
|
|
944
|
+
type="button"
|
|
945
|
+
variant="ghost"
|
|
946
|
+
size="icon"
|
|
947
|
+
className="size-7"
|
|
948
|
+
aria-label={isExpanded ? "Collapse row" : "Expand row"}
|
|
949
|
+
aria-expanded={isExpanded}
|
|
950
|
+
onClick={() => toggleExpanded(id)}
|
|
951
|
+
>
|
|
952
|
+
<CaretDown
|
|
953
|
+
className={cn(
|
|
954
|
+
"size-3.5 text-muted transition-transform motion-safe:duration-200",
|
|
955
|
+
isExpanded ? "" : "-rotate-90",
|
|
956
|
+
)}
|
|
957
|
+
weight="bold"
|
|
958
|
+
/>
|
|
959
|
+
</Button>
|
|
960
|
+
</TableCell>
|
|
961
|
+
)}
|
|
917
962
|
{visibleColumns.map((c) => (
|
|
918
963
|
<TableCell
|
|
919
964
|
key={c.id}
|
|
@@ -923,23 +968,34 @@ export function DataTable<T>({
|
|
|
923
968
|
{c.cell(row)}
|
|
924
969
|
</TableCell>
|
|
925
970
|
))}
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
971
|
+
{rowActions && (
|
|
972
|
+
<TableCell
|
|
973
|
+
className="w-44 px-4 text-right"
|
|
974
|
+
onClick={(e) => {
|
|
975
|
+
// Dead-zone fix: only swallow clicks on the
|
|
976
|
+
// action controls themselves (menus, buttons);
|
|
977
|
+
// the cell's padding stays part of the clickable
|
|
978
|
+
// row.
|
|
979
|
+
if ((e.target as HTMLElement).closest("button, a, input, [role='menuitem']")) {
|
|
980
|
+
e.stopPropagation();
|
|
981
|
+
}
|
|
982
|
+
}}
|
|
983
|
+
>
|
|
984
|
+
{rowActions(row)}
|
|
985
|
+
</TableCell>
|
|
986
|
+
)}
|
|
987
|
+
</TableRow>
|
|
988
|
+
{renderExpanded && isExpanded ? (
|
|
989
|
+
<TableRow className="hover:bg-inherit" data-expanded="">
|
|
990
|
+
<TableCell
|
|
991
|
+
colSpan={columnCount}
|
|
992
|
+
className="border-t border-line bg-elevated/60 px-(--table-pad-x) py-3 align-top text-[13px] text-muted"
|
|
993
|
+
>
|
|
994
|
+
{renderExpanded(row)}
|
|
995
|
+
</TableCell>
|
|
996
|
+
</TableRow>
|
|
997
|
+
) : null}
|
|
998
|
+
</Fragment>
|
|
943
999
|
);
|
|
944
1000
|
})}
|
|
945
1001
|
</TableBody>
|
package/src/table-surface.tsx
CHANGED
|
@@ -34,6 +34,10 @@ interface TableSurfaceProps {
|
|
|
34
34
|
headerClassName?: string;
|
|
35
35
|
/** Inner panel overrides (background, border color, …). */
|
|
36
36
|
panelClassName?: string;
|
|
37
|
+
/** Optional footer strip in the outer shell, below the panel (hairline top border). */
|
|
38
|
+
footer?: ReactNode;
|
|
39
|
+
/** Footer strip overrides (padding, colors, …). */
|
|
40
|
+
footerClassName?: string;
|
|
37
41
|
/** Minimum panel height; keeps empty states from collapsing. */
|
|
38
42
|
minHeight?: string;
|
|
39
43
|
/**
|
|
@@ -87,6 +91,8 @@ export function TableSurface({
|
|
|
87
91
|
className,
|
|
88
92
|
headerClassName,
|
|
89
93
|
panelClassName,
|
|
94
|
+
footer,
|
|
95
|
+
footerClassName,
|
|
90
96
|
minHeight,
|
|
91
97
|
scrollMode = "surface",
|
|
92
98
|
headerContentRef,
|
|
@@ -170,6 +176,16 @@ export function TableSurface({
|
|
|
170
176
|
{panel}
|
|
171
177
|
</div>
|
|
172
178
|
)}
|
|
179
|
+
{footer ? (
|
|
180
|
+
<div
|
|
181
|
+
className={cn(
|
|
182
|
+
"border-t border-line px-(--table-pad-x) py-3 text-table-header",
|
|
183
|
+
footerClassName,
|
|
184
|
+
)}
|
|
185
|
+
>
|
|
186
|
+
{footer}
|
|
187
|
+
</div>
|
|
188
|
+
) : null}
|
|
173
189
|
{actionNode ? (
|
|
174
190
|
<div className="pointer-events-none absolute right-4 top-(--table-inset) flex h-(--table-header-h) items-center">
|
|
175
191
|
<div className="pointer-events-auto">{actionNode}</div>
|