intable 0.0.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.
- package/LICENSE +21 -0
- package/README.md +22 -0
- package/dist/chevron-right.js +8 -0
- package/dist/components/Columns.d.ts +3 -0
- package/dist/components/Columns.js +105 -0
- package/dist/components/DocTree.d.ts +4 -0
- package/dist/components/DocTree.js +40 -0
- package/dist/components/Menu.d.ts +1 -0
- package/dist/components/Menu.js +131 -0
- package/dist/components/Popover.d.ts +14 -0
- package/dist/components/Popover.js +49 -0
- package/dist/components/Render.d.ts +4 -0
- package/dist/components/Render.js +21 -0
- package/dist/components/Split.d.ts +15 -0
- package/dist/components/Split.js +88 -0
- package/dist/components/Tree.d.ts +37 -0
- package/dist/components/Tree.js +101 -0
- package/dist/components/utils.d.ts +3 -0
- package/dist/components/utils.js +10 -0
- package/dist/demo.d.ts +2 -0
- package/dist/demo.js +64 -0
- package/dist/hooks/index.d.ts +38 -0
- package/dist/hooks/index.js +182 -0
- package/dist/hooks/useDir.d.ts +11 -0
- package/dist/hooks/useDir.js +59 -0
- package/dist/hooks/useVirtualizer.d.ts +25 -0
- package/dist/hooks/useVirtualizer.js +92 -0
- package/dist/index.d.ts +116 -0
- package/dist/index.js +348 -0
- package/dist/intable.css +277 -0
- package/dist/loading.js +8 -0
- package/dist/plugins/CellChangeHighlightPlugin.d.ts +2 -0
- package/dist/plugins/CellChangeHighlightPlugin.js +4 -0
- package/dist/plugins/CellSelectionPlugin.d.ts +15 -0
- package/dist/plugins/CellSelectionPlugin.js +150 -0
- package/dist/plugins/CommandPlugin.d.ts +14 -0
- package/dist/plugins/CommandPlugin.js +9 -0
- package/dist/plugins/CopyPastePlugin.d.ts +14 -0
- package/dist/plugins/CopyPastePlugin.js +54 -0
- package/dist/plugins/DiffPlugin.d.ts +23 -0
- package/dist/plugins/DiffPlugin.js +68 -0
- package/dist/plugins/DragColumnPlugin.d.ts +2 -0
- package/dist/plugins/DragColumnPlugin.js +4 -0
- package/dist/plugins/EditablePlugin.d.ts +49 -0
- package/dist/plugins/EditablePlugin.js +191 -0
- package/dist/plugins/ExpandPlugin.d.ts +20 -0
- package/dist/plugins/ExpandPlugin.js +56 -0
- package/dist/plugins/HistoryPlugin.d.ts +10 -0
- package/dist/plugins/HistoryPlugin.js +35 -0
- package/dist/plugins/MenuPlugin.d.ts +18 -0
- package/dist/plugins/MenuPlugin.js +131 -0
- package/dist/plugins/RenderPlugin/components.d.ts +5 -0
- package/dist/plugins/RenderPlugin/components.js +105 -0
- package/dist/plugins/RenderPlugin/index.d.ts +30 -0
- package/dist/plugins/RenderPlugin/index.js +61 -0
- package/dist/plugins/ResizePlugin.d.ts +27 -0
- package/dist/plugins/ResizePlugin.js +103 -0
- package/dist/plugins/RowGroupPlugin.d.ts +17 -0
- package/dist/plugins/RowGroupPlugin.js +99 -0
- package/dist/plugins/RowSelectionPlugin.d.ts +32 -0
- package/dist/plugins/RowSelectionPlugin.js +69 -0
- package/dist/plugins/VirtualScrollPlugin.d.ts +15 -0
- package/dist/plugins/VirtualScrollPlugin.js +121 -0
- package/dist/plus.js +8 -0
- package/dist/types/auto-imports.d.js +0 -0
- package/dist/utils.d.ts +29 -0
- package/dist/utils.js +88 -0
- package/dist/vite.svg +1 -0
- package/dist/wc.d.ts +1 -0
- package/dist/wc.js +24 -0
- package/dist/web-component.d.ts +1 -0
- package/dist/web-component.js +2 -0
- package/dist/x.js +8 -0
- package/package.json +71 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type Plugin } from '..';
|
|
2
|
+
declare module '../index' {
|
|
3
|
+
interface TableProps {
|
|
4
|
+
}
|
|
5
|
+
interface TableStore {
|
|
6
|
+
selected: {
|
|
7
|
+
start: number[];
|
|
8
|
+
end: number[];
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
interface Commands {
|
|
12
|
+
getAreaRows(): any[];
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export declare const CellSelectionPlugin: Plugin;
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { usePointerDrag, useTinykeys } from "../hooks/index.js";
|
|
2
|
+
import { Ctx } from "../index.js";
|
|
3
|
+
import { createComponent, memo, mergeProps, template } from "solid-js/web";
|
|
4
|
+
import { batch, createMemo, useContext } from "solid-js";
|
|
5
|
+
import { combineProps } from "@solid-primitives/props";
|
|
6
|
+
var _tmpl$ = /* @__PURE__ */ template(`<div class=area>`);
|
|
7
|
+
var inrange = (v, min, max) => v <= max && v >= min;
|
|
8
|
+
const CellSelectionPlugin = {
|
|
9
|
+
store: () => ({ selected: {
|
|
10
|
+
start: [],
|
|
11
|
+
end: []
|
|
12
|
+
} }),
|
|
13
|
+
commands: (store) => ({ getAreaRows() {
|
|
14
|
+
const { start, end } = store.selected;
|
|
15
|
+
const [y1, y2] = [start[1], end[1]].sort((a, b) => a - b);
|
|
16
|
+
return store.props.data.slice(y1, y2 + 1);
|
|
17
|
+
} }),
|
|
18
|
+
rewriteProps: {
|
|
19
|
+
Th: ({ Th }, { store }) => (o) => {
|
|
20
|
+
const clazz = createMemo(() => {
|
|
21
|
+
const { start, end } = store.selected;
|
|
22
|
+
return inrange(o.x, ...[start[0], end[0]].sort((a, b) => a - b)) ? "col-range-highlight" : "";
|
|
23
|
+
});
|
|
24
|
+
const mo = combineProps(o, { get class() {
|
|
25
|
+
return clazz();
|
|
26
|
+
} });
|
|
27
|
+
return createComponent(Th, mergeProps(mo, { get children() {
|
|
28
|
+
return [memo(() => mo.children), memo(() => memo(() => !!clazz())() && _tmpl$())];
|
|
29
|
+
} }));
|
|
30
|
+
},
|
|
31
|
+
Td: ({ Td }, { store }) => (o) => {
|
|
32
|
+
const clazz = createMemo(() => {
|
|
33
|
+
let clazz$1 = "";
|
|
34
|
+
const { xs, ys } = store.cellSelectionRect();
|
|
35
|
+
const inx = inrange(o.x, xs[0], xs[1]);
|
|
36
|
+
const iny = inrange(o.y, ys[0], ys[1]);
|
|
37
|
+
if (inx && iny) {
|
|
38
|
+
clazz$1 += "range-selected ";
|
|
39
|
+
if (o.x == xs[0]) clazz$1 += "range-selected-l ";
|
|
40
|
+
if (o.x == xs[1]) clazz$1 += "range-selected-r ";
|
|
41
|
+
if (o.y == ys[0]) clazz$1 += "range-selected-t ";
|
|
42
|
+
if (o.y == ys[1]) clazz$1 += "range-selected-b ";
|
|
43
|
+
}
|
|
44
|
+
if (o.x == 0 && iny) clazz$1 += "row-range-highlight ";
|
|
45
|
+
return clazz$1;
|
|
46
|
+
});
|
|
47
|
+
const mo = combineProps(o, {
|
|
48
|
+
get class() {
|
|
49
|
+
return clazz();
|
|
50
|
+
},
|
|
51
|
+
tabindex: -1
|
|
52
|
+
});
|
|
53
|
+
return createComponent(Td, mergeProps(mo, { get children() {
|
|
54
|
+
return [memo(() => mo.children), memo(() => memo(() => !!clazz())() && _tmpl$())];
|
|
55
|
+
} }));
|
|
56
|
+
},
|
|
57
|
+
Table: ({ Table }, { store }) => (o) => {
|
|
58
|
+
const { props } = useContext(Ctx);
|
|
59
|
+
store.cellSelectionRect ??= createMemo(() => {
|
|
60
|
+
const { start, end } = store.selected;
|
|
61
|
+
const xs = [start[0], end[0]].sort((a, b) => a - b);
|
|
62
|
+
const ys = [start[1], end[1]].sort((a, b) => a - b);
|
|
63
|
+
return {
|
|
64
|
+
xs,
|
|
65
|
+
ys
|
|
66
|
+
};
|
|
67
|
+
});
|
|
68
|
+
usePointerDrag(() => store.table, { start(e, move, end) {
|
|
69
|
+
batch(() => {
|
|
70
|
+
const findCell = (e$1) => e$1.composedPath().find((e$2) => e$2.tagName == "TH" || e$2.tagName == "TD");
|
|
71
|
+
const getXY = (cell$1) => [cell$1.getAttribute("x"), cell$1.getAttribute("y")];
|
|
72
|
+
const cell = findCell(e);
|
|
73
|
+
if (!cell) return;
|
|
74
|
+
if (e.buttons != 1 && cell.classList.contains("range-selected")) return;
|
|
75
|
+
if (cell.tagName == "TH") {
|
|
76
|
+
const [x, y] = getXY(cell);
|
|
77
|
+
if (x == null) return;
|
|
78
|
+
store.selected.start = [+x, 0];
|
|
79
|
+
store.selected.end = [+x, Infinity];
|
|
80
|
+
move((e$1) => {
|
|
81
|
+
const cell$1 = findCell(e$1);
|
|
82
|
+
if (!cell$1) return;
|
|
83
|
+
const [x$1, y$1] = getXY(cell$1);
|
|
84
|
+
if (x$1 == null) return;
|
|
85
|
+
store.selected.end = [+x$1, Infinity];
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
if (cell.classList.contains("index")) {
|
|
89
|
+
const [x, y] = getXY(cell);
|
|
90
|
+
if (x == null || y == null) return;
|
|
91
|
+
store.selected.start = [0, +y];
|
|
92
|
+
store.selected.end = [Infinity, +y];
|
|
93
|
+
move((e$1) => {
|
|
94
|
+
const cell$1 = findCell(e$1);
|
|
95
|
+
if (!cell$1) return;
|
|
96
|
+
const [x$1, y$1] = getXY(cell$1);
|
|
97
|
+
if (x$1 == null || y$1 == null) return;
|
|
98
|
+
store.selected.end = [Infinity, +y$1];
|
|
99
|
+
});
|
|
100
|
+
} else if (cell.tagName == "TD") {
|
|
101
|
+
const [x, y] = getXY(cell);
|
|
102
|
+
if (x == null || y == null) return;
|
|
103
|
+
store.selected.start = [+x, +y];
|
|
104
|
+
store.selected.end = [...store.selected.start];
|
|
105
|
+
move((e$1) => {
|
|
106
|
+
const cell$1 = findCell(e$1);
|
|
107
|
+
if (!cell$1) return;
|
|
108
|
+
const [x$1, y$1] = getXY(cell$1);
|
|
109
|
+
if (x$1 == null || y$1 == null) return;
|
|
110
|
+
store.selected.end = [+x$1, +y$1];
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
} });
|
|
115
|
+
useTinykeys(() => store.table, {
|
|
116
|
+
"ArrowLeft": () => {
|
|
117
|
+
const { start, end } = store.selected;
|
|
118
|
+
start[0] = end[0] = Math.max(start[0] - 1, 0);
|
|
119
|
+
end[1] = start[1];
|
|
120
|
+
scrollIntoView();
|
|
121
|
+
},
|
|
122
|
+
"ArrowRight": () => {
|
|
123
|
+
const { start, end } = store.selected;
|
|
124
|
+
start[0] = end[0] = Math.min(start[0] + 1, props.columns.length - 1);
|
|
125
|
+
end[1] = start[1];
|
|
126
|
+
scrollIntoView();
|
|
127
|
+
},
|
|
128
|
+
"ArrowUp": () => {
|
|
129
|
+
const { start, end } = store.selected;
|
|
130
|
+
start[1] = end[1] = Math.max(start[1] - 1, 0);
|
|
131
|
+
end[0] = start[0];
|
|
132
|
+
scrollIntoView();
|
|
133
|
+
},
|
|
134
|
+
"ArrowDown": () => {
|
|
135
|
+
const { start, end } = store.selected;
|
|
136
|
+
start[1] = end[1] = Math.min(start[1] + 1, props.data.length - 1);
|
|
137
|
+
end[0] = start[0];
|
|
138
|
+
scrollIntoView();
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
const scrollIntoView = () => {
|
|
142
|
+
const cell = store.table.querySelector(`td[x="${store.selected.start[0]}"][y="${store.selected.start[1]}"]`);
|
|
143
|
+
cell?.scrollIntoViewIfNeeded(false);
|
|
144
|
+
cell?.focus();
|
|
145
|
+
};
|
|
146
|
+
return createComponent(Table, o);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
export { CellSelectionPlugin };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type Plugin } from '..';
|
|
2
|
+
declare module '../index' {
|
|
3
|
+
interface TableProps {
|
|
4
|
+
}
|
|
5
|
+
interface TableStore {
|
|
6
|
+
commands: Commands;
|
|
7
|
+
}
|
|
8
|
+
interface Plugin {
|
|
9
|
+
commands?: (store: TableStore, commands: Partial<Commands>) => Partial<Commands> & Record<string, any>;
|
|
10
|
+
}
|
|
11
|
+
interface Commands {
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export declare const CommandPlugin: Plugin;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { createComponent } from "solid-js/web";
|
|
2
|
+
import { createComputed } from "solid-js";
|
|
3
|
+
const CommandPlugin = { rewriteProps: { Table: ({ Table }, { store }) => (o) => {
|
|
4
|
+
createComputed(() => {
|
|
5
|
+
store.commands = store.plugins.reduce((o$1, e) => Object.assign(o$1, e.commands?.(store, { ...o$1 })), {});
|
|
6
|
+
});
|
|
7
|
+
return createComponent(Table, o);
|
|
8
|
+
} } };
|
|
9
|
+
export { CommandPlugin };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type Plugin } from '..';
|
|
2
|
+
declare module '../index' {
|
|
3
|
+
interface TableProps {
|
|
4
|
+
}
|
|
5
|
+
interface TableStore {
|
|
6
|
+
}
|
|
7
|
+
interface Plugin {
|
|
8
|
+
}
|
|
9
|
+
interface Commands {
|
|
10
|
+
copy: () => void;
|
|
11
|
+
paste: () => void;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export declare const ClipboardPlugin: Plugin;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { useTinykeys } from "../hooks/index.js";
|
|
2
|
+
import { createComponent } from "solid-js/web";
|
|
3
|
+
import { createEffect } from "solid-js";
|
|
4
|
+
import { combineProps } from "@solid-primitives/props";
|
|
5
|
+
const ClipboardPlugin = {
|
|
6
|
+
rewriteProps: { Table: ({ Table }, { store }) => (o) => {
|
|
7
|
+
let el;
|
|
8
|
+
useTinykeys(() => el, {
|
|
9
|
+
"Control+C": () => {
|
|
10
|
+
store.commands.copy();
|
|
11
|
+
el.classList.add("copied");
|
|
12
|
+
},
|
|
13
|
+
"Control+V": () => store.commands.paste()
|
|
14
|
+
});
|
|
15
|
+
createEffect(() => {
|
|
16
|
+
JSON.stringify(store.selected);
|
|
17
|
+
el.classList.remove("copied");
|
|
18
|
+
});
|
|
19
|
+
o = combineProps({
|
|
20
|
+
ref: (e) => el = e,
|
|
21
|
+
tabindex: -1
|
|
22
|
+
}, o);
|
|
23
|
+
return createComponent(Table, o);
|
|
24
|
+
} },
|
|
25
|
+
menus: (store) => [],
|
|
26
|
+
commands: (store) => ({
|
|
27
|
+
copy: () => {
|
|
28
|
+
const { start, end } = store.selected;
|
|
29
|
+
if (start.length == 0) return;
|
|
30
|
+
const [x1, x2] = [start[0], end[0]].sort((a, b) => a - b);
|
|
31
|
+
const [y1, y2] = [start[1], end[1]].sort((a, b) => a - b);
|
|
32
|
+
const cols = store.props.columns.slice(x1, x2 + 1);
|
|
33
|
+
const text = store.props.data.slice(y1, y2 + 1).map((row) => cols.map((col) => row[col.id])).map((row) => row.join(" ")).join("\n");
|
|
34
|
+
navigator.clipboard.writeText(text);
|
|
35
|
+
},
|
|
36
|
+
paste: async () => {
|
|
37
|
+
const { start, end } = store.selected;
|
|
38
|
+
if (start.length == 0) return;
|
|
39
|
+
const arr2 = (await navigator.clipboard.readText()).split("\n").map((row) => row.split(" "));
|
|
40
|
+
const cols = store.props.columns.slice(start[0], start[0] + arr2[0].length);
|
|
41
|
+
const data = store.props.data.slice();
|
|
42
|
+
arr2.forEach((row, y) => {
|
|
43
|
+
row = Object.fromEntries(cols.map((col, x) => [col.id, row[x]]));
|
|
44
|
+
data[start[1] + y] = {
|
|
45
|
+
...data[start[1] + y],
|
|
46
|
+
...row
|
|
47
|
+
};
|
|
48
|
+
});
|
|
49
|
+
store.selected.end = [start[0] + cols.length - 1, Math.min(start[1] + arr2.length - 1, ctx.props.data.length - 1)];
|
|
50
|
+
store.props.onDataChange?.(data);
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
};
|
|
54
|
+
export { ClipboardPlugin };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type Plugin } from '..';
|
|
2
|
+
declare module '../index' {
|
|
3
|
+
interface TableProps {
|
|
4
|
+
diff?: {
|
|
5
|
+
/** @default true */ added?: boolean;
|
|
6
|
+
/** @default true */ removed?: boolean;
|
|
7
|
+
/** @default true */ changed?: boolean;
|
|
8
|
+
onCommit?: (data: any, opt: {
|
|
9
|
+
added: any[];
|
|
10
|
+
removed: any[];
|
|
11
|
+
changed: any[];
|
|
12
|
+
}) => any;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
interface TableStore {
|
|
16
|
+
diffData: any[];
|
|
17
|
+
diffDataKeyed: () => any;
|
|
18
|
+
}
|
|
19
|
+
interface Commands {
|
|
20
|
+
diffCommit(data?: any[]): void;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export declare const DiffPlugin: Plugin;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { useTinykeys } from "../hooks/index.js";
|
|
2
|
+
import { createComponent } from "solid-js/web";
|
|
3
|
+
import { unwrap } from "solid-js/store";
|
|
4
|
+
import { isEqual, keyBy } from "es-toolkit";
|
|
5
|
+
import { combineProps } from "@solid-primitives/props";
|
|
6
|
+
import { createLazyMemo } from "@solid-primitives/memo";
|
|
7
|
+
import { v4 } from "uuid";
|
|
8
|
+
import { diffArrays } from "diff";
|
|
9
|
+
var DEL = Symbol("del");
|
|
10
|
+
var NEW = Symbol("new");
|
|
11
|
+
const DiffPlugin = {
|
|
12
|
+
priority: Infinity,
|
|
13
|
+
store: (store) => {
|
|
14
|
+
const data = store.rawProps.data || [];
|
|
15
|
+
data.forEach((row) => unwrap(row)[store.rawProps.rowKey] ??= v4());
|
|
16
|
+
return {
|
|
17
|
+
diffData: structuredClone(unwrap(data || [])),
|
|
18
|
+
diffDataKeyed: createLazyMemo(() => keyBy(store.diffData, (e) => e[store.props.rowKey]))
|
|
19
|
+
};
|
|
20
|
+
},
|
|
21
|
+
commands: (store) => ({ async diffCommit(data = store.rawProps.data || []) {
|
|
22
|
+
const { rowKey } = store.props || {};
|
|
23
|
+
data.forEach((row) => unwrap(row)[rowKey] ??= v4());
|
|
24
|
+
data = structuredClone(unwrap(data));
|
|
25
|
+
const added = [], removed = [], changed = [];
|
|
26
|
+
const keyed = keyBy(data, (e) => e[rowKey]);
|
|
27
|
+
for (const e of data) {
|
|
28
|
+
const old = store.diffDataKeyed()[e[rowKey]];
|
|
29
|
+
if (!old) added.push(e);
|
|
30
|
+
else if (!isEqual(e, old)) changed.push(e);
|
|
31
|
+
}
|
|
32
|
+
for (const e of store.diffData) !keyed[e[rowKey]] && removed.push(e);
|
|
33
|
+
await store.props.diff?.onCommit?.(data, {
|
|
34
|
+
added,
|
|
35
|
+
removed,
|
|
36
|
+
changed
|
|
37
|
+
});
|
|
38
|
+
added[NEW] = 0;
|
|
39
|
+
store.diffData = data;
|
|
40
|
+
} }),
|
|
41
|
+
rewriteProps: {
|
|
42
|
+
diff: ({ diff }) => ({
|
|
43
|
+
added: true,
|
|
44
|
+
removed: true,
|
|
45
|
+
changed: true,
|
|
46
|
+
...diff
|
|
47
|
+
}),
|
|
48
|
+
data: ({ data }, { store }) => {
|
|
49
|
+
const { rowKey, diff } = store.props || {};
|
|
50
|
+
return diffArrays(store.diffData || [], data, { comparator: (a, b) => a[rowKey] == b[rowKey] }).flatMap((e) => e.added ? e.value.map((e$1) => (e$1[NEW] = 1, e$1)) : e.removed ? diff.removed ? e.value.map((e$1) => ({
|
|
51
|
+
...e$1,
|
|
52
|
+
[DEL]: 1,
|
|
53
|
+
[store.internal]: 1
|
|
54
|
+
})) : [] : e.value);
|
|
55
|
+
},
|
|
56
|
+
Table: ({ Table }, { store }) => (o) => {
|
|
57
|
+
useTinykeys(() => store.table, { "Control+S": () => store.commands.diffCommit() });
|
|
58
|
+
o = combineProps({ tabindex: -1 }, o);
|
|
59
|
+
return createComponent(Table, o);
|
|
60
|
+
},
|
|
61
|
+
tdProps: ({ tdProps }, { store }) => (o) => combineProps(tdProps?.(o) || {}, { get class() {
|
|
62
|
+
const { diff } = store.props || {};
|
|
63
|
+
const id = unwrap(o.data)[store.props.rowKey];
|
|
64
|
+
return [o.data[NEW] ? diff?.added ? "bg-#dafaea" : "" : o.data[DEL] ? "bg-#ffe8e8" : o.data[store.internal] ? "" : diff.changed && o.data[o.col.id] != store.diffDataKeyed()[id][o.col.id] ? "bg-#dafaea" : ""].join(" ");
|
|
65
|
+
} })
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
export { DiffPlugin };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { type JSX } from 'solid-js';
|
|
2
|
+
import { type Plugin, type TableColumn } from '..';
|
|
3
|
+
declare module '../index' {
|
|
4
|
+
interface TableProps {
|
|
5
|
+
}
|
|
6
|
+
interface TableColumn {
|
|
7
|
+
editable?: boolean;
|
|
8
|
+
editor?: string | Editor;
|
|
9
|
+
editorProps?: any;
|
|
10
|
+
editorPopup?: boolean;
|
|
11
|
+
editOnInput?: boolean;
|
|
12
|
+
}
|
|
13
|
+
interface TableStore {
|
|
14
|
+
editors: {
|
|
15
|
+
[key: string]: Editor;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export type Editor = (props: EditorOpt) => {
|
|
20
|
+
el: JSX.Element;
|
|
21
|
+
getValue: () => any;
|
|
22
|
+
destroy: () => void;
|
|
23
|
+
focus?: () => void;
|
|
24
|
+
blur?: () => void;
|
|
25
|
+
};
|
|
26
|
+
export interface EditorOpt {
|
|
27
|
+
col: TableColumn;
|
|
28
|
+
data: any;
|
|
29
|
+
value: any;
|
|
30
|
+
eventKey?: string;
|
|
31
|
+
ok: () => void;
|
|
32
|
+
cancel: () => void;
|
|
33
|
+
props?: any;
|
|
34
|
+
}
|
|
35
|
+
export declare const EditablePlugin: Plugin;
|
|
36
|
+
export declare const editors: {
|
|
37
|
+
text: Editor;
|
|
38
|
+
number: Editor;
|
|
39
|
+
range: Editor;
|
|
40
|
+
date: Editor;
|
|
41
|
+
time: Editor;
|
|
42
|
+
datetime: Editor;
|
|
43
|
+
color: Editor;
|
|
44
|
+
tel: Editor;
|
|
45
|
+
password: Editor;
|
|
46
|
+
file: Editor;
|
|
47
|
+
checkbox: Editor;
|
|
48
|
+
select: Editor;
|
|
49
|
+
};
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { chooseFile, resolveOptions } from "../utils.js";
|
|
2
|
+
import { Checkbox, Files } from "./RenderPlugin/components.js";
|
|
3
|
+
import { Ctx } from "../index.js";
|
|
4
|
+
import { createComponent, delegateEvents, effect, insert, memo, mergeProps, spread, template, use } from "solid-js/web";
|
|
5
|
+
import { createComputed, createEffect, createMemo, createRoot, createSignal, on, onCleanup, useContext } from "solid-js";
|
|
6
|
+
import { createMutable } from "solid-js/store";
|
|
7
|
+
import { delay } from "es-toolkit";
|
|
8
|
+
import { combineProps } from "@solid-primitives/props";
|
|
9
|
+
import { createAsyncMemo } from "@solid-primitives/memo";
|
|
10
|
+
var _tmpl$ = /* @__PURE__ */ template(`<input style=position:absolute;margin-top:1em;width:0;height:0;pointer-events:none;opacity:0>`), _tmpl$2 = /* @__PURE__ */ template(`<div class=in-cell-edit-wrapper>`), _tmpl$3 = /* @__PURE__ */ template(`<input>`), _tmpl$4 = /* @__PURE__ */ template(`<select>`), _tmpl$5 = /* @__PURE__ */ template(`<option>`), _tmpl$6 = /* @__PURE__ */ template(`<label class="h-full flex items-center">`);
|
|
11
|
+
const EditablePlugin = {
|
|
12
|
+
store: () => ({ editors: { ...editors } }),
|
|
13
|
+
rewriteProps: { Td: ({ Td }, { store }) => (o) => {
|
|
14
|
+
let el;
|
|
15
|
+
const { props } = useContext(Ctx);
|
|
16
|
+
const editable = createMemo(() => !!o.col.editable && !o.data[store.internal] && !o.col[store.internal]);
|
|
17
|
+
const [editing, setEditing] = createSignal(false);
|
|
18
|
+
let eventKey = "";
|
|
19
|
+
const selected = createMemo(() => (([x, y]) => o.x == x && o.y == y)(store.selected.start || []));
|
|
20
|
+
const preEdit = createMemo(() => selected() && editable() && !editing() && o.col.editOnInput);
|
|
21
|
+
const editorState = createAsyncMemo(async () => {
|
|
22
|
+
if (editing()) {
|
|
23
|
+
let canceled = false;
|
|
24
|
+
const editor = ((editor$1) => typeof editor$1 == "string" ? store.editors[editor$1] : editor$1)(o.col.editor || "text");
|
|
25
|
+
const opt = {
|
|
26
|
+
props: o.col.editorProps,
|
|
27
|
+
col: o.col,
|
|
28
|
+
eventKey,
|
|
29
|
+
data: o.data,
|
|
30
|
+
value: o.data[o.col.id],
|
|
31
|
+
ok: () => setEditing(false),
|
|
32
|
+
cancel: () => (canceled = true, setEditing(false))
|
|
33
|
+
};
|
|
34
|
+
const ret = editor(opt);
|
|
35
|
+
onCleanup(() => {
|
|
36
|
+
if (!canceled && ret.getValue() !== o.data[o.col.id]) {
|
|
37
|
+
const arr = [...props.data];
|
|
38
|
+
arr[o.y] = {
|
|
39
|
+
...arr[o.y],
|
|
40
|
+
[o.col.id]: ret.getValue()
|
|
41
|
+
};
|
|
42
|
+
props.onDataChange?.(arr);
|
|
43
|
+
}
|
|
44
|
+
ret.destroy();
|
|
45
|
+
});
|
|
46
|
+
return [opt, ret];
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
createEffect(() => {
|
|
50
|
+
editorState()?.[1]?.focus?.();
|
|
51
|
+
});
|
|
52
|
+
createEffect(() => {
|
|
53
|
+
if (editing()) {
|
|
54
|
+
const sss = createMemo(() => JSON.stringify(store.selected));
|
|
55
|
+
createEffect(on(sss, () => setEditing(false), { defer: true }));
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
let input;
|
|
59
|
+
const size = createMutable({
|
|
60
|
+
w: 0,
|
|
61
|
+
h: 0
|
|
62
|
+
});
|
|
63
|
+
createComputed(() => editing() && (size.w = el.getBoundingClientRect().width, size.h = el.getBoundingClientRect().height));
|
|
64
|
+
o = combineProps(o, {
|
|
65
|
+
ref: (v) => el = v,
|
|
66
|
+
get class() {
|
|
67
|
+
return editing() ? "is-editing" : "";
|
|
68
|
+
},
|
|
69
|
+
get style() {
|
|
70
|
+
return editing() ? `width: ${size.w}px; height: ${size.h}px; padding: 0; ` : "";
|
|
71
|
+
},
|
|
72
|
+
onClick: () => input?.focus?.(),
|
|
73
|
+
onDblClick: () => setEditing(editable()),
|
|
74
|
+
onKeyDown: (e) => e.key == "Escape" && editorState()?.[0].cancel()
|
|
75
|
+
});
|
|
76
|
+
return createComponent(Td, mergeProps(o, { get children() {
|
|
77
|
+
return [memo(() => memo(() => !!preEdit())() && (() => {
|
|
78
|
+
var _el$ = _tmpl$();
|
|
79
|
+
_el$.addEventListener("compositionend", () => {
|
|
80
|
+
setEditing(true);
|
|
81
|
+
});
|
|
82
|
+
_el$.$$input = (e) => {
|
|
83
|
+
eventKey = e.target.value;
|
|
84
|
+
setEditing(!e.isComposing);
|
|
85
|
+
};
|
|
86
|
+
_el$.$$keydown = (e) => {
|
|
87
|
+
e.key == " " && e.preventDefault();
|
|
88
|
+
};
|
|
89
|
+
use((e) => {
|
|
90
|
+
input = e;
|
|
91
|
+
delay(0).then(() => e.focus({ preventScroll: true }));
|
|
92
|
+
}, _el$);
|
|
93
|
+
return _el$;
|
|
94
|
+
})()), memo(() => memo(() => !!editorState()?.[1]?.el)() ? (() => {
|
|
95
|
+
var _el$2 = _tmpl$2();
|
|
96
|
+
insert(_el$2, () => editorState()?.[1]?.el);
|
|
97
|
+
return _el$2;
|
|
98
|
+
})() : o.children)];
|
|
99
|
+
} }));
|
|
100
|
+
} }
|
|
101
|
+
};
|
|
102
|
+
var createEditor = (Comp, extra, isSelector) => ({ eventKey, value, col, ok, cancel, props }) => createRoot((destroy) => {
|
|
103
|
+
const [v, setV] = createSignal(eventKey || value);
|
|
104
|
+
let el;
|
|
105
|
+
createComponent(Comp, mergeProps({
|
|
106
|
+
ref: (e) => el = e,
|
|
107
|
+
"class": "relative block px-2 size-full z-9 box-border resize-none outline-0",
|
|
108
|
+
get value() {
|
|
109
|
+
return v();
|
|
110
|
+
},
|
|
111
|
+
onInput: (e) => setV(e instanceof Event ? e.target.value : e),
|
|
112
|
+
onChange: (e) => (setV(e instanceof Event ? e.target.value : e), isSelector && ok()),
|
|
113
|
+
"on:pointerdown": (e) => e.stopPropagation(),
|
|
114
|
+
"on:keydown": (e) => {
|
|
115
|
+
e.stopPropagation();
|
|
116
|
+
e.key == "Enter" && ok();
|
|
117
|
+
e.key == "Escape" && cancel();
|
|
118
|
+
},
|
|
119
|
+
get options() {
|
|
120
|
+
return memo(() => !!col.enum)() ? resolveOptions(col.enum ?? []) : void 0;
|
|
121
|
+
}
|
|
122
|
+
}, extra, props));
|
|
123
|
+
return {
|
|
124
|
+
el,
|
|
125
|
+
getValue: v,
|
|
126
|
+
focus: () => el.focus(),
|
|
127
|
+
destroy
|
|
128
|
+
};
|
|
129
|
+
});
|
|
130
|
+
var Input = (o) => (() => {
|
|
131
|
+
var _el$3 = _tmpl$3();
|
|
132
|
+
spread(_el$3, o, false, false);
|
|
133
|
+
return _el$3;
|
|
134
|
+
})();
|
|
135
|
+
var text = createEditor(Input);
|
|
136
|
+
var number = createEditor(Input, { type: "number" });
|
|
137
|
+
var range$1 = createEditor(Input, { type: "range" });
|
|
138
|
+
var color = createEditor(Input, { type: "color" });
|
|
139
|
+
var tel = createEditor(Input, { type: "tel" });
|
|
140
|
+
var password = createEditor(Input, { type: "password" });
|
|
141
|
+
var date = createEditor(Input, { type: "date" }, true);
|
|
142
|
+
var time = createEditor(Input, { type: "time" }, true);
|
|
143
|
+
var datetime = createEditor(Input, { type: "datetime-local" }, true);
|
|
144
|
+
var select = createEditor((o) => (() => {
|
|
145
|
+
var _el$4 = _tmpl$4();
|
|
146
|
+
spread(_el$4, o, false, true);
|
|
147
|
+
insert(_el$4, () => o.options?.map((e) => (() => {
|
|
148
|
+
var _el$5 = _tmpl$5();
|
|
149
|
+
insert(_el$5, () => e.label);
|
|
150
|
+
effect(() => _el$5.value = e.value);
|
|
151
|
+
return _el$5;
|
|
152
|
+
})()));
|
|
153
|
+
return _el$4;
|
|
154
|
+
})(), {}, true);
|
|
155
|
+
var file = createEditor((o) => {
|
|
156
|
+
const onAdd = () => chooseFile({ multiple: true }).then((files) => o.onChange([...o.value || [], ...files.map((e) => ({
|
|
157
|
+
name: e.name,
|
|
158
|
+
size: e.size
|
|
159
|
+
}))]));
|
|
160
|
+
return createComponent(Files, mergeProps(o, {
|
|
161
|
+
"class": "relative z-9 outline-2 outline-blue min-h-a! h-a! p-1 bg-#fff",
|
|
162
|
+
onAdd
|
|
163
|
+
}));
|
|
164
|
+
});
|
|
165
|
+
var checkbox = createEditor((o) => (() => {
|
|
166
|
+
var _el$6 = _tmpl$6();
|
|
167
|
+
var _ref$ = o.ref;
|
|
168
|
+
typeof _ref$ === "function" ? use(_ref$, _el$6) : o.ref = _el$6;
|
|
169
|
+
insert(_el$6, createComponent(Checkbox, mergeProps(o, {
|
|
170
|
+
ref: () => {},
|
|
171
|
+
onInput: () => {},
|
|
172
|
+
"class": "mx-3!"
|
|
173
|
+
})));
|
|
174
|
+
return _el$6;
|
|
175
|
+
})());
|
|
176
|
+
const editors = {
|
|
177
|
+
text,
|
|
178
|
+
number,
|
|
179
|
+
range: range$1,
|
|
180
|
+
date,
|
|
181
|
+
time,
|
|
182
|
+
datetime,
|
|
183
|
+
color,
|
|
184
|
+
tel,
|
|
185
|
+
password,
|
|
186
|
+
file,
|
|
187
|
+
checkbox,
|
|
188
|
+
select
|
|
189
|
+
};
|
|
190
|
+
delegateEvents(["keydown", "input"]);
|
|
191
|
+
export { EditablePlugin, editors };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { JSX } from 'solid-js';
|
|
2
|
+
import { type Plugin } from '..';
|
|
3
|
+
declare module '../index' {
|
|
4
|
+
interface TableProps {
|
|
5
|
+
expand?: {
|
|
6
|
+
enable?: boolean;
|
|
7
|
+
render?: (props: {
|
|
8
|
+
data: any;
|
|
9
|
+
y: number;
|
|
10
|
+
}) => JSX.Element;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
interface TableStore {
|
|
14
|
+
expands: any[];
|
|
15
|
+
expandCol: TableColumn;
|
|
16
|
+
isExpand: (data: any) => boolean;
|
|
17
|
+
toggleExpand: (data: any) => void;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export declare const ExpandPlugin: Plugin;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { renderComponent, solidComponent } from "../components/utils.js";
|
|
2
|
+
import { Ctx } from "../index.js";
|
|
3
|
+
import chevron_right_default from "../chevron-right.js";
|
|
4
|
+
import { createComponent, effect, insert, memo, mergeProps, setAttribute, template } from "solid-js/web";
|
|
5
|
+
import { createMemo, useContext } from "solid-js";
|
|
6
|
+
import { unwrap } from "solid-js/store";
|
|
7
|
+
import { remove } from "es-toolkit";
|
|
8
|
+
var _tmpl$ = /* @__PURE__ */ template(`<td style=width:100%>`), _tmpl$2 = /* @__PURE__ */ template(`<div style=display:flex;align-items:center;width:100%;height:100%;opacity:.4>`);
|
|
9
|
+
const ExpandPlugin = {
|
|
10
|
+
store: (store) => ({
|
|
11
|
+
expands: [],
|
|
12
|
+
expandCol: {
|
|
13
|
+
id: Symbol("expand"),
|
|
14
|
+
fixed: "left",
|
|
15
|
+
width: 45,
|
|
16
|
+
render: solidComponent((o) => createComponent(ArrowCell, {
|
|
17
|
+
store,
|
|
18
|
+
get data() {
|
|
19
|
+
return o.data;
|
|
20
|
+
}
|
|
21
|
+
})),
|
|
22
|
+
props: (o) => ({ onClick: () => store.toggleExpand(o.data) }),
|
|
23
|
+
[store.internal]: 1
|
|
24
|
+
},
|
|
25
|
+
isExpand: (data) => !!store.expands.find((e) => unwrap(e) == unwrap(data)),
|
|
26
|
+
toggleExpand: (data) => store.isExpand(data) ? remove(store.expands, (e) => unwrap(e) == unwrap(data)) : store.expands.push(unwrap(data))
|
|
27
|
+
}),
|
|
28
|
+
rewriteProps: {
|
|
29
|
+
columns: ({ columns }, { store }) => [store.expandCol, ...columns],
|
|
30
|
+
Tr: ({ Tr }, { store }) => (o) => {
|
|
31
|
+
const { props } = useContext(Ctx);
|
|
32
|
+
if (!o.data?.[store.expandCol.id]) return createComponent(Tr, o);
|
|
33
|
+
return createComponent(Tr, mergeProps(o, { get children() {
|
|
34
|
+
var _el$ = _tmpl$();
|
|
35
|
+
insert(_el$, (() => {
|
|
36
|
+
var _c$ = memo(() => !!props.expand?.render);
|
|
37
|
+
return () => _c$() && renderComponent(props.expand.render, o, props.renderer);
|
|
38
|
+
})());
|
|
39
|
+
effect(() => setAttribute(_el$, "colspan", props.columns?.length));
|
|
40
|
+
return _el$;
|
|
41
|
+
} }));
|
|
42
|
+
},
|
|
43
|
+
data: ({ data }, { store }) => store.expands.length ? data?.flatMap((e) => store.isExpand(e) ? [e, { [store.expandCol.id]: 1 }] : e) : data
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
var ArrowCell = (_props) => {
|
|
47
|
+
const show = createMemo(() => _props.store.isExpand(_props.data));
|
|
48
|
+
return (() => {
|
|
49
|
+
var _el$2 = _tmpl$2();
|
|
50
|
+
insert(_el$2, createComponent(chevron_right_default, { get style() {
|
|
51
|
+
return `transform: rotate(${show() ? 90 : 0}deg);`;
|
|
52
|
+
} }));
|
|
53
|
+
return _el$2;
|
|
54
|
+
})();
|
|
55
|
+
};
|
|
56
|
+
export { ExpandPlugin };
|