@serkonda7/solid-components 0.0.6 → 0.0.7
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 +2 -1
- package/dist/combobox.d.ts +48 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +300 -120
- package/dist/styles.css +218 -0
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ Reusable components for [SolidJS](https://www.solidjs.com/).
|
|
|
8
8
|
|
|
9
9
|
## 📦 Installation
|
|
10
10
|
```sh
|
|
11
|
-
bun install @serkonda7/solid-components solid-js
|
|
11
|
+
bun install @serkonda7/solid-components solid-js @tabler/icons-solidjs
|
|
12
12
|
```
|
|
13
13
|
|
|
14
14
|
|
|
@@ -26,6 +26,7 @@ import '@serkonda7/solid-components/styles.css'
|
|
|
26
26
|
|
|
27
27
|
These components are available:
|
|
28
28
|
- `DataTable` - generic table with optional sorting, row selection, actions, loading, empty states, and column customizer.
|
|
29
|
+
- `Combobox` - searchable, accessible dropdown with keyboard navigation, option icons, a detail column, and an optional "Add …" entry.
|
|
29
30
|
|
|
30
31
|
For the full API, examples, and agent notes, see [docs.md](docs.md).
|
|
31
32
|
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { Component, JSX } from 'solid-js';
|
|
2
|
+
/** Icon component rendered before an option label, e.g. one from `@tabler/icons-solidjs`. */
|
|
3
|
+
export type ComboboxIcon = Component<{
|
|
4
|
+
size?: number;
|
|
5
|
+
}>;
|
|
6
|
+
/** One `Combobox` entry. */
|
|
7
|
+
export interface ComboboxOption {
|
|
8
|
+
value: number | string;
|
|
9
|
+
label: string;
|
|
10
|
+
/** Secondary text (e.g. the manufacturer), shown muted in a column after the labels. */
|
|
11
|
+
detail?: string;
|
|
12
|
+
/** Glyph shown before the label, in the list and in the closed input. */
|
|
13
|
+
icon?: ComboboxIcon;
|
|
14
|
+
}
|
|
15
|
+
export interface ComboboxProps {
|
|
16
|
+
/** Input id, for pairing with an external `<label for>`. Generated when omitted. */
|
|
17
|
+
id?: string;
|
|
18
|
+
/** Selected option value as a string; `''` means nothing (or the empty entry) is selected. */
|
|
19
|
+
value: string;
|
|
20
|
+
/** Omitted on read-only comboboxes. */
|
|
21
|
+
onChange?: (value: string) => void;
|
|
22
|
+
options: ComboboxOption[];
|
|
23
|
+
/** Label of the empty (`''`) first entry; omit for no empty choice. */
|
|
24
|
+
emptyLabel?: string;
|
|
25
|
+
required?: boolean;
|
|
26
|
+
disabled?: boolean;
|
|
27
|
+
autofocus?: boolean;
|
|
28
|
+
ariaLabel?: string;
|
|
29
|
+
describedBy?: string;
|
|
30
|
+
/** Called whenever the list opens, e.g. to refetch the options. */
|
|
31
|
+
onOpen?: () => unknown;
|
|
32
|
+
/** Pins an "Add …" entry at the end of the list; receives the trimmed search text. */
|
|
33
|
+
onAdd?: (query: string) => void;
|
|
34
|
+
/** Text of the pinned add entry. Defaults to `Add`. */
|
|
35
|
+
addLabel?: string;
|
|
36
|
+
/** Placeholder while open and nothing is selected. Defaults to `Search`. */
|
|
37
|
+
searchLabel?: string;
|
|
38
|
+
/** Shown when no option matches the search. Defaults to `No matching objects`. */
|
|
39
|
+
noMatchesLabel?: string;
|
|
40
|
+
class?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Searchable dropdown of `options`, with an optional leading empty choice.
|
|
44
|
+
* A text combobox: typing filters the options by label and detail, arrow keys
|
|
45
|
+
* move the highlight (wrapping around), Enter picks it, Escape closes. The
|
|
46
|
+
* input shows the selected label while closed; the value sits in `data-value`.
|
|
47
|
+
*/
|
|
48
|
+
export declare function Combobox(props: ComboboxProps): JSX.Element;
|
package/dist/index.d.ts
CHANGED
|
@@ -4,4 +4,5 @@
|
|
|
4
4
|
* Add components here as they are implemented so consumers can import them
|
|
5
5
|
* from the package root.
|
|
6
6
|
*/
|
|
7
|
+
export { Combobox, type ComboboxIcon, type ComboboxOption, type ComboboxProps, } from './combobox';
|
|
7
8
|
export { DataTable, type DataTableColumn, type DataTableProps, type DataTableSort, type DataTableSortDirection, } from './data-table';
|
package/dist/index.js
CHANGED
|
@@ -1,209 +1,389 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { Dynamic as e, className as t, createComponent as n, delegateEvents as r, effect as i, insert as a, memo as o, setAttribute as s, template as c, use as l } from "solid-js/web";
|
|
2
|
+
import { IconChevronDown as u, IconPlus as d } from "@tabler/icons-solidjs";
|
|
3
|
+
import { For as f, Show as p, createEffect as m, createMemo as h, createSignal as g, createUniqueId as _, onCleanup as v, onMount as y } from "solid-js";
|
|
4
|
+
//#region src/combobox.tsx
|
|
5
|
+
var b = /*#__PURE__*/ c("<span class=combobox-value aria-hidden=true><span class=combobox-option-label></span><span class=combobox-detail>"), x = /*#__PURE__*/ c("<div role=option class=\"combobox-option combobox-option-add\">"), S = /*#__PURE__*/ c("<div class=combobox-list role=listbox>"), C = /*#__PURE__*/ c("<div><input class=combobox-input role=combobox aria-autocomplete=list autocomplete=off>"), w = /*#__PURE__*/ c("<span class=combobox-icon aria-hidden=true>"), T = /*#__PURE__*/ c("<div class=combobox-empty>"), E = /*#__PURE__*/ c("<span class=combobox-detail>"), D = /*#__PURE__*/ c("<div role=option class=combobox-option><span class=combobox-option-label>"), ee = /*#__PURE__*/ c("<span class=combobox-option-icon aria-hidden=true>");
|
|
6
|
+
function O(r) {
|
|
7
|
+
let c, v, O = _(), k = () => r.id ?? O, A = () => `${k()}-listbox`, j = (e) => `${k()}-option-${e}`, [M, N] = g(!1), [P, F] = g(""), [I, L] = g(0), R = h(() => r.emptyLabel === void 0 ? r.options : [{
|
|
8
|
+
value: "",
|
|
9
|
+
label: r.emptyLabel
|
|
10
|
+
}, ...r.options]), z = h(() => r.value === "" ? void 0 : R().find((e) => String(e.value) === r.value)), B = h(() => {
|
|
11
|
+
let e = P().trim().toLowerCase();
|
|
12
|
+
return e === "" ? R() : R().filter((t) => t.label.toLowerCase().includes(e) || (t.detail?.toLowerCase().includes(e) ?? !1));
|
|
13
|
+
}), V = () => r.options.some((e) => e.detail !== void 0), H = () => B().length, U = () => B().length + +!!r.onAdd, W = () => !r.disabled && r.onChange !== void 0;
|
|
14
|
+
y(() => {
|
|
15
|
+
r.autofocus === !0 && c?.focus();
|
|
16
|
+
}), m(() => {
|
|
17
|
+
M() && v?.querySelector(`[data-index="${I()}"]`)?.scrollIntoView({ block: "nearest" });
|
|
18
|
+
});
|
|
19
|
+
function G() {
|
|
20
|
+
if (M() || !W()) return;
|
|
21
|
+
F("");
|
|
22
|
+
let e = R().findIndex((e) => String(e.value) === r.value);
|
|
23
|
+
L(Math.max(e, 0)), N(!0), r.onOpen?.();
|
|
24
|
+
}
|
|
25
|
+
function K(e) {
|
|
26
|
+
if (N(!1), r.onAdd && e === H()) {
|
|
27
|
+
r.onAdd(P().trim());
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
let t = B()[e];
|
|
31
|
+
t && String(t.value) !== r.value && r.onChange?.(String(t.value));
|
|
32
|
+
}
|
|
33
|
+
function q(e) {
|
|
34
|
+
let t = U();
|
|
35
|
+
M() ? t > 0 && L((I() + e + t) % t) : G();
|
|
36
|
+
}
|
|
37
|
+
function J(e) {
|
|
38
|
+
if (e.key === "ArrowDown" || e.key === "ArrowUp") {
|
|
39
|
+
e.preventDefault(), q(e.key === "ArrowDown" ? 1 : -1);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
M() && (e.key === "Enter" ? (e.preventDefault(), K(I())) : e.key === "Escape" && (e.preventDefault(), e.stopPropagation(), N(!1)));
|
|
43
|
+
}
|
|
44
|
+
let te = () => M() ? z()?.label ?? r.emptyLabel ?? r.searchLabel ?? "Search" : r.emptyLabel;
|
|
45
|
+
return (() => {
|
|
46
|
+
var m = C(), h = m.firstChild;
|
|
47
|
+
h.addEventListener("blur", () => N(!1)), h.$$keydown = J, h.$$input = (e) => {
|
|
48
|
+
let t = e.currentTarget.value;
|
|
49
|
+
G(), F(t), L(0);
|
|
50
|
+
}, h.$$click = G;
|
|
51
|
+
var g = c;
|
|
52
|
+
return typeof g == "function" ? l(g, h) : c = h, a(m, n(p, {
|
|
53
|
+
get when() {
|
|
54
|
+
return o(() => !M())() && z()?.icon;
|
|
55
|
+
},
|
|
56
|
+
children: (t) => (() => {
|
|
57
|
+
var r = w();
|
|
58
|
+
return a(r, n(e, {
|
|
59
|
+
get component() {
|
|
60
|
+
return t();
|
|
61
|
+
},
|
|
62
|
+
size: 14
|
|
63
|
+
})), r;
|
|
64
|
+
})()
|
|
65
|
+
}), null), a(m, n(p, {
|
|
66
|
+
get when() {
|
|
67
|
+
return o(() => !M())() && z()?.detail;
|
|
68
|
+
},
|
|
69
|
+
get children() {
|
|
70
|
+
var e = b(), t = e.firstChild, n = t.nextSibling;
|
|
71
|
+
return a(t, () => z()?.label), a(n, () => z()?.detail), e;
|
|
72
|
+
}
|
|
73
|
+
}), null), a(m, n(u, {
|
|
74
|
+
class: "combobox-chevron",
|
|
75
|
+
size: 16,
|
|
76
|
+
"aria-hidden": "true"
|
|
77
|
+
}), null), a(m, n(p, {
|
|
78
|
+
get when() {
|
|
79
|
+
return M();
|
|
80
|
+
},
|
|
81
|
+
get children() {
|
|
82
|
+
var t = S(), o = v;
|
|
83
|
+
return typeof o == "function" ? l(o, t) : v = t, a(t, n(f, {
|
|
84
|
+
get each() {
|
|
85
|
+
return B();
|
|
86
|
+
},
|
|
87
|
+
get fallback() {
|
|
88
|
+
return (() => {
|
|
89
|
+
var e = T();
|
|
90
|
+
return a(e, () => r.noMatchesLabel ?? "No matching objects"), e;
|
|
91
|
+
})();
|
|
92
|
+
},
|
|
93
|
+
children: (t, o) => (() => {
|
|
94
|
+
var c = D(), l = c.firstChild;
|
|
95
|
+
return c.$$click = () => K(o()), c.$$mousemove = () => L(o()), c.$$mousedown = (e) => e.preventDefault(), a(l, n(p, {
|
|
96
|
+
get when() {
|
|
97
|
+
return t.icon;
|
|
98
|
+
},
|
|
99
|
+
children: (t) => (() => {
|
|
100
|
+
var r = ee();
|
|
101
|
+
return a(r, n(e, {
|
|
102
|
+
get component() {
|
|
103
|
+
return t();
|
|
104
|
+
},
|
|
105
|
+
size: 14
|
|
106
|
+
})), r;
|
|
107
|
+
})()
|
|
108
|
+
}), null), a(l, () => t.label, null), a(c, n(p, {
|
|
109
|
+
get when() {
|
|
110
|
+
return t.detail;
|
|
111
|
+
},
|
|
112
|
+
get children() {
|
|
113
|
+
var e = E();
|
|
114
|
+
return a(e, () => t.detail), e;
|
|
115
|
+
}
|
|
116
|
+
}), null), i((e) => {
|
|
117
|
+
var n = j(o()), i = o(), a = String(t.value) === r.value, l = o() === I(), u = t.value === "";
|
|
118
|
+
return n !== e.e && s(c, "id", e.e = n), i !== e.t && s(c, "data-index", e.t = i), a !== e.a && s(c, "aria-selected", e.a = a), l !== e.o && c.classList.toggle("combobox-option-active", e.o = l), u !== e.i && c.classList.toggle("combobox-option-empty", e.i = u), e;
|
|
119
|
+
}, {
|
|
120
|
+
e: void 0,
|
|
121
|
+
t: void 0,
|
|
122
|
+
a: void 0,
|
|
123
|
+
o: void 0,
|
|
124
|
+
i: void 0
|
|
125
|
+
}), c;
|
|
126
|
+
})()
|
|
127
|
+
}), null), a(t, n(p, {
|
|
128
|
+
get when() {
|
|
129
|
+
return r.onAdd;
|
|
130
|
+
},
|
|
131
|
+
get children() {
|
|
132
|
+
var e = x();
|
|
133
|
+
return e.$$click = () => K(H()), e.$$mousemove = () => L(H()), e.$$mousedown = (e) => e.preventDefault(), s(e, "aria-selected", !1), a(e, n(d, {
|
|
134
|
+
size: 14,
|
|
135
|
+
"aria-hidden": "true"
|
|
136
|
+
}), null), a(e, () => r.addLabel ?? "Add", null), i((t) => {
|
|
137
|
+
var n = j(H()), r = H(), i = H() === I();
|
|
138
|
+
return n !== t.e && s(e, "id", t.e = n), r !== t.t && s(e, "data-index", t.t = r), i !== t.a && e.classList.toggle("combobox-option-active", t.a = i), t;
|
|
139
|
+
}, {
|
|
140
|
+
e: void 0,
|
|
141
|
+
t: void 0,
|
|
142
|
+
a: void 0
|
|
143
|
+
}), e;
|
|
144
|
+
}
|
|
145
|
+
}), null), i((e) => {
|
|
146
|
+
var n = !!V(), r = A();
|
|
147
|
+
return n !== e.e && t.classList.toggle("combobox-list-detail", e.e = n), r !== e.t && s(t, "id", e.t = r), e;
|
|
148
|
+
}, {
|
|
149
|
+
e: void 0,
|
|
150
|
+
t: void 0
|
|
151
|
+
}), t;
|
|
152
|
+
}
|
|
153
|
+
}), null), i((e) => {
|
|
154
|
+
var n = r.class ? `combobox ${r.class}` : "combobox", i = !!M(), a = !(M() || !z()?.detail), o = !(M() || z()?.icon === void 0), c = k(), l = M(), u = A(), d = M() && U() > 0 ? j(I()) : void 0, f = r.ariaLabel, p = r.describedBy, g = r.required, _ = r.disabled, v = r.onChange === void 0, y = r.value, b = te();
|
|
155
|
+
return n !== e.e && t(m, e.e = n), i !== e.t && m.classList.toggle("combobox-open", e.t = i), a !== e.a && m.classList.toggle("combobox-with-detail", e.a = a), o !== e.o && m.classList.toggle("combobox-with-icon", e.o = o), c !== e.i && s(h, "id", e.i = c), l !== e.n && s(h, "aria-expanded", e.n = l), u !== e.s && s(h, "aria-controls", e.s = u), d !== e.h && s(h, "aria-activedescendant", e.h = d), f !== e.r && s(h, "aria-label", e.r = f), p !== e.d && s(h, "aria-describedby", e.d = p), g !== e.l && (h.required = e.l = g), _ !== e.u && (h.disabled = e.u = _), v !== e.c && (h.readOnly = e.c = v), y !== e.w && s(h, "data-value", e.w = y), b !== e.m && s(h, "placeholder", e.m = b), e;
|
|
156
|
+
}, {
|
|
157
|
+
e: void 0,
|
|
158
|
+
t: void 0,
|
|
159
|
+
a: void 0,
|
|
160
|
+
o: void 0,
|
|
161
|
+
i: void 0,
|
|
162
|
+
n: void 0,
|
|
163
|
+
s: void 0,
|
|
164
|
+
h: void 0,
|
|
165
|
+
r: void 0,
|
|
166
|
+
d: void 0,
|
|
167
|
+
l: void 0,
|
|
168
|
+
u: void 0,
|
|
169
|
+
c: void 0,
|
|
170
|
+
w: void 0,
|
|
171
|
+
m: void 0
|
|
172
|
+
}), i(() => h.value = M() ? P() : z()?.label ?? ""), m;
|
|
173
|
+
})();
|
|
174
|
+
}
|
|
175
|
+
r([
|
|
176
|
+
"click",
|
|
177
|
+
"input",
|
|
178
|
+
"keydown",
|
|
179
|
+
"mousedown",
|
|
180
|
+
"mousemove"
|
|
181
|
+
]);
|
|
182
|
+
//#endregion
|
|
3
183
|
//#region src/data-table.tsx
|
|
4
|
-
var
|
|
5
|
-
function
|
|
184
|
+
var k = /*#__PURE__*/ c("<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>"), A = /*#__PURE__*/ c("<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> "), j = /*#__PURE__*/ c("<th class=data-table-checkbox><span class=data-table-visually-hidden>Select rows</span><input type=checkbox>"), M = /*#__PURE__*/ c("<th>Actions"), N = /*#__PURE__*/ c("<div><div class=data-table-scroll><table class=data-table><thead><tr></tr></thead><tbody>"), P = /*#__PURE__*/ c("<li><label class=data-table-customizer-option><input type=checkbox>"), F = /*#__PURE__*/ c("<button type=button class=data-table-sort><span class=data-table-sort-indicator aria-hidden=true>"), I = /*#__PURE__*/ c("<th>"), L = /*#__PURE__*/ c("<td class=data-table-checkbox><input type=checkbox>"), R = /*#__PURE__*/ c("<td>"), z = /*#__PURE__*/ c("<tr>"), B = /*#__PURE__*/ c("<p class=data-table-status>Loading…"), V = /*#__PURE__*/ c("<p class=data-table-status>No results.");
|
|
185
|
+
function H(e) {
|
|
6
186
|
return typeof e == "function" ? e() : e;
|
|
7
187
|
}
|
|
8
|
-
function
|
|
9
|
-
let
|
|
10
|
-
let
|
|
11
|
-
return
|
|
12
|
-
},
|
|
13
|
-
function
|
|
188
|
+
function U(e) {
|
|
189
|
+
let r = h(() => H(e.rows)), c = () => H(e.loading ?? !1), u = () => H(e.selected ?? []), d = e.sortKey !== void 0 || e.sortDirection !== void 0, [y, b] = g(e.defaultSort), x = () => d ? H(e.sortKey ?? void 0) : y()?.key, S = () => d ? H(e.sortDirection ?? "asc") : y()?.direction ?? "asc", C = () => H(e.showColumnCustomizer ?? !1), w = () => e.selected !== void 0 && e.onSelectionChange !== void 0, T = () => {
|
|
190
|
+
let t = u();
|
|
191
|
+
return r().length > 0 && r().every((n) => t.includes(e.getRowId(n)));
|
|
192
|
+
}, E = h(() => e.defaultVisibleColumns ?? e.columns.filter((e) => e.defaultVisible !== !1).map((e) => e.key)), [D, ee] = g(void 0), O = () => e.visibleColumns === void 0 ? D() ?? E() : H(e.visibleColumns), U = h(() => new Set(O())), W = h(() => e.columns.filter((e) => e.toggleable === !1 || U().has(e.key))), G = h(() => e.columns.filter((e) => e.toggleable !== !1)), K = h(() => G().map((e) => e.key));
|
|
193
|
+
function q(e, t) {
|
|
14
194
|
return t.sortValue ? t.sortValue(e) : e[t.key];
|
|
15
195
|
}
|
|
16
|
-
function
|
|
196
|
+
function J(e, t) {
|
|
17
197
|
return e === t ? 0 : e == null ? -1 : t == null ? 1 : typeof e == "number" && typeof t == "number" ? e - t : String(e).localeCompare(String(t), void 0, { numeric: !0 });
|
|
18
198
|
}
|
|
19
|
-
let
|
|
20
|
-
let
|
|
21
|
-
if (
|
|
22
|
-
let
|
|
23
|
-
if (!
|
|
24
|
-
let
|
|
25
|
-
return [...
|
|
199
|
+
let te = h(() => {
|
|
200
|
+
let t = r(), n = x();
|
|
201
|
+
if (d || !n) return t;
|
|
202
|
+
let i = e.columns.find((e) => e.key === n);
|
|
203
|
+
if (!i) return t;
|
|
204
|
+
let a = S() === "asc" ? 1 : -1;
|
|
205
|
+
return [...t].sort((e, t) => a * J(q(e, i), q(t, i)));
|
|
26
206
|
});
|
|
27
|
-
function
|
|
28
|
-
let
|
|
29
|
-
key:
|
|
30
|
-
direction:
|
|
207
|
+
function ne(t) {
|
|
208
|
+
let n = x() === t, r = n && S() === "desc" ? void 0 : {
|
|
209
|
+
key: t,
|
|
210
|
+
direction: n ? "desc" : "asc"
|
|
31
211
|
};
|
|
32
|
-
|
|
212
|
+
d || b(r), e.onSort?.(t), r || e.onSortClear?.(), e.onSortChange?.(r);
|
|
33
213
|
}
|
|
34
|
-
function
|
|
35
|
-
let
|
|
36
|
-
return [...
|
|
214
|
+
function re(t) {
|
|
215
|
+
let n = new Map(e.columns.map((e, t) => [e.key, t]));
|
|
216
|
+
return [...t].sort((e, t) => (n.get(e) ?? 0) - (n.get(t) ?? 0));
|
|
37
217
|
}
|
|
38
|
-
function
|
|
39
|
-
let
|
|
40
|
-
|
|
218
|
+
function Y(t) {
|
|
219
|
+
let n = re(t);
|
|
220
|
+
e.visibleColumns === void 0 && ee(n), e.onVisibleColumnsChange?.(n);
|
|
41
221
|
}
|
|
42
|
-
function
|
|
43
|
-
let n = new Set(
|
|
44
|
-
t ? n.add(e) : n.delete(e),
|
|
222
|
+
function ie(e, t) {
|
|
223
|
+
let n = new Set(O());
|
|
224
|
+
t ? n.add(e) : n.delete(e), Y(K().filter((e) => n.has(e)));
|
|
45
225
|
}
|
|
46
|
-
function
|
|
47
|
-
|
|
226
|
+
function ae() {
|
|
227
|
+
Y(K());
|
|
48
228
|
}
|
|
49
|
-
function
|
|
50
|
-
|
|
229
|
+
function oe() {
|
|
230
|
+
Y(E());
|
|
51
231
|
}
|
|
52
|
-
let
|
|
53
|
-
|
|
54
|
-
if (!
|
|
232
|
+
let se = `${_()}-panel`, [X, Z] = g(!1), Q;
|
|
233
|
+
m(() => {
|
|
234
|
+
if (!X() || !C()) return;
|
|
55
235
|
function e(e) {
|
|
56
|
-
|
|
236
|
+
Q && !Q.contains(e.target) && Z(!1);
|
|
57
237
|
}
|
|
58
238
|
function t(e) {
|
|
59
|
-
e.key === "Escape" &&
|
|
239
|
+
e.key === "Escape" && Z(!1);
|
|
60
240
|
}
|
|
61
|
-
document.addEventListener("pointerdown", e), document.addEventListener("keydown", t),
|
|
241
|
+
document.addEventListener("pointerdown", e), document.addEventListener("keydown", t), v(() => {
|
|
62
242
|
document.removeEventListener("pointerdown", e), document.removeEventListener("keydown", t);
|
|
63
243
|
});
|
|
64
244
|
});
|
|
65
|
-
let
|
|
66
|
-
|
|
67
|
-
|
|
245
|
+
let $;
|
|
246
|
+
m(() => {
|
|
247
|
+
$ && ($.indeterminate = u().length > 0 && !T());
|
|
68
248
|
});
|
|
69
|
-
function
|
|
70
|
-
|
|
249
|
+
function ce(t) {
|
|
250
|
+
e.onSelectionChange?.(t ? r().map(e.getRowId) : []);
|
|
71
251
|
}
|
|
72
|
-
function le(
|
|
73
|
-
let r =
|
|
74
|
-
|
|
252
|
+
function le(t, n) {
|
|
253
|
+
let r = e.getRowId(t), i = u(), a = n ? [...i, r] : i.filter((e) => e !== r);
|
|
254
|
+
e.onSelectionChange?.(a);
|
|
75
255
|
}
|
|
76
|
-
function ue(
|
|
77
|
-
return
|
|
256
|
+
function ue(t) {
|
|
257
|
+
return u().includes(e.getRowId(t));
|
|
78
258
|
}
|
|
79
259
|
function de(e) {
|
|
80
|
-
return e.toggleable === !1 ||
|
|
260
|
+
return e.toggleable === !1 || U().has(e.key);
|
|
81
261
|
}
|
|
82
|
-
function fe(
|
|
83
|
-
return
|
|
262
|
+
function fe(t, n) {
|
|
263
|
+
return e.getCell?.(t, n) ?? n.getValue?.(t) ?? null;
|
|
84
264
|
}
|
|
85
265
|
return (() => {
|
|
86
|
-
var
|
|
87
|
-
return
|
|
266
|
+
var u = N(), m = u.firstChild, h = m.firstChild.firstChild, g = h.firstChild, _ = h.nextSibling;
|
|
267
|
+
return a(u, n(p, {
|
|
88
268
|
get when() {
|
|
89
|
-
return
|
|
269
|
+
return C();
|
|
90
270
|
},
|
|
91
271
|
get children() {
|
|
92
|
-
var
|
|
93
|
-
|
|
94
|
-
var
|
|
95
|
-
return typeof
|
|
272
|
+
var t = A(), r = t.firstChild, o = r.firstChild;
|
|
273
|
+
o.firstChild.nextSibling;
|
|
274
|
+
var c = Q;
|
|
275
|
+
return typeof c == "function" ? l(c, r) : Q = r, o.$$click = () => Z((e) => !e), s(o, "aria-controls", se), a(o, () => e.columnCustomizerLabel ?? "Columns", null), a(r, n(p, {
|
|
96
276
|
get when() {
|
|
97
|
-
return
|
|
277
|
+
return X();
|
|
98
278
|
},
|
|
99
279
|
get children() {
|
|
100
|
-
var
|
|
101
|
-
return
|
|
280
|
+
var t = k(), r = t.firstChild, o = r.nextSibling, c = o.nextSibling.firstChild, l = c.nextSibling;
|
|
281
|
+
return s(t, "id", se), a(r, () => e.columnCustomizerTitle ?? "Shown columns"), a(o, n(f, {
|
|
102
282
|
get each() {
|
|
103
|
-
return
|
|
283
|
+
return e.columns;
|
|
104
284
|
},
|
|
105
285
|
children: (e) => (() => {
|
|
106
|
-
var t =
|
|
107
|
-
return
|
|
286
|
+
var t = P(), n = t.firstChild, r = n.firstChild;
|
|
287
|
+
return r.addEventListener("change", (t) => ie(e.key, t.currentTarget.checked)), a(n, () => e.ariaLabel ?? e.label, null), i(() => r.disabled = e.toggleable === !1), i(() => r.checked = de(e)), t;
|
|
108
288
|
})()
|
|
109
|
-
})), c.$$click =
|
|
289
|
+
})), c.$$click = ae, a(c, () => e.columnCustomizerShowAllLabel ?? "Show all"), l.$$click = oe, a(l, () => e.columnCustomizerResetLabel ?? "Reset"), i(() => s(t, "aria-label", e.columnCustomizerTitle ?? "Customize columns")), t;
|
|
110
290
|
}
|
|
111
|
-
}), null),
|
|
291
|
+
}), null), i(() => s(o, "aria-expanded", X())), t;
|
|
112
292
|
}
|
|
113
|
-
}),
|
|
293
|
+
}), m), a(g, n(p, {
|
|
114
294
|
get when() {
|
|
115
|
-
return
|
|
295
|
+
return w();
|
|
116
296
|
},
|
|
117
297
|
get children() {
|
|
118
|
-
var
|
|
119
|
-
|
|
120
|
-
var
|
|
121
|
-
return typeof
|
|
298
|
+
var t = j(), n = t.firstChild.nextSibling;
|
|
299
|
+
n.addEventListener("change", (e) => ce(e.currentTarget.checked));
|
|
300
|
+
var r = $;
|
|
301
|
+
return typeof r == "function" ? l(r, n) : $ = n, i(() => s(n, "aria-label", e.selectionLabel ?? "Select all rows")), i(() => n.checked = T()), t;
|
|
122
302
|
}
|
|
123
|
-
}), null),
|
|
303
|
+
}), null), a(g, n(f, {
|
|
124
304
|
get each() {
|
|
125
|
-
return
|
|
305
|
+
return W();
|
|
126
306
|
},
|
|
127
|
-
children: (
|
|
128
|
-
var c =
|
|
129
|
-
return
|
|
307
|
+
children: (r) => (() => {
|
|
308
|
+
var c = I();
|
|
309
|
+
return a(c, n(p, {
|
|
130
310
|
get when() {
|
|
131
|
-
return
|
|
311
|
+
return o(() => !!r.sortable)() && (!d || e.onSort || e.onSortChange);
|
|
132
312
|
},
|
|
133
313
|
get fallback() {
|
|
134
|
-
return
|
|
314
|
+
return r.label;
|
|
135
315
|
},
|
|
136
316
|
get children() {
|
|
137
|
-
var e =
|
|
138
|
-
return e.$$click = () =>
|
|
139
|
-
var e =
|
|
140
|
-
return () => e() ?
|
|
317
|
+
var e = F(), t = e.firstChild;
|
|
318
|
+
return e.$$click = () => ne(r.key), a(e, () => r.label, t), a(t, (() => {
|
|
319
|
+
var e = o(() => x() === r.key);
|
|
320
|
+
return () => e() ? S() === "asc" ? "▲" : "▼" : "";
|
|
141
321
|
})()), e;
|
|
142
322
|
}
|
|
143
|
-
})),
|
|
144
|
-
var n =
|
|
145
|
-
return n !==
|
|
323
|
+
})), i((e) => {
|
|
324
|
+
var n = r.class, i = r.sortable ? x() === r.key ? S() === "asc" ? "ascending" : "descending" : "none" : void 0;
|
|
325
|
+
return n !== e.e && t(c, e.e = n), i !== e.t && s(c, "aria-sort", e.t = i), e;
|
|
146
326
|
}, {
|
|
147
327
|
e: void 0,
|
|
148
328
|
t: void 0
|
|
149
329
|
}), c;
|
|
150
330
|
})()
|
|
151
|
-
}), null),
|
|
331
|
+
}), null), a(g, n(p, {
|
|
152
332
|
get when() {
|
|
153
|
-
return
|
|
333
|
+
return e.rowActions;
|
|
154
334
|
},
|
|
155
335
|
get children() {
|
|
156
|
-
return
|
|
336
|
+
return M();
|
|
157
337
|
}
|
|
158
|
-
}), null),
|
|
338
|
+
}), null), a(_, n(f, {
|
|
159
339
|
get each() {
|
|
160
|
-
return
|
|
340
|
+
return te();
|
|
161
341
|
},
|
|
162
|
-
children: (
|
|
163
|
-
var
|
|
164
|
-
return
|
|
342
|
+
children: (r) => (() => {
|
|
343
|
+
var o = z();
|
|
344
|
+
return a(o, n(p, {
|
|
165
345
|
get when() {
|
|
166
|
-
return
|
|
346
|
+
return w();
|
|
167
347
|
},
|
|
168
348
|
get children() {
|
|
169
|
-
var
|
|
170
|
-
return
|
|
349
|
+
var t = L(), n = t.firstChild;
|
|
350
|
+
return n.addEventListener("change", (e) => le(r, e.currentTarget.checked)), i(() => s(n, "aria-label", `Select row ${e.getRowId(r)}`)), i(() => n.checked = ue(r)), t;
|
|
171
351
|
}
|
|
172
|
-
}), null),
|
|
352
|
+
}), null), a(o, n(f, {
|
|
173
353
|
get each() {
|
|
174
|
-
return
|
|
354
|
+
return W();
|
|
175
355
|
},
|
|
176
|
-
children: (
|
|
177
|
-
var n =
|
|
178
|
-
return
|
|
356
|
+
children: (e) => (() => {
|
|
357
|
+
var n = R();
|
|
358
|
+
return a(n, () => fe(r, e)), i(() => t(n, e.class)), n;
|
|
179
359
|
})()
|
|
180
|
-
}), null),
|
|
360
|
+
}), null), a(o, n(p, {
|
|
181
361
|
get when() {
|
|
182
|
-
return
|
|
362
|
+
return e.rowActions;
|
|
183
363
|
},
|
|
184
364
|
get children() {
|
|
185
|
-
var
|
|
186
|
-
return
|
|
365
|
+
var t = R();
|
|
366
|
+
return a(t, () => e.rowActions?.(r)), t;
|
|
187
367
|
}
|
|
188
|
-
}), null),
|
|
368
|
+
}), null), o;
|
|
189
369
|
})()
|
|
190
|
-
})),
|
|
370
|
+
})), a(u, n(p, {
|
|
191
371
|
get when() {
|
|
192
|
-
return
|
|
372
|
+
return c();
|
|
193
373
|
},
|
|
194
374
|
get children() {
|
|
195
|
-
return
|
|
375
|
+
return e.loadingContent ?? B();
|
|
196
376
|
}
|
|
197
|
-
}), null),
|
|
377
|
+
}), null), a(u, n(p, {
|
|
198
378
|
get when() {
|
|
199
|
-
return
|
|
379
|
+
return o(() => !c())() && (e.empty === void 0 ? r().length === 0 : H(e.empty));
|
|
200
380
|
},
|
|
201
381
|
get children() {
|
|
202
|
-
return
|
|
382
|
+
return e.emptyContent ?? V();
|
|
203
383
|
}
|
|
204
|
-
}), null),
|
|
384
|
+
}), null), i(() => t(u, `data-table-wrap${e.class ? ` ${e.class}` : ""}`)), u;
|
|
205
385
|
})();
|
|
206
386
|
}
|
|
207
|
-
|
|
387
|
+
r(["click"]);
|
|
208
388
|
//#endregion
|
|
209
|
-
export {
|
|
389
|
+
export { O as Combobox, U as DataTable };
|
package/dist/styles.css
CHANGED
|
@@ -137,3 +137,221 @@
|
|
|
137
137
|
clip: rect(0 0 0 0);
|
|
138
138
|
white-space: nowrap;
|
|
139
139
|
}
|
|
140
|
+
|
|
141
|
+
/* Combobox: text input plus an absolutely positioned listbox below it. */
|
|
142
|
+
.combobox {
|
|
143
|
+
position: relative;
|
|
144
|
+
min-width: 0;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.combobox-input {
|
|
148
|
+
box-sizing: border-box;
|
|
149
|
+
width: 100%;
|
|
150
|
+
padding: 0.375rem 1.8rem 0.375rem 0.5rem;
|
|
151
|
+
border: 1px solid
|
|
152
|
+
var(--combobox-border, var(--border, light-dark(#d0d0d0, #3a3e45)));
|
|
153
|
+
border-radius: 0.375rem;
|
|
154
|
+
background: var(
|
|
155
|
+
--combobox-bg,
|
|
156
|
+
var(--surface, light-dark(#ffffff, #1d2024))
|
|
157
|
+
);
|
|
158
|
+
color: inherit;
|
|
159
|
+
font: inherit;
|
|
160
|
+
text-overflow: ellipsis;
|
|
161
|
+
cursor: pointer;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.combobox-open .combobox-input {
|
|
165
|
+
cursor: text;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.combobox-input:disabled {
|
|
169
|
+
cursor: not-allowed;
|
|
170
|
+
opacity: 0.6;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.combobox-with-detail .combobox-input {
|
|
174
|
+
/* The `.combobox-value` overlay renders the label alongside its detail. */
|
|
175
|
+
color: transparent;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.combobox-with-icon .combobox-input {
|
|
179
|
+
padding-left: 1.7rem;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/* Closed-state glyph of the selected option, inside the input's left padding. */
|
|
183
|
+
.combobox-icon {
|
|
184
|
+
position: absolute;
|
|
185
|
+
top: 50%;
|
|
186
|
+
left: 0.55rem;
|
|
187
|
+
display: inline-flex;
|
|
188
|
+
transform: translateY(-50%);
|
|
189
|
+
color: var(
|
|
190
|
+
--combobox-muted,
|
|
191
|
+
var(--text-secondary, light-dark(#616161, #9b9da5))
|
|
192
|
+
);
|
|
193
|
+
pointer-events: none;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
.combobox-option-icon {
|
|
197
|
+
display: inline-flex;
|
|
198
|
+
margin-right: 0.4rem;
|
|
199
|
+
vertical-align: -0.15em;
|
|
200
|
+
color: var(
|
|
201
|
+
--combobox-muted,
|
|
202
|
+
var(--text-secondary, light-dark(#616161, #9b9da5))
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.combobox-chevron {
|
|
207
|
+
position: absolute;
|
|
208
|
+
top: 50%;
|
|
209
|
+
right: 0.5rem;
|
|
210
|
+
transform: translateY(-50%);
|
|
211
|
+
color: var(
|
|
212
|
+
--combobox-muted,
|
|
213
|
+
var(--text-secondary, light-dark(#616161, #9b9da5))
|
|
214
|
+
);
|
|
215
|
+
pointer-events: none;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.combobox-list {
|
|
219
|
+
position: absolute;
|
|
220
|
+
top: calc(100% + 0.2rem);
|
|
221
|
+
left: 0;
|
|
222
|
+
right: 0;
|
|
223
|
+
z-index: 20;
|
|
224
|
+
max-height: 16rem;
|
|
225
|
+
overflow-y: auto;
|
|
226
|
+
margin: 0;
|
|
227
|
+
padding: 0.2rem;
|
|
228
|
+
border: 1px solid
|
|
229
|
+
var(--combobox-border, var(--border, light-dark(#d0d0d0, #3a3e45)));
|
|
230
|
+
border-radius: 0.375rem;
|
|
231
|
+
background: var(
|
|
232
|
+
--combobox-panel-bg,
|
|
233
|
+
var(--surface, light-dark(#ffffff, #1d2024))
|
|
234
|
+
);
|
|
235
|
+
box-shadow: 0 8px 24px rgb(0 0 0 / 12%);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
.combobox-option,
|
|
239
|
+
.combobox-empty {
|
|
240
|
+
padding: 0.3rem 0.5rem;
|
|
241
|
+
border-radius: 0.25rem;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
.combobox-option {
|
|
245
|
+
cursor: pointer;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
.combobox-option-label,
|
|
249
|
+
.combobox-detail {
|
|
250
|
+
overflow: hidden;
|
|
251
|
+
text-overflow: ellipsis;
|
|
252
|
+
white-space: nowrap;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
.combobox-detail {
|
|
256
|
+
color: var(
|
|
257
|
+
--combobox-muted,
|
|
258
|
+
var(--text-secondary, light-dark(#616161, #9b9da5))
|
|
259
|
+
);
|
|
260
|
+
font-weight: 400;
|
|
261
|
+
font-size: 0.875em;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/* Closed-state value with detail, overlaid on the (transparent) input text. */
|
|
265
|
+
.combobox-value {
|
|
266
|
+
position: absolute;
|
|
267
|
+
top: 50%;
|
|
268
|
+
left: calc(0.5rem + 1px);
|
|
269
|
+
right: 1.8rem;
|
|
270
|
+
transform: translateY(-50%);
|
|
271
|
+
display: flex;
|
|
272
|
+
align-items: baseline;
|
|
273
|
+
gap: 0.6rem;
|
|
274
|
+
min-width: 0;
|
|
275
|
+
pointer-events: none;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
.combobox-with-icon .combobox-value {
|
|
279
|
+
left: calc(1.7rem + 1px);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
.combobox-value > .combobox-option-label {
|
|
283
|
+
flex: 0 1 auto;
|
|
284
|
+
min-width: 3rem;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
.combobox-value > .combobox-detail {
|
|
288
|
+
flex: 0 1 auto;
|
|
289
|
+
min-width: 0;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
.combobox-option-active {
|
|
293
|
+
background: var(
|
|
294
|
+
--combobox-hover-bg,
|
|
295
|
+
var(--surface-hover, light-dark(#f5f5f5, #292d33))
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
.combobox-option[aria-selected="true"] {
|
|
300
|
+
font-weight: 600;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/* Pinned "Add …" entry below the options, kept in view while scrolling. */
|
|
304
|
+
.combobox-option-add {
|
|
305
|
+
position: sticky;
|
|
306
|
+
bottom: -0.2rem;
|
|
307
|
+
display: flex;
|
|
308
|
+
align-items: center;
|
|
309
|
+
gap: 0.4rem;
|
|
310
|
+
margin-top: 0.2rem;
|
|
311
|
+
border-top: 1px solid
|
|
312
|
+
var(--combobox-border, var(--border, light-dark(#d0d0d0, #3a3e45)));
|
|
313
|
+
border-radius: 0 0 0.25rem 0.25rem;
|
|
314
|
+
background: var(
|
|
315
|
+
--combobox-panel-bg,
|
|
316
|
+
var(--surface, light-dark(#ffffff, #1d2024))
|
|
317
|
+
);
|
|
318
|
+
color: var(--combobox-accent, var(--primary, light-dark(#1a66d6, #6ea8fe)));
|
|
319
|
+
font-weight: 600;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
.combobox-option-add.combobox-option-active {
|
|
323
|
+
background: var(
|
|
324
|
+
--combobox-hover-bg,
|
|
325
|
+
var(--surface-hover, light-dark(#f5f5f5, #292d33))
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
.combobox-option-empty,
|
|
330
|
+
.combobox-empty {
|
|
331
|
+
color: var(
|
|
332
|
+
--combobox-muted,
|
|
333
|
+
var(--text-secondary, light-dark(#616161, #9b9da5))
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/* Options with a detail line up in two columns: the detail starts right
|
|
338
|
+
after the longest label. */
|
|
339
|
+
.combobox-list-detail {
|
|
340
|
+
display: grid;
|
|
341
|
+
grid-template-columns: minmax(0, max-content) minmax(0, 1fr);
|
|
342
|
+
column-gap: 1rem;
|
|
343
|
+
align-content: start;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
.combobox-list-detail > .combobox-option,
|
|
347
|
+
.combobox-list-detail > .combobox-empty {
|
|
348
|
+
display: grid;
|
|
349
|
+
grid-column: 1 / -1;
|
|
350
|
+
grid-template-columns: subgrid;
|
|
351
|
+
align-items: baseline;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
.combobox-list-detail > .combobox-option-add {
|
|
355
|
+
display: flex;
|
|
356
|
+
align-items: center;
|
|
357
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@serkonda7/solid-components",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7",
|
|
4
4
|
"description": "Reusable components for SolidJS",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "serkonda7",
|
|
@@ -39,17 +39,19 @@
|
|
|
39
39
|
},
|
|
40
40
|
"packageManager": "bun@1.4.2",
|
|
41
41
|
"peerDependencies": {
|
|
42
|
+
"@tabler/icons-solidjs": ">=3.0.0",
|
|
42
43
|
"solid-js": ">=1.9.0"
|
|
43
44
|
},
|
|
44
45
|
"devDependencies": {
|
|
45
46
|
"@biomejs/biome": "2.5.14",
|
|
47
|
+
"@tabler/icons-solidjs": "~3.48.0",
|
|
46
48
|
"@types/bun": "1.4.2",
|
|
47
49
|
"@vitest/browser-playwright": "^5.0.2",
|
|
48
|
-
"playwright": "
|
|
50
|
+
"playwright": "~1.63.0",
|
|
49
51
|
"solid-js": "~1.9.15",
|
|
50
52
|
"typescript": "~7.0.2",
|
|
51
53
|
"vite": "~8.3.0",
|
|
52
54
|
"vite-plugin-solid": "~2.11.14",
|
|
53
|
-
"vitest": "
|
|
55
|
+
"vitest": "~5.0.2"
|
|
54
56
|
}
|
|
55
57
|
}
|