@dust-tt/sparkle 0.2.236 → 0.2.238
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.js +38 -40
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/components/DataTable.d.ts +17 -6
- package/dist/esm/components/DataTable.d.ts.map +1 -1
- package/dist/esm/components/DataTable.js +34 -22
- package/dist/esm/components/DataTable.js.map +1 -1
- package/dist/esm/components/Dialog.d.ts.map +1 -1
- package/dist/esm/components/Dialog.js +2 -2
- package/dist/esm/components/Dialog.js.map +1 -1
- package/dist/esm/components/TextArea.d.ts +2 -2
- package/dist/esm/components/TextArea.d.ts.map +1 -1
- package/dist/esm/components/TextArea.js +3 -17
- package/dist/esm/components/TextArea.js.map +1 -1
- package/dist/esm/stories/DataTable.stories.d.ts.map +1 -1
- package/dist/esm/stories/DataTable.stories.js +32 -2
- package/dist/esm/stories/DataTable.stories.js.map +1 -1
- package/dist/esm/stories/TextArea.stories.js +1 -1
- package/dist/esm/stories/TextArea.stories.js.map +1 -1
- package/dist/sparkle.css +4 -4
- package/package.json +1 -1
- package/src/components/DataTable.tsx +74 -19
- package/src/components/Dialog.tsx +2 -4
- package/src/components/TextArea.tsx +4 -20
- package/src/stories/DataTable.stories.tsx +32 -0
- package/src/stories/TextArea.stories.tsx +1 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
Column,
|
|
2
3
|
type ColumnDef,
|
|
3
4
|
ColumnFiltersState,
|
|
4
5
|
flexRender,
|
|
@@ -28,6 +29,15 @@ import { classNames } from "@sparkle/lib/utils";
|
|
|
28
29
|
import { Icon } from "./Icon";
|
|
29
30
|
import { breakpoints, useWindowSize } from "./WindowUtility";
|
|
30
31
|
|
|
32
|
+
declare module "@tanstack/react-table" {
|
|
33
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
34
|
+
interface ColumnMeta<TData, TValue> {
|
|
35
|
+
className?: string;
|
|
36
|
+
width?: string;
|
|
37
|
+
flex?: number;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
31
41
|
interface TBaseData {
|
|
32
42
|
onClick?: () => void;
|
|
33
43
|
moreMenuItems?: DropdownItemProps[];
|
|
@@ -42,6 +52,7 @@ interface DataTableProps<TData extends TBaseData> {
|
|
|
42
52
|
totalRowCount?: number;
|
|
43
53
|
columns: ColumnDef<TData, any>[]; // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
44
54
|
className?: string;
|
|
55
|
+
widthClassName?: string;
|
|
45
56
|
filter?: string;
|
|
46
57
|
filterColumn?: string;
|
|
47
58
|
pagination?: PaginationState;
|
|
@@ -66,6 +77,7 @@ export function DataTable<TData extends TBaseData>({
|
|
|
66
77
|
totalRowCount,
|
|
67
78
|
columns,
|
|
68
79
|
className,
|
|
80
|
+
widthClassName = "s-w-full s-max-w-4xl",
|
|
69
81
|
filter,
|
|
70
82
|
filterColumn,
|
|
71
83
|
initialColumnOrder,
|
|
@@ -118,11 +130,17 @@ export function DataTable<TData extends TBaseData>({
|
|
|
118
130
|
}, [filter, filterColumn]);
|
|
119
131
|
|
|
120
132
|
return (
|
|
121
|
-
<div
|
|
122
|
-
|
|
133
|
+
<div
|
|
134
|
+
className={classNames(
|
|
135
|
+
"s-flex s-flex-col s-gap-2",
|
|
136
|
+
className || "",
|
|
137
|
+
widthClassName
|
|
138
|
+
)}
|
|
139
|
+
>
|
|
140
|
+
<DataTable.Root>
|
|
123
141
|
<DataTable.Header>
|
|
124
142
|
{table.getHeaderGroups().map((headerGroup) => (
|
|
125
|
-
<DataTable.Row key={headerGroup.id}>
|
|
143
|
+
<DataTable.Row key={headerGroup.id} widthClassName={widthClassName}>
|
|
126
144
|
{headerGroup.headers.map((header) => {
|
|
127
145
|
const breakpoint = columnsBreakpoints[header.id];
|
|
128
146
|
if (
|
|
@@ -133,6 +151,7 @@ export function DataTable<TData extends TBaseData>({
|
|
|
133
151
|
}
|
|
134
152
|
return (
|
|
135
153
|
<DataTable.Head
|
|
154
|
+
column={header.column}
|
|
136
155
|
key={header.id}
|
|
137
156
|
onClick={header.column.getToggleSortingHandler()}
|
|
138
157
|
className={classNames(
|
|
@@ -172,6 +191,7 @@ export function DataTable<TData extends TBaseData>({
|
|
|
172
191
|
<DataTable.Body>
|
|
173
192
|
{table.getRowModel().rows.map((row) => (
|
|
174
193
|
<DataTable.Row
|
|
194
|
+
widthClassName={widthClassName}
|
|
175
195
|
key={row.id}
|
|
176
196
|
onClick={row.original.onClick}
|
|
177
197
|
moreMenuItems={row.original.moreMenuItems}
|
|
@@ -185,7 +205,7 @@ export function DataTable<TData extends TBaseData>({
|
|
|
185
205
|
return null;
|
|
186
206
|
}
|
|
187
207
|
return (
|
|
188
|
-
<DataTable.Cell key={cell.id}>
|
|
208
|
+
<DataTable.Cell column={cell.column} key={cell.id}>
|
|
189
209
|
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
|
190
210
|
</DataTable.Cell>
|
|
191
211
|
);
|
|
@@ -213,14 +233,10 @@ interface DataTableRootProps extends React.HTMLAttributes<HTMLTableElement> {
|
|
|
213
233
|
|
|
214
234
|
DataTable.Root = function DataTableRoot({
|
|
215
235
|
children,
|
|
216
|
-
className,
|
|
217
236
|
...props
|
|
218
237
|
}: DataTableRootProps) {
|
|
219
238
|
return (
|
|
220
|
-
<table
|
|
221
|
-
className={classNames("s-w-full s-border-collapse", className || "")}
|
|
222
|
-
{...props}
|
|
223
|
-
>
|
|
239
|
+
<table className="s-w-full s-border-collapse" {...props}>
|
|
224
240
|
{children}
|
|
225
241
|
</table>
|
|
226
242
|
);
|
|
@@ -247,13 +263,20 @@ DataTable.Header = function Header({
|
|
|
247
263
|
|
|
248
264
|
interface HeadProps extends React.ThHTMLAttributes<HTMLTableCellElement> {
|
|
249
265
|
children?: ReactNode;
|
|
266
|
+
column: Column<any>; // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
250
267
|
}
|
|
251
268
|
|
|
252
|
-
DataTable.Head = function Head({
|
|
269
|
+
DataTable.Head = function Head({
|
|
270
|
+
children,
|
|
271
|
+
className,
|
|
272
|
+
column,
|
|
273
|
+
...props
|
|
274
|
+
}: HeadProps) {
|
|
253
275
|
return (
|
|
254
276
|
<th
|
|
277
|
+
style={getSize(column.columnDef)}
|
|
255
278
|
className={classNames(
|
|
256
|
-
"s-
|
|
279
|
+
"s-py-1 s-pr-3 s-text-left s-font-medium s-text-element-800",
|
|
257
280
|
className || ""
|
|
258
281
|
)}
|
|
259
282
|
{...props}
|
|
@@ -279,6 +302,7 @@ interface RowProps extends React.HTMLAttributes<HTMLTableRowElement> {
|
|
|
279
302
|
children: ReactNode;
|
|
280
303
|
onClick?: () => void;
|
|
281
304
|
moreMenuItems?: DropdownItemProps[];
|
|
305
|
+
widthClassName: string;
|
|
282
306
|
}
|
|
283
307
|
|
|
284
308
|
DataTable.Row = function Row({
|
|
@@ -286,24 +310,31 @@ DataTable.Row = function Row({
|
|
|
286
310
|
className,
|
|
287
311
|
onClick,
|
|
288
312
|
moreMenuItems,
|
|
313
|
+
widthClassName,
|
|
289
314
|
...props
|
|
290
315
|
}: RowProps) {
|
|
291
316
|
return (
|
|
292
317
|
<tr
|
|
293
318
|
className={classNames(
|
|
294
|
-
"s-group/dt s-border-b s-border-structure-200 s-text-sm s-transition-colors s-duration-300 s-ease-out",
|
|
319
|
+
"s-group/dt s-flex s-items-center s-border-b s-border-structure-200 s-text-sm s-transition-colors s-duration-300 s-ease-out",
|
|
295
320
|
onClick ? "s-cursor-pointer hover:s-bg-structure-50" : "",
|
|
321
|
+
widthClassName,
|
|
296
322
|
className || ""
|
|
297
323
|
)}
|
|
298
324
|
onClick={onClick ? onClick : undefined}
|
|
299
325
|
{...props}
|
|
300
326
|
>
|
|
301
327
|
{children}
|
|
302
|
-
<td className="s-w-
|
|
328
|
+
<td className="s-flex s-w-8 s-cursor-pointer s-items-center s-pl-1 s-text-element-600">
|
|
303
329
|
{moreMenuItems && moreMenuItems.length > 0 && (
|
|
304
330
|
<DropdownMenu className="s-mr-1.5 s-flex">
|
|
305
331
|
<DropdownMenu.Button>
|
|
306
|
-
<IconButton
|
|
332
|
+
<IconButton
|
|
333
|
+
icon={MoreIcon}
|
|
334
|
+
size="sm"
|
|
335
|
+
variant="tertiary"
|
|
336
|
+
className="s-m-1"
|
|
337
|
+
/>
|
|
307
338
|
</DropdownMenu.Button>
|
|
308
339
|
<DropdownMenu.Items origin="topRight" width={220}>
|
|
309
340
|
{moreMenuItems?.map((item, index) => (
|
|
@@ -319,13 +350,22 @@ DataTable.Row = function Row({
|
|
|
319
350
|
|
|
320
351
|
interface CellProps extends React.HTMLAttributes<HTMLTableCellElement> {
|
|
321
352
|
children: ReactNode;
|
|
353
|
+
column: Column<any>; // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
322
354
|
}
|
|
323
355
|
|
|
324
|
-
DataTable.Cell = function Cell({
|
|
356
|
+
DataTable.Cell = function Cell({
|
|
357
|
+
children,
|
|
358
|
+
className,
|
|
359
|
+
column,
|
|
360
|
+
...props
|
|
361
|
+
}: CellProps) {
|
|
362
|
+
column.columnDef.minSize;
|
|
325
363
|
return (
|
|
326
364
|
<td
|
|
365
|
+
style={getSize(column.columnDef)}
|
|
327
366
|
className={classNames(
|
|
328
|
-
"s-h-12 s-whitespace-nowrap s-pl-1.5 s-text-element-800",
|
|
367
|
+
"s-flex s-h-12 s-items-center s-truncate s-whitespace-nowrap s-pl-1.5 s-text-element-800",
|
|
368
|
+
column.columnDef.meta?.className || "",
|
|
329
369
|
className || ""
|
|
330
370
|
)}
|
|
331
371
|
{...props}
|
|
@@ -335,6 +375,16 @@ DataTable.Cell = function Cell({ children, className, ...props }: CellProps) {
|
|
|
335
375
|
);
|
|
336
376
|
};
|
|
337
377
|
|
|
378
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
379
|
+
function getSize(columnDef: ColumnDef<any>) {
|
|
380
|
+
if (columnDef.meta?.width) {
|
|
381
|
+
return { width: columnDef.meta.width };
|
|
382
|
+
}
|
|
383
|
+
return {
|
|
384
|
+
flex: columnDef.meta?.flex ?? 1,
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
|
|
338
388
|
interface CellContentProps extends React.TdHTMLAttributes<HTMLDivElement> {
|
|
339
389
|
avatarUrl?: string;
|
|
340
390
|
avatarTooltipLabel?: string;
|
|
@@ -358,7 +408,10 @@ DataTable.CellContent = function CellContent({
|
|
|
358
408
|
}: CellContentProps) {
|
|
359
409
|
return (
|
|
360
410
|
<div
|
|
361
|
-
className={classNames(
|
|
411
|
+
className={classNames(
|
|
412
|
+
"s-flex s-w-full s-items-center s-py-2",
|
|
413
|
+
className || ""
|
|
414
|
+
)}
|
|
362
415
|
{...props}
|
|
363
416
|
>
|
|
364
417
|
{avatarUrl && avatarTooltipLabel && (
|
|
@@ -389,8 +442,10 @@ DataTable.CellContent = function CellContent({
|
|
|
389
442
|
)}
|
|
390
443
|
/>
|
|
391
444
|
)}
|
|
392
|
-
<div className="s-flex">
|
|
393
|
-
<span className="s-text-sm s-text-element-800">
|
|
445
|
+
<div className="s-flex s-shrink s-truncate">
|
|
446
|
+
<span className="s-truncate s-text-sm s-text-element-800">
|
|
447
|
+
{children}
|
|
448
|
+
</span>
|
|
394
449
|
{description && (
|
|
395
450
|
<span className="s-pl-2 s-text-sm s-text-element-600">
|
|
396
451
|
{description}
|
|
@@ -73,10 +73,8 @@ export function Dialog({
|
|
|
73
73
|
<HeadlessDialog.Title className="s-text-element-950 s-truncate s-text-lg s-font-medium">
|
|
74
74
|
{title}
|
|
75
75
|
</HeadlessDialog.Title>
|
|
76
|
-
<div className="s-
|
|
77
|
-
|
|
78
|
-
</div>
|
|
79
|
-
<div className="s-z-10 s-flex s-w-full s-justify-end">
|
|
76
|
+
<div className="s-text-base s-text-element-700">{children}</div>
|
|
77
|
+
<div className="s-flex s-w-full s-justify-end">
|
|
80
78
|
<Button.List>
|
|
81
79
|
{!isSaving && (
|
|
82
80
|
<>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { useRef } from "react";
|
|
2
2
|
|
|
3
3
|
import { classNames } from "@sparkle/lib/utils";
|
|
4
4
|
|
|
@@ -9,7 +9,7 @@ type TextAreaProps = {
|
|
|
9
9
|
error?: string | null;
|
|
10
10
|
showErrorLabel?: boolean;
|
|
11
11
|
className?: string;
|
|
12
|
-
|
|
12
|
+
minRows?: number;
|
|
13
13
|
};
|
|
14
14
|
|
|
15
15
|
export function TextArea({
|
|
@@ -19,21 +19,14 @@ export function TextArea({
|
|
|
19
19
|
error,
|
|
20
20
|
showErrorLabel = false,
|
|
21
21
|
className,
|
|
22
|
-
|
|
22
|
+
minRows = 10
|
|
23
23
|
}: TextAreaProps) {
|
|
24
24
|
const textareaRef = useRef<HTMLTextAreaElement>(null);
|
|
25
25
|
|
|
26
|
-
useEffect(() => {
|
|
27
|
-
const textarea = textareaRef.current;
|
|
28
|
-
if (textarea) {
|
|
29
|
-
textarea.style.height = 'auto'; // Reset height
|
|
30
|
-
textarea.style.height = `${textarea.scrollHeight}px`; // Set to scroll height
|
|
31
|
-
}
|
|
32
|
-
}, [value]); // Re-run when value changes
|
|
33
26
|
return (
|
|
34
27
|
<div className="s-flex s-flex-col s-gap-1 s-p-px">
|
|
35
28
|
<textarea
|
|
36
|
-
rows={
|
|
29
|
+
rows={minRows}
|
|
37
30
|
ref={textareaRef}
|
|
38
31
|
className={classNames(
|
|
39
32
|
"overflow-y-auto s-block s-w-full s-min-w-0 s-rounded-xl s-text-sm s-placeholder-element-700 s-transition-all s-duration-200 s-scrollbar-hide",
|
|
@@ -47,15 +40,6 @@ export function TextArea({
|
|
|
47
40
|
placeholder={placeholder}
|
|
48
41
|
value={value ?? ""}
|
|
49
42
|
onChange={(e) => {
|
|
50
|
-
const newValue = e.target.value;
|
|
51
|
-
const textAreaComponent = textareaRef.current;
|
|
52
|
-
if (
|
|
53
|
-
textAreaComponent &&
|
|
54
|
-
value?.length &&
|
|
55
|
-
newValue.length < value.length
|
|
56
|
-
) {
|
|
57
|
-
textAreaComponent.style.height = "auto"; // Reset height to recalculate
|
|
58
|
-
}
|
|
59
43
|
onChange(e.target.value);
|
|
60
44
|
}}
|
|
61
45
|
/>
|
|
@@ -68,6 +68,22 @@ const data: Data[] = [
|
|
|
68
68
|
],
|
|
69
69
|
onClick: () => alert("Design clicked"),
|
|
70
70
|
},
|
|
71
|
+
{
|
|
72
|
+
name: "Very long name that should be truncated at some point to avoid overflow and make the table more readable",
|
|
73
|
+
usedBy: 2,
|
|
74
|
+
addedBy: "Another very long user name that should be truncated",
|
|
75
|
+
lastUpdated: "2023-07-09",
|
|
76
|
+
size: "64kb",
|
|
77
|
+
icon: FolderIcon,
|
|
78
|
+
moreMenuItems: [
|
|
79
|
+
{
|
|
80
|
+
label: "Edit (disabled)",
|
|
81
|
+
onClick: () => alert("Design menu clicked"),
|
|
82
|
+
disabled: true,
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
onClick: () => alert("Design clicked"),
|
|
86
|
+
},
|
|
71
87
|
{
|
|
72
88
|
name: "design",
|
|
73
89
|
usedBy: 3,
|
|
@@ -124,7 +140,12 @@ const columns: ColumnDef<Data>[] = [
|
|
|
124
140
|
},
|
|
125
141
|
{
|
|
126
142
|
accessorKey: "usedBy",
|
|
143
|
+
minSize: 100,
|
|
144
|
+
size: 100,
|
|
127
145
|
header: "Used by",
|
|
146
|
+
meta: {
|
|
147
|
+
width: "100px",
|
|
148
|
+
},
|
|
128
149
|
cell: (info) => (
|
|
129
150
|
<DataTable.CellContent>{info.row.original.usedBy}</DataTable.CellContent>
|
|
130
151
|
),
|
|
@@ -132,6 +153,9 @@ const columns: ColumnDef<Data>[] = [
|
|
|
132
153
|
{
|
|
133
154
|
accessorKey: "addedBy",
|
|
134
155
|
header: "Added by",
|
|
156
|
+
meta: {
|
|
157
|
+
width: "100px",
|
|
158
|
+
},
|
|
135
159
|
cell: (info) => (
|
|
136
160
|
<DataTable.CellContent>{info.row.original.addedBy}</DataTable.CellContent>
|
|
137
161
|
),
|
|
@@ -139,6 +163,9 @@ const columns: ColumnDef<Data>[] = [
|
|
|
139
163
|
{
|
|
140
164
|
accessorKey: "lastUpdated",
|
|
141
165
|
header: "Last updated",
|
|
166
|
+
meta: {
|
|
167
|
+
width: "200px",
|
|
168
|
+
},
|
|
142
169
|
cell: (info) => (
|
|
143
170
|
<DataTable.CellContent>
|
|
144
171
|
{info.row.original.lastUpdated}
|
|
@@ -149,6 +176,9 @@ const columns: ColumnDef<Data>[] = [
|
|
|
149
176
|
{
|
|
150
177
|
accessorKey: "size",
|
|
151
178
|
header: "Size",
|
|
179
|
+
meta: {
|
|
180
|
+
width: "100px",
|
|
181
|
+
},
|
|
152
182
|
cell: (info) => (
|
|
153
183
|
<DataTable.CellContent>{info.row.original.size}</DataTable.CellContent>
|
|
154
184
|
),
|
|
@@ -192,6 +222,7 @@ export const DataTablePaginatedExample = () => {
|
|
|
192
222
|
onChange={(v) => setFilter(v)}
|
|
193
223
|
/>
|
|
194
224
|
<DataTable
|
|
225
|
+
className="s-w-full s-max-w-4xl s-overflow-x-auto"
|
|
195
226
|
data={data}
|
|
196
227
|
filter={filter}
|
|
197
228
|
filterColumn="name"
|
|
@@ -227,6 +258,7 @@ export const DataTablePaginatedServerSideExample = () => {
|
|
|
227
258
|
onChange={(v) => setFilter(v)}
|
|
228
259
|
/>
|
|
229
260
|
<DataTable
|
|
261
|
+
className="s-w-full s-max-w-4xl s-overflow-x-auto"
|
|
230
262
|
data={rows}
|
|
231
263
|
totalRowCount={data.length}
|
|
232
264
|
filter={filter}
|