@serkonda7/solid-components 0.0.2 → 0.0.3
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 +7 -17
- package/dist/data-table.d.ts +12 -0
- package/dist/index.js +105 -44
- package/dist/styles.css +88 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -14,31 +14,21 @@ bun install @serkonda7/solid-components solid-js
|
|
|
14
14
|
|
|
15
15
|
## 🚀 Usage
|
|
16
16
|
```tsx
|
|
17
|
-
import {
|
|
17
|
+
import { DataTable } from '@serkonda7/solid-components'
|
|
18
18
|
import '@serkonda7/solid-components/styles.css'
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
These components are available:
|
|
22
|
-
- `DataTable` - generic table with optional sorting, row selection, actions, loading, and empty states.
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
## Components
|
|
26
|
-
### DataTable
|
|
27
|
-
The table does not fetch data or perform navigation.
|
|
28
|
-
Consumers provide the rows, cell rendering, and callbacks:
|
|
29
19
|
|
|
30
|
-
```tsx
|
|
31
20
|
<DataTable
|
|
32
21
|
rows={items}
|
|
33
22
|
getRowId={(item) => item.id}
|
|
34
|
-
columns={[{ key: 'name', label: 'Name'
|
|
35
|
-
sortKey={sortKey}
|
|
36
|
-
sortDirection={sortDirection}
|
|
37
|
-
onSort={setSortKey}
|
|
38
|
-
getCell={(item, column) => column.key === 'name' ? item.name : null}
|
|
23
|
+
columns={[{ key: 'name', label: 'Name' }]}
|
|
39
24
|
/>
|
|
40
25
|
```
|
|
41
26
|
|
|
27
|
+
These components are available:
|
|
28
|
+
- `DataTable` - generic table with optional sorting, row selection, actions, loading, empty states, and column customizer.
|
|
29
|
+
|
|
30
|
+
For the full API, examples, and agent notes, see [docs.md](docs.md).
|
|
31
|
+
|
|
42
32
|
|
|
43
33
|
## 📜 License
|
|
44
34
|
This repo is licensed under the [MIT License](LICENSE.txt).
|
package/dist/data-table.d.ts
CHANGED
|
@@ -7,6 +7,10 @@ export interface DataTableColumn<TRow> {
|
|
|
7
7
|
class?: string;
|
|
8
8
|
ariaLabel?: string;
|
|
9
9
|
getValue?: (row: TRow) => JSX.Element;
|
|
10
|
+
/** Whether the column is visible by default when the column customizer is used. Defaults to `true`. */
|
|
11
|
+
defaultVisible?: boolean;
|
|
12
|
+
/** Whether the column can be hidden via the column customizer. Defaults to `true`. Non-toggleable columns are always shown. */
|
|
13
|
+
toggleable?: boolean;
|
|
10
14
|
}
|
|
11
15
|
export interface DataTableProps<TRow> {
|
|
12
16
|
rows: TRow[] | Accessor<TRow[]>;
|
|
@@ -20,6 +24,14 @@ export interface DataTableProps<TRow> {
|
|
|
20
24
|
sortKey?: string | Accessor<string | undefined>;
|
|
21
25
|
sortDirection?: DataTableSortDirection | Accessor<DataTableSortDirection>;
|
|
22
26
|
onSort?: (key: string) => void;
|
|
27
|
+
visibleColumns?: string[] | Accessor<string[]>;
|
|
28
|
+
defaultVisibleColumns?: string[];
|
|
29
|
+
onVisibleColumnsChange?: (visibleKeys: string[]) => void;
|
|
30
|
+
showColumnCustomizer?: boolean | Accessor<boolean>;
|
|
31
|
+
columnCustomizerLabel?: string;
|
|
32
|
+
columnCustomizerTitle?: string;
|
|
33
|
+
columnCustomizerShowAllLabel?: string;
|
|
34
|
+
columnCustomizerResetLabel?: string;
|
|
23
35
|
loading?: boolean | Accessor<boolean>;
|
|
24
36
|
empty?: boolean | Accessor<boolean>;
|
|
25
37
|
loadingContent?: JSX.Element;
|
package/dist/index.js
CHANGED
|
@@ -1,49 +1,110 @@
|
|
|
1
1
|
import { className as e, createComponent as t, delegateEvents as n, effect as r, insert as i, memo as a, setAttribute as o, template as s, use as c } from "solid-js/web";
|
|
2
|
-
import { For as l, Show as u, createEffect as d, createMemo as f } from "solid-js";
|
|
2
|
+
import { For as l, Show as u, createEffect as d, createMemo as f, createSignal as p, createUniqueId as m, onCleanup as h } from "solid-js";
|
|
3
3
|
//#region src/data-table.tsx
|
|
4
|
-
var p = /*#__PURE__*/ s("<th class=data-table-checkbox><span class=data-table-visually-hidden>Select rows</span><input type=checkbox>"),
|
|
5
|
-
function
|
|
4
|
+
var g = /*#__PURE__*/ s("<div role=dialog class=data-table-customizer-panel><p class=data-table-customizer-title></p><ul class=data-table-customizer-list></ul><div class=data-table-customizer-actions><button type=button></button><button type=button>"), _ = /*#__PURE__*/ s("<div class=data-table-toolbar><div class=data-table-customizer><button type=button class=data-table-customizer-button aria-haspopup=dialog><span aria-hidden=true>⚙</span> "), v = /*#__PURE__*/ s("<th class=data-table-checkbox><span class=data-table-visually-hidden>Select rows</span><input type=checkbox>"), y = /*#__PURE__*/ s("<th>Actions"), b = /*#__PURE__*/ s("<div><div class=data-table-scroll><table class=data-table><thead><tr></tr></thead><tbody>"), x = /*#__PURE__*/ s("<li><label class=data-table-customizer-option><input type=checkbox>"), S = /*#__PURE__*/ s("<button type=button class=data-table-sort>"), C = /*#__PURE__*/ s("<th>"), ee = /*#__PURE__*/ s("<td class=data-table-checkbox><input type=checkbox>"), w = /*#__PURE__*/ s("<td>"), T = /*#__PURE__*/ s("<tr>"), E = /*#__PURE__*/ s("<p class=data-table-status>Loading…"), D = /*#__PURE__*/ s("<p class=data-table-status>No results.");
|
|
5
|
+
function O(e) {
|
|
6
6
|
return typeof e == "function" ? e() : e;
|
|
7
7
|
}
|
|
8
|
-
function
|
|
9
|
-
let s = f(() =>
|
|
10
|
-
let e =
|
|
8
|
+
function k(n) {
|
|
9
|
+
let s = f(() => O(n.rows)), k = () => O(n.loading ?? !1), A = () => O(n.selected ?? []), j = () => O(n.sortKey ?? void 0), M = () => O(n.sortDirection ?? "asc"), N = () => O(n.showColumnCustomizer ?? !1), P = () => n.selected !== void 0 && n.onSelectionChange !== void 0, F = () => {
|
|
10
|
+
let e = A();
|
|
11
11
|
return s().length > 0 && s().every((t) => e.includes(n.getRowId(t)));
|
|
12
|
-
},
|
|
12
|
+
}, I = f(() => n.defaultVisibleColumns ?? n.columns.filter((e) => e.defaultVisible !== !1).map((e) => e.key)), [L, R] = p(void 0), z = () => n.visibleColumns === void 0 ? L() ?? I() : O(n.visibleColumns), B = f(() => new Set(z())), V = f(() => n.columns.filter((e) => e.toggleable === !1 || B().has(e.key))), H = f(() => n.columns.filter((e) => e.toggleable !== !1)), U = f(() => H().map((e) => e.key));
|
|
13
|
+
function W(e) {
|
|
14
|
+
let t = new Map(n.columns.map((e, t) => [e.key, t]));
|
|
15
|
+
return [...e].sort((e, n) => (t.get(e) ?? 0) - (t.get(n) ?? 0));
|
|
16
|
+
}
|
|
17
|
+
function G(e) {
|
|
18
|
+
let t = W(e);
|
|
19
|
+
n.visibleColumns === void 0 && R(t), n.onVisibleColumnsChange?.(t);
|
|
20
|
+
}
|
|
21
|
+
function K(e, t) {
|
|
22
|
+
let n = new Set(z());
|
|
23
|
+
t ? n.add(e) : n.delete(e), G(U().filter((e) => n.has(e)));
|
|
24
|
+
}
|
|
25
|
+
function q() {
|
|
26
|
+
G(U());
|
|
27
|
+
}
|
|
28
|
+
function J() {
|
|
29
|
+
G(I());
|
|
30
|
+
}
|
|
31
|
+
let Y = `${m()}-panel`, [X, Z] = p(!1), Q;
|
|
32
|
+
d(() => {
|
|
33
|
+
if (!X() || !N()) return;
|
|
34
|
+
function e(e) {
|
|
35
|
+
Q && !Q.contains(e.target) && Z(!1);
|
|
36
|
+
}
|
|
37
|
+
function t(e) {
|
|
38
|
+
e.key === "Escape" && Z(!1);
|
|
39
|
+
}
|
|
40
|
+
document.addEventListener("pointerdown", e), document.addEventListener("keydown", t), h(() => {
|
|
41
|
+
document.removeEventListener("pointerdown", e), document.removeEventListener("keydown", t);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
let $;
|
|
13
45
|
d(() => {
|
|
14
|
-
|
|
46
|
+
$ && ($.indeterminate = A().length > 0 && !F());
|
|
15
47
|
});
|
|
16
|
-
function
|
|
48
|
+
function te(e) {
|
|
17
49
|
n.onSelectionChange?.(e ? s().map(n.getRowId) : []);
|
|
18
50
|
}
|
|
19
|
-
function
|
|
20
|
-
let r = n.getRowId(e), i =
|
|
51
|
+
function ne(e, t) {
|
|
52
|
+
let r = n.getRowId(e), i = A(), a = t ? [...i, r] : i.filter((e) => e !== r);
|
|
21
53
|
n.onSelectionChange?.(a);
|
|
22
54
|
}
|
|
23
|
-
function
|
|
24
|
-
return
|
|
55
|
+
function re(e) {
|
|
56
|
+
return A().includes(n.getRowId(e));
|
|
57
|
+
}
|
|
58
|
+
function ie(e) {
|
|
59
|
+
return e.toggleable === !1 || B().has(e.key);
|
|
25
60
|
}
|
|
26
|
-
function
|
|
61
|
+
function ae(e, t) {
|
|
27
62
|
return n.getCell?.(e, t) ?? t.getValue?.(e) ?? null;
|
|
28
63
|
}
|
|
29
64
|
return (() => {
|
|
30
|
-
var d =
|
|
31
|
-
return i(
|
|
65
|
+
var d = b(), f = d.firstChild, p = f.firstChild.firstChild, m = p.firstChild, h = p.nextSibling;
|
|
66
|
+
return i(d, t(u, {
|
|
67
|
+
get when() {
|
|
68
|
+
return N();
|
|
69
|
+
},
|
|
70
|
+
get children() {
|
|
71
|
+
var e = _(), a = e.firstChild, s = a.firstChild;
|
|
72
|
+
s.firstChild.nextSibling;
|
|
73
|
+
var d = Q;
|
|
74
|
+
return typeof d == "function" ? c(d, a) : Q = a, s.$$click = () => Z((e) => !e), o(s, "aria-controls", Y), i(s, () => n.columnCustomizerLabel ?? "Columns", null), i(a, t(u, {
|
|
75
|
+
get when() {
|
|
76
|
+
return X();
|
|
77
|
+
},
|
|
78
|
+
get children() {
|
|
79
|
+
var e = g(), a = e.firstChild, s = a.nextSibling, c = s.nextSibling.firstChild, u = c.nextSibling;
|
|
80
|
+
return o(e, "id", Y), i(a, () => n.columnCustomizerTitle ?? "Shown columns"), i(s, t(l, {
|
|
81
|
+
get each() {
|
|
82
|
+
return n.columns;
|
|
83
|
+
},
|
|
84
|
+
children: (e) => (() => {
|
|
85
|
+
var t = x(), n = t.firstChild, a = n.firstChild;
|
|
86
|
+
return a.addEventListener("change", (t) => K(e.key, t.currentTarget.checked)), i(n, () => e.ariaLabel ?? e.label, null), r(() => a.disabled = e.toggleable === !1), r(() => a.checked = ie(e)), t;
|
|
87
|
+
})()
|
|
88
|
+
})), c.$$click = q, i(c, () => n.columnCustomizerShowAllLabel ?? "Show all"), u.$$click = J, i(u, () => n.columnCustomizerResetLabel ?? "Reset"), r(() => o(e, "aria-label", n.columnCustomizerTitle ?? "Customize columns")), e;
|
|
89
|
+
}
|
|
90
|
+
}), null), r(() => o(s, "aria-expanded", X())), e;
|
|
91
|
+
}
|
|
92
|
+
}), f), i(m, t(u, {
|
|
32
93
|
get when() {
|
|
33
|
-
return
|
|
94
|
+
return P();
|
|
34
95
|
},
|
|
35
96
|
get children() {
|
|
36
|
-
var e =
|
|
37
|
-
t.addEventListener("change", (e) =>
|
|
38
|
-
var i =
|
|
39
|
-
return typeof i == "function" ? c(i, t) :
|
|
97
|
+
var e = v(), t = e.firstChild.nextSibling;
|
|
98
|
+
t.addEventListener("change", (e) => te(e.currentTarget.checked));
|
|
99
|
+
var i = $;
|
|
100
|
+
return typeof i == "function" ? c(i, t) : $ = t, r(() => o(t, "aria-label", n.selectionLabel ?? "Select all rows")), r(() => t.checked = F()), e;
|
|
40
101
|
}
|
|
41
|
-
}), null), i(
|
|
102
|
+
}), null), i(m, t(l, {
|
|
42
103
|
get each() {
|
|
43
|
-
return
|
|
104
|
+
return V();
|
|
44
105
|
},
|
|
45
106
|
children: (s) => (() => {
|
|
46
|
-
var c =
|
|
107
|
+
var c = C();
|
|
47
108
|
return i(c, t(u, {
|
|
48
109
|
get when() {
|
|
49
110
|
return a(() => !!s.sortable)() && n.onSort;
|
|
@@ -52,76 +113,76 @@ function w(n) {
|
|
|
52
113
|
return s.label;
|
|
53
114
|
},
|
|
54
115
|
get children() {
|
|
55
|
-
var e =
|
|
116
|
+
var e = S();
|
|
56
117
|
return e.$$click = () => n.onSort?.(s.key), i(e, () => s.label, null), i(e, (() => {
|
|
57
|
-
var e = a(() =>
|
|
58
|
-
return () => e() ?
|
|
118
|
+
var e = a(() => j() === s.key);
|
|
119
|
+
return () => e() ? M() === "asc" ? " ▲" : " ▼" : "";
|
|
59
120
|
})(), null), e;
|
|
60
121
|
}
|
|
61
122
|
})), r((t) => {
|
|
62
|
-
var n = s.class, r = s.sortable ?
|
|
123
|
+
var n = s.class, r = s.sortable ? j() === s.key ? M() === "asc" ? "ascending" : "descending" : "none" : void 0;
|
|
63
124
|
return n !== t.e && e(c, t.e = n), r !== t.t && o(c, "aria-sort", t.t = r), t;
|
|
64
125
|
}, {
|
|
65
126
|
e: void 0,
|
|
66
127
|
t: void 0
|
|
67
128
|
}), c;
|
|
68
129
|
})()
|
|
69
|
-
}), null), i(
|
|
130
|
+
}), null), i(m, t(u, {
|
|
70
131
|
get when() {
|
|
71
132
|
return n.rowActions;
|
|
72
133
|
},
|
|
73
134
|
get children() {
|
|
74
|
-
return
|
|
135
|
+
return y();
|
|
75
136
|
}
|
|
76
|
-
}), null), i(
|
|
137
|
+
}), null), i(h, t(l, {
|
|
77
138
|
get each() {
|
|
78
139
|
return s();
|
|
79
140
|
},
|
|
80
141
|
children: (a) => (() => {
|
|
81
|
-
var s =
|
|
142
|
+
var s = T();
|
|
82
143
|
return i(s, t(u, {
|
|
83
144
|
get when() {
|
|
84
|
-
return
|
|
145
|
+
return P();
|
|
85
146
|
},
|
|
86
147
|
get children() {
|
|
87
|
-
var e =
|
|
88
|
-
return t.addEventListener("change", (e) =>
|
|
148
|
+
var e = ee(), t = e.firstChild;
|
|
149
|
+
return t.addEventListener("change", (e) => ne(a, e.currentTarget.checked)), r(() => o(t, "aria-label", `Select row ${n.getRowId(a)}`)), r(() => t.checked = re(a)), e;
|
|
89
150
|
}
|
|
90
151
|
}), null), i(s, t(l, {
|
|
91
152
|
get each() {
|
|
92
|
-
return
|
|
153
|
+
return V();
|
|
93
154
|
},
|
|
94
155
|
children: (t) => (() => {
|
|
95
|
-
var n =
|
|
96
|
-
return i(n, () =>
|
|
156
|
+
var n = w();
|
|
157
|
+
return i(n, () => ae(a, t)), r(() => e(n, t.class)), n;
|
|
97
158
|
})()
|
|
98
159
|
}), null), i(s, t(u, {
|
|
99
160
|
get when() {
|
|
100
161
|
return n.rowActions;
|
|
101
162
|
},
|
|
102
163
|
get children() {
|
|
103
|
-
var e =
|
|
164
|
+
var e = w();
|
|
104
165
|
return i(e, () => n.rowActions?.(a)), e;
|
|
105
166
|
}
|
|
106
167
|
}), null), s;
|
|
107
168
|
})()
|
|
108
169
|
})), i(d, t(u, {
|
|
109
170
|
get when() {
|
|
110
|
-
return
|
|
171
|
+
return k();
|
|
111
172
|
},
|
|
112
173
|
get children() {
|
|
113
|
-
return n.loadingContent ??
|
|
174
|
+
return n.loadingContent ?? E();
|
|
114
175
|
}
|
|
115
176
|
}), null), i(d, t(u, {
|
|
116
177
|
get when() {
|
|
117
|
-
return a(() => !
|
|
178
|
+
return a(() => !k())() && (n.empty === void 0 ? s().length === 0 : O(n.empty));
|
|
118
179
|
},
|
|
119
180
|
get children() {
|
|
120
|
-
return n.emptyContent ??
|
|
181
|
+
return n.emptyContent ?? D();
|
|
121
182
|
}
|
|
122
183
|
}), null), r(() => e(d, `data-table-wrap${n.class ? ` ${n.class}` : ""}`)), d;
|
|
123
184
|
})();
|
|
124
185
|
}
|
|
125
186
|
n(["click"]);
|
|
126
187
|
//#endregion
|
|
127
|
-
export {
|
|
188
|
+
export { k as DataTable };
|
package/dist/styles.css
CHANGED
|
@@ -1,7 +1,95 @@
|
|
|
1
1
|
.data-table-wrap {
|
|
2
|
+
/* `color-scheme` is intentionally inherited so `light-dark()` below follows
|
|
3
|
+
the consumer's theme (e.g. the dark example). */
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.data-table-scroll {
|
|
2
7
|
overflow-x: auto;
|
|
3
8
|
}
|
|
4
9
|
|
|
10
|
+
.data-table-toolbar {
|
|
11
|
+
display: flex;
|
|
12
|
+
justify-content: flex-end;
|
|
13
|
+
margin-bottom: 0.5rem;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.data-table-customizer {
|
|
17
|
+
position: relative;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.data-table-customizer-button {
|
|
21
|
+
display: inline-flex;
|
|
22
|
+
align-items: center;
|
|
23
|
+
gap: 0.375rem;
|
|
24
|
+
padding: 0.375rem 0.625rem;
|
|
25
|
+
border: 1px solid
|
|
26
|
+
var(--data-table-border, var(--border, light-dark(#d0d0d0, #3a3e45)));
|
|
27
|
+
border-radius: 0.375rem;
|
|
28
|
+
background: var(
|
|
29
|
+
--data-table-customizer-bg,
|
|
30
|
+
var(--surface, light-dark(#ffffff, #1d2024))
|
|
31
|
+
);
|
|
32
|
+
color: inherit;
|
|
33
|
+
font: inherit;
|
|
34
|
+
cursor: pointer;
|
|
35
|
+
white-space: nowrap;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.data-table-customizer-button:hover {
|
|
39
|
+
background: var(
|
|
40
|
+
--data-table-customizer-hover-bg,
|
|
41
|
+
var(--surface-hover, light-dark(#f5f5f5, #292d33))
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.data-table-customizer-panel {
|
|
46
|
+
position: absolute;
|
|
47
|
+
top: calc(100% + 0.375rem);
|
|
48
|
+
right: 0;
|
|
49
|
+
z-index: 20;
|
|
50
|
+
min-width: 12rem;
|
|
51
|
+
padding: 0.75rem;
|
|
52
|
+
border: 1px solid
|
|
53
|
+
var(--data-table-border, var(--border, light-dark(#d0d0d0, #30343a)));
|
|
54
|
+
border-radius: 0.5rem;
|
|
55
|
+
background: var(
|
|
56
|
+
--data-table-panel-bg,
|
|
57
|
+
var(--surface, light-dark(#ffffff, #1d2024))
|
|
58
|
+
);
|
|
59
|
+
box-shadow: 0 8px 24px rgb(0 0 0 / 12%);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.data-table-customizer-title {
|
|
63
|
+
margin: 0 0 0.5rem;
|
|
64
|
+
font-weight: 600;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.data-table-customizer-list {
|
|
68
|
+
margin: 0;
|
|
69
|
+
padding: 0;
|
|
70
|
+
list-style: none;
|
|
71
|
+
display: grid;
|
|
72
|
+
gap: 0.375rem;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.data-table-customizer-option {
|
|
76
|
+
display: flex;
|
|
77
|
+
align-items: center;
|
|
78
|
+
gap: 0.5rem;
|
|
79
|
+
cursor: pointer;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.data-table-customizer-option:has(input:disabled) {
|
|
83
|
+
opacity: 0.6;
|
|
84
|
+
cursor: not-allowed;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.data-table-customizer-actions {
|
|
88
|
+
display: flex;
|
|
89
|
+
gap: 0.5rem;
|
|
90
|
+
margin-top: 0.75rem;
|
|
91
|
+
}
|
|
92
|
+
|
|
5
93
|
.data-table {
|
|
6
94
|
width: 100%;
|
|
7
95
|
max-width: 100%;
|