@toolbox-web/grid-react 0.0.2

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 ADDED
@@ -0,0 +1,402 @@
1
+ # @toolbox-web/grid-react
2
+
3
+ React adapter library for [@toolbox-web/grid](https://www.npmjs.com/package/@toolbox-web/grid) - a high-performance, framework-agnostic data grid web component.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @toolbox-web/grid @toolbox-web/grid-react
9
+ ```
10
+
11
+ ## Basic Usage
12
+
13
+ ```tsx
14
+ import { DataGrid, GridColumn } from '@toolbox-web/grid-react';
15
+
16
+ interface Employee {
17
+ id: number;
18
+ name: string;
19
+ department: string;
20
+ salary: number;
21
+ }
22
+
23
+ function EmployeeGrid() {
24
+ const [employees, setEmployees] = useState<Employee[]>([
25
+ { id: 1, name: 'Alice', department: 'Engineering', salary: 95000 },
26
+ { id: 2, name: 'Bob', department: 'Marketing', salary: 75000 },
27
+ { id: 3, name: 'Charlie', department: 'Sales', salary: 85000 },
28
+ ]);
29
+
30
+ return (
31
+ <DataGrid
32
+ rows={employees}
33
+ columns={[
34
+ { field: 'id', header: 'ID', width: 60 },
35
+ { field: 'name', header: 'Name', sortable: true },
36
+ { field: 'department', header: 'Department', sortable: true },
37
+ { field: 'salary', header: 'Salary', type: 'number' },
38
+ ]}
39
+ onRowsChange={setEmployees}
40
+ />
41
+ );
42
+ }
43
+ ```
44
+
45
+ ## Custom Cell Renderers
46
+
47
+ There are two ways to define custom renderers: inline in the configuration, or via `GridColumn` components.
48
+
49
+ ### Inline Configuration (Recommended)
50
+
51
+ Define renderers directly in your `ReactGridConfig`:
52
+
53
+ ```tsx
54
+ import { DataGrid, type ReactGridConfig } from '@toolbox-web/grid-react';
55
+
56
+ const config: ReactGridConfig<Employee> = {
57
+ columns: [
58
+ { field: 'name', header: 'Name' },
59
+ {
60
+ field: 'status',
61
+ header: 'Status',
62
+ // Custom React renderer - same property name as vanilla!
63
+ renderer: (ctx) => (
64
+ <span className={`badge badge-${ctx.value.toLowerCase()}`}>
65
+ {ctx.value}
66
+ </span>
67
+ ),
68
+ },
69
+ ],
70
+ };
71
+
72
+ function EmployeeGrid() {
73
+ return <DataGrid rows={employees} gridConfig={config} />;
74
+ }
75
+ ```
76
+
77
+ ### Using GridColumn Components
78
+
79
+ Use the `GridColumn` component with a render prop:
80
+
81
+ ```tsx
82
+ import { DataGrid, GridColumn } from '@toolbox-web/grid-react';
83
+
84
+ function StatusBadge({ status }: { status: string }) {
85
+ return <span className={`badge badge-${status.toLowerCase()}`}>{status}</span>;
86
+ }
87
+
88
+ function EmployeeGrid() {
89
+ return (
90
+ <DataGrid rows={employees}>
91
+ <GridColumn field="name" header="Name" />
92
+ <GridColumn field="status">{(ctx) => <StatusBadge status={ctx.value} />}</GridColumn>
93
+ </DataGrid>
94
+ );
95
+ }
96
+ ```
97
+
98
+ ## Custom Cell Editors
99
+
100
+ Define editors inline in your configuration or via `GridColumn`:
101
+
102
+ ### Inline Configuration
103
+
104
+ ```tsx
105
+ const config: ReactGridConfig<Employee> = {
106
+ columns: [
107
+ {
108
+ field: 'status',
109
+ header: 'Status',
110
+ editable: true,
111
+ renderer: (ctx) => <StatusBadge status={ctx.value} />,
112
+ editor: (ctx) => (
113
+ <select
114
+ defaultValue={ctx.value}
115
+ autoFocus
116
+ onChange={(e) => ctx.commit(e.target.value)}
117
+ onKeyDown={(e) => e.key === 'Escape' && ctx.cancel()}
118
+ >
119
+ <option value="active">Active</option>
120
+ <option value="inactive">Inactive</option>
121
+ </select>
122
+ ),
123
+ },
124
+ ],
125
+ };
126
+ ```
127
+
128
+ ### Using GridColumn
129
+
130
+ ```tsx
131
+ <DataGrid rows={employees}>
132
+ <GridColumn
133
+ field="name"
134
+ editable
135
+ editor={(ctx) => (
136
+ <input
137
+ autoFocus
138
+ defaultValue={ctx.value}
139
+ onBlur={(e) => ctx.commit(e.target.value)}
140
+ onKeyDown={(e) => {
141
+ if (e.key === 'Enter') ctx.commit(e.currentTarget.value);
142
+ if (e.key === 'Escape') ctx.cancel();
143
+ }}
144
+ />
145
+ )}
146
+ />
147
+ </DataGrid>
148
+ ```
149
+
150
+ ## Master-Detail with GridDetailPanel
151
+
152
+ Create expandable row details using the `GridDetailPanel` component:
153
+
154
+ ```tsx
155
+ import { DataGrid, GridDetailPanel } from '@toolbox-web/grid-react';
156
+ import { MasterDetailPlugin } from '@toolbox-web/grid/all';
157
+
158
+ function EmployeeGrid() {
159
+ const config: ReactGridConfig<Employee> = {
160
+ columns: [...],
161
+ plugins: [new MasterDetailPlugin()],
162
+ };
163
+
164
+ return (
165
+ <DataGrid rows={employees} gridConfig={config}>
166
+ <GridDetailPanel showExpandColumn animation="slide">
167
+ {({ row, rowIndex }) => (
168
+ <div className="detail-panel">
169
+ <h4>{row.name}'s Details</h4>
170
+ <p>Email: {row.email}</p>
171
+ <EmployeeHistory employeeId={row.id} />
172
+ </div>
173
+ )}
174
+ </GridDetailPanel>
175
+ </DataGrid>
176
+ );
177
+ }
178
+ ```
179
+
180
+ **GridDetailPanel Props:**
181
+
182
+ | Prop | Type | Default | Description |
183
+ | ------------------ | ----------------------------------------- | --------- | ------------------------------------ |
184
+ | `children` | `(ctx: DetailPanelContext) => ReactNode` | Required | Render function for panel content |
185
+ | `showExpandColumn` | `boolean` | `true` | Show expand/collapse chevron column |
186
+ | `animation` | `'slide' \| 'fade' \| false` | `'slide'` | Animation style for expand/collapse |
187
+
188
+ ## Custom Tool Panels with GridToolPanel
189
+
190
+ Add custom sidebar panels to the grid shell:
191
+
192
+ ```tsx
193
+ import { DataGrid, GridToolPanel, GridToolButtons } from '@toolbox-web/grid-react';
194
+ import { ShellPlugin } from '@toolbox-web/grid/all';
195
+
196
+ function EmployeeGrid() {
197
+ const config: ReactGridConfig<Employee> = {
198
+ columns: [...],
199
+ plugins: [new ShellPlugin()],
200
+ };
201
+
202
+ return (
203
+ <DataGrid rows={employees} gridConfig={config}>
204
+ {/* Toolbar buttons */}
205
+ <GridToolButtons>
206
+ <button onClick={handleExport}>Export CSV</button>
207
+ <button onClick={handlePrint}>Print</button>
208
+ </GridToolButtons>
209
+
210
+ {/* Custom sidebar panel */}
211
+ <GridToolPanel id="quick-filters" title="Quick Filters" icon="🔍" order={10}>
212
+ {({ grid }) => (
213
+ <div className="filter-panel">
214
+ <label>
215
+ Department:
216
+ <select onChange={(e) => applyFilter(grid, 'department', e.target.value)}>
217
+ <option value="">All</option>
218
+ <option value="Engineering">Engineering</option>
219
+ <option value="Marketing">Marketing</option>
220
+ </select>
221
+ </label>
222
+ </div>
223
+ )}
224
+ </GridToolPanel>
225
+ </DataGrid>
226
+ );
227
+ }
228
+ ```
229
+
230
+ **GridToolPanel Props:**
231
+
232
+ | Prop | Type | Default | Description |
233
+ | ---------- | --------------------------------------- | ---------- | ------------------------------------ |
234
+ | `id` | `string` | Required | Unique panel identifier |
235
+ | `title` | `string` | Required | Panel title in accordion header |
236
+ | `children` | `(ctx: ToolPanelContext) => ReactNode` | Required | Render function for panel content |
237
+ | `icon` | `string` | - | Icon for the accordion header |
238
+ | `tooltip` | `string` | - | Tooltip text for header |
239
+ | `order` | `number` | `100` | Panel sort order (lower = higher) |
240
+
241
+ ## Using Refs
242
+
243
+ Access the grid instance for programmatic control:
244
+
245
+ ```tsx
246
+ import { DataGrid, DataGridRef } from '@toolbox-web/grid-react';
247
+ import { useRef } from 'react';
248
+
249
+ function MyComponent() {
250
+ const gridRef = useRef<DataGridRef>(null);
251
+
252
+ const handleExport = async () => {
253
+ const config = await gridRef.current?.getConfig();
254
+ console.log('Columns:', config?.columns);
255
+ };
256
+
257
+ return (
258
+ <>
259
+ <button onClick={handleExport}>Export</button>
260
+ <DataGrid ref={gridRef} rows={employees} />
261
+ </>
262
+ );
263
+ }
264
+ ```
265
+
266
+ ## useGrid Hook
267
+
268
+ For more complex scenarios, use the `useGrid` hook:
269
+
270
+ ```tsx
271
+ import { DataGrid, useGrid } from '@toolbox-web/grid-react';
272
+
273
+ function MyComponent() {
274
+ const { ref, isReady, forceLayout } = useGrid<Employee>();
275
+
276
+ return (
277
+ <>
278
+ <button onClick={() => forceLayout()}>Refresh Layout</button>
279
+ <DataGrid ref={ref} rows={employees} />
280
+ </>
281
+ );
282
+ }
283
+ ```
284
+
285
+ ## Event Handling
286
+
287
+ ### Via Props
288
+
289
+ ```tsx
290
+ <DataGrid
291
+ rows={employees}
292
+ onCellEdit={(e) => console.log('Edited:', e.detail)}
293
+ onRowClick={(e) => console.log('Clicked:', e.detail.row)}
294
+ onSortChange={(e) => console.log('Sort:', e.detail)}
295
+ />
296
+ ```
297
+
298
+ ### Via useGridEvent Hook
299
+
300
+ ```tsx
301
+ import { DataGrid, useGridEvent, DataGridRef } from '@toolbox-web/grid-react';
302
+
303
+ function MyComponent() {
304
+ const gridRef = useRef<DataGridRef>(null);
305
+
306
+ useGridEvent(gridRef, 'selection-change', (event) => {
307
+ console.log('Selected:', event.detail.selectedRows);
308
+ });
309
+
310
+ return <DataGrid ref={gridRef} rows={employees} />;
311
+ }
312
+ ```
313
+
314
+ ## Plugins
315
+
316
+ Use plugins from `@toolbox-web/grid/all`:
317
+
318
+ ```tsx
319
+ import { DataGrid } from '@toolbox-web/grid-react';
320
+ import { SelectionPlugin, FilteringPlugin } from '@toolbox-web/grid/all';
321
+
322
+ function MyComponent() {
323
+ return (
324
+ <DataGrid
325
+ rows={employees}
326
+ gridConfig={{
327
+ columns: [...],
328
+ plugins: [
329
+ new SelectionPlugin({ mode: 'row' }),
330
+ new FilteringPlugin({ debounceMs: 200 }),
331
+ ],
332
+ }}
333
+ />
334
+ );
335
+ }
336
+ ```
337
+
338
+ ## Custom Styles
339
+
340
+ Inject custom CSS into the grid's shadow DOM:
341
+
342
+ ```tsx
343
+ <DataGrid
344
+ rows={employees}
345
+ customStyles={`
346
+ .my-custom-cell {
347
+ background: #f0f0f0;
348
+ padding: 8px;
349
+ }
350
+ `}
351
+ />
352
+ ```
353
+
354
+ ## API Reference
355
+
356
+ ### DataGrid Props
357
+
358
+ | Prop | Type | Description |
359
+ | -------------- | ------------------------------------------ | ----------------------------- |
360
+ | `rows` | `TRow[]` | Row data to display |
361
+ | `columns` | `ColumnConfig[]` | Column definitions |
362
+ | `gridConfig` | `GridConfig` | Full configuration object |
363
+ | `fitMode` | `'stretch' \| 'fit-columns' \| 'auto-fit'` | Column sizing mode |
364
+ | `editOn` | `'click' \| 'dblclick' \| 'none'` | Edit trigger |
365
+ | `customStyles` | `string` | CSS to inject into shadow DOM |
366
+ | `onRowsChange` | `(rows: TRow[]) => void` | Rows changed callback |
367
+ | `onCellEdit` | `(event: CustomEvent) => void` | Cell edited callback |
368
+ | `onRowClick` | `(event: CustomEvent) => void` | Row clicked callback |
369
+
370
+ ### GridColumn Props
371
+
372
+ | Prop | Type | Description |
373
+ | ----------- | --------------------------------------------- | ----------------------- |
374
+ | `field` | `string` | Field key in row object |
375
+ | `header` | `string` | Column header text |
376
+ | `type` | `'string' \| 'number' \| 'date' \| 'boolean'` | Data type |
377
+ | `editable` | `boolean` | Enable editing |
378
+ | `sortable` | `boolean` | Enable sorting |
379
+ | `resizable` | `boolean` | Enable column resizing |
380
+ | `width` | `string \| number` | Column width |
381
+ | `children` | `(ctx: CellRenderContext) => ReactNode` | Custom renderer |
382
+ | `editor` | `(ctx: ColumnEditorContext) => ReactNode` | Custom editor |
383
+
384
+ ### DataGridRef Methods
385
+
386
+ | Method | Description |
387
+ | ------------------------- | --------------------------- |
388
+ | `getConfig()` | Get effective configuration |
389
+ | `ready()` | Wait for grid ready |
390
+ | `forceLayout()` | Force layout recalculation |
391
+ | `toggleGroup(key)` | Toggle group expansion |
392
+ | `registerStyles(id, css)` | Register custom styles |
393
+ | `unregisterStyles(id)` | Remove custom styles |
394
+
395
+ ## Requirements
396
+
397
+ - React 18.0.0 or higher
398
+ - @toolbox-web/grid 0.2.0 or higher
399
+
400
+ ## License
401
+
402
+ MIT
package/index.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ export { DataGrid } from './lib/data-grid';
2
+ export { GridColumn } from './lib/grid-column';
3
+ export { GridDetailPanel, type DetailPanelContext, type GridDetailPanelProps } from './lib/grid-detail-panel';
4
+ export { GridToolButtons, type GridToolButtonsProps } from './lib/grid-tool-button';
5
+ export { GridToolPanel, type GridToolPanelProps, type ToolPanelContext } from './lib/grid-tool-panel';
6
+ export type { ReactColumnConfig, ReactGridConfig } from './lib/react-column-config';
7
+ export { useGrid } from './lib/use-grid';
8
+ export { useGridEvent } from './lib/use-grid-event';
9
+ export { ReactGridAdapter, getRegisteredFields } from './lib/react-grid-adapter';
10
+ export type { GridCellContext, GridDetailContext, GridEditorContext, GridToolPanelContext } from './lib/context-types';
11
+ export type { CellRenderContext, ColumnConfig, ColumnEditorContext, GridConfig } from '../../../dist/libs/grid/index.d.ts';
12
+ //# sourceMappingURL=index.d.ts.map
package/index.d.ts.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../libs/grid-react/src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,YAAY,CAAC;AAGpB,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,KAAK,kBAAkB,EAAE,KAAK,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC9G,OAAO,EAAE,eAAe,EAAE,KAAK,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AACpF,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,KAAK,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAGtG,YAAY,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAGpF,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGpD,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAGjF,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAGvH,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC"}