gridsmith-ui 0.4.0 → 0.6.1

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.
Files changed (59) hide show
  1. package/README.md +63 -3
  2. package/dist/charts.d.ts +246 -0
  3. package/dist/charts.js +1028 -0
  4. package/dist/charts.js.map +1 -0
  5. package/dist/chunk-CHNY75QI.js +278 -0
  6. package/dist/chunk-CHNY75QI.js.map +1 -0
  7. package/dist/chunk-DPF6776I.js +36 -0
  8. package/dist/chunk-DPF6776I.js.map +1 -0
  9. package/dist/{chunk-6TMNEBBJ.js → chunk-GX6O72IV.js} +44 -35
  10. package/dist/chunk-GX6O72IV.js.map +1 -0
  11. package/dist/{chunk-5XIPPVH7.js → chunk-IUBWNDUK.js} +15 -4
  12. package/dist/chunk-IUBWNDUK.js.map +1 -0
  13. package/dist/chunk-OUYJXVLQ.js +41 -0
  14. package/dist/chunk-OUYJXVLQ.js.map +1 -0
  15. package/dist/chunk-UYGTAVKR.js +93 -0
  16. package/dist/chunk-UYGTAVKR.js.map +1 -0
  17. package/dist/data-grid.d.ts +27 -0
  18. package/dist/data-grid.js +293 -0
  19. package/dist/data-grid.js.map +1 -0
  20. package/dist/editor.d.ts +18 -0
  21. package/dist/editor.js +632 -0
  22. package/dist/editor.js.map +1 -0
  23. package/dist/{feather-432JQGUB.js → feather-U45EQTAU.js} +4 -4
  24. package/dist/feather-U45EQTAU.js.map +1 -0
  25. package/dist/{heroicons-CCKJHFZY.js → heroicons-D3G7QU45.js} +4 -4
  26. package/dist/heroicons-D3G7QU45.js.map +1 -0
  27. package/dist/icons.d.ts +1 -1
  28. package/dist/icons.js +1 -2
  29. package/dist/index.d.ts +430 -133
  30. package/dist/index.js +10535 -98014
  31. package/dist/index.js.map +1 -1
  32. package/dist/kanban.d.ts +25 -0
  33. package/dist/kanban.js +224 -0
  34. package/dist/kanban.js.map +1 -0
  35. package/dist/{lucide-Z74WVRAK.js → lucide-OGUV44TQ.js} +4 -4
  36. package/dist/lucide-OGUV44TQ.js.map +1 -0
  37. package/dist/{phosphor-DYUCR5S2.js → phosphor-QG2ZMEMZ.js} +4 -4
  38. package/dist/phosphor-QG2ZMEMZ.js.map +1 -0
  39. package/dist/resizable.d.ts +39 -0
  40. package/dist/resizable.js +89 -0
  41. package/dist/resizable.js.map +1 -0
  42. package/dist/roots.css +46 -11
  43. package/dist/{tabler-GRXDPAHR.js → tabler-MW2HN55L.js} +4 -4
  44. package/dist/tabler-MW2HN55L.js.map +1 -0
  45. package/dist/use-breakpoint-Cn51IubK.d.ts +30 -0
  46. package/dist/utils.js +1 -2
  47. package/dist/virtualized.d.ts +16 -0
  48. package/dist/virtualized.js +55 -0
  49. package/dist/virtualized.js.map +1 -0
  50. package/package.json +144 -4
  51. package/dist/chunk-5WRI5ZAA.js +0 -29
  52. package/dist/chunk-5WRI5ZAA.js.map +0 -1
  53. package/dist/chunk-5XIPPVH7.js.map +0 -1
  54. package/dist/chunk-6TMNEBBJ.js.map +0 -1
  55. package/dist/feather-432JQGUB.js.map +0 -1
  56. package/dist/heroicons-CCKJHFZY.js.map +0 -1
  57. package/dist/lucide-Z74WVRAK.js.map +0 -1
  58. package/dist/phosphor-DYUCR5S2.js.map +0 -1
  59. 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-GX6O72IV.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"]}
@@ -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 };