@fluixi-ui/table 0.2.0-alpha.17 → 0.2.0-alpha.19
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/dist/index.js +3 -15
- package/dist/table-menu.js +266 -147
- package/dist/table.js +251 -146
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -1,17 +1,5 @@
|
|
|
1
|
-
import "@fluixi-ui/tokens/css/base.css";
|
|
2
|
-
import "@fluixi-ui/tokens/css/table.css";
|
|
3
1
|
import { Table, TableBody, TableCell, TableFooter, TableHead, TableHeader, TableRow, flexRender, useTableContext } from "./table.js";
|
|
4
2
|
import { TableColumnMenu, TableViewMenu } from "./table-menu.js";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
TableCell,
|
|
9
|
-
TableColumnMenu,
|
|
10
|
-
TableFooter,
|
|
11
|
-
TableHead,
|
|
12
|
-
TableHeader,
|
|
13
|
-
TableRow,
|
|
14
|
-
TableViewMenu,
|
|
15
|
-
flexRender,
|
|
16
|
-
useTableContext
|
|
17
|
-
};
|
|
3
|
+
import "@fluixi-ui/tokens/css/base.css";
|
|
4
|
+
import "@fluixi-ui/tokens/css/table.css";
|
|
5
|
+
export { Table, TableBody, TableCell, TableColumnMenu, TableFooter, TableHead, TableHeader, TableRow, TableViewMenu, flexRender, useTableContext };
|
package/dist/table-menu.js
CHANGED
|
@@ -1,155 +1,274 @@
|
|
|
1
|
-
import { createComponent, createNativeElement,
|
|
1
|
+
import { createComponent, createNativeElement, delegateEvents, insert, spread } from "@fluixi/dom";
|
|
2
2
|
import { createMemo, onCleanup } from "@fluixi/reactive/signal";
|
|
3
|
-
import {
|
|
4
|
-
import { ContextMenu,
|
|
3
|
+
import { For, Show } from "@fluixi/core";
|
|
4
|
+
import { ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuSeparator, ContextMenuTrigger } from "@fluixi-ui/context-menu";
|
|
5
|
+
//#region src/table-menu.tsx
|
|
5
6
|
delegateEvents(["click"]);
|
|
7
|
+
/** Stop a `contextmenu` event from bubbling past this node. Added as a ref so it
|
|
8
|
+
* fires on the same node as (and after) the menu's own open handler, letting a
|
|
9
|
+
* header menu win over an outer table-wide menu. */
|
|
6
10
|
function stopContextMenu(node) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
11
|
+
const handler = (event) => event.stopPropagation();
|
|
12
|
+
node.addEventListener("contextmenu", handler);
|
|
13
|
+
onCleanup(() => node.removeEventListener("contextmenu", handler));
|
|
10
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* Right-click menu for a single column header. Auto-lists the actions that make
|
|
17
|
+
* sense for the column — sort ascending/descending/clear (when sortable) and
|
|
18
|
+
* hide (when hideable) — plus any extra `children` items. Drop it in as a
|
|
19
|
+
* {@link TableHead}'s child; left-click still sorts. Stops propagation so it
|
|
20
|
+
* takes precedence over a surrounding {@link TableViewMenu}.
|
|
21
|
+
*/
|
|
11
22
|
function TableColumnMenu(props) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
23
|
+
const column = props.column;
|
|
24
|
+
const canSort = () => column.getCanSort?.() ?? false;
|
|
25
|
+
const isSorted = () => canSort() ? column.getIsSorted() : false;
|
|
26
|
+
const canHide = () => column.getCanHide?.() ?? false;
|
|
27
|
+
const canPin = () => column.getCanPin?.() ?? false;
|
|
28
|
+
const pinned = () => canPin() ? column.getIsPinned() : false;
|
|
29
|
+
return createMemo(() => createComponent(ContextMenu, { get children() {
|
|
30
|
+
return [createMemo(() => createComponent(ContextMenuTrigger, {
|
|
31
|
+
get ref() {
|
|
32
|
+
return stopContextMenu;
|
|
33
|
+
},
|
|
34
|
+
get "data-table-column-menu-trigger"() {
|
|
35
|
+
return "";
|
|
36
|
+
},
|
|
37
|
+
get "data-sortable"() {
|
|
38
|
+
return () => canSort() ? "" : void 0;
|
|
39
|
+
},
|
|
40
|
+
get onClick() {
|
|
41
|
+
return canSort() ? column.getToggleSortingHandler() : void 0;
|
|
42
|
+
},
|
|
43
|
+
get children() {
|
|
44
|
+
return [() => props.label ?? String(column.columnDef.header ?? column.id), createMemo(() => createComponent(Show, {
|
|
45
|
+
get when() {
|
|
46
|
+
return canSort();
|
|
47
|
+
},
|
|
48
|
+
get children() {
|
|
49
|
+
return (() => {
|
|
50
|
+
const _el$ = createNativeElement("span");
|
|
51
|
+
spread({
|
|
52
|
+
element: _el$,
|
|
53
|
+
props: {
|
|
54
|
+
"data-table-sort-indicator": "",
|
|
55
|
+
"data-direction": () => isSorted() || "none",
|
|
56
|
+
"aria-hidden": "true"
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
return _el$;
|
|
60
|
+
})();
|
|
61
|
+
}
|
|
62
|
+
}))];
|
|
63
|
+
}
|
|
64
|
+
})), createMemo(() => createComponent(ContextMenuPortal, { get children() {
|
|
65
|
+
return createMemo(() => createComponent(ContextMenuContent, { get children() {
|
|
66
|
+
return [
|
|
67
|
+
createMemo(() => createComponent(Show, {
|
|
68
|
+
get when() {
|
|
69
|
+
return canSort();
|
|
70
|
+
},
|
|
71
|
+
get children() {
|
|
72
|
+
return [
|
|
73
|
+
createMemo(() => createComponent(ContextMenuItem, {
|
|
74
|
+
get onSelect() {
|
|
75
|
+
return () => column.toggleSorting(false);
|
|
76
|
+
},
|
|
77
|
+
get children() {
|
|
78
|
+
return () => props.labels?.sortAscending ?? "Sort ascending";
|
|
79
|
+
}
|
|
80
|
+
})),
|
|
81
|
+
createMemo(() => createComponent(ContextMenuItem, {
|
|
82
|
+
get onSelect() {
|
|
83
|
+
return () => column.toggleSorting(true);
|
|
84
|
+
},
|
|
85
|
+
get children() {
|
|
86
|
+
return () => props.labels?.sortDescending ?? "Sort descending";
|
|
87
|
+
}
|
|
88
|
+
})),
|
|
89
|
+
createMemo(() => createComponent(Show, {
|
|
90
|
+
get when() {
|
|
91
|
+
return !!isSorted();
|
|
92
|
+
},
|
|
93
|
+
get children() {
|
|
94
|
+
return createMemo(() => createComponent(ContextMenuItem, {
|
|
95
|
+
get onSelect() {
|
|
96
|
+
return () => column.clearSorting();
|
|
97
|
+
},
|
|
98
|
+
get children() {
|
|
99
|
+
return () => props.labels?.clearSort ?? "Clear sort";
|
|
100
|
+
}
|
|
101
|
+
}));
|
|
102
|
+
}
|
|
103
|
+
}))
|
|
104
|
+
];
|
|
105
|
+
}
|
|
106
|
+
})),
|
|
107
|
+
createMemo(() => createComponent(Show, {
|
|
108
|
+
get when() {
|
|
109
|
+
return canSort() && (canPin() || canHide());
|
|
110
|
+
},
|
|
111
|
+
get children() {
|
|
112
|
+
return createMemo(() => createComponent(ContextMenuSeparator, {}));
|
|
113
|
+
}
|
|
114
|
+
})),
|
|
115
|
+
createMemo(() => createComponent(Show, {
|
|
116
|
+
get when() {
|
|
117
|
+
return canPin();
|
|
118
|
+
},
|
|
119
|
+
get children() {
|
|
120
|
+
return [
|
|
121
|
+
createMemo(() => createComponent(Show, {
|
|
122
|
+
get when() {
|
|
123
|
+
return pinned() !== "left";
|
|
124
|
+
},
|
|
125
|
+
get children() {
|
|
126
|
+
return createMemo(() => createComponent(ContextMenuItem, {
|
|
127
|
+
get onSelect() {
|
|
128
|
+
return () => column.pin("left");
|
|
129
|
+
},
|
|
130
|
+
get children() {
|
|
131
|
+
return () => props.labels?.pinLeft ?? "Pin left";
|
|
132
|
+
}
|
|
133
|
+
}));
|
|
134
|
+
}
|
|
135
|
+
})),
|
|
136
|
+
createMemo(() => createComponent(Show, {
|
|
137
|
+
get when() {
|
|
138
|
+
return pinned() !== "right";
|
|
139
|
+
},
|
|
140
|
+
get children() {
|
|
141
|
+
return createMemo(() => createComponent(ContextMenuItem, {
|
|
142
|
+
get onSelect() {
|
|
143
|
+
return () => column.pin("right");
|
|
144
|
+
},
|
|
145
|
+
get children() {
|
|
146
|
+
return () => props.labels?.pinRight ?? "Pin right";
|
|
147
|
+
}
|
|
148
|
+
}));
|
|
149
|
+
}
|
|
150
|
+
})),
|
|
151
|
+
createMemo(() => createComponent(Show, {
|
|
152
|
+
get when() {
|
|
153
|
+
return !!pinned();
|
|
154
|
+
},
|
|
155
|
+
get children() {
|
|
156
|
+
return createMemo(() => createComponent(ContextMenuItem, {
|
|
157
|
+
get onSelect() {
|
|
158
|
+
return () => column.pin(false);
|
|
159
|
+
},
|
|
160
|
+
get children() {
|
|
161
|
+
return () => props.labels?.unpin ?? "Unpin";
|
|
162
|
+
}
|
|
163
|
+
}));
|
|
164
|
+
}
|
|
165
|
+
}))
|
|
166
|
+
];
|
|
167
|
+
}
|
|
168
|
+
})),
|
|
169
|
+
createMemo(() => createComponent(Show, {
|
|
170
|
+
get when() {
|
|
171
|
+
return canPin() && canHide();
|
|
172
|
+
},
|
|
173
|
+
get children() {
|
|
174
|
+
return createMemo(() => createComponent(ContextMenuSeparator, {}));
|
|
175
|
+
}
|
|
176
|
+
})),
|
|
177
|
+
createMemo(() => createComponent(Show, {
|
|
178
|
+
get when() {
|
|
179
|
+
return canHide();
|
|
180
|
+
},
|
|
181
|
+
get children() {
|
|
182
|
+
return createMemo(() => createComponent(ContextMenuItem, {
|
|
183
|
+
get onSelect() {
|
|
184
|
+
return () => column.toggleVisibility(false);
|
|
185
|
+
},
|
|
186
|
+
get children() {
|
|
187
|
+
return () => props.labels?.hideColumn ?? "Hide column";
|
|
188
|
+
}
|
|
189
|
+
}));
|
|
190
|
+
}
|
|
191
|
+
})),
|
|
192
|
+
props.children
|
|
193
|
+
];
|
|
194
|
+
} }));
|
|
195
|
+
} }))];
|
|
196
|
+
} }));
|
|
107
197
|
}
|
|
198
|
+
/**
|
|
199
|
+
* Table-wide right-click menu. Lists every hideable column as a toggle (so
|
|
200
|
+
* hidden columns can be restored) plus show-all and reset-view actions. Wrap
|
|
201
|
+
* it around the whole `<Table>`; header menus stop propagation, so right-clicking
|
|
202
|
+
* a header opens its {@link TableColumnMenu} instead of this one.
|
|
203
|
+
*/
|
|
108
204
|
function TableViewMenu(props) {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
205
|
+
const table = props.table;
|
|
206
|
+
const hideableColumns = table.getAllLeafColumns().filter((c) => c.getCanHide?.() && typeof c.columnDef.header === "string");
|
|
207
|
+
const showAll = () => props.onShowAll ? props.onShowAll() : table.toggleAllColumnsVisible(true);
|
|
208
|
+
const resetView = () => {
|
|
209
|
+
if (props.onReset) return props.onReset();
|
|
210
|
+
table.resetSorting?.();
|
|
211
|
+
table.resetColumnFilters?.();
|
|
212
|
+
table.resetColumnVisibility?.();
|
|
213
|
+
table.resetColumnOrder?.();
|
|
214
|
+
};
|
|
215
|
+
return createMemo(() => createComponent(ContextMenu, { get children() {
|
|
216
|
+
return [createMemo(() => createComponent(ContextMenuTrigger, { get children() {
|
|
217
|
+
return props.children;
|
|
218
|
+
} })), createMemo(() => createComponent(ContextMenuPortal, { get children() {
|
|
219
|
+
return createMemo(() => createComponent(ContextMenuContent, { get children() {
|
|
220
|
+
return [
|
|
221
|
+
createMemo(() => createComponent(ContextMenuLabel, { get children() {
|
|
222
|
+
return () => props.labels?.columns ?? "Columns";
|
|
223
|
+
} })),
|
|
224
|
+
createMemo(() => createComponent(For, {
|
|
225
|
+
get each() {
|
|
226
|
+
return hideableColumns;
|
|
227
|
+
},
|
|
228
|
+
get children() {
|
|
229
|
+
return (column) => createMemo(() => createComponent(ContextMenuItem, {
|
|
230
|
+
get onSelect() {
|
|
231
|
+
return () => column.toggleVisibility();
|
|
232
|
+
},
|
|
233
|
+
get children() {
|
|
234
|
+
return [(() => {
|
|
235
|
+
const _el$ = createNativeElement("span");
|
|
236
|
+
spread({
|
|
237
|
+
element: _el$,
|
|
238
|
+
props: {
|
|
239
|
+
"data-table-menu-check": "",
|
|
240
|
+
"data-checked": () => column.getIsVisible() || void 0
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
insert(_el$, "✓");
|
|
244
|
+
return _el$;
|
|
245
|
+
})(), () => String(column.columnDef.header)];
|
|
246
|
+
}
|
|
247
|
+
}));
|
|
248
|
+
}
|
|
249
|
+
})),
|
|
250
|
+
createMemo(() => createComponent(ContextMenuSeparator, {})),
|
|
251
|
+
createMemo(() => createComponent(ContextMenuItem, {
|
|
252
|
+
get onSelect() {
|
|
253
|
+
return showAll;
|
|
254
|
+
},
|
|
255
|
+
get children() {
|
|
256
|
+
return () => props.labels?.showAllColumns ?? "Show all columns";
|
|
257
|
+
}
|
|
258
|
+
})),
|
|
259
|
+
createMemo(() => createComponent(ContextMenuItem, {
|
|
260
|
+
get onSelect() {
|
|
261
|
+
return resetView;
|
|
262
|
+
},
|
|
263
|
+
get children() {
|
|
264
|
+
return () => props.labels?.resetView ?? "Reset view";
|
|
265
|
+
}
|
|
266
|
+
})),
|
|
267
|
+
() => props.extra
|
|
268
|
+
];
|
|
269
|
+
} }));
|
|
270
|
+
} }))];
|
|
271
|
+
} }));
|
|
151
272
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
TableViewMenu
|
|
155
|
-
};
|
|
273
|
+
//#endregion
|
|
274
|
+
export { TableColumnMenu, TableViewMenu };
|