intable 0.0.28 → 0.0.30
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 -21
- package/README.md +464 -379
- package/dist/__uno.css +1 -1
- package/dist/components/Popover.d.ts +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +84 -75
- package/dist/plugins/AggregatePlugin.d.ts +28 -0
- package/dist/plugins/AggregatePlugin.js +71 -0
- package/dist/plugins/AutoFillPlugin.d.ts +20 -0
- package/dist/plugins/AutoFillPlugin.js +132 -0
- package/dist/plugins/ColumnVisibilityPlugin.d.ts +16 -0
- package/dist/plugins/ColumnVisibilityPlugin.js +60 -0
- package/dist/plugins/EditablePlugin.js +58 -60
- package/dist/plugins/ImportExportPlugin.js +1 -1
- package/dist/plugins/MenuPlugin.d.ts +1 -1
- package/dist/plugins/MenuPlugin.js +74 -78
- package/dist/plugins/RenderPlugin/index.js +8 -8
- package/dist/plugins/RowSelectionPlugin.js +5 -5
- package/dist/plugins/SortPlugin.d.ts +36 -0
- package/dist/plugins/SortPlugin.js +93 -0
- package/dist/plugins/ValidatorPlugin.js +1 -0
- package/dist/style.css +2 -2
- package/dist/theme/antd.scss +41 -41
- package/dist/theme/dark.scss +46 -46
- package/dist/theme/element-plus.scss +38 -38
- package/dist/theme/github.scss +80 -80
- package/dist/theme/material.scss +73 -73
- package/dist/theme/shadcn.scss +66 -66
- package/dist/theme/stripe.scss +57 -57
- package/package.json +1 -1
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { usePointerDrag } from "../hooks/index.js";
|
|
2
|
+
import { delegateEvents, effect, style, template, use } from "solid-js/web";
|
|
3
|
+
import { createMemo, createSignal } from "solid-js";
|
|
4
|
+
import { createScrollPosition } from "@solid-primitives/scroll";
|
|
5
|
+
var _tmpl$ = /* @__PURE__ */ template("<div>"), _tmpl$2 = /* @__PURE__ */ template("<div title=\"Drag to fill\">");
|
|
6
|
+
function inferFill(e, t, n = 1) {
|
|
7
|
+
if (!e.length) return Array(t).fill(null);
|
|
8
|
+
let r = e.map((e) => typeof e == "number" ? e : Number(e));
|
|
9
|
+
if (r.every(isFinite)) {
|
|
10
|
+
let i = e.length > 1 ? r.at(-1) - r.at(-2) : 1, a = n === 1 ? r.at(-1) : r[0];
|
|
11
|
+
return Array.from({ length: t }, (e, r) => +(n === 1 ? a + i * (r + 1) : a - i * (t - r)).toFixed(10));
|
|
12
|
+
}
|
|
13
|
+
if (e.every((e) => typeof e == "string" && /^\d{4}-\d{2}-\d{2}/.test(e))) {
|
|
14
|
+
let r = e.map((e) => new Date(e).getTime());
|
|
15
|
+
if (r.every(isFinite)) {
|
|
16
|
+
let e = r.length > 1 ? r.at(-1) - r.at(-2) : 864e5, i = n === 1 ? r.at(-1) : r[0];
|
|
17
|
+
return Array.from({ length: t }, (r, a) => new Date(n === 1 ? i + e * (a + 1) : i - e * (t - a)).toISOString().slice(0, 10));
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return Array.from({ length: t }, (t, n) => e[n % e.length]);
|
|
21
|
+
}
|
|
22
|
+
function applyFill(e, t, n, r, i) {
|
|
23
|
+
let { internal: a } = i, { data: o, columns: s } = i.props, c = r > 0 ? 1 : -1, l = Math.abs(r), u = /* @__PURE__ */ new Map(), f = (e) => (u.has(e) || u.set(e, { ...o[e] }), u.get(e)), p, m;
|
|
24
|
+
if (n === "v") {
|
|
25
|
+
let n = o.slice(t[0], t[1] + 1);
|
|
26
|
+
for (let r = e[0]; r <= e[1] && r < s.length; r++) {
|
|
27
|
+
let e = s[r];
|
|
28
|
+
if (!e || e[a]) continue;
|
|
29
|
+
let i = inferFill(n.map((t) => t[e.id]), l, c);
|
|
30
|
+
for (let n = 0; n < l; n++) {
|
|
31
|
+
let r = c === 1 ? t[1] + 1 + n : t[0] - l + n;
|
|
32
|
+
r >= 0 && r < o.length && (f(r)[e.id] = i[n]);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
p = [e[0], c === 1 ? t[0] : Math.max(t[0] - l, 0)], m = [e[1], c === 1 ? Math.min(t[1] + l, o.length - 1) : t[1]];
|
|
36
|
+
} else {
|
|
37
|
+
for (let n = t[0]; n <= t[1] && n < o.length; n++) {
|
|
38
|
+
let t = s.slice(e[0], e[1] + 1).filter((e) => e && !e[a]).map((e) => o[n][e.id]), r = inferFill(t, l, c);
|
|
39
|
+
for (let t = 0; t < l; t++) {
|
|
40
|
+
let i = c === 1 ? e[1] + 1 + t : e[0] - l + t;
|
|
41
|
+
if (i < 0 || i >= s.length) continue;
|
|
42
|
+
let o = s[i];
|
|
43
|
+
o && !o[a] && (f(n)[o.id] = r[t]);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
p = [c === 1 ? e[0] : Math.max(e[0] - l, 0), t[0]], m = [c === 1 ? Math.min(e[1] + l, s.length - 1) : e[1], t[1]];
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
rowsMap: u,
|
|
50
|
+
newStart: p,
|
|
51
|
+
newEnd: m
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
const AutoFillPlugin = {
|
|
55
|
+
name: "auto-fill",
|
|
56
|
+
layers: [(t) => {
|
|
57
|
+
let i = createScrollPosition(() => t.scroll_el), d = createMemo(() => {
|
|
58
|
+
let { start: e, end: n } = t.selected ?? {};
|
|
59
|
+
if (!e?.length || !n?.length) return null;
|
|
60
|
+
let r = [e[0], n[0]].sort((e, t) => e - t), i = [e[1], n[1]].sort((e, t) => e - t);
|
|
61
|
+
return Number.isFinite(r[1]) && Number.isFinite(i[1]) ? {
|
|
62
|
+
xs: r,
|
|
63
|
+
ys: i
|
|
64
|
+
} : null;
|
|
65
|
+
}), p = createMemo(() => {
|
|
66
|
+
let e = t.thSizes ?? [], n = t.trSizes ?? [], r = e[0]?.height ?? 30, a = i.x, o = i.y, s = (t) => e.slice(0, t).reduce((e, t) => e + (t?.width ?? 0), 0) - a, c = (t) => s(t) + (e[t]?.width ?? 0), l = (e) => r + n.slice(0, e).reduce((e, t) => e + (t?.height ?? 28), 0) - o;
|
|
67
|
+
return {
|
|
68
|
+
colX: s,
|
|
69
|
+
colR: c,
|
|
70
|
+
rowY: l,
|
|
71
|
+
rowB: (e) => l(e) + (n[e]?.height ?? 28)
|
|
72
|
+
};
|
|
73
|
+
}), m = createMemo(() => {
|
|
74
|
+
let e = t.props.autoFill;
|
|
75
|
+
return e === !0 || e?.enable === !0;
|
|
76
|
+
}), h = createMemo(() => {
|
|
77
|
+
if (!m()) return "display:none;position:absolute";
|
|
78
|
+
let e = d();
|
|
79
|
+
if (!e) return "display:none;position:absolute";
|
|
80
|
+
let { colR: t, rowB: n } = p(), r = t(e.xs[1]), i = n(e.ys[1]);
|
|
81
|
+
return `position:absolute;left:${r - 4}px;top:${i - 4}px;width:8px;height:8px;background:var(--c-primary);border:2px solid var(--table-bg);border-radius:1px;box-shadow:0 0 0 1px var(--c-primary);z-index:3;cursor:crosshair`;
|
|
82
|
+
}), [g, _] = createSignal(null), v = createMemo(() => {
|
|
83
|
+
let e = g(), n = d();
|
|
84
|
+
if (!e || !n || !e.delta) return "display:none;position:absolute";
|
|
85
|
+
let { xs: r, ys: i } = n, { colX: a, colR: o, rowY: s, rowB: c } = p(), l = e.delta > 0 ? 1 : -1, u = Math.abs(e.delta), f = t.props.data.length, m = t.props.columns.length, h, _, v, y;
|
|
86
|
+
e.axis === "v" ? (h = a(r[0]), v = o(r[1]), [_, y] = l > 0 ? [c(i[1]), c(Math.min(i[1] + u, f - 1))] : [s(Math.max(i[0] - u, 0)), s(i[0])]) : (_ = s(i[0]), y = c(i[1]), [h, v] = l > 0 ? [o(r[1]), o(Math.min(r[1] + u, m - 1))] : [a(Math.max(r[0] - u, 0)), a(r[0])]);
|
|
87
|
+
let b = v - h, x = y - _;
|
|
88
|
+
return b <= 0 || x <= 0 ? "display:none;position:absolute" : `position:absolute;left:${h}px;top:${_}px;width:${b}px;height:${x}px;border:1.5px dashed var(--c-primary);background:rgba(99,102,241,0.08);pointer-events:none;z-index:3`;
|
|
89
|
+
}), y, b = (e, n, r, i) => {
|
|
90
|
+
let { rowsMap: a, newStart: o, newEnd: s } = applyFill(e, n, r, i, t);
|
|
91
|
+
a.size && (t.commands.rowsChange([...a.values()]), t.selected.start = o, t.selected.end = s);
|
|
92
|
+
}, x = (e) => {
|
|
93
|
+
e.stopPropagation();
|
|
94
|
+
let n = d();
|
|
95
|
+
if (!n) return;
|
|
96
|
+
let { xs: r, ys: i } = n, { data: a, columns: o } = t.props, s = r[0] > 0 ? r[0] - 1 : r[1] < o.length - 1 ? r[1] + 1 : -1, c = a.length - 1;
|
|
97
|
+
if (s >= 0) {
|
|
98
|
+
let e = o[s];
|
|
99
|
+
if (e && !e[t.internal]) for (let t = i[1] + 1; t < a.length; t++) {
|
|
100
|
+
let n = a[t][e.id];
|
|
101
|
+
if (n != null && n !== "") c = t;
|
|
102
|
+
else break;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
b(r, i, "v", c - i[1]);
|
|
106
|
+
};
|
|
107
|
+
return usePointerDrag(() => y, { start(e, n, r) {
|
|
108
|
+
e.stopPropagation(), e.preventDefault();
|
|
109
|
+
let i = d();
|
|
110
|
+
if (!i) return;
|
|
111
|
+
let { xs: a, ys: o } = i, s = 0, c = "v";
|
|
112
|
+
n((e, { ox: n, oy: r }) => {
|
|
113
|
+
Math.abs(r) >= Math.abs(n) ? (c = "v", s = Math.round(r / (t.trSizes?.[o[1]]?.height ?? 28))) : (c = "h", s = Math.round(n / (t.thSizes?.[a[1]]?.width ?? 100))), _(s ? {
|
|
114
|
+
axis: c,
|
|
115
|
+
delta: s
|
|
116
|
+
} : null);
|
|
117
|
+
}), r(() => {
|
|
118
|
+
_(null), b(a, o, c, s);
|
|
119
|
+
});
|
|
120
|
+
} }), [(() => {
|
|
121
|
+
var e = _tmpl$();
|
|
122
|
+
return effect((t) => style(e, v(), t)), e;
|
|
123
|
+
})(), (() => {
|
|
124
|
+
var e = _tmpl$2();
|
|
125
|
+
e.$$dblclick = x;
|
|
126
|
+
var t = y;
|
|
127
|
+
return typeof t == "function" ? use(t, e) : y = e, effect((t) => style(e, h() + ";pointer-events:auto", t)), e;
|
|
128
|
+
})()];
|
|
129
|
+
}]
|
|
130
|
+
};
|
|
131
|
+
delegateEvents(["dblclick"]);
|
|
132
|
+
export { AutoFillPlugin };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type Plugin } from '..';
|
|
2
|
+
declare module '../index' {
|
|
3
|
+
interface TableProps {
|
|
4
|
+
columnVisibility?: {
|
|
5
|
+
/** Column IDs (string or number) to hide on initial render. */
|
|
6
|
+
defaultHidden?: (string | number)[];
|
|
7
|
+
/** Called whenever the hidden column list changes. */
|
|
8
|
+
onChange?: (hiddenIds: string[]) => void;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
interface TableStore {
|
|
12
|
+
/** O(1) set of currently hidden column IDs (as strings). Mutate directly. */
|
|
13
|
+
hiddenCols: Record<string, true | undefined>;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export declare const ColumnVisibilityPlugin: Plugin;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Popover } from "../components/Popover.js";
|
|
2
|
+
import { createComponent, delegateEvents, effect, insert, template } from "solid-js/web";
|
|
3
|
+
import { For, Show } from "solid-js";
|
|
4
|
+
import { offset } from "@floating-ui/dom";
|
|
5
|
+
var _tmpl$ = /* @__PURE__ */ template("<div style=position:absolute;top:4px;right:4px;z-index:100;pointer-events:auto>"), _tmpl$2 = /* @__PURE__ */ template("<button class=\"flex items-center justify-center w-6.5 h-6.5 rd-1 shadow-sm b-(1 solid var(--table-b-c)) cursor-pointer bg-[--table-header-bg]\"title=\"Column Visibility\"><svg viewBox=\"0 0 24 24\"fill=none stroke=currentColor stroke-width=2 class=\"w-3.5 h-3.5\"><path stroke-linecap=round stroke-linejoin=round d=\"M4 6h16M4 12h16M4 18h7\">"), _tmpl$3 = /* @__PURE__ */ template("<div class=\"rd-1.5 shadow-xl py-1 min-w-44 bg-[--table-header-bg]\"style=\"border:1px solid var(--table-b-c);z-index:101\"><div class=\"flex items-center justify-between px-3 py-1.5\"style=\"border-bottom:1px solid var(--table-b-c)\"><span class=\"text-xs font-semibold uppercase tracking-wide\"style=color:var(--table-c)>Columns</span><button class=\"text-xs cursor-pointer hover:underline c-[--c-primary]\"></button></div><div class=\"max-h-60 of-y-auto\">"), _tmpl$4 = /* @__PURE__ */ template("<span class=text-xs style=opacity:0.6>hidden"), _tmpl$5 = /* @__PURE__ */ template("<label class=\"flex items-center gap-2 px-3 py-1.5 text-sm cursor-pointer select-none hover:bg-[--li-hover-bg]\"><input type=checkbox class=\"w-3.5 h-3.5 cursor-pointer\"><span class=\"truncate flex-1\">");
|
|
6
|
+
const ColumnVisibilityPlugin = {
|
|
7
|
+
name: "column-visibility",
|
|
8
|
+
store: (e) => {
|
|
9
|
+
let s = {};
|
|
10
|
+
return (e.rawProps.columnVisibility?.defaultHidden ?? []).forEach((e) => {
|
|
11
|
+
s[String(e)] = !0;
|
|
12
|
+
}), { hiddenCols: s };
|
|
13
|
+
},
|
|
14
|
+
rewriteProps: { columns: ({ columns: e }, { store: s }) => (e ?? []).filter((e) => !s.hiddenCols[String(e.id)]) },
|
|
15
|
+
layers: [(c) => {
|
|
16
|
+
let l = () => (c.rawProps.columns ?? []).filter((e) => !e[c.internal]), m = (e) => !!c.hiddenCols[e], h = () => c.rawProps.columnVisibility?.onChange?.(Object.keys(c.hiddenCols).filter((e) => !!c.hiddenCols[e])), g = (e) => {
|
|
17
|
+
m(e) ? delete c.hiddenCols[e] : c.hiddenCols[e] = !0, h();
|
|
18
|
+
}, _ = () => l().every((e) => m(String(e.id))), v = () => {
|
|
19
|
+
_() ? l().forEach((e) => delete c.hiddenCols[String(e.id)]) : l().forEach((e) => {
|
|
20
|
+
c.hiddenCols[String(e.id)] = !0;
|
|
21
|
+
}), h();
|
|
22
|
+
};
|
|
23
|
+
return (() => {
|
|
24
|
+
var c = _tmpl$();
|
|
25
|
+
return insert(c, createComponent(Popover, {
|
|
26
|
+
trigger: "click",
|
|
27
|
+
placement: "bottom-end",
|
|
28
|
+
get middleware() {
|
|
29
|
+
return [offset({ mainAxis: 4 })];
|
|
30
|
+
},
|
|
31
|
+
get reference() {
|
|
32
|
+
return _tmpl$2();
|
|
33
|
+
},
|
|
34
|
+
get floating() {
|
|
35
|
+
return (() => {
|
|
36
|
+
var e = _tmpl$3(), c = e.firstChild, d = c.firstChild, f = d.nextSibling, p = c.nextSibling;
|
|
37
|
+
return f.$$click = v, insert(f, () => _() ? "Show all" : "Hide all"), insert(p, createComponent(For, {
|
|
38
|
+
get each() {
|
|
39
|
+
return l();
|
|
40
|
+
},
|
|
41
|
+
children: (e) => (() => {
|
|
42
|
+
var c = _tmpl$5(), l = c.firstChild, u = l.nextSibling;
|
|
43
|
+
return l.addEventListener("change", () => g(e.id)), insert(u, () => e.name ?? e.id), insert(c, createComponent(Show, {
|
|
44
|
+
get when() {
|
|
45
|
+
return m(e.id);
|
|
46
|
+
},
|
|
47
|
+
get children() {
|
|
48
|
+
return _tmpl$4();
|
|
49
|
+
}
|
|
50
|
+
}), null), effect(() => l.checked = !m(e.id)), c;
|
|
51
|
+
})()
|
|
52
|
+
})), e;
|
|
53
|
+
})();
|
|
54
|
+
}
|
|
55
|
+
})), c;
|
|
56
|
+
})();
|
|
57
|
+
}]
|
|
58
|
+
};
|
|
59
|
+
delegateEvents(["click"]);
|
|
60
|
+
export { ColumnVisibilityPlugin };
|
|
@@ -12,36 +12,36 @@ const EditablePlugin = {
|
|
|
12
12
|
name: "editable",
|
|
13
13
|
store: () => ({ editors: { ...editors } }),
|
|
14
14
|
rewriteProps: {
|
|
15
|
-
editable: ({ editable: e }, { store:
|
|
16
|
-
let
|
|
17
|
-
return !!
|
|
15
|
+
editable: ({ editable: e }, { store: v }) => (b) => {
|
|
16
|
+
let x = [b.col.editable, e].filter((e) => e != null);
|
|
17
|
+
return !!x.length && x.every((e) => unFn(e, b)) && !b.data[v.internal] && !b.col[v.internal];
|
|
18
18
|
},
|
|
19
|
-
Td: ({ Td: e }, { store:
|
|
20
|
-
let
|
|
21
|
-
if (
|
|
22
|
-
let e = !1,
|
|
23
|
-
props:
|
|
24
|
-
col:
|
|
25
|
-
eventKey:
|
|
26
|
-
data:
|
|
27
|
-
value:
|
|
19
|
+
Td: ({ Td: e }, { store: v }) => (b) => {
|
|
20
|
+
let x, { props: w } = useContext(Ctx), [T, D] = createSignal(!1), O = "", j = () => unFn(w.editable, b), M = () => (([e, v]) => b.x == e && b.y == v)(v.selected.start || []), N = () => M() && j() && !T(), [P, F] = createSignal(!1), I = createAsyncMemo(() => {
|
|
21
|
+
if (T()) {
|
|
22
|
+
let e = !1, y = b.data[b.col.id], x = ((e) => typeof e == "string" ? v.editors[e] : e)(b.col.editor ?? b.col.type ?? "text"), S = {
|
|
23
|
+
props: b.col.editorProps,
|
|
24
|
+
col: b.col,
|
|
25
|
+
eventKey: O,
|
|
26
|
+
data: b.data,
|
|
27
|
+
value: y,
|
|
28
28
|
ok: async () => {
|
|
29
|
-
await L(
|
|
29
|
+
await L(C.getValue()), D(!1);
|
|
30
30
|
},
|
|
31
|
-
cancel: () => (e = !0,
|
|
32
|
-
onChange: (e) =>
|
|
33
|
-
},
|
|
31
|
+
cancel: () => (e = !0, D(!1)),
|
|
32
|
+
onChange: (e) => T() && L(e).catch(() => {})
|
|
33
|
+
}, C = x(S);
|
|
34
34
|
return onCleanup(() => {
|
|
35
|
-
!e &&
|
|
36
|
-
...
|
|
37
|
-
[
|
|
38
|
-
}), e || L(
|
|
39
|
-
}), [
|
|
35
|
+
!e && C.getValue() !== y && v.commands.rowChange({
|
|
36
|
+
...w.data[b.y],
|
|
37
|
+
[b.col.id]: C.getValue()
|
|
38
|
+
}), e || L(C.getValue()).catch(() => {}), O = "", C.destroy();
|
|
39
|
+
}), [S, C];
|
|
40
40
|
}
|
|
41
41
|
});
|
|
42
42
|
async function L(e) {
|
|
43
43
|
try {
|
|
44
|
-
F(!0), await
|
|
44
|
+
F(!0), await v.validateCell(e, b.data, b.col);
|
|
45
45
|
} finally {
|
|
46
46
|
F(!1);
|
|
47
47
|
}
|
|
@@ -49,39 +49,41 @@ const EditablePlugin = {
|
|
|
49
49
|
createEffect(() => {
|
|
50
50
|
I()?.[1]?.focus?.();
|
|
51
51
|
}), createEffect(() => {
|
|
52
|
-
if (
|
|
53
|
-
let e = createMemo(() => JSON.stringify(
|
|
54
|
-
createEffect(on(e, () =>
|
|
52
|
+
if (T()) {
|
|
53
|
+
let e = createMemo(() => JSON.stringify(v.selected ?? "{}"));
|
|
54
|
+
createEffect(on(e, () => D(!1), { defer: !0 }));
|
|
55
55
|
}
|
|
56
56
|
});
|
|
57
57
|
let R, z = createMutable({
|
|
58
58
|
w: 0,
|
|
59
59
|
h: 0
|
|
60
60
|
});
|
|
61
|
-
return createComputed(() =>
|
|
62
|
-
ref: (e) =>
|
|
61
|
+
return createComputed(() => T() && (z.w = x.getBoundingClientRect().width, z.h = x.getBoundingClientRect().height)), b = combineProps(b, {
|
|
62
|
+
ref: (e) => x = e,
|
|
63
63
|
get class() {
|
|
64
|
-
return
|
|
64
|
+
return T() ? "is-editing" : "";
|
|
65
65
|
},
|
|
66
66
|
get style() {
|
|
67
|
-
return
|
|
67
|
+
return T() ? `width: ${z.w}px; height: ${z.h}px; padding: 0; ` : "";
|
|
68
68
|
},
|
|
69
69
|
onClick: () => R?.focus?.(),
|
|
70
|
-
onDblClick: () =>
|
|
70
|
+
onDblClick: () => D(j()),
|
|
71
71
|
onKeyDown: (e) => e.key == "Escape" && I()?.[0].cancel()
|
|
72
|
-
}), createComponent(e, mergeProps(
|
|
72
|
+
}), createComponent(e, mergeProps(b, { get children() {
|
|
73
73
|
return [memo(() => memo(() => !!I()?.[1]?.el)() ? (() => {
|
|
74
74
|
var e = _tmpl$();
|
|
75
|
-
return addEventListener(e, "keydown", (e) =>
|
|
75
|
+
return addEventListener(e, "keydown", (e) => {
|
|
76
|
+
e.stopPropagation(), e.key == "Enter" && !e.shiftKey && I()?.[0].ok(), e.key == "Escape" && I()?.[0].cancel();
|
|
77
|
+
}), addEventListener(e, "pointerdown", (e) => e.stopPropagation()), insert(e, () => I()?.[1]?.el, null), insert(e, (() => {
|
|
76
78
|
var e = memo(() => !!P());
|
|
77
79
|
return () => e() && _tmpl$2();
|
|
78
80
|
})(), null), e;
|
|
79
|
-
})() :
|
|
81
|
+
})() : b.children), memo(() => memo(() => !!N())() && (() => {
|
|
80
82
|
var e = _tmpl$3();
|
|
81
83
|
return e.addEventListener("compositionend", () => {
|
|
82
|
-
|
|
84
|
+
D(!0);
|
|
83
85
|
}), e.$$input = (e) => {
|
|
84
|
-
|
|
86
|
+
O = e.target.value, D(!e.isComposing);
|
|
85
87
|
}, e.$$keydown = (e) => {
|
|
86
88
|
e.key == " " && e.preventDefault();
|
|
87
89
|
}, use((e) => {
|
|
@@ -92,38 +94,34 @@ const EditablePlugin = {
|
|
|
92
94
|
}
|
|
93
95
|
}
|
|
94
96
|
};
|
|
95
|
-
var createEditor = (e,
|
|
96
|
-
let [O, k] = createSignal(
|
|
97
|
+
var createEditor = (e, y, b) => ({ eventKey: x, value: S, col: C, ok: w, cancel: T, props: E, onChange: D }) => createRoot((T) => {
|
|
98
|
+
let [O, k] = createSignal(x || S), A;
|
|
97
99
|
return createComponent(e, mergeProps({
|
|
98
100
|
ref: (e) => A = e,
|
|
99
101
|
class: "relative block px-2 size-full z-9 box-border resize-none outline-0",
|
|
100
102
|
get value() {
|
|
101
103
|
return O();
|
|
102
104
|
},
|
|
103
|
-
onInput: (e) => (k(e instanceof Event ? e.target.value : e),
|
|
104
|
-
onChange: (e) => (k(e instanceof Event ? e.target.value : e),
|
|
105
|
-
"on:pointerdown": (e) => e.stopPropagation(),
|
|
106
|
-
"on:keydown": (e) => {
|
|
107
|
-
e.stopPropagation(), e.key == "Enter" && !e.shiftKey && C(), e.key == "Escape" && w();
|
|
108
|
-
},
|
|
105
|
+
onInput: (e) => (k(e instanceof Event ? e.target.value : e), D?.(O())),
|
|
106
|
+
onChange: (e) => (k(e instanceof Event ? e.target.value : e), D?.(O()), b && w()),
|
|
109
107
|
get options() {
|
|
110
|
-
return memo(() => !!
|
|
108
|
+
return memo(() => !!C.enum)() ? resolveOptions(C.enum ?? []) : void 0;
|
|
111
109
|
}
|
|
112
|
-
},
|
|
110
|
+
}, y, E)), {
|
|
113
111
|
el: A,
|
|
114
112
|
getValue: O,
|
|
115
113
|
focus: () => A.focus(),
|
|
116
|
-
destroy:
|
|
114
|
+
destroy: T
|
|
117
115
|
};
|
|
118
116
|
}), Input = (e) => (() => {
|
|
119
|
-
var
|
|
120
|
-
return spread(
|
|
117
|
+
var v = _tmpl$4();
|
|
118
|
+
return spread(v, e, !1, !1), v;
|
|
121
119
|
})();
|
|
122
120
|
const editors = {
|
|
123
121
|
text: createEditor(Input),
|
|
124
122
|
textarea: createEditor((e) => (() => {
|
|
125
|
-
var
|
|
126
|
-
return spread(
|
|
123
|
+
var v = _tmpl$5();
|
|
124
|
+
return spread(v, e, !1, !1), v;
|
|
127
125
|
})()),
|
|
128
126
|
number: createEditor(Input, { type: "number" }),
|
|
129
127
|
range: createEditor(Input, { type: "range" }),
|
|
@@ -133,27 +131,27 @@ const editors = {
|
|
|
133
131
|
color: createEditor(Input, { type: "color" }),
|
|
134
132
|
tel: createEditor(Input, { type: "tel" }),
|
|
135
133
|
password: createEditor(Input, { type: "password" }),
|
|
136
|
-
file: createEditor((
|
|
134
|
+
file: createEditor((v) => createComponent(Files, mergeProps(v, {
|
|
137
135
|
class: "relative z-9 outline-2 outline-blue min-h-a! h-a! p-1 bg-#fff",
|
|
138
|
-
onAdd: () => chooseFile({ multiple: !0 }).then((e) =>
|
|
136
|
+
onAdd: () => chooseFile({ multiple: !0 }).then((e) => v.onChange([...v.value || [], ...e.map((e) => ({
|
|
139
137
|
name: e.name,
|
|
140
138
|
size: e.size
|
|
141
139
|
}))]))
|
|
142
140
|
}))),
|
|
143
141
|
checkbox: createEditor((e) => (() => {
|
|
144
|
-
var
|
|
145
|
-
return typeof
|
|
142
|
+
var v = _tmpl$6(), y = e.ref;
|
|
143
|
+
return typeof y == "function" ? use(y, v) : e.ref = v, insert(v, createComponent(Checkbox, mergeProps(e, {
|
|
146
144
|
ref: () => {},
|
|
147
145
|
onInput: () => {},
|
|
148
146
|
class: "mx-3!"
|
|
149
|
-
}))),
|
|
147
|
+
}))), v;
|
|
150
148
|
})()),
|
|
151
149
|
select: createEditor((e) => (() => {
|
|
152
|
-
var
|
|
153
|
-
return spread(
|
|
154
|
-
var
|
|
155
|
-
return insert(
|
|
156
|
-
})())),
|
|
150
|
+
var v = _tmpl$7();
|
|
151
|
+
return spread(v, e, !1, !0), insert(v, () => e.options?.map((e) => (() => {
|
|
152
|
+
var v = _tmpl$8();
|
|
153
|
+
return insert(v, () => e.label), effect(() => v.value = e.value), v;
|
|
154
|
+
})())), v;
|
|
157
155
|
})(), {}, !0)
|
|
158
156
|
};
|
|
159
157
|
delegateEvents(["keydown", "input"]);
|
|
@@ -27,7 +27,7 @@ const ImportExportPlugin = {
|
|
|
27
27
|
},
|
|
28
28
|
readExcel: async (n) => {
|
|
29
29
|
n ??= await chooseFile({ accept: ".xlsx,.xls,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel" });
|
|
30
|
-
let i = await readFileAsArrayBuffer(n), a = await import("xlsx"), o = a.read(i, { type: "array" }), s = o.Sheets[o.SheetNames[0]], c = a.utils.sheet_to_json(s
|
|
30
|
+
let i = await readFileAsArrayBuffer(n), a = await import("xlsx"), o = a.read(i, { type: "array" }), s = o.Sheets[o.SheetNames[0]], c = a.utils.sheet_to_json(s);
|
|
31
31
|
if (c.length < 1) return;
|
|
32
32
|
let l = r.props.columns.filter((e) => !e[r.internal]);
|
|
33
33
|
return c.slice(1).map((e) => Object.fromEntries(l.map((t) => [t.id, e[t.name]])));
|
|
@@ -10,7 +10,7 @@ declare module '../index' {
|
|
|
10
10
|
interface Commands {
|
|
11
11
|
rowEquals: (a: any, b: any) => boolean;
|
|
12
12
|
rowIndexOf: (data: any[], row: any) => number;
|
|
13
|
-
rowChange: (row: any
|
|
13
|
+
rowChange: (row: any) => void;
|
|
14
14
|
rowsChange: (rows: any) => void;
|
|
15
15
|
addRows: (i: number, rows: any[], before?: boolean) => void;
|
|
16
16
|
deleteRows: (i: number[]) => void;
|
|
@@ -2,9 +2,8 @@ import { useMemoAsync } from "../hooks/index.js";
|
|
|
2
2
|
import { findParent } from "../tree.js";
|
|
3
3
|
import "../utils.js";
|
|
4
4
|
import { Menu } from "../components/Menu.js";
|
|
5
|
-
import { createComponent, memo
|
|
5
|
+
import { createComponent, memo } from "solid-js/web";
|
|
6
6
|
import { batch, createMemo, createSignal, mapArray } from "solid-js";
|
|
7
|
-
import { combineProps } from "@solid-primitives/props";
|
|
8
7
|
import { delay, range, remove } from "es-toolkit";
|
|
9
8
|
import { createEventListener } from "@solid-primitives/event-listener";
|
|
10
9
|
import { autoPlacement, computePosition } from "@floating-ui/dom";
|
|
@@ -12,50 +11,47 @@ const MenuPlugin = {
|
|
|
12
11
|
name: "menu",
|
|
13
12
|
priority: Infinity,
|
|
14
13
|
store: (e) => ({}),
|
|
15
|
-
|
|
16
|
-
let [
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
layers: [(t) => {
|
|
15
|
+
let [a, l] = createSignal(), u = mapArray(() => t.plugins || [], (e) => createMemo(() => e.menus?.(t))), d = createMemo(() => u().flatMap((e) => e() || [])), [h, g] = createSignal();
|
|
16
|
+
createEventListener(() => t.table, "contextmenu", _);
|
|
17
|
+
function _(e) {
|
|
18
|
+
e.preventDefault(), t.table.contains(e.target) && g({
|
|
19
19
|
x: e.x,
|
|
20
20
|
y: e.y
|
|
21
21
|
});
|
|
22
22
|
}
|
|
23
23
|
createEventListener(document, "pointerdown", (e) => {
|
|
24
|
-
|
|
24
|
+
a()?.contains(e.target) || g();
|
|
25
25
|
});
|
|
26
|
-
let
|
|
27
|
-
let e =
|
|
28
|
-
if (e) return computePosition({ getBoundingClientRect: () => DOMRect.fromRect(
|
|
26
|
+
let v = useMemoAsync(() => {
|
|
27
|
+
let e = a();
|
|
28
|
+
if (e) return computePosition({ getBoundingClientRect: () => DOMRect.fromRect(h()) }, e, {
|
|
29
29
|
strategy: "fixed",
|
|
30
30
|
placement: "top-start",
|
|
31
31
|
middleware: [autoPlacement({
|
|
32
32
|
boundary: document.body,
|
|
33
33
|
alignment: "start"
|
|
34
34
|
})]
|
|
35
|
-
}).then(({ x: e, y:
|
|
35
|
+
}).then(({ x: e, y: t }) => ({
|
|
36
36
|
position: "fixed",
|
|
37
|
-
transform: `translate(${e}px, ${
|
|
37
|
+
transform: `translate(${e}px, ${t}px)`,
|
|
38
38
|
top: 0,
|
|
39
39
|
left: 0,
|
|
40
40
|
"z-index": 10
|
|
41
41
|
}));
|
|
42
42
|
});
|
|
43
|
-
return
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
onAction: () => b()
|
|
56
|
-
})), memo(() => p.children)];
|
|
57
|
-
} }));
|
|
58
|
-
} },
|
|
43
|
+
return memo(() => memo(() => !!h())() && createComponent(Menu, {
|
|
44
|
+
ref: l,
|
|
45
|
+
class: "pointer-events-auto",
|
|
46
|
+
get style() {
|
|
47
|
+
return v() || "position: fixed";
|
|
48
|
+
},
|
|
49
|
+
get items() {
|
|
50
|
+
return d();
|
|
51
|
+
},
|
|
52
|
+
onAction: () => g()
|
|
53
|
+
}));
|
|
54
|
+
}],
|
|
59
55
|
menus: (e) => [
|
|
60
56
|
{
|
|
61
57
|
label: "新增行 ↑",
|
|
@@ -67,74 +63,74 @@ const MenuPlugin = {
|
|
|
67
63
|
},
|
|
68
64
|
{
|
|
69
65
|
label: "删除行",
|
|
70
|
-
cb: () => e.commands.deleteRows(range(...((e) => [e[0], e[1] + 1])([e.selected.start[1], e.selected.end[1]].sort((e,
|
|
66
|
+
cb: () => e.commands.deleteRows(range(...((e) => [e[0], e[1] + 1])([e.selected.start[1], e.selected.end[1]].sort((e, t) => e - t))))
|
|
71
67
|
}
|
|
72
68
|
],
|
|
73
69
|
commands: (e) => ({
|
|
74
|
-
rowEquals(
|
|
75
|
-
let
|
|
76
|
-
return
|
|
70
|
+
rowEquals(t, n) {
|
|
71
|
+
let r = e.props.rowKey;
|
|
72
|
+
return t == n || r != null && t?.[r] == n?.[r];
|
|
77
73
|
},
|
|
78
|
-
rowIndexOf(
|
|
79
|
-
return
|
|
74
|
+
rowIndexOf(t, n) {
|
|
75
|
+
return t.findIndex((t) => e.commands.rowEquals(t, n));
|
|
80
76
|
},
|
|
81
|
-
rowChange(
|
|
82
|
-
let
|
|
83
|
-
|
|
77
|
+
rowChange(t) {
|
|
78
|
+
let n = [...e.rawProps.data || []], r = e.commands.rowIndexOf(n, t);
|
|
79
|
+
r > -1 && (n[r] = t, e.props.onDataChange?.(n));
|
|
84
80
|
},
|
|
85
|
-
rowsChange(
|
|
86
|
-
let
|
|
87
|
-
|
|
88
|
-
let
|
|
89
|
-
|
|
90
|
-
}), e.props.onDataChange?.(
|
|
81
|
+
rowsChange(t) {
|
|
82
|
+
let n = [...e.rawProps.data || []];
|
|
83
|
+
t.forEach((t) => {
|
|
84
|
+
let r = e.commands.rowIndexOf(n, t);
|
|
85
|
+
r > -1 && (n[r] = t);
|
|
86
|
+
}), e.props.onDataChange?.(n);
|
|
91
87
|
},
|
|
92
|
-
addRows(
|
|
93
|
-
addRows(e,
|
|
88
|
+
addRows(t, n, r = !0) {
|
|
89
|
+
addRows(e, t, n, r);
|
|
94
90
|
},
|
|
95
|
-
deleteRows(
|
|
96
|
-
let { rowKey:
|
|
97
|
-
remove(
|
|
91
|
+
deleteRows(t) {
|
|
92
|
+
let { rowKey: n, data: r } = e.props, i = [...e.rawProps.data || []], a = new Set(t.map((e) => r[e]));
|
|
93
|
+
remove(i, (e) => a.has(e)), e.props?.onDataChange?.(i);
|
|
98
94
|
},
|
|
99
|
-
moveRows(
|
|
100
|
-
let { data:
|
|
101
|
-
if (!
|
|
102
|
-
let
|
|
103
|
-
function
|
|
104
|
-
return e.reduce((e,
|
|
105
|
-
if (
|
|
106
|
-
if (Array.isArray(
|
|
107
|
-
let e =
|
|
108
|
-
|
|
109
|
-
...
|
|
110
|
-
[
|
|
95
|
+
moveRows(n, r) {
|
|
96
|
+
let { data: i } = e.props, a = n.map((e) => i[e]).filter((t) => t && !t?.[e.internal]);
|
|
97
|
+
if (!a.length) return;
|
|
98
|
+
let o = r >= 0 && r < i.length ? i[r] : null, { rowKey: s } = e.props, c = e.props.tree?.children || Symbol(), l = new Set(a.map((e) => e[s])), u = [];
|
|
99
|
+
function d(e) {
|
|
100
|
+
return e.reduce((e, t) => {
|
|
101
|
+
if (l.has(t[s])) return u.push(t), e;
|
|
102
|
+
if (Array.isArray(t[c]) && t[c].length) {
|
|
103
|
+
let e = d(t[c]);
|
|
104
|
+
t = e.length === t[c].length ? t : {
|
|
105
|
+
...t,
|
|
106
|
+
[c]: e
|
|
111
107
|
};
|
|
112
108
|
}
|
|
113
|
-
return e.push(
|
|
109
|
+
return e.push(t), e;
|
|
114
110
|
}, []);
|
|
115
111
|
}
|
|
116
|
-
let
|
|
117
|
-
if (
|
|
118
|
-
let
|
|
119
|
-
e.selected.start = [0,
|
|
112
|
+
let f = d([...e.rawProps.data || []]), p = findParent(f, (e) => e[s] === o?.[s])?.children ?? f, m = o ? p.findIndex((e) => e[s] === o[s]) : -1;
|
|
113
|
+
if (m > -1 ? p.splice(m, 0, u) : p.push(...u), e.selected) {
|
|
114
|
+
let t = Math.max(0, r - a.length);
|
|
115
|
+
e.selected.start = [0, t], e.selected.end = [Infinity, t + u.length - 1];
|
|
120
116
|
}
|
|
121
|
-
e.props?.onDataChange?.(
|
|
117
|
+
e.props?.onDataChange?.(f);
|
|
122
118
|
}
|
|
123
119
|
})
|
|
124
120
|
};
|
|
125
|
-
function addRows(e,
|
|
126
|
-
let { data:
|
|
127
|
-
for (
|
|
128
|
-
return
|
|
129
|
-
},
|
|
130
|
-
for (
|
|
131
|
-
return
|
|
132
|
-
},
|
|
133
|
-
|
|
134
|
-
|
|
121
|
+
function addRows(e, t, n, r) {
|
|
122
|
+
let { data: i } = e.props, o = (t) => {
|
|
123
|
+
for (r = !1; --t >= 0 && i[t]?.[e.internal];);
|
|
124
|
+
return t >= 0 ? i[t] : null;
|
|
125
|
+
}, s = (t) => {
|
|
126
|
+
for (r = !0; ++t < i.length && i[t]?.[e.internal];);
|
|
127
|
+
return t < i.length ? i[t] : null;
|
|
128
|
+
}, c = i[t]?.[e.internal] ? r ? o(t) || s(t) : s(t) || o(t) : i[t];
|
|
129
|
+
c && batch(() => {
|
|
130
|
+
t = e.commands.rowIndexOf(i, c), e.selected && (e.selected.start = [0, t + (r ? 0 : 1)], e.selected.end = [Infinity, t + n.length - 1 + (r ? 0 : 1)]);
|
|
135
131
|
}), (() => {
|
|
136
|
-
let
|
|
137
|
-
|
|
132
|
+
let t = [...e.rawProps.data || []], i = c ? e.commands.rowIndexOf(t, c) + (r ? 0 : 1) : t.length;
|
|
133
|
+
t.splice(i, 0, ...n), e.props?.onDataChange?.(t);
|
|
138
134
|
})(), delay(0).then(() => {
|
|
139
135
|
e.scrollCellIfNeeded(e.selected.start[0], e.selected.start[1]);
|
|
140
136
|
});
|