gridsmith-ui 0.4.0 → 0.6.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/README.md +63 -3
- package/dist/charts.d.ts +246 -0
- package/dist/charts.js +1028 -0
- package/dist/charts.js.map +1 -0
- package/dist/chunk-4SDKQDYV.js +93 -0
- package/dist/chunk-4SDKQDYV.js.map +1 -0
- package/dist/chunk-CHNY75QI.js +278 -0
- package/dist/chunk-CHNY75QI.js.map +1 -0
- package/dist/chunk-DPF6776I.js +36 -0
- package/dist/chunk-DPF6776I.js.map +1 -0
- package/dist/{chunk-5XIPPVH7.js → chunk-IUBWNDUK.js} +15 -4
- package/dist/chunk-IUBWNDUK.js.map +1 -0
- package/dist/chunk-OUYJXVLQ.js +41 -0
- package/dist/chunk-OUYJXVLQ.js.map +1 -0
- package/dist/{chunk-6TMNEBBJ.js → chunk-XUBVMRIE.js} +44 -35
- package/dist/chunk-XUBVMRIE.js.map +1 -0
- package/dist/data-grid.d.ts +27 -0
- package/dist/data-grid.js +293 -0
- package/dist/data-grid.js.map +1 -0
- package/dist/editor.d.ts +18 -0
- package/dist/editor.js +632 -0
- package/dist/editor.js.map +1 -0
- package/dist/{feather-432JQGUB.js → feather-V32UNIQL.js} +2 -3
- package/dist/feather-V32UNIQL.js.map +1 -0
- package/dist/{heroicons-CCKJHFZY.js → heroicons-CA5OQ76O.js} +2 -3
- package/dist/heroicons-CA5OQ76O.js.map +1 -0
- package/dist/icons.js +1 -2
- package/dist/index.d.ts +430 -133
- package/dist/index.js +10510 -98031
- package/dist/index.js.map +1 -1
- package/dist/kanban.d.ts +25 -0
- package/dist/kanban.js +224 -0
- package/dist/kanban.js.map +1 -0
- package/dist/{lucide-Z74WVRAK.js → lucide-AILUUOAJ.js} +2 -3
- package/dist/lucide-AILUUOAJ.js.map +1 -0
- package/dist/{phosphor-DYUCR5S2.js → phosphor-A4JOBGMT.js} +2 -3
- package/dist/phosphor-A4JOBGMT.js.map +1 -0
- package/dist/resizable.d.ts +39 -0
- package/dist/resizable.js +89 -0
- package/dist/resizable.js.map +1 -0
- package/dist/roots.css +46 -11
- package/dist/{tabler-GRXDPAHR.js → tabler-TVOR6AFM.js} +2 -3
- package/dist/tabler-TVOR6AFM.js.map +1 -0
- package/dist/use-breakpoint-Cn51IubK.d.ts +30 -0
- package/dist/utils.js +1 -2
- package/dist/virtualized.d.ts +16 -0
- package/dist/virtualized.js +55 -0
- package/dist/virtualized.js.map +1 -0
- package/package.json +144 -4
- package/dist/chunk-5WRI5ZAA.js +0 -29
- package/dist/chunk-5WRI5ZAA.js.map +0 -1
- package/dist/chunk-5XIPPVH7.js.map +0 -1
- package/dist/chunk-6TMNEBBJ.js.map +0 -1
- package/dist/feather-432JQGUB.js.map +0 -1
- package/dist/heroicons-CCKJHFZY.js.map +0 -1
- package/dist/lucide-Z74WVRAK.js.map +0 -1
- package/dist/phosphor-DYUCR5S2.js.map +0 -1
- package/dist/tabler-GRXDPAHR.js.map +0 -1
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
import { useBreakpoint } from './chunk-DPF6776I.js';
|
|
2
|
+
import { useTextOverflow, Tooltip } from './chunk-CHNY75QI.js';
|
|
3
|
+
import { Icon } from './chunk-XUBVMRIE.js';
|
|
4
|
+
import { cn } from './chunk-IUBWNDUK.js';
|
|
5
|
+
import { useState, useMemo, useCallback } from 'react';
|
|
6
|
+
import { useReactTable, getPaginationRowModel, getSortedRowModel, getCoreRowModel, flexRender } from '@tanstack/react-table';
|
|
7
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
8
|
+
|
|
9
|
+
function TruncCell({ children, lines }) {
|
|
10
|
+
const { ref, isTruncated } = useTextOverflow({ lines });
|
|
11
|
+
const clampClass = lines === 1 ? "truncate" : `line-clamp-${lines}`;
|
|
12
|
+
const cell = /* @__PURE__ */ jsx("span", { ref, className: cn(clampClass, "block"), children });
|
|
13
|
+
if (!isTruncated) return cell;
|
|
14
|
+
return /* @__PURE__ */ jsx(Tooltip, { content: children, children: cell });
|
|
15
|
+
}
|
|
16
|
+
function DataGrid({
|
|
17
|
+
data,
|
|
18
|
+
columns,
|
|
19
|
+
pageSize = 10,
|
|
20
|
+
editable = false,
|
|
21
|
+
onCellEdit,
|
|
22
|
+
mobileBreakpoint = "md",
|
|
23
|
+
className
|
|
24
|
+
}) {
|
|
25
|
+
const isMobile = useBreakpoint(mobileBreakpoint);
|
|
26
|
+
const [sorting, setSorting] = useState([]);
|
|
27
|
+
const [editCell, setEditCell] = useState(null);
|
|
28
|
+
const [editValue, setEditValue] = useState("");
|
|
29
|
+
const tableColumns = useMemo(() => {
|
|
30
|
+
if (!editable) return columns;
|
|
31
|
+
return columns.map((col) => ({
|
|
32
|
+
...col,
|
|
33
|
+
cell: (info) => {
|
|
34
|
+
const rowIdx = info.row.index;
|
|
35
|
+
const colId = info.column.id;
|
|
36
|
+
const isEditing = editCell?.row === rowIdx && editCell?.col === colId;
|
|
37
|
+
if (isEditing) {
|
|
38
|
+
return /* @__PURE__ */ jsx(
|
|
39
|
+
"input",
|
|
40
|
+
{
|
|
41
|
+
autoFocus: true,
|
|
42
|
+
className: cn(
|
|
43
|
+
"w-full h-full bg-transparent text-sm text-[var(--ds-text-primary)]",
|
|
44
|
+
"outline-none border-none px-0"
|
|
45
|
+
),
|
|
46
|
+
value: editValue,
|
|
47
|
+
onChange: (e) => setEditValue(e.target.value),
|
|
48
|
+
onBlur: () => {
|
|
49
|
+
onCellEdit?.(rowIdx, colId, editValue);
|
|
50
|
+
setEditCell(null);
|
|
51
|
+
},
|
|
52
|
+
onKeyDown: (e) => {
|
|
53
|
+
if (e.key === "Enter") {
|
|
54
|
+
onCellEdit?.(rowIdx, colId, editValue);
|
|
55
|
+
setEditCell(null);
|
|
56
|
+
} else if (e.key === "Escape") {
|
|
57
|
+
setEditCell(null);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
const rendered = typeof col.cell === "function" ? col.cell(info) : info.getValue();
|
|
64
|
+
return /* @__PURE__ */ jsx(
|
|
65
|
+
"span",
|
|
66
|
+
{
|
|
67
|
+
onDoubleClick: () => {
|
|
68
|
+
setEditCell({ row: rowIdx, col: colId });
|
|
69
|
+
setEditValue(String(info.getValue() ?? ""));
|
|
70
|
+
},
|
|
71
|
+
className: "cursor-default",
|
|
72
|
+
children: rendered
|
|
73
|
+
}
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
}));
|
|
77
|
+
}, [columns, editable, editCell, editValue, onCellEdit]);
|
|
78
|
+
const table = useReactTable({
|
|
79
|
+
data,
|
|
80
|
+
columns: tableColumns,
|
|
81
|
+
state: { sorting },
|
|
82
|
+
onSortingChange: setSorting,
|
|
83
|
+
getCoreRowModel: getCoreRowModel(),
|
|
84
|
+
getSortedRowModel: getSortedRowModel(),
|
|
85
|
+
getPaginationRowModel: getPaginationRowModel(),
|
|
86
|
+
initialState: { pagination: { pageSize } }
|
|
87
|
+
});
|
|
88
|
+
const handlePageChange = useCallback(
|
|
89
|
+
(page) => table.setPageIndex(page),
|
|
90
|
+
[table]
|
|
91
|
+
);
|
|
92
|
+
const pageCount = table.getPageCount();
|
|
93
|
+
const currentPage = table.getState().pagination.pageIndex;
|
|
94
|
+
if (isMobile) {
|
|
95
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("space-y-ds-3", className), children: [
|
|
96
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-col gap-ds-3", children: table.getRowModel().rows.map((row) => /* @__PURE__ */ jsx(
|
|
97
|
+
"div",
|
|
98
|
+
{
|
|
99
|
+
className: cn(
|
|
100
|
+
"border-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
|
|
101
|
+
"rounded-[var(--ds-radius-md)] bg-[var(--ds-bg-surface)]",
|
|
102
|
+
"p-ds-4 space-y-ds-2"
|
|
103
|
+
),
|
|
104
|
+
children: row.getVisibleCells().map((cell) => /* @__PURE__ */ jsxs("div", { className: "flex justify-between gap-ds-2 text-sm", children: [
|
|
105
|
+
/* @__PURE__ */ jsx("span", { className: "text-[var(--ds-text-secondary)] font-medium text-xs uppercase tracking-wider", children: typeof cell.column.columnDef.header === "string" ? cell.column.columnDef.header : cell.column.id }),
|
|
106
|
+
/* @__PURE__ */ jsx("span", { className: "text-[var(--ds-text-primary)] text-right", children: flexRender(cell.column.columnDef.cell, cell.getContext()) })
|
|
107
|
+
] }, cell.id))
|
|
108
|
+
},
|
|
109
|
+
row.id
|
|
110
|
+
)) }),
|
|
111
|
+
pageCount > 1 && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-sm", children: [
|
|
112
|
+
/* @__PURE__ */ jsxs("span", { className: "text-[var(--ds-text-muted)]", children: [
|
|
113
|
+
"Page ",
|
|
114
|
+
currentPage + 1,
|
|
115
|
+
" of ",
|
|
116
|
+
pageCount
|
|
117
|
+
] }),
|
|
118
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-ds-1", children: [
|
|
119
|
+
/* @__PURE__ */ jsx(PagerBtn, { onClick: () => handlePageChange(currentPage - 1), disabled: currentPage === 0, label: "Prev" }),
|
|
120
|
+
/* @__PURE__ */ jsx(PagerBtn, { onClick: () => handlePageChange(currentPage + 1), disabled: currentPage >= pageCount - 1, label: "Next" })
|
|
121
|
+
] })
|
|
122
|
+
] })
|
|
123
|
+
] });
|
|
124
|
+
}
|
|
125
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("space-y-ds-3", className), children: [
|
|
126
|
+
/* @__PURE__ */ jsx(
|
|
127
|
+
"div",
|
|
128
|
+
{
|
|
129
|
+
className: cn(
|
|
130
|
+
"w-full overflow-auto rounded-[var(--ds-radius-md)]",
|
|
131
|
+
"border-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
|
|
132
|
+
"shadow-[var(--ds-shadow-card)]",
|
|
133
|
+
"bg-[var(--ds-bg-surface)]"
|
|
134
|
+
),
|
|
135
|
+
children: /* @__PURE__ */ jsxs("table", { className: "w-full text-sm", children: [
|
|
136
|
+
/* @__PURE__ */ jsx("thead", { className: "bg-[var(--ds-bg-muted)]", children: table.getHeaderGroups().map((hg) => /* @__PURE__ */ jsx("tr", { className: "border-b-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)]", children: hg.headers.map((header) => {
|
|
137
|
+
const canSort = header.column.getCanSort();
|
|
138
|
+
const sorted = header.column.getIsSorted();
|
|
139
|
+
const meta = header.column.columnDef.meta;
|
|
140
|
+
return /* @__PURE__ */ jsx(
|
|
141
|
+
"th",
|
|
142
|
+
{
|
|
143
|
+
className: cn(
|
|
144
|
+
"px-ds-4 py-ds-3 text-left text-xs font-[var(--ds-weight-heading)] uppercase tracking-wider",
|
|
145
|
+
"text-[var(--ds-text-secondary)]",
|
|
146
|
+
canSort && "cursor-pointer select-none hover:text-[var(--ds-text-primary)]"
|
|
147
|
+
),
|
|
148
|
+
style: meta?.maxWidth ? { maxWidth: meta.maxWidth } : void 0,
|
|
149
|
+
onClick: canSort ? header.column.getToggleSortingHandler() : void 0,
|
|
150
|
+
children: /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-ds-1", children: [
|
|
151
|
+
flexRender(header.column.columnDef.header, header.getContext()),
|
|
152
|
+
canSort && /* @__PURE__ */ jsxs("span", { className: "inline-flex flex-col -space-y-ds-1.5", children: [
|
|
153
|
+
/* @__PURE__ */ jsx(
|
|
154
|
+
Icon,
|
|
155
|
+
{
|
|
156
|
+
name: "chevron-up",
|
|
157
|
+
size: 10,
|
|
158
|
+
className: sorted === "asc" ? "text-[var(--ds-accent-primary)]" : "opacity-30"
|
|
159
|
+
}
|
|
160
|
+
),
|
|
161
|
+
/* @__PURE__ */ jsx(
|
|
162
|
+
Icon,
|
|
163
|
+
{
|
|
164
|
+
name: "chevron-down",
|
|
165
|
+
size: 10,
|
|
166
|
+
className: sorted === "desc" ? "text-[var(--ds-accent-primary)]" : "opacity-30"
|
|
167
|
+
}
|
|
168
|
+
)
|
|
169
|
+
] })
|
|
170
|
+
] })
|
|
171
|
+
},
|
|
172
|
+
header.id
|
|
173
|
+
);
|
|
174
|
+
}) }, hg.id)) }),
|
|
175
|
+
/* @__PURE__ */ jsx("tbody", { children: table.getRowModel().rows.map((row) => /* @__PURE__ */ jsx(
|
|
176
|
+
"tr",
|
|
177
|
+
{
|
|
178
|
+
className: cn(
|
|
179
|
+
"border-b-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)] last:border-b-0",
|
|
180
|
+
"hover:bg-[var(--ds-bg-muted)] transition-colors"
|
|
181
|
+
),
|
|
182
|
+
children: row.getVisibleCells().map((cell) => {
|
|
183
|
+
const meta = cell.column.columnDef.meta;
|
|
184
|
+
const truncLines = meta?.truncate === true ? 1 : meta?.truncate ? meta.truncate.lines : 0;
|
|
185
|
+
const rendered = flexRender(cell.column.columnDef.cell, cell.getContext());
|
|
186
|
+
return /* @__PURE__ */ jsx(
|
|
187
|
+
"td",
|
|
188
|
+
{
|
|
189
|
+
className: "px-ds-4 py-ds-3 text-[var(--ds-text-primary)]",
|
|
190
|
+
style: meta?.maxWidth ? { maxWidth: meta.maxWidth } : void 0,
|
|
191
|
+
children: truncLines > 0 ? /* @__PURE__ */ jsx(TruncCell, { lines: truncLines, children: rendered }) : rendered
|
|
192
|
+
},
|
|
193
|
+
cell.id
|
|
194
|
+
);
|
|
195
|
+
})
|
|
196
|
+
},
|
|
197
|
+
row.id
|
|
198
|
+
)) })
|
|
199
|
+
] })
|
|
200
|
+
}
|
|
201
|
+
),
|
|
202
|
+
pageCount > 1 && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-sm", children: [
|
|
203
|
+
/* @__PURE__ */ jsxs("span", { className: "text-[var(--ds-text-muted)]", children: [
|
|
204
|
+
"Page ",
|
|
205
|
+
currentPage + 1,
|
|
206
|
+
" of ",
|
|
207
|
+
pageCount
|
|
208
|
+
] }),
|
|
209
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-ds-1", children: [
|
|
210
|
+
/* @__PURE__ */ jsx(
|
|
211
|
+
PagerBtn,
|
|
212
|
+
{
|
|
213
|
+
onClick: () => handlePageChange(0),
|
|
214
|
+
disabled: currentPage === 0,
|
|
215
|
+
label: "First"
|
|
216
|
+
}
|
|
217
|
+
),
|
|
218
|
+
/* @__PURE__ */ jsx(
|
|
219
|
+
PagerBtn,
|
|
220
|
+
{
|
|
221
|
+
onClick: () => handlePageChange(currentPage - 1),
|
|
222
|
+
disabled: currentPage === 0,
|
|
223
|
+
label: "Prev"
|
|
224
|
+
}
|
|
225
|
+
),
|
|
226
|
+
Array.from({ length: Math.min(pageCount, 5) }, (_, i) => {
|
|
227
|
+
let page;
|
|
228
|
+
if (pageCount <= 5) {
|
|
229
|
+
page = i;
|
|
230
|
+
} else if (currentPage < 3) {
|
|
231
|
+
page = i;
|
|
232
|
+
} else if (currentPage > pageCount - 4) {
|
|
233
|
+
page = pageCount - 5 + i;
|
|
234
|
+
} else {
|
|
235
|
+
page = currentPage - 2 + i;
|
|
236
|
+
}
|
|
237
|
+
return /* @__PURE__ */ jsx(
|
|
238
|
+
PagerBtn,
|
|
239
|
+
{
|
|
240
|
+
onClick: () => handlePageChange(page),
|
|
241
|
+
active: page === currentPage,
|
|
242
|
+
label: String(page + 1)
|
|
243
|
+
},
|
|
244
|
+
page
|
|
245
|
+
);
|
|
246
|
+
}),
|
|
247
|
+
/* @__PURE__ */ jsx(
|
|
248
|
+
PagerBtn,
|
|
249
|
+
{
|
|
250
|
+
onClick: () => handlePageChange(currentPage + 1),
|
|
251
|
+
disabled: currentPage >= pageCount - 1,
|
|
252
|
+
label: "Next"
|
|
253
|
+
}
|
|
254
|
+
),
|
|
255
|
+
/* @__PURE__ */ jsx(
|
|
256
|
+
PagerBtn,
|
|
257
|
+
{
|
|
258
|
+
onClick: () => handlePageChange(pageCount - 1),
|
|
259
|
+
disabled: currentPage >= pageCount - 1,
|
|
260
|
+
label: "Last"
|
|
261
|
+
}
|
|
262
|
+
)
|
|
263
|
+
] })
|
|
264
|
+
] })
|
|
265
|
+
] });
|
|
266
|
+
}
|
|
267
|
+
function PagerBtn({
|
|
268
|
+
onClick,
|
|
269
|
+
disabled,
|
|
270
|
+
active,
|
|
271
|
+
label
|
|
272
|
+
}) {
|
|
273
|
+
return /* @__PURE__ */ jsx(
|
|
274
|
+
"button",
|
|
275
|
+
{
|
|
276
|
+
type: "button",
|
|
277
|
+
onClick,
|
|
278
|
+
disabled,
|
|
279
|
+
className: cn(
|
|
280
|
+
"h-8 min-w-[32px] px-ds-2 text-xs font-medium rounded-[var(--ds-radius-sm)]",
|
|
281
|
+
"transition-colors duration-[var(--ds-transition-speed)] cursor-pointer",
|
|
282
|
+
"focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]",
|
|
283
|
+
"disabled:opacity-disabled disabled:cursor-not-allowed",
|
|
284
|
+
active ? "bg-[var(--ds-accent-primary)] text-[var(--ds-text-on-primary)]" : "text-[var(--ds-text-secondary)] hover:bg-[var(--ds-bg-muted)] hover:text-[var(--ds-text-primary)]"
|
|
285
|
+
),
|
|
286
|
+
children: label
|
|
287
|
+
}
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
export { DataGrid };
|
|
292
|
+
//# sourceMappingURL=data-grid.js.map
|
|
293
|
+
//# sourceMappingURL=data-grid.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../showcase/src/components/DataGrid.tsx"],"names":[],"mappings":"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","file":"data-grid.js","sourcesContent":["import { useState, useCallback, useMemo, type ReactNode } from \"react\";\nimport {\n useReactTable,\n getCoreRowModel,\n getSortedRowModel,\n getPaginationRowModel,\n flexRender,\n type ColumnDef,\n type SortingState,\n} from \"@tanstack/react-table\";\nimport { cn } from \"../lib/utils\";\nimport { Icon } from \"../lib/icons\";\nimport { Tooltip } from \"./Tooltip\";\nimport { useTextOverflow } from \"../lib/use-text-overflow\";\nimport { useBreakpoint, type BreakpointKey } from \"../lib/use-breakpoint\";\n\n/** Column meta for opt-in truncation. Set on ColumnDef.meta. */\nexport interface DataGridColumnMeta {\n /** true = single-line, or { lines: N } for multi-line clamp. */\n truncate?: boolean | { lines: number };\n /** CSS max-width for the column. */\n maxWidth?: string;\n}\n\nfunction TruncCell({ children, lines }: { children: ReactNode; lines: number }) {\n const { ref, isTruncated } = useTextOverflow({ lines });\n const clampClass = lines === 1 ? \"truncate\" : `line-clamp-${lines}`;\n const cell = <span ref={ref} className={cn(clampClass, \"block\")}>{children}</span>;\n if (!isTruncated) return cell;\n return <Tooltip content={children}>{cell}</Tooltip>;\n}\n\nexport interface DataGridProps<T> {\n data: T[];\n columns: ColumnDef<T, any>[];\n pageSize?: number;\n editable?: boolean;\n onCellEdit?: (rowIndex: number, columnId: string, value: unknown) => void;\n /** Breakpoint at which the grid switches to card layout. Defaults to \"md\" (768px). */\n mobileBreakpoint?: BreakpointKey;\n className?: string;\n}\n\nexport function DataGrid<T>({\n data,\n columns,\n pageSize = 10,\n editable = false,\n onCellEdit,\n mobileBreakpoint = \"md\",\n className,\n}: DataGridProps<T>) {\n const isMobile = useBreakpoint(mobileBreakpoint);\n const [sorting, setSorting] = useState<SortingState>([]);\n const [editCell, setEditCell] = useState<{ row: number; col: string } | null>(null);\n const [editValue, setEditValue] = useState(\"\");\n\n const tableColumns = useMemo(() => {\n if (!editable) return columns;\n return columns.map((col) => ({\n ...col,\n cell: (info: any) => {\n const rowIdx = info.row.index;\n const colId = info.column.id;\n const isEditing = editCell?.row === rowIdx && editCell?.col === colId;\n\n if (isEditing) {\n return (\n <input\n autoFocus\n className={cn(\n \"w-full h-full bg-transparent text-sm text-[var(--ds-text-primary)]\",\n \"outline-none border-none px-0\",\n )}\n value={editValue}\n onChange={(e) => setEditValue(e.target.value)}\n onBlur={() => {\n onCellEdit?.(rowIdx, colId, editValue);\n setEditCell(null);\n }}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") {\n onCellEdit?.(rowIdx, colId, editValue);\n setEditCell(null);\n } else if (e.key === \"Escape\") {\n setEditCell(null);\n }\n }}\n />\n );\n }\n\n const rendered = typeof col.cell === \"function\" ? col.cell(info) : info.getValue();\n return (\n <span\n onDoubleClick={() => {\n setEditCell({ row: rowIdx, col: colId });\n setEditValue(String(info.getValue() ?? \"\"));\n }}\n className=\"cursor-default\"\n >\n {rendered as React.ReactNode}\n </span>\n );\n },\n }));\n }, [columns, editable, editCell, editValue, onCellEdit]);\n\n const table = useReactTable({\n data,\n columns: tableColumns,\n state: { sorting },\n onSortingChange: setSorting,\n getCoreRowModel: getCoreRowModel(),\n getSortedRowModel: getSortedRowModel(),\n getPaginationRowModel: getPaginationRowModel(),\n initialState: { pagination: { pageSize } },\n });\n\n const handlePageChange = useCallback(\n (page: number) => table.setPageIndex(page),\n [table],\n );\n\n const pageCount = table.getPageCount();\n const currentPage = table.getState().pagination.pageIndex;\n\n if (isMobile) {\n return (\n <div className={cn(\"space-y-ds-3\", className)}>\n <div className=\"flex flex-col gap-ds-3\">\n {table.getRowModel().rows.map((row) => (\n <div\n key={row.id}\n className={cn(\n \"border-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]\",\n \"rounded-[var(--ds-radius-md)] bg-[var(--ds-bg-surface)]\",\n \"p-ds-4 space-y-ds-2\",\n )}\n >\n {row.getVisibleCells().map((cell) => (\n <div key={cell.id} className=\"flex justify-between gap-ds-2 text-sm\">\n <span className=\"text-[var(--ds-text-secondary)] font-medium text-xs uppercase tracking-wider\">\n {typeof cell.column.columnDef.header === \"string\"\n ? cell.column.columnDef.header\n : cell.column.id}\n </span>\n <span className=\"text-[var(--ds-text-primary)] text-right\">\n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n </span>\n </div>\n ))}\n </div>\n ))}\n </div>\n\n {pageCount > 1 && (\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"text-[var(--ds-text-muted)]\">\n Page {currentPage + 1} of {pageCount}\n </span>\n <div className=\"flex items-center gap-ds-1\">\n <PagerBtn onClick={() => handlePageChange(currentPage - 1)} disabled={currentPage === 0} label=\"Prev\" />\n <PagerBtn onClick={() => handlePageChange(currentPage + 1)} disabled={currentPage >= pageCount - 1} label=\"Next\" />\n </div>\n </div>\n )}\n </div>\n );\n }\n\n return (\n <div className={cn(\"space-y-ds-3\", className)}>\n <div\n className={cn(\n \"w-full overflow-auto rounded-[var(--ds-radius-md)]\",\n \"border-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]\",\n \"shadow-[var(--ds-shadow-card)]\",\n \"bg-[var(--ds-bg-surface)]\",\n )}\n >\n <table className=\"w-full text-sm\">\n <thead className=\"bg-[var(--ds-bg-muted)]\">\n {table.getHeaderGroups().map((hg) => (\n <tr key={hg.id} className=\"border-b-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)]\">\n {hg.headers.map((header) => {\n const canSort = header.column.getCanSort();\n const sorted = header.column.getIsSorted();\n const meta = header.column.columnDef.meta as DataGridColumnMeta | undefined;\n return (\n <th\n key={header.id}\n className={cn(\n \"px-ds-4 py-ds-3 text-left text-xs font-[var(--ds-weight-heading)] uppercase tracking-wider\",\n \"text-[var(--ds-text-secondary)]\",\n canSort && \"cursor-pointer select-none hover:text-[var(--ds-text-primary)]\",\n )}\n style={meta?.maxWidth ? { maxWidth: meta.maxWidth } : undefined}\n onClick={canSort ? header.column.getToggleSortingHandler() : undefined}\n >\n <span className=\"flex items-center gap-ds-1\">\n {flexRender(header.column.columnDef.header, header.getContext())}\n {canSort && (\n <span className=\"inline-flex flex-col -space-y-ds-1.5\">\n <Icon\n name=\"chevron-up\"\n size={10}\n className={sorted === \"asc\" ? \"text-[var(--ds-accent-primary)]\" : \"opacity-30\"}\n />\n <Icon\n name=\"chevron-down\"\n size={10}\n className={sorted === \"desc\" ? \"text-[var(--ds-accent-primary)]\" : \"opacity-30\"}\n />\n </span>\n )}\n </span>\n </th>\n );\n })}\n </tr>\n ))}\n </thead>\n <tbody>\n {table.getRowModel().rows.map((row) => (\n <tr\n key={row.id}\n className={cn(\n \"border-b-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)] last:border-b-0\",\n \"hover:bg-[var(--ds-bg-muted)] transition-colors\",\n )}\n >\n {row.getVisibleCells().map((cell) => {\n const meta = cell.column.columnDef.meta as DataGridColumnMeta | undefined;\n const truncLines = meta?.truncate === true ? 1 : meta?.truncate ? meta.truncate.lines : 0;\n const rendered = flexRender(cell.column.columnDef.cell, cell.getContext());\n return (\n <td\n key={cell.id}\n className=\"px-ds-4 py-ds-3 text-[var(--ds-text-primary)]\"\n style={meta?.maxWidth ? { maxWidth: meta.maxWidth } : undefined}\n >\n {truncLines > 0 ? <TruncCell lines={truncLines}>{rendered}</TruncCell> : rendered}\n </td>\n );\n })}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n\n {pageCount > 1 && (\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"text-[var(--ds-text-muted)]\">\n Page {currentPage + 1} of {pageCount}\n </span>\n <div className=\"flex items-center gap-ds-1\">\n <PagerBtn\n onClick={() => handlePageChange(0)}\n disabled={currentPage === 0}\n label=\"First\"\n />\n <PagerBtn\n onClick={() => handlePageChange(currentPage - 1)}\n disabled={currentPage === 0}\n label=\"Prev\"\n />\n {Array.from({ length: Math.min(pageCount, 5) }, (_, i) => {\n let page: number;\n if (pageCount <= 5) {\n page = i;\n } else if (currentPage < 3) {\n page = i;\n } else if (currentPage > pageCount - 4) {\n page = pageCount - 5 + i;\n } else {\n page = currentPage - 2 + i;\n }\n return (\n <PagerBtn\n key={page}\n onClick={() => handlePageChange(page)}\n active={page === currentPage}\n label={String(page + 1)}\n />\n );\n })}\n <PagerBtn\n onClick={() => handlePageChange(currentPage + 1)}\n disabled={currentPage >= pageCount - 1}\n label=\"Next\"\n />\n <PagerBtn\n onClick={() => handlePageChange(pageCount - 1)}\n disabled={currentPage >= pageCount - 1}\n label=\"Last\"\n />\n </div>\n </div>\n )}\n </div>\n );\n}\n\nfunction PagerBtn({\n onClick,\n disabled,\n active,\n label,\n}: {\n onClick: () => void;\n disabled?: boolean;\n active?: boolean;\n label: string;\n}) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n disabled={disabled}\n className={cn(\n \"h-8 min-w-[32px] px-ds-2 text-xs font-medium rounded-[var(--ds-radius-sm)]\",\n \"transition-colors duration-[var(--ds-transition-speed)] cursor-pointer\",\n \"focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]\",\n \"disabled:opacity-disabled disabled:cursor-not-allowed\",\n active\n ? \"bg-[var(--ds-accent-primary)] text-[var(--ds-text-on-primary)]\"\n : \"text-[var(--ds-text-secondary)] hover:bg-[var(--ds-bg-muted)] hover:text-[var(--ds-text-primary)]\",\n )}\n >\n {label}\n </button>\n );\n}\n"]}
|
package/dist/editor.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { Ref } from 'react';
|
|
3
|
+
|
|
4
|
+
type ToolbarGroup = "blockType" | "fontFamily" | "textSize" | "formatting" | "colors" | "alignment" | "lists" | "blocks" | "insert" | "extras" | "history";
|
|
5
|
+
interface RichTextEditorProps {
|
|
6
|
+
content?: string;
|
|
7
|
+
placeholder?: string;
|
|
8
|
+
onChange?: (html: string) => void;
|
|
9
|
+
editable?: boolean;
|
|
10
|
+
toolbar?: ToolbarGroup[] | "full" | "minimal";
|
|
11
|
+
className?: string;
|
|
12
|
+
ref?: Ref<HTMLDivElement>;
|
|
13
|
+
/** Accessible name for the editable area. Default "Rich text editor". */
|
|
14
|
+
label?: string;
|
|
15
|
+
}
|
|
16
|
+
declare function RichTextEditor({ content, placeholder, onChange, editable, toolbar, className, ref, label }: RichTextEditorProps): react_jsx_runtime.JSX.Element | null;
|
|
17
|
+
|
|
18
|
+
export { RichTextEditor };
|