intable 0.0.22 → 0.0.24

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.
@@ -1,43 +1,41 @@
1
1
  import { createComponent } from "solid-js/web";
2
2
  import { createMemo, getOwner, runWithOwner } from "solid-js";
3
3
  import { combineProps } from "@solid-primitives/props";
4
+ import { createLazyMemo } from "@solid-primitives/memo";
4
5
  import { createEventListener } from "@solid-primitives/event-listener";
5
6
  import { createKeybindingsHandler } from "tinykeys";
6
7
  const CommandPlugin = {
7
8
  name: "command",
8
9
  priority: Infinity,
9
10
  store: (e) => {
10
- let a = getOwner(), o = createMemo(() => e.plugins.reduce((n, r) => Object.assign(n, runWithOwner(a, () => r.commands?.(e, { ...n }))), {}));
11
- return {
12
- get commands() {
13
- return o();
14
- },
15
- scrollToCell(n, r, i) {
16
- n = typeof n == "object" ? e.props.columns.indexOf(n) : n, r = typeof r == "object" ? e.props.data.indexOf(r) : r;
17
- let a = e.table.querySelector(`[x="${n}"][y="${r}"]`);
18
- a && a.scrollIntoView({
11
+ let r = getOwner(), o = createLazyMemo(() => e.plugins.reduce((i, o) => Object.assign(i, runWithOwner(r, () => o.commands?.(e, { ...i }))), {}));
12
+ return Object.defineProperty(e, "commands", { get: () => o() }), {
13
+ scrollToCell(r, i, a) {
14
+ r = typeof r == "object" ? e.props.columns.indexOf(r) : r, i = typeof i == "object" ? e.props.data.indexOf(i) : i;
15
+ let o = e.table.querySelector(`[x="${r}"][y="${i}"]`);
16
+ o && o.scrollIntoView({
19
17
  behavior: "smooth",
20
- ...i
18
+ ...a
21
19
  });
22
20
  },
23
- scrollCellIfNeeded(n, r, i = !1) {
24
- n = typeof n == "object" ? e.props.columns.indexOf(n) : n, r = typeof r == "object" ? e.props.data.indexOf(r) : r;
25
- let a = e.table.querySelector(`[x="${n}"][y="${r}"]`);
26
- a && (a.scrollIntoViewIfNeeded(i), a.focus());
21
+ scrollCellIfNeeded(r, i, a = !1) {
22
+ r = typeof r == "object" ? e.props.columns.indexOf(r) : r, i = typeof i == "object" ? e.props.data.indexOf(i) : i;
23
+ let o = e.table.querySelector(`[x="${r}"][y="${i}"]`);
24
+ o && (o.scrollIntoViewIfNeeded(a), o.focus());
27
25
  }
28
26
  };
29
27
  },
30
28
  rewriteProps: { Table: ({ Table: s }, { store: c }) => (l) => {
31
29
  let u = getOwner(), d = createMemo(() => {
32
30
  let e = {};
33
- for (let n of c.plugins) {
34
- let r = runWithOwner(u, () => n.keybindings?.(c));
35
- r && Object.assign(e, r);
31
+ for (let r of c.plugins) {
32
+ let i = runWithOwner(u, () => r.keybindings?.(c));
33
+ i && Object.assign(e, i);
36
34
  }
37
- let n = c.props?.keybindings;
38
- if (n) for (let [r, i] of Object.entries(n)) i === !1 ? delete e[r] : typeof i == "function" && (e[r] = i);
39
- return createKeybindingsHandler(Object.fromEntries(Object.entries(e).map(([e, n]) => [e, (e) => {
40
- e.preventDefault(), n(e);
35
+ let r = c.props?.keybindings;
36
+ if (r) for (let [i, a] of Object.entries(r)) a === !1 ? delete e[i] : typeof a == "function" && (e[i] = a);
37
+ return createKeybindingsHandler(Object.fromEntries(Object.entries(e).map(([e, r]) => [e, (e) => {
38
+ e.preventDefault(), r(e);
41
39
  }])));
42
40
  });
43
41
  return createEventListener(() => c.scroll_el, "keydown", (e) => d()(e)), l = combineProps({ tabindex: -1 }, l), createComponent(s, l);
@@ -19,7 +19,7 @@ const EditablePlugin = {
19
19
  Td: ({ Td: e }, { store: h }) => (_) => {
20
20
  let v, { props: x } = useContext(Ctx), S = createMemo(() => unFn(x.editable, _)), [w, T] = createSignal(!1), A = "", j = createMemo(() => (([e, h]) => _.x == e && _.y == h)(h.selected.start || [])), M = createMemo(() => j() && S() && !w()), [N, P] = createSignal(!1), F = createAsyncMemo(() => {
21
21
  if (w()) {
22
- let e = !1, g = _.data[_.col.id], v = ((e) => typeof e == "string" ? h.editors[e] : e)(_.col.editor || "text"), y = {
22
+ let e = !1, g = _.data[_.col.id], v = ((e) => typeof e == "string" ? h.editors[e] : e)(_.col.editor ?? _.col.type ?? "text"), y = {
23
23
  props: _.col.editorProps,
24
24
  col: _.col,
25
25
  eventKey: A,
@@ -32,20 +32,16 @@ const EditablePlugin = {
32
32
  onChange: (e) => w() && I(e).catch(() => {})
33
33
  }, b = v(y);
34
34
  return onCleanup(() => {
35
- if (!e && b.getValue() !== g) {
36
- let e = [...x.data];
37
- e[_.y] = {
38
- ...e[_.y],
39
- [_.col.id]: b.getValue()
40
- }, x.onDataChange?.(e);
41
- }
42
- e || I(b.getValue()).catch(() => {}), b.destroy();
35
+ !e && b.getValue() !== g && h.commands.rowChange({
36
+ ...x.data[_.y],
37
+ [_.col.id]: b.getValue()
38
+ }), e || I(b.getValue()).catch(() => {}), A = "", b.destroy();
43
39
  }), [y, b];
44
40
  }
45
41
  });
46
42
  async function I(e) {
47
43
  try {
48
- P(!0), console.log("validate", e), await h.validateCell(e, _.data, _.col);
44
+ P(!0), await h.validateCell(e, _.data, _.col);
49
45
  } finally {
50
46
  P(!1);
51
47
  }
@@ -0,0 +1,18 @@
1
+ import type { Plugin } from '..';
2
+ import type { AndOrNode } from '../components/AndOr';
3
+ declare module '../index' {
4
+ interface TableProps {
5
+ filter?: {
6
+ onChange?: (value: AndOrNode[]) => void;
7
+ /** @default true */
8
+ autoMatch?: boolean;
9
+ };
10
+ }
11
+ interface TableColumn {
12
+ filterable?: boolean;
13
+ }
14
+ interface TableStore {
15
+ filters: Record<string, AndOrNode>;
16
+ }
17
+ }
18
+ export declare const FilterPlugin: Plugin;
@@ -0,0 +1,123 @@
1
+ import { normalizeType } from "../components/AndOrFields.js";
2
+ import { Filter } from "../components/Filter.js";
3
+ import { createComponent, memo, mergeProps } from "solid-js/web";
4
+ import { Show } from "solid-js";
5
+ function isBlank(e) {
6
+ return e == null || String(e).trim() === "";
7
+ }
8
+ function toNum(e) {
9
+ let c = Number(e);
10
+ return Number.isNaN(c) ? null : c;
11
+ }
12
+ function toDateTs(e) {
13
+ if (isBlank(e)) return null;
14
+ let c = new Date(String(e)).getTime();
15
+ return Number.isNaN(c) ? null : c;
16
+ }
17
+ function toBool(e) {
18
+ if (typeof e == "boolean") return e;
19
+ if (typeof e == "number") return e !== 0;
20
+ let c = String(e ?? "").trim().toLowerCase();
21
+ return [
22
+ "1",
23
+ "true",
24
+ "yes",
25
+ "y",
26
+ "on"
27
+ ].includes(c) ? !0 : [
28
+ "0",
29
+ "false",
30
+ "no",
31
+ "n",
32
+ "off",
33
+ ""
34
+ ].includes(c) ? !1 : !!e;
35
+ }
36
+ function isRuleNode(e) {
37
+ return "field" in e;
38
+ }
39
+ function hasActiveRule(e) {
40
+ return !!e.op;
41
+ }
42
+ function hasActiveTree(e) {
43
+ return e ? isRuleNode(e) ? hasActiveRule(e) : (e.children ?? []).some(hasActiveTree) : !1;
44
+ }
45
+ function matchFilter(e, c, l) {
46
+ let u = c.op;
47
+ if (u === "blank") return isBlank(e);
48
+ if (u === "noblank") return !isBlank(e);
49
+ if (u === "true") return toBool(e);
50
+ if (u === "false") return !toBool(e);
51
+ let d = c.value;
52
+ if (l === "number") {
53
+ let c = toNum(e), l = toNum(d);
54
+ if (c == null || l == null) return !1;
55
+ if (u === "eq") return c === l;
56
+ if (u === "lt") return c < l;
57
+ if (u === "gt") return c > l;
58
+ if (u === "lte") return c <= l;
59
+ if (u === "gte") return c >= l;
60
+ }
61
+ if (l === "date") {
62
+ let c = toDateTs(e), l = toDateTs(d);
63
+ if (c == null || l == null) return !1;
64
+ if (u === "eq") return c === l;
65
+ if (u === "lt") return c < l;
66
+ if (u === "gt") return c > l;
67
+ if (u === "lte") return c <= l;
68
+ if (u === "gte") return c >= l;
69
+ }
70
+ let f = String(e ?? "").toLowerCase(), g = String(d ?? "").toLowerCase();
71
+ return u === "eq" ? f === g : u === "neq" ? f !== g : u === "startwith" ? f.startsWith(g) : u === "endwith" ? f.endsWith(g) : f.includes(g);
72
+ }
73
+ function evaluateFilterTree(e, c, l) {
74
+ if (isRuleNode(c)) return hasActiveRule(c) ? matchFilter(e, c, l) : !0;
75
+ let u = (c.children ?? []).filter(hasActiveTree);
76
+ return u.length ? c.op === "or" ? u.some((c) => evaluateFilterTree(e, c, l)) : u.every((c) => evaluateFilterTree(e, c, l)) : !0;
77
+ }
78
+ function passesFilters(c, l, u, d) {
79
+ return u.every((u) => {
80
+ if (u[d] || !u.filterable) return !0;
81
+ let f = l[u.id];
82
+ return !f || !hasActiveTree(f) ? !0 : evaluateFilterTree(c[u.id], f, normalizeType(u));
83
+ });
84
+ }
85
+ const FilterPlugin = {
86
+ name: "filter",
87
+ store: () => ({ filters: {} }),
88
+ rewriteProps: {
89
+ filter: ({ filter: e }, { store: c }) => ({
90
+ autoMatch: !0,
91
+ ...e
92
+ }),
93
+ data: ({ data: e }, { store: c }) => {
94
+ if (!e) return e;
95
+ let { filters: l } = c, { columns: u, filter: d } = c.props;
96
+ return !d.autoMatch || !Object.values(l).some(hasActiveTree) ? e : e.filter((e) => passesFilters(e, l, u, c.internal));
97
+ },
98
+ Th: ({ Th: e }, { store: p }) => (m) => {
99
+ let h = () => !!m.col.filterable && !m.col[p.internal];
100
+ return createComponent(e, mergeProps(m, { get children() {
101
+ return [memo(() => m.children), createComponent(Show, {
102
+ get when() {
103
+ return h();
104
+ },
105
+ get children() {
106
+ return createComponent(Filter, {
107
+ get col() {
108
+ return m.col;
109
+ },
110
+ get tree() {
111
+ return p.filters[m.col.id];
112
+ },
113
+ setTree: (e) => {
114
+ e ? p.filters[m.col.id] = e : delete p.filters[m.col.id], p.props.filter?.onChange?.(Object.values(p.filters));
115
+ }
116
+ });
117
+ }
118
+ })];
119
+ } }));
120
+ }
121
+ }
122
+ };
123
+ export { FilterPlugin };
@@ -0,0 +1,24 @@
1
+ import { type Component } from 'solid-js';
2
+ import type { Plugin } from '..';
3
+ declare module '../index' {
4
+ interface TableProps {
5
+ loadMore?: {
6
+ enable?: boolean;
7
+ threshold?: number;
8
+ debounce?: number;
9
+ loading?: boolean;
10
+ hasMore?: boolean;
11
+ loadingText?: string;
12
+ noMoreText?: string;
13
+ onLoadMore?: () => void | Promise<void>;
14
+ };
15
+ LoadMore?: Component<TableProps['loadMore']>;
16
+ }
17
+ interface TableStore {
18
+ loadMore: {
19
+ pending: boolean;
20
+ lastTriggerAt: number;
21
+ };
22
+ }
23
+ }
24
+ export declare const LoadMorePlugin: Plugin;
@@ -0,0 +1,62 @@
1
+ import { createComponent, insert, memo, mergeProps, template } from "solid-js/web";
2
+ import { Show, createEffect } from "solid-js";
3
+ import { combineProps } from "@solid-primitives/props";
4
+ import { delay } from "es-toolkit";
5
+ import { createEventListener } from "@solid-primitives/event-listener";
6
+ var _tmpl$ = /* @__PURE__ */ template("<div class=\"data-table__load-more sticky left-0\">");
7
+ function isPromiseLike(e) {
8
+ return !!e && typeof e.then == "function";
9
+ }
10
+ var LoadMoreLayer = (s) => {
11
+ let c = () => !!s.enable && (s.loading || s.hasMore === !1), l = () => s.loading ? s.loadingText ?? "loading..." : s.noMoreText ?? "无更多数据";
12
+ return createComponent(Show, {
13
+ get when() {
14
+ return c();
15
+ },
16
+ get children() {
17
+ var e = _tmpl$();
18
+ return insert(e, l), e;
19
+ }
20
+ });
21
+ };
22
+ const LoadMorePlugin = {
23
+ name: "loadMore",
24
+ store: () => ({ loadMore: {
25
+ pending: !1,
26
+ lastTriggerAt: 0
27
+ } }),
28
+ rewriteProps: {
29
+ loadMore: ({ loadMore: e }, { store: o }) => ({
30
+ enable: !1,
31
+ threshold: 40,
32
+ debounce: 200,
33
+ ...e
34
+ }),
35
+ LoadMore: ({ LoadMore: o = LoadMoreLayer }, { store: s }) => () => createComponent(o, mergeProps(() => s.props.loadMore)),
36
+ Footer: ({ Footer: o }, { store: l }) => (u) => createComponent(o, mergeProps(() => combineProps({ class: "contents" }, u), { get children() {
37
+ return [memo(() => u.children), createComponent(l.props.LoadMore, {})];
38
+ } }))
39
+ },
40
+ onMount: (e) => {
41
+ let o = () => {
42
+ let s = e.props.loadMore;
43
+ if (!s.enable || !s.onLoadMore || s.hasMore === !1 || s.loading || e.loadMore.pending) return;
44
+ let c = e.scroll_el;
45
+ if (!c) return;
46
+ let l = c.scrollHeight - c.scrollTop - c.clientHeight, u = s.threshold;
47
+ if (l > u) return;
48
+ let d = Date.now(), f = s.debounce;
49
+ if (d - e.loadMore.lastTriggerAt < f) return;
50
+ e.loadMore.lastTriggerAt = d;
51
+ let p = s.onLoadMore();
52
+ isPromiseLike(p) && (e.loadMore.pending = !0, p.finally(() => {
53
+ e.loadMore.pending = !1, delay(0).then(o);
54
+ }));
55
+ };
56
+ createEffect(() => {
57
+ let s = e.scroll_el, c = e.props.loadMore;
58
+ !s || !c.enable || (createEventListener(() => e.scroll_el, "scroll", o, { passive: !0 }), queueMicrotask(o));
59
+ });
60
+ }
61
+ };
62
+ export { LoadMorePlugin };
@@ -71,15 +71,16 @@ const MenuPlugin = {
71
71
  }
72
72
  ],
73
73
  commands: (e) => ({
74
- rowEquals(e, r) {
75
- return e == r;
74
+ rowEquals(r, i) {
75
+ let a = e.props.rowKey;
76
+ return r == i || a != null && r?.[a] == i?.[a];
76
77
  },
77
78
  rowIndexOf(r, i) {
78
79
  return r.findIndex((r) => e.commands.rowEquals(r, i));
79
80
  },
80
81
  rowChange(r, i) {
81
82
  let a = [...e.rawProps.data || []];
82
- i = i == null ? e.commands.rowIndexOf(a, r) : a.findIndex((r) => r == e.props.data[i]), i > -1 && (a[i] = r, e.props.onDataChange?.(a));
83
+ i = i == null ? e.commands.rowIndexOf(a, r) : a.findIndex((r) => e.commands.rowEquals(r, e.props.data[i])), i > -1 && (a[i] = r, e.props.onDataChange?.(a));
83
84
  },
84
85
  addRows(r, i, a = !0) {
85
86
  addRows(e, r, i, a);
@@ -4,6 +4,7 @@ declare module '../../index' {
4
4
  interface TableProps {
5
5
  }
6
6
  interface TableColumn {
7
+ type?: string;
7
8
  render?: Render;
8
9
  enum?: Record<string, any> | {
9
10
  label?: string;
@@ -10,7 +10,7 @@ const RenderPlugin = {
10
10
  store: () => ({ renders: { ...renders } }),
11
11
  rewriteProps: { Td: ({ Td: e }, { store: p }) => (m) => createComponent(e, mergeProps(m, { get children() {
12
12
  return (() => {
13
- let e = ((e) => typeof e == "string" ? p.renders[e] : e)(m.col.render) || text;
13
+ let e = ((e) => typeof e == "string" ? p.renders[e] : e)(m.col.render ?? m.col.type) || text;
14
14
  return renderComponent(e, mergeProps$1(m, { onChange: (e) => p.commands.rowChange({
15
15
  ...m.data,
16
16
  [m.col.id]: e
@@ -1,72 +1,73 @@
1
+ import { isEmpty } from "../utils.js";
1
2
  import { createComponent, insert, memo, mergeProps, template } from "solid-js/web";
2
3
  import { combineProps } from "@solid-primitives/props";
3
- var _tmpl$ = /* @__PURE__ */ template("<div class=cell-validation-error>"), _tmpl$2 = /* @__PURE__ */ template("<span class=\"mr-1 c-red/75\">*"), isEmpty = (e) => e == null || e === "" || Array.isArray(e) && e.length === 0 || typeof e == "object" && Object.keys(e).length === 0;
4
+ var _tmpl$ = /* @__PURE__ */ template("<div class=cell-validation-error>"), _tmpl$2 = /* @__PURE__ */ template("<span class=\"mr-1 c-red/75\">*");
4
5
  const ValidatorPlugin = {
5
6
  name: "validator",
6
- store: (e) => ({
7
+ store: (t) => ({
7
8
  cellValidationErrors: {},
8
- validateCell: async (t, n, r, i) => {
9
- if (n[e.internal] || r[e.internal]) return;
10
- let a = [
9
+ validateCell: async (n, r, i, a) => {
10
+ if (r[t.internal] || i[t.internal]) return;
11
+ let o = [
11
12
  () => {
12
- if (r.required && isEmpty(t)) throw Error("Required");
13
+ if (i.required && isEmpty(n)) throw Error("Required");
13
14
  },
14
- r.validator,
15
- e.props.validator
16
- ], o = n[e.props.rowKey];
17
- for (let s of a) {
18
- if (!s) continue;
15
+ i.validator,
16
+ t.props.validator
17
+ ], s = r[t.props.rowKey];
18
+ for (let e of o) {
19
+ if (!e) continue;
19
20
  try {
20
- await s(t, n, r);
21
- } catch (t) {
22
- let a = t.message || "Error";
23
- throw e.cellValidationErrors[o] ??= {}, e.cellValidationErrors[o][r.id] = a, i && e.scrollToCell?.(r, n), Error(a);
21
+ await e(n, r, i);
22
+ } catch (e) {
23
+ let n = e.message || "Error";
24
+ throw t.cellValidationErrors[s] ??= {}, t.cellValidationErrors[s][i.id] = n, a && t.scrollToCell?.(i, r), Error(n);
24
25
  }
25
26
  }
26
- e.cellValidationErrors[o] ??= {}, e.cellValidationErrors[o][r.id] = null;
27
+ t.cellValidationErrors[s] ??= {}, t.cellValidationErrors[s][i.id] = null;
27
28
  },
28
- validateRow: async (t, n) => {
29
- let r = e.props.columns, i = r.map((n) => e.validateCell(t[n.id], t, n)), a = await Promise.all(i.map((e) => e.catch((e) => e))), o = a.map((e, t) => e instanceof Error ? [r[t].id, e] : null).filter((e) => e);
29
+ validateRow: async (e, n) => {
30
+ let r = t.props.columns, i = r.map((n) => t.validateCell(e[n.id], e, n)), a = await Promise.all(i.map((e) => e.catch((e) => e))), o = a.map((e, t) => e instanceof Error ? [r[t].id, e] : null).filter((e) => e);
30
31
  if (o.length) {
31
32
  if (n) {
32
33
  let n = r[a.findIndex((e) => e instanceof Error)];
33
- e.scrollToCell?.(n, t);
34
+ t.scrollToCell?.(n, e);
34
35
  }
35
36
  throw Object.fromEntries(o);
36
37
  }
37
38
  },
38
39
  validate: async () => {
39
- let t = (e.rawProps.data || []).map((t) => e.validateRow(t)), n = (await Promise.all(t.map((e) => e.catch((e) => e)))).map((e, t) => e ? [t, e] : null).filter((e) => e);
40
- if (n.length) throw e.scrollToCell?.(e.props.columns.findIndex((e) => e.id === Object.keys(n[0][1])[0]), e.props.data?.[n[0][0]]), n[0][1];
40
+ let e = (t.rawProps.data || []).map((e) => t.validateRow(e)), n = (await Promise.all(e.map((e) => e.catch((e) => e)))).map((e, t) => e ? [t, e] : null).filter((e) => e);
41
+ if (n.length) throw t.scrollToCell?.(t.props.columns.findIndex((e) => e.id === Object.keys(n[0][1])[0]), t.props.data?.[n[0][0]]), n[0][1];
41
42
  },
42
- clearCellValidation: (t, n) => {
43
- let r = t[e.props.rowKey];
44
- e.cellValidationErrors[r] && (e.cellValidationErrors[r][n.id] = null);
43
+ clearCellValidation: (e, n) => {
44
+ let r = e[t.props.rowKey];
45
+ t.cellValidationErrors[r] && (t.cellValidationErrors[r][n.id] = null);
45
46
  },
46
- clearRowValidation: (t) => {
47
- let n = t[e.props.rowKey];
48
- if (!e.cellValidationErrors[n]) return;
49
- let r = e.props.columns;
50
- for (let t of r) e.cellValidationErrors[n][t.id] = null;
47
+ clearRowValidation: (e) => {
48
+ let n = e[t.props.rowKey];
49
+ if (!t.cellValidationErrors[n]) return;
50
+ let r = t.props.columns;
51
+ for (let e of r) t.cellValidationErrors[n][e.id] = null;
51
52
  },
52
53
  clearValidation: () => {
53
- e.cellValidationErrors = {};
54
+ t.cellValidationErrors = {};
54
55
  }
55
56
  }),
56
57
  rewriteProps: {
57
- Td: ({ Td: i }, { store: s }) => (c) => {
58
- let l = () => s.cellValidationErrors[c.data[s.props.rowKey]]?.[c.col.id], u = combineProps(c, { get class() {
58
+ Td: ({ Td: e }, { store: a }) => (c) => {
59
+ let l = () => a.cellValidationErrors[c.data[a.props.rowKey]]?.[c.col.id], u = combineProps(c, { get class() {
59
60
  return l() == null ? "" : "is-invalid";
60
61
  } });
61
- return createComponent(i, mergeProps(u, { get children() {
62
+ return createComponent(e, mergeProps(u, { get children() {
62
63
  return [memo(() => c.children), memo(() => memo(() => l() != null)() && (() => {
63
64
  var e = _tmpl$();
64
65
  return insert(e, l), e;
65
66
  })())];
66
67
  } }));
67
68
  },
68
- Th: ({ Th: t }, { store: i }) => (i) => createComponent(t, mergeProps(i, { get children() {
69
- return [memo(() => memo(() => !!i.col.required)() && _tmpl$2()), memo(() => i.children)];
69
+ Th: ({ Th: e }, { store: n }) => (n) => createComponent(e, mergeProps(n, { get children() {
70
+ return [memo(() => memo(() => !!n.col.required)() && _tmpl$2()), memo(() => n.children)];
70
71
  } }))
71
72
  }
72
73
  };