@dust-tt/sparkle 0.2.239 → 0.2.241
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 +45 -28
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/components/DataTable.d.ts +5 -4
- package/dist/esm/components/DataTable.d.ts.map +1 -1
- package/dist/esm/components/DataTable.js +17 -21
- package/dist/esm/components/DataTable.js.map +1 -1
- package/dist/esm/components/DropdownMenu.d.ts +3 -1
- package/dist/esm/components/DropdownMenu.d.ts.map +1 -1
- package/dist/esm/components/DropdownMenu.js +29 -8
- package/dist/esm/components/DropdownMenu.js.map +1 -1
- package/dist/esm/stories/DataTable.stories.d.ts +1 -0
- package/dist/esm/stories/DataTable.stories.d.ts.map +1 -1
- package/dist/esm/stories/DataTable.stories.js +18 -4
- package/dist/esm/stories/DataTable.stories.js.map +1 -1
- package/dist/esm/stories/DropdownMenu.stories.js +1 -1
- package/dist/esm/stories/DropdownMenu.stories.js.map +1 -1
- package/package.json +2 -2
- package/src/components/DataTable.tsx +31 -11
- package/src/components/DropdownMenu.tsx +134 -104
- package/src/stories/DataTable.stories.tsx +43 -5
- package/src/stories/DropdownMenu.stories.tsx +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Menu, Transition } from "@headlessui/react";
|
|
2
2
|
import React, {
|
|
3
3
|
ComponentType,
|
|
4
|
+
forwardRef,
|
|
4
5
|
Fragment,
|
|
5
6
|
JSXElementConstructor,
|
|
6
7
|
MouseEvent,
|
|
@@ -102,135 +103,164 @@ export interface DropdownButtonProps {
|
|
|
102
103
|
className?: string;
|
|
103
104
|
disabled?: boolean;
|
|
104
105
|
children?: React.ReactNode;
|
|
106
|
+
ref?: React.Ref<HTMLButtonElement>;
|
|
107
|
+
onClick?: () => void;
|
|
105
108
|
}
|
|
106
109
|
|
|
107
|
-
DropdownMenu.Button =
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
110
|
+
DropdownMenu.Button = forwardRef<HTMLButtonElement, DropdownButtonProps>(
|
|
111
|
+
function DropdownMenuButton(
|
|
112
|
+
{
|
|
113
|
+
label,
|
|
114
|
+
type = "menu",
|
|
115
|
+
size = "sm",
|
|
116
|
+
tooltip,
|
|
117
|
+
icon,
|
|
118
|
+
children,
|
|
119
|
+
tooltipPosition = "above",
|
|
120
|
+
className = "",
|
|
121
|
+
disabled = false,
|
|
122
|
+
onClick,
|
|
123
|
+
},
|
|
124
|
+
forwardedRef
|
|
125
|
+
) {
|
|
126
|
+
const contextRef = useContext(ButtonRefContext);
|
|
127
|
+
|
|
128
|
+
const finalLabelClasses = classNames(
|
|
129
|
+
labelClasses.base,
|
|
130
|
+
labelSizeClasses[size],
|
|
131
|
+
labelClasses.dark.base,
|
|
132
|
+
!disabled ? labelClasses.active : "",
|
|
133
|
+
!disabled ? labelClasses.dark.active : "",
|
|
134
|
+
!disabled ? labelClasses.hover : "",
|
|
135
|
+
!disabled ? labelClasses.dark.hover : "",
|
|
136
|
+
disabled ? labelClasses.disabled : ""
|
|
137
|
+
);
|
|
128
138
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
139
|
+
const finalIconClasses = classNames(
|
|
140
|
+
iconClasses.base,
|
|
141
|
+
iconClasses.dark.base,
|
|
142
|
+
!disabled ? iconClasses.hover : "",
|
|
143
|
+
!disabled ? iconClasses.dark.hover : "",
|
|
144
|
+
disabled ? iconClasses.disabled : ""
|
|
145
|
+
);
|
|
136
146
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
147
|
+
const finalChevronClasses = classNames(
|
|
148
|
+
chevronClasses.base,
|
|
149
|
+
!disabled ? chevronClasses.hover : "",
|
|
150
|
+
chevronClasses.dark.base,
|
|
151
|
+
!disabled ? chevronClasses.dark.hover : "",
|
|
152
|
+
disabled ? chevronClasses.disabled : ""
|
|
153
|
+
);
|
|
144
154
|
|
|
145
|
-
|
|
155
|
+
const aggregatedRef = (value: HTMLButtonElement) => {
|
|
156
|
+
if (contextRef) {
|
|
157
|
+
contextRef.current = value;
|
|
158
|
+
}
|
|
159
|
+
if (typeof forwardedRef === "function") {
|
|
160
|
+
forwardedRef(value);
|
|
161
|
+
} else if (forwardedRef) {
|
|
162
|
+
forwardedRef.current = value;
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
if (children) {
|
|
167
|
+
return (
|
|
168
|
+
<Menu.Button
|
|
169
|
+
as="div"
|
|
170
|
+
disabled={disabled}
|
|
171
|
+
ref={aggregatedRef}
|
|
172
|
+
className={classNames(
|
|
173
|
+
disabled ? "s-cursor-default" : "s-cursor-pointer",
|
|
174
|
+
className,
|
|
175
|
+
"s-group/dm s-flex s-justify-items-center s-text-sm s-font-medium focus:s-outline-none focus:s-ring-0",
|
|
176
|
+
label ? "s-gap-1.5" : "s-gap-0"
|
|
177
|
+
)}
|
|
178
|
+
onClick={(e) => e.stopPropagation()}
|
|
179
|
+
>
|
|
180
|
+
{tooltip ? (
|
|
181
|
+
<Tooltip position={tooltipPosition} label={tooltip}>
|
|
182
|
+
{children}
|
|
183
|
+
</Tooltip>
|
|
184
|
+
) : (
|
|
185
|
+
children
|
|
186
|
+
)}
|
|
187
|
+
</Menu.Button>
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const chevronIcon =
|
|
192
|
+
type === "select"
|
|
193
|
+
? ChevronUpDownIcon
|
|
194
|
+
: type === "submenu"
|
|
195
|
+
? ChevronRightIcon
|
|
196
|
+
: ChevronDownIcon;
|
|
146
197
|
|
|
147
|
-
if (children) {
|
|
148
198
|
return (
|
|
149
|
-
|
|
150
|
-
as="div"
|
|
151
|
-
disabled={disabled}
|
|
152
|
-
ref={buttonRef}
|
|
153
|
-
className={classNames(
|
|
154
|
-
disabled ? "s-cursor-default" : "s-cursor-pointer",
|
|
155
|
-
className,
|
|
156
|
-
"s-group/dm s-flex s-justify-items-center s-text-sm s-font-medium focus:s-outline-none focus:s-ring-0",
|
|
157
|
-
label ? "s-gap-1.5" : "s-gap-0"
|
|
158
|
-
)}
|
|
159
|
-
onClick={(e) => e.stopPropagation()}
|
|
160
|
-
>
|
|
199
|
+
<>
|
|
161
200
|
{tooltip ? (
|
|
162
|
-
<Tooltip
|
|
163
|
-
|
|
201
|
+
<Tooltip label={tooltip} position={tooltipPosition}>
|
|
202
|
+
<Menu.Button
|
|
203
|
+
disabled={disabled}
|
|
204
|
+
ref={aggregatedRef}
|
|
205
|
+
className={classNames(
|
|
206
|
+
disabled ? "s-cursor-default" : "s-cursor-pointer",
|
|
207
|
+
className,
|
|
208
|
+
"s-group/dm s-flex s-justify-items-center s-text-sm s-font-medium focus:s-outline-none focus:s-ring-0",
|
|
209
|
+
label ? (size === "md" ? "s-gap-2" : "s-gap-1.5") : "s-gap-0.5"
|
|
210
|
+
)}
|
|
211
|
+
onClick={(e) => {
|
|
212
|
+
e.stopPropagation();
|
|
213
|
+
if (onClick) {
|
|
214
|
+
onClick();
|
|
215
|
+
}
|
|
216
|
+
}}
|
|
217
|
+
>
|
|
218
|
+
<Icon visual={icon} size={size} className={finalIconClasses} />
|
|
219
|
+
<Icon
|
|
220
|
+
visual={chevronIcon}
|
|
221
|
+
size={size === "sm" ? "xs" : "sm"}
|
|
222
|
+
className={finalChevronClasses}
|
|
223
|
+
/>
|
|
224
|
+
</Menu.Button>
|
|
164
225
|
</Tooltip>
|
|
165
226
|
) : (
|
|
166
|
-
children
|
|
167
|
-
)}
|
|
168
|
-
</Menu.Button>
|
|
169
|
-
);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
const chevronIcon =
|
|
173
|
-
type === "select"
|
|
174
|
-
? ChevronUpDownIcon
|
|
175
|
-
: type === "submenu"
|
|
176
|
-
? ChevronRightIcon
|
|
177
|
-
: ChevronDownIcon;
|
|
178
|
-
|
|
179
|
-
return (
|
|
180
|
-
<>
|
|
181
|
-
{tooltip ? (
|
|
182
|
-
<Tooltip label={tooltip} position={tooltipPosition}>
|
|
183
227
|
<Menu.Button
|
|
184
228
|
disabled={disabled}
|
|
185
|
-
ref={
|
|
229
|
+
ref={aggregatedRef}
|
|
186
230
|
className={classNames(
|
|
187
231
|
disabled ? "s-cursor-default" : "s-cursor-pointer",
|
|
188
232
|
className,
|
|
189
233
|
"s-group/dm s-flex s-justify-items-center s-text-sm s-font-medium focus:s-outline-none focus:s-ring-0",
|
|
190
|
-
label ? (size === "md" ? "s-gap-2" : "s-gap-1.5") : "s-gap-0.5"
|
|
234
|
+
label ? (size === "md" ? "s-gap-2" : "s-gap-1.5") : "s-gap-0.5",
|
|
235
|
+
type === "submenu" ? "s-opacity-50" : ""
|
|
191
236
|
)}
|
|
192
|
-
onClick={(e) =>
|
|
237
|
+
onClick={(e) => {
|
|
238
|
+
e.stopPropagation();
|
|
239
|
+
if (onClick) {
|
|
240
|
+
onClick();
|
|
241
|
+
}
|
|
242
|
+
}}
|
|
193
243
|
>
|
|
194
244
|
<Icon visual={icon} size={size} className={finalIconClasses} />
|
|
245
|
+
<span
|
|
246
|
+
className={classNames(
|
|
247
|
+
finalLabelClasses,
|
|
248
|
+
type === "submenu" ? "s-w-full" : ""
|
|
249
|
+
)}
|
|
250
|
+
>
|
|
251
|
+
{label}
|
|
252
|
+
</span>
|
|
195
253
|
<Icon
|
|
196
254
|
visual={chevronIcon}
|
|
197
255
|
size={size === "sm" ? "xs" : "sm"}
|
|
198
256
|
className={finalChevronClasses}
|
|
199
257
|
/>
|
|
200
258
|
</Menu.Button>
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
className={classNames(
|
|
207
|
-
disabled ? "s-cursor-default" : "s-cursor-pointer",
|
|
208
|
-
className,
|
|
209
|
-
"s-group/dm s-flex s-justify-items-center s-text-sm s-font-medium focus:s-outline-none focus:s-ring-0",
|
|
210
|
-
label ? (size === "md" ? "s-gap-2" : "s-gap-1.5") : "s-gap-0.5",
|
|
211
|
-
type === "submenu" ? "s-opacity-50" : ""
|
|
212
|
-
)}
|
|
213
|
-
onClick={(e) => e.stopPropagation()}
|
|
214
|
-
>
|
|
215
|
-
<Icon visual={icon} size={size} className={finalIconClasses} />
|
|
216
|
-
<span
|
|
217
|
-
className={classNames(
|
|
218
|
-
finalLabelClasses,
|
|
219
|
-
type === "submenu" ? "s-w-full" : ""
|
|
220
|
-
)}
|
|
221
|
-
>
|
|
222
|
-
{label}
|
|
223
|
-
</span>
|
|
224
|
-
<Icon
|
|
225
|
-
visual={chevronIcon}
|
|
226
|
-
size={size === "sm" ? "xs" : "sm"}
|
|
227
|
-
className={finalChevronClasses}
|
|
228
|
-
/>
|
|
229
|
-
</Menu.Button>
|
|
230
|
-
)}
|
|
231
|
-
</>
|
|
232
|
-
);
|
|
233
|
-
};
|
|
259
|
+
)}
|
|
260
|
+
</>
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
);
|
|
234
264
|
|
|
235
265
|
export interface DropdownItemProps {
|
|
236
266
|
children?: React.ReactNode;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Meta } from "@storybook/react";
|
|
2
|
-
import { ColumnDef, PaginationState } from "@tanstack/react-table";
|
|
2
|
+
import { ColumnDef, PaginationState, SortingState } from "@tanstack/react-table";
|
|
3
3
|
import React, { useMemo } from "react";
|
|
4
4
|
|
|
5
5
|
import { DropdownItemProps } from "@sparkle/components/DropdownMenu";
|
|
@@ -206,6 +206,32 @@ export const DataTableExample = () => {
|
|
|
206
206
|
);
|
|
207
207
|
};
|
|
208
208
|
|
|
209
|
+
export const DataTableClientSideSortingExample = () => {
|
|
210
|
+
const [sorting, setSorting] = React.useState<SortingState>([{ id: "name", desc: true }])
|
|
211
|
+
const [filter, setFilter] = React.useState<string>("");
|
|
212
|
+
|
|
213
|
+
return (
|
|
214
|
+
<div className="s-w-full s-max-w-4xl s-overflow-x-auto">
|
|
215
|
+
<Input
|
|
216
|
+
name="filter"
|
|
217
|
+
placeholder="Filter"
|
|
218
|
+
value={filter}
|
|
219
|
+
onChange={(v) => setFilter(v)}
|
|
220
|
+
/>
|
|
221
|
+
<DataTable
|
|
222
|
+
className="s-w-full s-max-w-4xl s-overflow-x-auto"
|
|
223
|
+
data={data}
|
|
224
|
+
filter={filter}
|
|
225
|
+
filterColumn="name"
|
|
226
|
+
columns={columns}
|
|
227
|
+
columnsBreakpoints={{ lastUpdated: "sm" }}
|
|
228
|
+
sorting={sorting}
|
|
229
|
+
setSorting={setSorting}
|
|
230
|
+
/>
|
|
231
|
+
</div>
|
|
232
|
+
);
|
|
233
|
+
};
|
|
234
|
+
|
|
209
235
|
export const DataTablePaginatedExample = () => {
|
|
210
236
|
const [pagination, setPagination] = React.useState<PaginationState>({
|
|
211
237
|
pageIndex: 0,
|
|
@@ -229,7 +255,6 @@ export const DataTablePaginatedExample = () => {
|
|
|
229
255
|
pagination={pagination}
|
|
230
256
|
setPagination={setPagination}
|
|
231
257
|
columns={columns}
|
|
232
|
-
initialColumnOrder={[{ id: "name", desc: false }]}
|
|
233
258
|
columnsBreakpoints={{ lastUpdated: "sm" }}
|
|
234
259
|
/>
|
|
235
260
|
</div>
|
|
@@ -241,14 +266,25 @@ export const DataTablePaginatedServerSideExample = () => {
|
|
|
241
266
|
pageIndex: 0,
|
|
242
267
|
pageSize: 2,
|
|
243
268
|
});
|
|
269
|
+
const [sorting, setSorting] = React.useState<SortingState>([{ id: "name", desc: true }])
|
|
244
270
|
const [filter, setFilter] = React.useState<string>("");
|
|
245
271
|
const rows = useMemo(() => {
|
|
272
|
+
if (sorting.length > 0) {
|
|
273
|
+
const order = sorting[0].desc ? -1: 1;
|
|
274
|
+
return data.sort(
|
|
275
|
+
(a: Data, b: Data) => {
|
|
276
|
+
return a.name.toLowerCase().localeCompare(b.name.toLowerCase()) * order
|
|
277
|
+
}
|
|
278
|
+
).slice(
|
|
279
|
+
pagination.pageIndex * pagination.pageSize,
|
|
280
|
+
(pagination.pageIndex + 1) * pagination.pageSize
|
|
281
|
+
);
|
|
282
|
+
}
|
|
246
283
|
return data.slice(
|
|
247
284
|
pagination.pageIndex * pagination.pageSize,
|
|
248
285
|
(pagination.pageIndex + 1) * pagination.pageSize
|
|
249
286
|
);
|
|
250
|
-
}, [data, pagination]);
|
|
251
|
-
|
|
287
|
+
}, [data, pagination, sorting]);
|
|
252
288
|
return (
|
|
253
289
|
<div className="s-w-full s-max-w-4xl s-overflow-x-auto">
|
|
254
290
|
<Input
|
|
@@ -266,8 +302,10 @@ export const DataTablePaginatedServerSideExample = () => {
|
|
|
266
302
|
pagination={pagination}
|
|
267
303
|
setPagination={setPagination}
|
|
268
304
|
columns={columns}
|
|
269
|
-
|
|
305
|
+
sorting={sorting}
|
|
306
|
+
setSorting={setSorting}
|
|
270
307
|
columnsBreakpoints={{ lastUpdated: "sm" }}
|
|
308
|
+
isServerSideSorting={true}
|
|
271
309
|
/>
|
|
272
310
|
</div>
|
|
273
311
|
);
|
|
@@ -48,7 +48,7 @@ export const DropdownExample = () => {
|
|
|
48
48
|
<div className="s-flex s-gap-6">
|
|
49
49
|
<div className="s-text-sm">Action</div>
|
|
50
50
|
<DropdownMenu>
|
|
51
|
-
<DropdownMenu.Button label="Action" />
|
|
51
|
+
<DropdownMenu.Button label="Action" onClick={() => console.log("CLICK")}/>
|
|
52
52
|
<DropdownMenu.Items width={220}>
|
|
53
53
|
<DropdownMenu.SectionHeader label="Edition" />
|
|
54
54
|
<DropdownMenu.Item
|