@dust-tt/sparkle 0.2.192 → 0.2.194-alpha-j
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/cjs/_index.d.ts +2 -0
- package/dist/cjs/components/Table.d.ts +43 -0
- package/dist/cjs/index.js +87 -3
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/stories/Table.stories.d.ts +9 -0
- package/dist/esm/_index.d.ts +2 -0
- package/dist/esm/components/Table.d.ts +43 -0
- package/dist/esm/index.js +87 -4
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/stories/Table.stories.d.ts +9 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/_index.ts +3 -0
- package/src/components/ContextItem.tsx +1 -1
- package/src/components/Table.tsx +286 -0
- package/src/components/Tooltip.tsx +1 -1
- package/src/stories/ContextItem.stories.tsx +3 -1
- package/src/stories/Table.stories.tsx +99 -0
package/package.json
CHANGED
package/src/_index.ts
CHANGED
|
@@ -148,6 +148,9 @@ export { Markdown };
|
|
|
148
148
|
import { DataTable } from "./components/DataTable";
|
|
149
149
|
export { DataTable };
|
|
150
150
|
|
|
151
|
+
import { Table } from "./components/Table";
|
|
152
|
+
export { Table };
|
|
153
|
+
|
|
151
154
|
import {
|
|
152
155
|
LogoHorizontalColor as LogoHorizontalColorLogo,
|
|
153
156
|
LogoHorizontalColorLayer1 as LogoHorizontalColorLogoLayer1,
|
|
@@ -48,7 +48,7 @@ export function ContextItem({
|
|
|
48
48
|
<div className="s-min-w-0 s-overflow-hidden s-text-ellipsis s-whitespace-nowrap s-text-base s-font-semibold">
|
|
49
49
|
{title}
|
|
50
50
|
</div>
|
|
51
|
-
<div className="s-flex s-flex-shrink-0 s-items-center s-gap-3 s-
|
|
51
|
+
<div className="s-flex s-flex-shrink-0 s-items-center s-gap-3 s-overflow-hidden s-pt-0.5 s-text-sm s-text-element-600">
|
|
52
52
|
{subElement}
|
|
53
53
|
</div>
|
|
54
54
|
</div>
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type ColumnDef,
|
|
3
|
+
ColumnFiltersState,
|
|
4
|
+
flexRender,
|
|
5
|
+
getCoreRowModel,
|
|
6
|
+
getFilteredRowModel,
|
|
7
|
+
getSortedRowModel,
|
|
8
|
+
type SortingState,
|
|
9
|
+
useReactTable,
|
|
10
|
+
} from "@tanstack/react-table";
|
|
11
|
+
import React, { ReactNode, useState } from "react";
|
|
12
|
+
|
|
13
|
+
import { Avatar, MoreIcon } from "@sparkle/index";
|
|
14
|
+
import { ArrowDownIcon, ArrowUpIcon } from "@sparkle/index";
|
|
15
|
+
import { classNames } from "@sparkle/lib/utils";
|
|
16
|
+
|
|
17
|
+
import { Icon } from "./Icon";
|
|
18
|
+
|
|
19
|
+
type FirstColumnWidth = "expanded" | "normal";
|
|
20
|
+
|
|
21
|
+
interface TableProps<TData, TValue> {
|
|
22
|
+
data: TData[];
|
|
23
|
+
columns: ColumnDef<TData, TValue>[];
|
|
24
|
+
className?: string;
|
|
25
|
+
width?: FirstColumnWidth;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function Table<TData, TValue>({
|
|
29
|
+
data,
|
|
30
|
+
columns,
|
|
31
|
+
className,
|
|
32
|
+
width = "normal",
|
|
33
|
+
}: TableProps<TData, TValue>) {
|
|
34
|
+
const [sorting, setSorting] = useState<SortingState>([]);
|
|
35
|
+
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
|
|
36
|
+
|
|
37
|
+
const table = useReactTable({
|
|
38
|
+
data,
|
|
39
|
+
columns,
|
|
40
|
+
onSortingChange: setSorting,
|
|
41
|
+
getCoreRowModel: getCoreRowModel(),
|
|
42
|
+
getSortedRowModel: getSortedRowModel(),
|
|
43
|
+
getFilteredRowModel: getFilteredRowModel(),
|
|
44
|
+
onColumnFiltersChange: setColumnFilters,
|
|
45
|
+
state: {
|
|
46
|
+
columnFilters,
|
|
47
|
+
sorting,
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<TableData className={className}>
|
|
53
|
+
<TableData.Header>
|
|
54
|
+
{table.getHeaderGroups().map((headerGroup) => (
|
|
55
|
+
<TableData.Row key={headerGroup.id}>
|
|
56
|
+
{headerGroup.headers.map((header) => (
|
|
57
|
+
<TableData.Head
|
|
58
|
+
key={header.id}
|
|
59
|
+
width={width}
|
|
60
|
+
onClick={header.column.getToggleSortingHandler()}
|
|
61
|
+
className={header.column.getCanSort() ? "s-cursor-pointer" : ""}
|
|
62
|
+
>
|
|
63
|
+
<div className="s-flex s-items-center s-space-x-1 s-whitespace-nowrap">
|
|
64
|
+
{flexRender(
|
|
65
|
+
header.column.columnDef.header,
|
|
66
|
+
header.getContext()
|
|
67
|
+
)}
|
|
68
|
+
{header.column.getCanSort() && (
|
|
69
|
+
<Icon
|
|
70
|
+
visual={
|
|
71
|
+
header.column.getIsSorted() === "asc"
|
|
72
|
+
? ArrowUpIcon
|
|
73
|
+
: header.column.getIsSorted() === "desc"
|
|
74
|
+
? ArrowDownIcon
|
|
75
|
+
: ArrowDownIcon
|
|
76
|
+
}
|
|
77
|
+
className={classNames(
|
|
78
|
+
"s-h-4 s-w-3 s-font-extralight",
|
|
79
|
+
header.column.getIsSorted()
|
|
80
|
+
? "s-opacity-100"
|
|
81
|
+
: "s-opacity-0"
|
|
82
|
+
)}
|
|
83
|
+
/>
|
|
84
|
+
)}
|
|
85
|
+
</div>
|
|
86
|
+
</TableData.Head>
|
|
87
|
+
))}
|
|
88
|
+
</TableData.Row>
|
|
89
|
+
))}
|
|
90
|
+
</TableData.Header>
|
|
91
|
+
<TableData.Body>
|
|
92
|
+
{table.getRowModel().rows.map((row) => (
|
|
93
|
+
<TableData.Row
|
|
94
|
+
key={row.id}
|
|
95
|
+
clickable={row.original.clickable}
|
|
96
|
+
onClick={row.original.onClick}
|
|
97
|
+
>
|
|
98
|
+
{row.getVisibleCells().map((cell) => (
|
|
99
|
+
<TableData.Cell key={cell.id}>
|
|
100
|
+
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
|
101
|
+
</TableData.Cell>
|
|
102
|
+
))}
|
|
103
|
+
</TableData.Row>
|
|
104
|
+
))}
|
|
105
|
+
</TableData.Body>
|
|
106
|
+
</TableData>
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
interface TableRootProps extends React.HTMLAttributes<HTMLTableElement> {
|
|
111
|
+
children: ReactNode;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
interface HeaderProps extends React.HTMLAttributes<HTMLTableSectionElement> {
|
|
115
|
+
children: ReactNode;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
interface HeadProps extends React.ThHTMLAttributes<HTMLTableCellElement> {
|
|
119
|
+
children?: ReactNode;
|
|
120
|
+
width?: FirstColumnWidth;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
interface CellProps extends React.TdHTMLAttributes<HTMLTableCellElement> {
|
|
124
|
+
avatarUrl?: string;
|
|
125
|
+
icon?: React.ComponentType<{ className?: string }>;
|
|
126
|
+
children?: ReactNode;
|
|
127
|
+
description?: string;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
interface RowProps extends React.HTMLAttributes<HTMLTableRowElement> {
|
|
131
|
+
children: ReactNode;
|
|
132
|
+
clickable?: boolean;
|
|
133
|
+
onClick?: () => void;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const TableRoot: React.FC<TableRootProps> = ({
|
|
137
|
+
children,
|
|
138
|
+
className,
|
|
139
|
+
...props
|
|
140
|
+
}) => {
|
|
141
|
+
return (
|
|
142
|
+
<table
|
|
143
|
+
className={classNames("s-w-full s-border-collapse", className || "")}
|
|
144
|
+
{...props}
|
|
145
|
+
>
|
|
146
|
+
{children}
|
|
147
|
+
</table>
|
|
148
|
+
);
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
const Header: React.FC<HeaderProps> = ({ children, className, ...props }) => {
|
|
152
|
+
return (
|
|
153
|
+
<thead
|
|
154
|
+
className={classNames("s-text-xs s-capitalize", className || "")}
|
|
155
|
+
{...props}
|
|
156
|
+
>
|
|
157
|
+
{children}
|
|
158
|
+
</thead>
|
|
159
|
+
);
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
const Head: React.FC<HeadProps> = ({
|
|
163
|
+
children,
|
|
164
|
+
className,
|
|
165
|
+
width,
|
|
166
|
+
...props
|
|
167
|
+
}) => {
|
|
168
|
+
return (
|
|
169
|
+
<th
|
|
170
|
+
className={classNames(
|
|
171
|
+
"s-py-1 s-pr-3 s-text-left s-font-medium s-text-element-800",
|
|
172
|
+
width === "expanded" ? "s-w-full" : "s-w-auto",
|
|
173
|
+
className || ""
|
|
174
|
+
)}
|
|
175
|
+
{...props}
|
|
176
|
+
>
|
|
177
|
+
<div className="s-flex s-items-center s-space-x-1 s-whitespace-nowrap">
|
|
178
|
+
{children}
|
|
179
|
+
</div>
|
|
180
|
+
</th>
|
|
181
|
+
);
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
const Body: React.FC<React.HTMLAttributes<HTMLTableSectionElement>> = ({
|
|
185
|
+
children,
|
|
186
|
+
className,
|
|
187
|
+
...props
|
|
188
|
+
}) => (
|
|
189
|
+
<tbody className={className || ""} {...props}>
|
|
190
|
+
{children}
|
|
191
|
+
</tbody>
|
|
192
|
+
);
|
|
193
|
+
|
|
194
|
+
const Footer: React.FC<React.HTMLAttributes<HTMLTableSectionElement>> = ({
|
|
195
|
+
children,
|
|
196
|
+
className,
|
|
197
|
+
...props
|
|
198
|
+
}) => (
|
|
199
|
+
<tfoot
|
|
200
|
+
className={classNames(
|
|
201
|
+
"s-border-t s-border-structure-200 s-bg-structure-50",
|
|
202
|
+
className || ""
|
|
203
|
+
)}
|
|
204
|
+
{...props}
|
|
205
|
+
>
|
|
206
|
+
{children}
|
|
207
|
+
</tfoot>
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
const Row: React.FC<RowProps> = ({
|
|
211
|
+
children,
|
|
212
|
+
className,
|
|
213
|
+
clickable = false,
|
|
214
|
+
onClick,
|
|
215
|
+
...props
|
|
216
|
+
}) => (
|
|
217
|
+
<tr
|
|
218
|
+
className={classNames(
|
|
219
|
+
"s-border-b s-border-structure-200 s-text-sm",
|
|
220
|
+
className || ""
|
|
221
|
+
)}
|
|
222
|
+
{...props}
|
|
223
|
+
>
|
|
224
|
+
{children}
|
|
225
|
+
{clickable && (
|
|
226
|
+
<td
|
|
227
|
+
className="s-w-1 s-cursor-pointer s-pl-1 s-text-element-600"
|
|
228
|
+
onClick={clickable ? onClick : undefined}
|
|
229
|
+
>
|
|
230
|
+
<Icon visual={MoreIcon} size="sm" />
|
|
231
|
+
</td>
|
|
232
|
+
)}
|
|
233
|
+
</tr>
|
|
234
|
+
);
|
|
235
|
+
|
|
236
|
+
const Cell: React.FC<CellProps> = ({
|
|
237
|
+
children,
|
|
238
|
+
className,
|
|
239
|
+
avatarUrl,
|
|
240
|
+
icon,
|
|
241
|
+
description,
|
|
242
|
+
...props
|
|
243
|
+
}) => (
|
|
244
|
+
<td
|
|
245
|
+
className={classNames(
|
|
246
|
+
"s-whitespace-nowrap s-py-2 s-pl-0.5 s-text-element-800",
|
|
247
|
+
className || ""
|
|
248
|
+
)}
|
|
249
|
+
{...props}
|
|
250
|
+
>
|
|
251
|
+
<div className="s-flex">
|
|
252
|
+
{avatarUrl && <Avatar visual={avatarUrl} size="xs" className="s-mr-2" />}
|
|
253
|
+
{icon && (
|
|
254
|
+
<Icon visual={icon} size="sm" className="s-mr-2 s-text-element-600" />
|
|
255
|
+
)}
|
|
256
|
+
<div className="s-flex">
|
|
257
|
+
<span className="s-text-sm s-text-element-800">{children}</span>
|
|
258
|
+
{description && (
|
|
259
|
+
<span className="s-pl-2 s-text-sm s-text-element-600">
|
|
260
|
+
{description}
|
|
261
|
+
</span>
|
|
262
|
+
)}
|
|
263
|
+
</div>
|
|
264
|
+
</div>
|
|
265
|
+
</td>
|
|
266
|
+
);
|
|
267
|
+
|
|
268
|
+
const Caption: React.FC<React.HTMLAttributes<HTMLTableCaptionElement>> = ({
|
|
269
|
+
children,
|
|
270
|
+
className,
|
|
271
|
+
...props
|
|
272
|
+
}) => (
|
|
273
|
+
<caption className={classNames(className || "")} {...props}>
|
|
274
|
+
{children}
|
|
275
|
+
</caption>
|
|
276
|
+
);
|
|
277
|
+
|
|
278
|
+
export const TableData = Object.assign(TableRoot, {
|
|
279
|
+
Header,
|
|
280
|
+
Body,
|
|
281
|
+
Footer,
|
|
282
|
+
Head,
|
|
283
|
+
Row,
|
|
284
|
+
Cell,
|
|
285
|
+
Caption,
|
|
286
|
+
});
|
|
@@ -39,9 +39,11 @@ export const ListItemExample = () => (
|
|
|
39
39
|
</div>
|
|
40
40
|
</>
|
|
41
41
|
}
|
|
42
|
-
action={<Chip size="xs" label="Last Sync ~7 days ago" color="pink" />}
|
|
43
42
|
visual={<Icon visual={FolderIcon} size="md" />}
|
|
44
43
|
>
|
|
44
|
+
<div className="s-py-2">
|
|
45
|
+
<Chip size="xs" label="Last Sync ~7 days ago" color="pink" />
|
|
46
|
+
</div>
|
|
45
47
|
<ContextItem.Description description="Lats, pricing, history of contacts, contact message" />
|
|
46
48
|
</ContextItem>
|
|
47
49
|
<ContextItem.SectionHeader
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { ColumnDef } from "@tanstack/react-table";
|
|
3
|
+
import React from 'react';
|
|
4
|
+
|
|
5
|
+
import { TableData } from "@sparkle/components/Table";
|
|
6
|
+
|
|
7
|
+
import { FolderIcon, Table } from "../index_with_tw_base";
|
|
8
|
+
|
|
9
|
+
const meta = {
|
|
10
|
+
title: "Components/Table",
|
|
11
|
+
component: Table
|
|
12
|
+
} satisfies Meta<typeof Table>;
|
|
13
|
+
|
|
14
|
+
export default meta;
|
|
15
|
+
type Story = StoryObj<typeof meta>;
|
|
16
|
+
|
|
17
|
+
type Data = {
|
|
18
|
+
name: string;
|
|
19
|
+
description?: string;
|
|
20
|
+
usedBy: number;
|
|
21
|
+
addedBy: string;
|
|
22
|
+
lastUpdated: string;
|
|
23
|
+
size: string;
|
|
24
|
+
avatarUrl?: string;
|
|
25
|
+
icon?: React.ComponentType<{ className?: string }>;
|
|
26
|
+
clickable?: boolean;
|
|
27
|
+
onClick?: () => void;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const TableExample = () => {
|
|
31
|
+
const data: Data[] = [
|
|
32
|
+
{
|
|
33
|
+
name: "Marketing",
|
|
34
|
+
description: "(23 items)",
|
|
35
|
+
usedBy: 8,
|
|
36
|
+
addedBy: "User1",
|
|
37
|
+
lastUpdated: "July 8, 2023",
|
|
38
|
+
size: "32kb",
|
|
39
|
+
avatarUrl: "https://dust.tt/static/droidavatar/Droid_Lime_3.jpg",
|
|
40
|
+
clickable: true,
|
|
41
|
+
onClick: (() => console.log("hehe"))
|
|
42
|
+
},
|
|
43
|
+
{ name: "Design", usedBy: 2, addedBy: "User2", lastUpdated: "2023-07-09", size: "64kb", icon: FolderIcon, clickable: false},
|
|
44
|
+
{ name: "Development", usedBy: 5, addedBy: "User3", lastUpdated: "2023-07-07", size: "128kb"},
|
|
45
|
+
{ name: "Sales", usedBy: 10, addedBy: "User4", lastUpdated: "2023-07-10", size: "16kb"},
|
|
46
|
+
{ name: "HR", usedBy: 3, addedBy: "User5", lastUpdated: "2023-07-06", size: "48kb"},
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
const columns: ColumnDef<Data>[] = [
|
|
50
|
+
{
|
|
51
|
+
accessorKey: "name",
|
|
52
|
+
header: "Name",
|
|
53
|
+
cell: info => (
|
|
54
|
+
<TableData.Cell
|
|
55
|
+
avatarUrl={info.row.original.avatarUrl}
|
|
56
|
+
icon={info.row.original.icon}
|
|
57
|
+
description={info.row.original.description}
|
|
58
|
+
>
|
|
59
|
+
{info.row.original.name}
|
|
60
|
+
</TableData.Cell>
|
|
61
|
+
),
|
|
62
|
+
meta: { width: "expanded" }
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
accessorKey: "usedBy",
|
|
66
|
+
header: "Used by",
|
|
67
|
+
cell: info => <TableData.Cell>{info.row.original.usedBy}</TableData.Cell>
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
accessorKey: "addedBy",
|
|
71
|
+
header: "Added by",
|
|
72
|
+
cell: info => <TableData.Cell>{info.row.original.addedBy}</TableData.Cell>
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
accessorKey: "lastUpdated",
|
|
76
|
+
header: "Last updated",
|
|
77
|
+
cell: info => <TableData.Cell>{info.row.original.lastUpdated}</TableData.Cell>,
|
|
78
|
+
enableSorting: false
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
accessorKey: "size",
|
|
82
|
+
header: "Size",
|
|
83
|
+
cell: info => <TableData.Cell>{info.row.original.size}</TableData.Cell>
|
|
84
|
+
}
|
|
85
|
+
];
|
|
86
|
+
|
|
87
|
+
return (
|
|
88
|
+
<div className="s-w-full s-max-w-4xl s-overflow-x-auto">
|
|
89
|
+
<Table
|
|
90
|
+
data={data}
|
|
91
|
+
columns={columns}
|
|
92
|
+
/>
|
|
93
|
+
</div>
|
|
94
|
+
);
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
export const Default: Story = {
|
|
98
|
+
render: () => <TableExample />,
|
|
99
|
+
};
|