intable 0.0.7 → 0.0.8
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/.github/copilot-instructions.md +102 -0
- package/docs/index-BaMALNy6.css +1 -1
- package/docs/index-CDN48t9E.js +2 -2
- package/index.html +13 -14
- package/package.json +9 -4
- package/packages/intable/package.json +1 -1
- package/packages/intable/src/index.tsx +25 -17
- package/packages/intable/src/plugins/CopyPastePlugin.tsx +49 -13
- package/packages/intable/src/plugins/DiffPlugin.tsx +31 -18
- package/packages/intable/src/theme/dark.scss +46 -0
- package/packages/intable/src/theme/github.scss +80 -0
- package/packages/intable/src/theme/material.scss +73 -0
- package/packages/intable/src/theme/shadcn.scss +66 -0
- package/packages/intable/src/theme/stripe.scss +57 -0
- package/packages/react/package.json +13 -8
- package/packages/react/src/index.ts +1 -1
- package/packages/vue/package.json +1 -1
- package/scripts/publish.js +1 -1
- package/src/index.tsx +20 -0
- package/src/pages/demo/BasicDemo.tsx +19 -0
- package/src/pages/demo/CellMergeDemo.tsx +41 -0
- package/src/pages/demo/CellSelectionDemo.tsx +24 -0
- package/src/pages/demo/CompositeDemo.tsx +60 -0
- package/src/pages/demo/CopyPasteDemo.tsx +26 -0
- package/src/pages/demo/DiffDemo.tsx +33 -0
- package/src/pages/demo/DragDemo.tsx +25 -0
- package/src/pages/demo/EditableDemo.tsx +58 -0
- package/src/pages/demo/ExpandDemo.tsx +32 -0
- package/src/pages/demo/HeaderGroupDemo.tsx +36 -0
- package/src/pages/demo/HistoryDemo.tsx +28 -0
- package/src/pages/demo/ReactDemo.tsx +59 -0
- package/src/pages/demo/ResizeDemo.tsx +24 -0
- package/src/pages/demo/RowGroupDemo.tsx +43 -0
- package/src/pages/demo/RowSelectionDemo.tsx +27 -0
- package/src/pages/demo/TreeDemo.tsx +45 -0
- package/src/pages/demo/VirtualScrollDemo.tsx +21 -0
- package/src/pages/demo/helpers.tsx +39 -0
- package/src/pages/demo/index.tsx +180 -0
- package/src/pages/index.tsx +2 -0
- package/src/pages/website.scss +37 -0
- package/src/pages/website.tsx +651 -0
- package/vite.config.ts +70 -63
- package/src/demo.tsx +0 -107
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Intable } from '../../../packages/intable/src'
|
|
2
|
+
import { makeCols, makeData, replaceArray } from './helpers'
|
|
3
|
+
|
|
4
|
+
const cols = makeCols(6)
|
|
5
|
+
const data = makeData(20, 6)
|
|
6
|
+
|
|
7
|
+
export const BasicDemo = () => (
|
|
8
|
+
<Intable
|
|
9
|
+
class='w-full h-60vh'
|
|
10
|
+
columns={cols}
|
|
11
|
+
onColumnsChange={v => replaceArray(cols, v)}
|
|
12
|
+
data={data}
|
|
13
|
+
onDataChange={v => replaceArray(data, v)}
|
|
14
|
+
index
|
|
15
|
+
border
|
|
16
|
+
stickyHeader
|
|
17
|
+
size='small'
|
|
18
|
+
/>
|
|
19
|
+
)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { createMutable } from 'solid-js/store'
|
|
2
|
+
import { range } from 'es-toolkit'
|
|
3
|
+
import { Intable } from '../../../packages/intable/src'
|
|
4
|
+
import { CellMergePlugin } from '../../../packages/intable/src/plugins/CellMergePlugin'
|
|
5
|
+
import { replaceArray } from './helpers'
|
|
6
|
+
|
|
7
|
+
const cols = createMutable([
|
|
8
|
+
{ id: 'group', name: 'Group', width: 100, mergeRow: true },
|
|
9
|
+
{ id: 'name', name: 'Name', width: 120 },
|
|
10
|
+
{ id: 'value', name: 'Value', width: 100 },
|
|
11
|
+
{ id: 'score', name: 'Score', width: 100 },
|
|
12
|
+
] as any[])
|
|
13
|
+
|
|
14
|
+
const data = createMutable(
|
|
15
|
+
range(20).map(i => ({
|
|
16
|
+
id: i,
|
|
17
|
+
group: 'G' + Math.floor(i / 4),
|
|
18
|
+
name: 'Item ' + i,
|
|
19
|
+
value: (i * 7) % 100,
|
|
20
|
+
score: (i * 13) % 100,
|
|
21
|
+
})),
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* The "Group" column auto-merges consecutive rows with equal values (mergeRow: true).
|
|
26
|
+
* CellMergePlugin is added manually since it's not a default plugin.
|
|
27
|
+
*/
|
|
28
|
+
export const CellMergeDemo = () => (
|
|
29
|
+
<Intable
|
|
30
|
+
class='w-full h-60vh'
|
|
31
|
+
columns={cols}
|
|
32
|
+
onColumnsChange={v => replaceArray(cols, v)}
|
|
33
|
+
data={data}
|
|
34
|
+
onDataChange={v => replaceArray(data, v)}
|
|
35
|
+
index
|
|
36
|
+
border
|
|
37
|
+
stickyHeader
|
|
38
|
+
size='small'
|
|
39
|
+
plugins={[CellMergePlugin]}
|
|
40
|
+
/>
|
|
41
|
+
)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Intable } from '../../../packages/intable/src'
|
|
2
|
+
import { makeCols, makeData, replaceArray } from './helpers'
|
|
3
|
+
|
|
4
|
+
const cols = makeCols(8)
|
|
5
|
+
const data = makeData(30, 8)
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* CellSelection is auto-loaded.
|
|
9
|
+
* Click a cell then drag or shift+click to select a range.
|
|
10
|
+
* Arrow keys to navigate.
|
|
11
|
+
*/
|
|
12
|
+
export const CellSelectionDemo = () => (
|
|
13
|
+
<Intable
|
|
14
|
+
class='w-full h-60vh'
|
|
15
|
+
columns={cols}
|
|
16
|
+
onColumnsChange={v => replaceArray(cols, v)}
|
|
17
|
+
data={data}
|
|
18
|
+
onDataChange={v => replaceArray(data, v)}
|
|
19
|
+
index
|
|
20
|
+
border
|
|
21
|
+
stickyHeader
|
|
22
|
+
size='small'
|
|
23
|
+
/>
|
|
24
|
+
)
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { batch } from 'solid-js'
|
|
2
|
+
import { createMutable } from 'solid-js/store'
|
|
3
|
+
import { range } from 'es-toolkit'
|
|
4
|
+
import { Intable } from '../../../packages/intable/src'
|
|
5
|
+
import { VirtualScrollPlugin } from '../../../packages/intable/src/plugins/VirtualScrollPlugin'
|
|
6
|
+
import { HistoryPlugin } from '../../../packages/intable/src/plugins/HistoryPlugin'
|
|
7
|
+
import { DiffPlugin } from '../../../packages/intable/src/plugins/DiffPlugin'
|
|
8
|
+
import { replaceArray } from './helpers'
|
|
9
|
+
|
|
10
|
+
const cols = createMutable([
|
|
11
|
+
{ name: 'Basic Info', children: [
|
|
12
|
+
{ id: 'col_0', name: 'Name', width: 100, editable: true },
|
|
13
|
+
{ id: 'col_1', name: 'Age', width: 80, editable: true, editor: 'number' },
|
|
14
|
+
]},
|
|
15
|
+
{ id: 'col_2', name: 'Status', width: 100, editable: true, editor: 'select', enum: { active: 'Active', inactive: 'Inactive' } },
|
|
16
|
+
{ name: 'Details', children: [
|
|
17
|
+
{ id: 'col_3', name: 'City', width: 100, editable: true },
|
|
18
|
+
{ id: 'col_4', name: 'Score', width: 80, editable: true, editor: 'number' },
|
|
19
|
+
]},
|
|
20
|
+
...range(5).map(i => ({ id: 'col_' + (i + 5), name: 'Extra ' + i, width: 80, editable: true })),
|
|
21
|
+
] as any[])
|
|
22
|
+
|
|
23
|
+
const leafColIds = range(10).map(i => 'col_' + i)
|
|
24
|
+
const data = createMutable(
|
|
25
|
+
range(200).map((_, i) => ({
|
|
26
|
+
id: i,
|
|
27
|
+
...Object.fromEntries(leafColIds.map(id => [id, `${id}_${i + 1}`])),
|
|
28
|
+
g: i % 5,
|
|
29
|
+
})),
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
cols.at(-1)!.fixed = 'right'
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Everything combined: header groups, virtual scroll, editable,
|
|
36
|
+
* expand, row selection, resize, drag, history, diff, index, border.
|
|
37
|
+
*/
|
|
38
|
+
export const CompositeDemo = () => (
|
|
39
|
+
<div>
|
|
40
|
+
<p class='text-sm c-gray mb-2'>All features enabled. Edit, drag, resize, select, expand, undo/redo, diff.</p>
|
|
41
|
+
<Intable
|
|
42
|
+
class='w-full h-60vh'
|
|
43
|
+
columns={cols}
|
|
44
|
+
onColumnsChange={v => replaceArray(cols, v)}
|
|
45
|
+
data={data}
|
|
46
|
+
onDataChange={v => replaceArray(data, v)}
|
|
47
|
+
index
|
|
48
|
+
border
|
|
49
|
+
stickyHeader
|
|
50
|
+
size='small'
|
|
51
|
+
colDrag
|
|
52
|
+
rowDrag
|
|
53
|
+
resizable={{ col: { enable: true }, row: { enable: true } }}
|
|
54
|
+
expand={{ enable: true, render: ({ data }) => <div class='p-2 c-blue'>{JSON.stringify(data)}</div> }}
|
|
55
|
+
rowSelection={{ enable: true, multiple: true }}
|
|
56
|
+
plugins={[VirtualScrollPlugin, HistoryPlugin, DiffPlugin]}
|
|
57
|
+
diff={{ onCommit: (d) => console.log('commit', d) }}
|
|
58
|
+
/>
|
|
59
|
+
</div>
|
|
60
|
+
)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Intable } from '../../../packages/intable/src'
|
|
2
|
+
import { makeCols, makeData, replaceArray } from './helpers'
|
|
3
|
+
|
|
4
|
+
const cols = makeCols(6, { editable: true })
|
|
5
|
+
const data = makeData(20, 6)
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Select a cell range then Ctrl+C to copy, Ctrl+V to paste.
|
|
9
|
+
* CopyPaste (ClipboardPlugin) is auto-loaded.
|
|
10
|
+
*/
|
|
11
|
+
export const CopyPasteDemo = () => (
|
|
12
|
+
<div>
|
|
13
|
+
<p class='text-sm c-gray mb-2'>Select cells → Ctrl+C to copy → click target cell → Ctrl+V to paste.</p>
|
|
14
|
+
<Intable
|
|
15
|
+
class='w-full h-50vh'
|
|
16
|
+
columns={cols}
|
|
17
|
+
onColumnsChange={v => replaceArray(cols, v)}
|
|
18
|
+
data={data}
|
|
19
|
+
onDataChange={v => replaceArray(data, v)}
|
|
20
|
+
index
|
|
21
|
+
border
|
|
22
|
+
stickyHeader
|
|
23
|
+
size='small'
|
|
24
|
+
/>
|
|
25
|
+
</div>
|
|
26
|
+
)
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Intable } from '../../../packages/intable/src'
|
|
2
|
+
import { DiffPlugin } from '../../../packages/intable/src/plugins/DiffPlugin'
|
|
3
|
+
import { makeCols, makeData, replaceArray } from './helpers'
|
|
4
|
+
|
|
5
|
+
const cols = makeCols(5, { editable: true })
|
|
6
|
+
const data = makeData(15, 5)
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Edit cells — changed cells are highlighted.
|
|
10
|
+
* Right-click → add/delete rows shows added/removed highlights.
|
|
11
|
+
* Press Ctrl+S to commit & clear highlights.
|
|
12
|
+
*/
|
|
13
|
+
export const DiffDemo = () => (
|
|
14
|
+
<div>
|
|
15
|
+
<p class='text-sm c-gray mb-2'>Edit cells to see change highlights. Ctrl+S to commit.</p>
|
|
16
|
+
<Intable
|
|
17
|
+
class='w-full h-50vh'
|
|
18
|
+
columns={cols}
|
|
19
|
+
onColumnsChange={v => replaceArray(cols, v)}
|
|
20
|
+
data={data}
|
|
21
|
+
onDataChange={v => replaceArray(data, v)}
|
|
22
|
+
index
|
|
23
|
+
border
|
|
24
|
+
stickyHeader
|
|
25
|
+
size='small'
|
|
26
|
+
plugins={[DiffPlugin]}
|
|
27
|
+
diff={{
|
|
28
|
+
enable: true,
|
|
29
|
+
onCommit: (d) => console.log('Diff committed:', d),
|
|
30
|
+
}}
|
|
31
|
+
/>
|
|
32
|
+
</div>
|
|
33
|
+
)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Intable } from '../../../packages/intable/src'
|
|
2
|
+
import { makeCols, makeData, replaceArray } from './helpers'
|
|
3
|
+
|
|
4
|
+
const cols = makeCols(6)
|
|
5
|
+
const data = makeData(20, 6)
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Drag column headers to reorder columns.
|
|
9
|
+
* Drag the index cell (row number) to reorder rows.
|
|
10
|
+
*/
|
|
11
|
+
export const DragDemo = () => (
|
|
12
|
+
<Intable
|
|
13
|
+
class='w-full h-60vh'
|
|
14
|
+
columns={cols}
|
|
15
|
+
onColumnsChange={v => replaceArray(cols, v)}
|
|
16
|
+
data={data}
|
|
17
|
+
onDataChange={v => replaceArray(data, v)}
|
|
18
|
+
index
|
|
19
|
+
border
|
|
20
|
+
stickyHeader
|
|
21
|
+
size='small'
|
|
22
|
+
colDrag
|
|
23
|
+
rowDrag
|
|
24
|
+
/>
|
|
25
|
+
)
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
import { createMutable } from 'solid-js/store'
|
|
3
|
+
import { Intable } from '../../../packages/intable/src'
|
|
4
|
+
import { ZodValidatorPlugin } from '../../../packages/intable/src/plugins/ZodValidatorPlugin'
|
|
5
|
+
import { makeData, replaceArray } from './helpers'
|
|
6
|
+
|
|
7
|
+
const RESERVED = ['admin', 'root', 'null']
|
|
8
|
+
|
|
9
|
+
const cols = createMutable([
|
|
10
|
+
{
|
|
11
|
+
id: 'col_0', name: 'Text (1–20 chars, no reserved)', width: 180, editable: true,
|
|
12
|
+
zodSchema: z.string().min(1, 'Required').max(20, 'Max 20 characters'),
|
|
13
|
+
validator: (value: string) =>
|
|
14
|
+
RESERVED.includes(value.toLowerCase()) ? `"${value}" is a reserved word` : true,
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
id: 'col_1', name: 'Number (0–100)', width: 140, editable: true, editor: 'number',
|
|
18
|
+
zodSchema: z.coerce.number({ error: 'Must be a number' }).min(0, 'Min 0').max(100, 'Max 100'),
|
|
19
|
+
},
|
|
20
|
+
{ id: 'col_2', name: 'Date', width: 130, editable: true, editor: 'date' },
|
|
21
|
+
{ id: 'col_3', name: 'Color', width: 100, editable: true, editor: 'color' },
|
|
22
|
+
{ id: 'col_4', name: 'Checkbox', width: 100, editable: true, editor: 'checkbox' },
|
|
23
|
+
{
|
|
24
|
+
id: 'col_5', name: 'Select', width: 120, editable: true, editor: 'select',
|
|
25
|
+
enum: { A: 'Option A', B: 'Option B', C: 'Option C' },
|
|
26
|
+
},
|
|
27
|
+
{ id: 'col_6', name: 'Range', width: 120, editable: true, editor: 'range' },
|
|
28
|
+
{ id: 'col_7', name: 'ReadOnly', width: 100 },
|
|
29
|
+
] as any[])
|
|
30
|
+
|
|
31
|
+
const data = makeData(20, 8)
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Double-click (or start typing) on an editable cell to enter edit mode.
|
|
35
|
+
* Press Enter or click outside to commit. Escape to cancel.
|
|
36
|
+
*
|
|
37
|
+
* Validation:
|
|
38
|
+
* - Text: Zod min/max length + col.validator blocks reserved words
|
|
39
|
+
* - Number: Zod coerce + range 0–100
|
|
40
|
+
* - Table-level validator: blocks any value containing "error"
|
|
41
|
+
*/
|
|
42
|
+
export const EditableDemo = () => (
|
|
43
|
+
<Intable
|
|
44
|
+
class='w-full h-60vh'
|
|
45
|
+
columns={cols}
|
|
46
|
+
onColumnsChange={v => replaceArray(cols, v)}
|
|
47
|
+
data={data}
|
|
48
|
+
onDataChange={v => replaceArray(data, v)}
|
|
49
|
+
index
|
|
50
|
+
border
|
|
51
|
+
stickyHeader
|
|
52
|
+
size='small'
|
|
53
|
+
plugins={[ZodValidatorPlugin]}
|
|
54
|
+
validator={(value) =>
|
|
55
|
+
String(value ?? '').toLowerCase().includes('error') ? 'Value must not contain "error"' : true
|
|
56
|
+
}
|
|
57
|
+
/>
|
|
58
|
+
)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Intable } from '../../../packages/intable/src'
|
|
2
|
+
import { makeCols, makeData, replaceArray } from './helpers'
|
|
3
|
+
|
|
4
|
+
const cols = makeCols(6)
|
|
5
|
+
const data = makeData(20, 6)
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Click the chevron on the left to expand a row.
|
|
9
|
+
* The expand render shows JSON of the row data.
|
|
10
|
+
*/
|
|
11
|
+
export const ExpandDemo = () => (
|
|
12
|
+
<Intable
|
|
13
|
+
class='w-full h-60vh'
|
|
14
|
+
columns={cols}
|
|
15
|
+
onColumnsChange={v => replaceArray(cols, v)}
|
|
16
|
+
data={data}
|
|
17
|
+
onDataChange={v => replaceArray(data, v)}
|
|
18
|
+
index
|
|
19
|
+
border
|
|
20
|
+
stickyHeader
|
|
21
|
+
size='small'
|
|
22
|
+
expand={{
|
|
23
|
+
enable: true,
|
|
24
|
+
render: ({ data }) => (
|
|
25
|
+
<div class='p-3 bg-gray-50 text-sm'>
|
|
26
|
+
<b>Row Detail:</b>
|
|
27
|
+
<pre class='mt-1'>{JSON.stringify(data, null, 2)}</pre>
|
|
28
|
+
</div>
|
|
29
|
+
),
|
|
30
|
+
}}
|
|
31
|
+
/>
|
|
32
|
+
)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { createMutable } from 'solid-js/store'
|
|
2
|
+
import { Intable } from '../../../packages/intable/src'
|
|
3
|
+
import { VirtualScrollPlugin } from '../../../packages/intable/src/plugins/VirtualScrollPlugin'
|
|
4
|
+
import { makeData, replaceArray } from './helpers'
|
|
5
|
+
import { range } from 'es-toolkit'
|
|
6
|
+
|
|
7
|
+
const cols = createMutable([
|
|
8
|
+
{ name: 'Basic Info', children: [
|
|
9
|
+
{ id: 'col_0', name: 'Name', width: 100 },
|
|
10
|
+
{ id: 'col_1', name: 'Age', width: 80 },
|
|
11
|
+
]},
|
|
12
|
+
{ id: 'col_2', name: 'Status', width: 100 },
|
|
13
|
+
{ name: 'Address', children: [
|
|
14
|
+
{ id: 'col_3', name: 'City', width: 100 },
|
|
15
|
+
{ id: 'col_4', name: 'Street', width: 120 },
|
|
16
|
+
{ id: 'col_5', name: 'Zip', width: 80 },
|
|
17
|
+
]},
|
|
18
|
+
...range(6).map(i => ({ id: 'col_' + (i + 6), name: 'Extra ' + i, width: 80 })),
|
|
19
|
+
] as any[])
|
|
20
|
+
|
|
21
|
+
const data = makeData(100, 12)
|
|
22
|
+
|
|
23
|
+
export const HeaderGroupDemo = () => (
|
|
24
|
+
<Intable
|
|
25
|
+
class='w-full h-60vh'
|
|
26
|
+
columns={cols}
|
|
27
|
+
onColumnsChange={v => replaceArray(cols, v)}
|
|
28
|
+
data={data}
|
|
29
|
+
onDataChange={v => replaceArray(data, v)}
|
|
30
|
+
index
|
|
31
|
+
border
|
|
32
|
+
stickyHeader
|
|
33
|
+
size='small'
|
|
34
|
+
plugins={[VirtualScrollPlugin]}
|
|
35
|
+
/>
|
|
36
|
+
)
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Intable } from '../../../packages/intable/src'
|
|
2
|
+
import { HistoryPlugin } from '../../../packages/intable/src/plugins/HistoryPlugin'
|
|
3
|
+
import { makeCols, makeData, replaceArray } from './helpers'
|
|
4
|
+
|
|
5
|
+
const cols = makeCols(5, { editable: true })
|
|
6
|
+
const data = makeData(15, 5)
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Edit cells then press Ctrl+Z to undo, Ctrl+Y to redo.
|
|
10
|
+
* HistoryPlugin must be added manually.
|
|
11
|
+
*/
|
|
12
|
+
export const HistoryDemo = () => (
|
|
13
|
+
<div>
|
|
14
|
+
<p class='text-sm c-gray mb-2'>Edit a cell, then Ctrl+Z to undo, Ctrl+Y to redo.</p>
|
|
15
|
+
<Intable
|
|
16
|
+
class='w-full h-50vh'
|
|
17
|
+
columns={cols}
|
|
18
|
+
onColumnsChange={v => replaceArray(cols, v)}
|
|
19
|
+
data={data}
|
|
20
|
+
onDataChange={v => replaceArray(data, v)}
|
|
21
|
+
index
|
|
22
|
+
border
|
|
23
|
+
stickyHeader
|
|
24
|
+
size='small'
|
|
25
|
+
plugins={[HistoryPlugin]}
|
|
26
|
+
/>
|
|
27
|
+
</div>
|
|
28
|
+
)
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { useEffect, useRef, useState, createElement as h, type FC } from 'react'
|
|
2
|
+
|
|
3
|
+
import { Intable, component } from '../../../packages/react/src'
|
|
4
|
+
import { range } from 'es-toolkit'
|
|
5
|
+
|
|
6
|
+
export const ReactDemo = component(() => {
|
|
7
|
+
const [cols, setCols] = useState([
|
|
8
|
+
{ id: 'col_0', name: 'Column 1', width: 120, editable: true },
|
|
9
|
+
{ name: 'HeaderGroup', children: [
|
|
10
|
+
{ id: 'col_1', name: 'Column 2', width: 120, editable: true, render: (props) => h('div', { style: { color: 'red' } }, props.data[props.col.id]) },
|
|
11
|
+
{ id: 'col_2', name: 'Column 3', width: 120, editable: true },
|
|
12
|
+
] },
|
|
13
|
+
{ id: 'col_3', name: 'Column 4', width: 120, editable: true },
|
|
14
|
+
{ id: 'col_4', name: 'Column 5', width: 120, editable: true },
|
|
15
|
+
{ id: 'col_5', name: 'Column 6', width: 120, editable: true },
|
|
16
|
+
{ id: 'col_6', name: 'Column 7', editable: true },
|
|
17
|
+
{ id: 'col_7', name: 'Column 8', editable: true },
|
|
18
|
+
])
|
|
19
|
+
|
|
20
|
+
const [data, setData] = useState(range(20).map(i => {
|
|
21
|
+
const row: Record<string, any> = { id: i }
|
|
22
|
+
for (let j = 0; j < cols.length; j++) {
|
|
23
|
+
row['col_' + j] = `col_${j}_${i + 1}`
|
|
24
|
+
}
|
|
25
|
+
return row
|
|
26
|
+
}))
|
|
27
|
+
|
|
28
|
+
return h(Intable, {
|
|
29
|
+
className: 'w-full h-60vh',
|
|
30
|
+
columns: cols,
|
|
31
|
+
onColumnsChange: v => setCols(v),
|
|
32
|
+
data: data,
|
|
33
|
+
onDataChange: v => setData(v),
|
|
34
|
+
index: true,
|
|
35
|
+
border: true,
|
|
36
|
+
stickyHeader: true,
|
|
37
|
+
size: 'small',
|
|
38
|
+
//
|
|
39
|
+
resizable: { col: { enable: true }, row: { enable: true } },
|
|
40
|
+
//
|
|
41
|
+
colDrag: true,
|
|
42
|
+
rowDrag: true,
|
|
43
|
+
//
|
|
44
|
+
rowSelection: {
|
|
45
|
+
enable: true,
|
|
46
|
+
multiple: true,
|
|
47
|
+
onChange: (selected, unselected) => console.log('selected:', selected, 'unselected:', unselected),
|
|
48
|
+
},
|
|
49
|
+
expand: {
|
|
50
|
+
enable: true,
|
|
51
|
+
render: ({ data }) => (
|
|
52
|
+
h('div', { className: 'p-3 bg-gray-50 text-sm' }, [
|
|
53
|
+
h('b', null, 'Row Detail:'),
|
|
54
|
+
h('pre', { className: 'mt-1' }, JSON.stringify(data, null, 2))
|
|
55
|
+
])
|
|
56
|
+
)
|
|
57
|
+
},
|
|
58
|
+
})
|
|
59
|
+
})
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Intable } from '../../../packages/intable/src'
|
|
2
|
+
import { makeCols, makeData, replaceArray } from './helpers'
|
|
3
|
+
|
|
4
|
+
const cols = makeCols(6)
|
|
5
|
+
const data = makeData(20, 6)
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Drag column header borders to resize columns.
|
|
9
|
+
* Row resize is also enabled — drag row bottom borders.
|
|
10
|
+
*/
|
|
11
|
+
export const ResizeDemo = () => (
|
|
12
|
+
<Intable
|
|
13
|
+
class='w-full h-60vh'
|
|
14
|
+
columns={cols}
|
|
15
|
+
onColumnsChange={v => replaceArray(cols, v)}
|
|
16
|
+
data={data}
|
|
17
|
+
onDataChange={v => replaceArray(data, v)}
|
|
18
|
+
index
|
|
19
|
+
border
|
|
20
|
+
stickyHeader
|
|
21
|
+
size='small'
|
|
22
|
+
resizable={{ col: { enable: true }, row: { enable: true } }}
|
|
23
|
+
/>
|
|
24
|
+
)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { createMutable } from 'solid-js/store'
|
|
2
|
+
import { range } from 'es-toolkit'
|
|
3
|
+
import { Intable } from '../../../packages/intable/src'
|
|
4
|
+
import { replaceArray } from './helpers'
|
|
5
|
+
|
|
6
|
+
const cols = createMutable([
|
|
7
|
+
{ id: 'name', name: 'Name', width: 120 },
|
|
8
|
+
{ id: 'category', name: 'Category', width: 120 },
|
|
9
|
+
{ id: 'region', name: 'Region', width: 120 },
|
|
10
|
+
{ id: 'value', name: 'Value', width: 100 },
|
|
11
|
+
])
|
|
12
|
+
|
|
13
|
+
const categories = ['Electronics', 'Clothing', 'Food']
|
|
14
|
+
const regions = ['East', 'West', 'North', 'South']
|
|
15
|
+
|
|
16
|
+
const data = createMutable(
|
|
17
|
+
range(40).map(i => ({
|
|
18
|
+
id: i,
|
|
19
|
+
name: 'Item ' + i,
|
|
20
|
+
category: categories[i % 3],
|
|
21
|
+
region: regions[i % 4],
|
|
22
|
+
value: Math.round(Math.random() * 1000),
|
|
23
|
+
})),
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Rows are grouped by `category` then `region`.
|
|
28
|
+
* Click group headers to expand/collapse.
|
|
29
|
+
*/
|
|
30
|
+
export const RowGroupDemo = () => (
|
|
31
|
+
<Intable
|
|
32
|
+
class='w-full h-60vh'
|
|
33
|
+
columns={cols}
|
|
34
|
+
onColumnsChange={v => replaceArray(cols, v)}
|
|
35
|
+
data={data}
|
|
36
|
+
onDataChange={v => replaceArray(data, v)}
|
|
37
|
+
index
|
|
38
|
+
border
|
|
39
|
+
stickyHeader
|
|
40
|
+
size='small'
|
|
41
|
+
rowGroup={{ fields: ['category', 'region'] }}
|
|
42
|
+
/>
|
|
43
|
+
)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Intable } from '../../../packages/intable/src'
|
|
2
|
+
import { makeCols, makeData, replaceArray } from './helpers'
|
|
3
|
+
|
|
4
|
+
const cols = makeCols(6)
|
|
5
|
+
const data = makeData(20, 6)
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Checkbox column on the left. Click to select, header checkbox for select-all.
|
|
9
|
+
*/
|
|
10
|
+
export const RowSelectionDemo = () => (
|
|
11
|
+
<Intable
|
|
12
|
+
class='w-full h-60vh'
|
|
13
|
+
columns={cols}
|
|
14
|
+
onColumnsChange={v => replaceArray(cols, v)}
|
|
15
|
+
data={data}
|
|
16
|
+
onDataChange={v => replaceArray(data, v)}
|
|
17
|
+
index
|
|
18
|
+
border
|
|
19
|
+
stickyHeader
|
|
20
|
+
size='small'
|
|
21
|
+
rowSelection={{
|
|
22
|
+
enable: true,
|
|
23
|
+
multiple: true,
|
|
24
|
+
onChange: (selected, unselected) => console.log('selected:', selected, 'unselected:', unselected),
|
|
25
|
+
}}
|
|
26
|
+
/>
|
|
27
|
+
)
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { createMutable } from 'solid-js/store'
|
|
2
|
+
import { Intable } from '../../../packages/intable/src'
|
|
3
|
+
import { replaceArray } from './helpers'
|
|
4
|
+
|
|
5
|
+
const cols = createMutable([
|
|
6
|
+
{ id: 'name', name: 'Name', width: 200 },
|
|
7
|
+
{ id: 'size', name: 'Size', width: 100 },
|
|
8
|
+
{ id: 'type', name: 'Type', width: 120 },
|
|
9
|
+
])
|
|
10
|
+
|
|
11
|
+
const data = createMutable([
|
|
12
|
+
{ id: 1, name: 'src', size: '-', type: 'folder', children: [
|
|
13
|
+
{ id: 2, name: 'index.ts', size: '2KB', type: 'file' },
|
|
14
|
+
{ id: 3, name: 'utils', size: '-', type: 'folder', children: [
|
|
15
|
+
{ id: 4, name: 'helper.ts', size: '1KB', type: 'file' },
|
|
16
|
+
{ id: 5, name: 'math.ts', size: '3KB', type: 'file' },
|
|
17
|
+
]},
|
|
18
|
+
{ id: 6, name: 'components', size: '-', type: 'folder', children: [
|
|
19
|
+
{ id: 7, name: 'App.tsx', size: '4KB', type: 'file' },
|
|
20
|
+
{ id: 8, name: 'Button.tsx', size: '1KB', type: 'file' },
|
|
21
|
+
]},
|
|
22
|
+
]},
|
|
23
|
+
{ id: 9, name: 'package.json', size: '1KB', type: 'file' },
|
|
24
|
+
{ id: 10, name: 'README.md', size: '2KB', type: 'file' },
|
|
25
|
+
])
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Tree-structured data with expand/collapse.
|
|
29
|
+
* TreePlugin must be added manually.
|
|
30
|
+
*/
|
|
31
|
+
export const TreeDemo = () => (
|
|
32
|
+
<Intable
|
|
33
|
+
class='w-full h-60vh'
|
|
34
|
+
columns={cols}
|
|
35
|
+
onColumnsChange={v => replaceArray(cols, v)}
|
|
36
|
+
data={data}
|
|
37
|
+
onDataChange={v => replaceArray(data, v)}
|
|
38
|
+
index
|
|
39
|
+
border
|
|
40
|
+
stickyHeader
|
|
41
|
+
size='small'
|
|
42
|
+
tree={{ children: 'children' }}
|
|
43
|
+
rowKey='id'
|
|
44
|
+
/>
|
|
45
|
+
)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Intable } from '../../../packages/intable/src'
|
|
2
|
+
import { VirtualScrollPlugin } from '../../../packages/intable/src/plugins/VirtualScrollPlugin'
|
|
3
|
+
import { makeCols, makeData, replaceArray } from './helpers'
|
|
4
|
+
|
|
5
|
+
const cols = makeCols(50, { width: 80 })
|
|
6
|
+
const data = makeData(1000, 50)
|
|
7
|
+
|
|
8
|
+
export const VirtualScrollDemo = () => (
|
|
9
|
+
<Intable
|
|
10
|
+
class='h-60vh'
|
|
11
|
+
columns={cols}
|
|
12
|
+
onColumnsChange={v => replaceArray(cols, v)}
|
|
13
|
+
data={data}
|
|
14
|
+
onDataChange={v => replaceArray(data, v)}
|
|
15
|
+
index
|
|
16
|
+
border
|
|
17
|
+
stickyHeader
|
|
18
|
+
size='small'
|
|
19
|
+
plugins={[VirtualScrollPlugin]}
|
|
20
|
+
/>
|
|
21
|
+
)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared helpers for demo data generation.
|
|
3
|
+
*/
|
|
4
|
+
import { createMutable } from 'solid-js/store'
|
|
5
|
+
import { batch } from 'solid-js'
|
|
6
|
+
import { range } from 'es-toolkit'
|
|
7
|
+
|
|
8
|
+
/** Generate flat tabular data */
|
|
9
|
+
export function makeData(rows: number, colCount: number) {
|
|
10
|
+
const colIds = range(colCount).map(i => 'col_' + i)
|
|
11
|
+
return createMutable(
|
|
12
|
+
range(rows).map((_, i) =>
|
|
13
|
+
Object.fromEntries([
|
|
14
|
+
['id', i],
|
|
15
|
+
...colIds.map(id => [id, `${id}_${i + 1}`]),
|
|
16
|
+
]),
|
|
17
|
+
),
|
|
18
|
+
)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Generate column definitions */
|
|
22
|
+
export function makeCols(count: number, extra?: Partial<{ width: number; editable: boolean }>) {
|
|
23
|
+
return createMutable(
|
|
24
|
+
range(count).map(i => ({
|
|
25
|
+
id: 'col_' + i,
|
|
26
|
+
name: 'Col ' + i,
|
|
27
|
+
width: 100,
|
|
28
|
+
...extra,
|
|
29
|
+
})),
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Shortcut for batch-replacing a reactive array */
|
|
34
|
+
export function replaceArray<T>(arr: T[], next: T[]) {
|
|
35
|
+
batch(() => {
|
|
36
|
+
arr.length = 0
|
|
37
|
+
arr.push(...next)
|
|
38
|
+
})
|
|
39
|
+
}
|