intable 0.0.29 → 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/README.md +87 -2
- 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/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/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 };
|
|
@@ -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
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { renderComponent, solidComponent } from "../../components/utils.js";
|
|
1
2
|
import { resolveOptions, toArr } from "../../utils.js";
|
|
2
3
|
import { Checkbox, Files } from "./components.js";
|
|
3
|
-
import { renderComponent, solidComponent } from "../../components/utils.js";
|
|
4
4
|
import { createComponent, insert, memo, mergeProps, template } from "solid-js/web";
|
|
5
5
|
import { mergeProps as mergeProps$1 } from "solid-js";
|
|
6
6
|
var _tmpl$ = /* @__PURE__ */ template("<div class=\"flex items-center h-full\">");
|
|
@@ -8,24 +8,24 @@ const RenderPlugin = {
|
|
|
8
8
|
name: "render",
|
|
9
9
|
priority: -Infinity,
|
|
10
10
|
store: () => ({ renders: { ...renders } }),
|
|
11
|
-
rewriteProps: { Td: ({ Td:
|
|
11
|
+
rewriteProps: { Td: ({ Td: p }, { store: m }) => (h) => createComponent(p, mergeProps(h, { get children() {
|
|
12
12
|
return (() => {
|
|
13
|
-
let
|
|
14
|
-
return renderComponent(
|
|
13
|
+
let p = ((e) => typeof e == "string" ? m.renders[e] : e)(h.col.render ?? h.col.type) || text;
|
|
14
|
+
return renderComponent(p, mergeProps$1(h, { onChange: (e) => m.commands.rowChange({
|
|
15
15
|
...h.data,
|
|
16
16
|
[h.col.id]: e
|
|
17
17
|
}) }), m);
|
|
18
18
|
})();
|
|
19
19
|
} })) }
|
|
20
20
|
};
|
|
21
|
-
var text = (
|
|
21
|
+
var text = (e) => memo(() => memo(() => !!e.col.enum)() ? toArr(e.value).map((p) => resolveOptions(e.col.enum).find((e) => e.value == p)?.label ?? p).join(", ") : e.value);
|
|
22
22
|
const renders = {
|
|
23
23
|
text,
|
|
24
24
|
number: text,
|
|
25
25
|
date: text,
|
|
26
26
|
checkbox: (e) => (() => {
|
|
27
|
-
var
|
|
28
|
-
return insert(
|
|
27
|
+
var p = _tmpl$();
|
|
28
|
+
return insert(p, createComponent(Checkbox, {
|
|
29
29
|
class: "",
|
|
30
30
|
get value() {
|
|
31
31
|
return e.value;
|
|
@@ -33,7 +33,7 @@ const renders = {
|
|
|
33
33
|
get onChange() {
|
|
34
34
|
return e.onChange;
|
|
35
35
|
}
|
|
36
|
-
})),
|
|
36
|
+
})), p;
|
|
37
37
|
})(),
|
|
38
38
|
file: (e) => createComponent(Files, {
|
|
39
39
|
get value() {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Checkbox } from "./RenderPlugin/components.js";
|
|
2
1
|
import { solidComponent } from "../components/utils.js";
|
|
2
|
+
import { Checkbox } from "./RenderPlugin/components.js";
|
|
3
3
|
import { useSelector } from "../hooks/useSelector.js";
|
|
4
4
|
import { createComponent, insert, template } from "solid-js/web";
|
|
5
5
|
import { mergeProps as mergeProps$1 } from "solid-js";
|
|
@@ -15,16 +15,16 @@ const RowSelectionPlugin = {
|
|
|
15
15
|
class: "row-selection",
|
|
16
16
|
width: 45,
|
|
17
17
|
resizable: !1,
|
|
18
|
-
render: solidComponent((
|
|
18
|
+
render: solidComponent((e) => (() => {
|
|
19
19
|
var l = _tmpl$();
|
|
20
20
|
return insert(l, createComponent(Checkbox, {
|
|
21
21
|
style: "position: absolute",
|
|
22
22
|
get value() {
|
|
23
|
-
return c.commands.rowSelector.has(
|
|
23
|
+
return c.commands.rowSelector.has(e.data);
|
|
24
24
|
},
|
|
25
|
-
onChange: (
|
|
25
|
+
onChange: (s) => s ? c.commands.rowSelector.add(e.data) : c.commands.rowSelector.del(e.data),
|
|
26
26
|
get disabled() {
|
|
27
|
-
return !c.props?.rowSelection?.selectable?.(
|
|
27
|
+
return !c.props?.rowSelection?.selectable?.(e.data);
|
|
28
28
|
}
|
|
29
29
|
})), l;
|
|
30
30
|
})())
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type Plugin } from '..';
|
|
2
|
+
export type SortOrder = 'asc' | 'desc';
|
|
3
|
+
export interface SortKey {
|
|
4
|
+
field: string;
|
|
5
|
+
order: SortOrder;
|
|
6
|
+
}
|
|
7
|
+
declare module '../index' {
|
|
8
|
+
interface TableProps {
|
|
9
|
+
sort?: {
|
|
10
|
+
/**
|
|
11
|
+
* Allow sorting by multiple columns simultaneously.
|
|
12
|
+
* @default false
|
|
13
|
+
*/
|
|
14
|
+
multiple?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Set to false to disable client-side sorting (e.g. server-side sorting).
|
|
17
|
+
* `onChange` is still called so you can refresh data yourself.
|
|
18
|
+
* @default true
|
|
19
|
+
*/
|
|
20
|
+
autoSort?: boolean;
|
|
21
|
+
/** Called whenever sort keys change. */
|
|
22
|
+
onChange?: (sorts: SortKey[]) => void;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
interface TableColumn {
|
|
26
|
+
/** Enable sort toggle on this column header. */
|
|
27
|
+
sortable?: boolean;
|
|
28
|
+
/** Custom comparator for this column. Return negative / 0 / positive. */
|
|
29
|
+
sortComparator?: (a: any, b: any) => number;
|
|
30
|
+
}
|
|
31
|
+
interface TableStore {
|
|
32
|
+
/** Current sort state. Read to render indicators; mutate to programmatically set sort. */
|
|
33
|
+
sortKeys: SortKey[];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export declare const SortPlugin: Plugin;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { createComponent, insert, mergeProps, template } from "solid-js/web";
|
|
2
|
+
import { Show } from "solid-js";
|
|
3
|
+
import { combineProps } from "@solid-primitives/props";
|
|
4
|
+
var _tmpl$ = /* @__PURE__ */ template("<svg viewBox=\"0 0 24 24\"fill=none stroke=currentColor stroke-width=2 class=\"w-3.5 h-3.5 opacity-50 shrink-0 flex-none\"><path stroke-linecap=round stroke-linejoin=round d=\"M8 9l4-4 4 4M16 15l-4 4-4-4\">"), _tmpl$2 = /* @__PURE__ */ template("<svg viewBox=\"0 0 24 24\"fill=none stroke=currentColor stroke-width=2.5 class=\"w-3.5 h-3.5 shrink-0 flex-none\"style=color:var(--c-primary,#6366f1)><path stroke-linecap=round stroke-linejoin=round d=\"M5 15l7-7 7 7\">"), _tmpl$3 = /* @__PURE__ */ template("<svg viewBox=\"0 0 24 24\"fill=none stroke=currentColor stroke-width=2.5 class=\"w-3.5 h-3.5 shrink-0 flex-none\"style=color:var(--c-primary,#6366f1)><path stroke-linecap=round stroke-linejoin=round d=\"M19 9l-7 7-7-7\">"), _tmpl$4 = /* @__PURE__ */ template("<div class=\"flex items-center w-full\">");
|
|
5
|
+
function compareValues(e, o) {
|
|
6
|
+
if (e == null && o == null) return 0;
|
|
7
|
+
if (e == null) return -1;
|
|
8
|
+
if (o == null) return 1;
|
|
9
|
+
let s = Number(e), c = Number(o);
|
|
10
|
+
if (!Number.isNaN(s) && !Number.isNaN(c)) return s - c;
|
|
11
|
+
if (typeof e == "string" && typeof o == "string") {
|
|
12
|
+
let s = Date.parse(e), c = Date.parse(o);
|
|
13
|
+
if (!Number.isNaN(s) && !Number.isNaN(c) && s !== c) return s - c;
|
|
14
|
+
}
|
|
15
|
+
return typeof e == "boolean" && typeof o == "boolean" ? Number(e) - Number(o) : String(e).localeCompare(String(o), void 0, {
|
|
16
|
+
numeric: !0,
|
|
17
|
+
sensitivity: "base"
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
function applySort(e, o, s) {
|
|
21
|
+
return o.length ? [...e].sort((e, c) => {
|
|
22
|
+
for (let { field: l, order: u } of o) {
|
|
23
|
+
let o = s[l], d = o?.sortComparator ? o.sortComparator(e[l], c[l]) : compareValues(e[l], c[l]);
|
|
24
|
+
if (d !== 0) return u === "asc" ? d : -d;
|
|
25
|
+
}
|
|
26
|
+
return 0;
|
|
27
|
+
}) : e;
|
|
28
|
+
}
|
|
29
|
+
var IconUnsorted = () => _tmpl$(), IconAsc = () => _tmpl$2(), IconDesc = () => _tmpl$3();
|
|
30
|
+
const SortPlugin = {
|
|
31
|
+
name: "sort",
|
|
32
|
+
priority: -1,
|
|
33
|
+
store: () => ({ sortKeys: [] }),
|
|
34
|
+
rewriteProps: {
|
|
35
|
+
sort: ({ sort: e }) => ({
|
|
36
|
+
multiple: !1,
|
|
37
|
+
autoSort: !0,
|
|
38
|
+
...e
|
|
39
|
+
}),
|
|
40
|
+
data: ({ data: e }, { store: o }) => {
|
|
41
|
+
if (!o.sortKeys.length || !o.props.sort?.autoSort) return e;
|
|
42
|
+
let s = Object.fromEntries(o.props.columns.map((e) => [e.id, e]));
|
|
43
|
+
return applySort(e, o.sortKeys, s);
|
|
44
|
+
},
|
|
45
|
+
Th: ({ Th: c }, { store: d }) => (f) => {
|
|
46
|
+
let p = () => !!f.col.sortable && !f.col[d.internal], m = () => p() ? d.sortKeys.find((e) => e.field === f.col.id) : void 0, h = combineProps(f, {
|
|
47
|
+
get class() {
|
|
48
|
+
return p() ? "cursor-pointer select-none" : "";
|
|
49
|
+
},
|
|
50
|
+
onClick: () => {
|
|
51
|
+
if (!p()) return;
|
|
52
|
+
let e = f.col.id, o = m(), s = o ? o.order === "asc" ? "desc" : null : "asc";
|
|
53
|
+
if (d.props.sort?.multiple) if (s === null) d.sortKeys = d.sortKeys.filter((o) => o.field !== e);
|
|
54
|
+
else if (o) {
|
|
55
|
+
let o = d.sortKeys.findIndex((o) => o.field === e);
|
|
56
|
+
d.sortKeys[o] = {
|
|
57
|
+
field: e,
|
|
58
|
+
order: s
|
|
59
|
+
};
|
|
60
|
+
} else d.sortKeys = [...d.sortKeys, {
|
|
61
|
+
field: e,
|
|
62
|
+
order: "asc"
|
|
63
|
+
}];
|
|
64
|
+
else d.sortKeys = s ? [{
|
|
65
|
+
field: e,
|
|
66
|
+
order: s
|
|
67
|
+
}] : [];
|
|
68
|
+
d.props.sort?.onChange?.([...d.sortKeys]);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
return createComponent(c, mergeProps(h, { get children() {
|
|
72
|
+
var s = _tmpl$4();
|
|
73
|
+
return insert(s, () => f.children, null), insert(s, createComponent(Show, {
|
|
74
|
+
get when() {
|
|
75
|
+
return p();
|
|
76
|
+
},
|
|
77
|
+
get children() {
|
|
78
|
+
return createComponent(Show, {
|
|
79
|
+
get when() {
|
|
80
|
+
return m();
|
|
81
|
+
},
|
|
82
|
+
get fallback() {
|
|
83
|
+
return createComponent(IconUnsorted, {});
|
|
84
|
+
},
|
|
85
|
+
children: (o) => o().order == "asc" ? createComponent(IconAsc, {}) : createComponent(IconDesc, {})
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}), null), s;
|
|
89
|
+
} }));
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
export { SortPlugin };
|
|
@@ -3,6 +3,7 @@ import { createComponent, insert, memo, mergeProps, template } from "solid-js/we
|
|
|
3
3
|
var _tmpl$ = /* @__PURE__ */ template("<div class=cell-validation-error>"), _tmpl$2 = /* @__PURE__ */ template("<span class=\"mr-1 c-red/75\">*");
|
|
4
4
|
const ValidatorPlugin = {
|
|
5
5
|
name: "validator",
|
|
6
|
+
priority: -1,
|
|
6
7
|
store: (t) => ({
|
|
7
8
|
cellValidationErrors: {},
|
|
8
9
|
validateCell: async (n, r, i, a) => {
|