@wpmoo/ui 1.0.0-rc.6 → 1.0.0-rc.8
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/ASSET_LICENSE.md +1 -1
- package/README.md +37 -6
- package/certification.json +6 -2
- package/dist/assets/css/moo-ui.css +7799 -8113
- package/dist/assets/css/moo-ui.min.css +5 -5
- package/dist/assets/css/moo.css +707 -685
- package/dist/assets/css/moo.min.css +5 -5
- package/dist/js/chart.js +57 -5
- package/dist/js/chart.min.js +3 -3
- package/dist/js/combobox.js +1 -1
- package/dist/js/context-menu.js +1 -1
- package/dist/js/datatable.js +114 -213
- package/dist/js/datepicker.js +79 -37
- package/dist/js/datepicker.min.js +2 -2
- package/dist/js/moo-ui.js +169 -52
- package/dist/js/moo-ui.min.js +3 -3
- package/dist/js/sidebar.js +122 -175
- package/dist/js/slider.js +1 -1
- package/dist/js/theme-prepaint.js +91 -0
- package/dist/release-manifest.json +24 -0
- package/package.json +12 -8
- package/scss/_components.scss +1 -4
- package/scss/components/_alert.scss +1 -2
- package/scss/components/_card.scss +5 -5
- package/scss/components/_close_button.scss +8 -3
- package/scss/components/_dialog.scss +16 -0
- package/scss/components/_dropdown.scss +12 -7
- package/scss/components/_search_trigger.scss +62 -0
- package/scss/components/_sidebar.scss +1 -2
- package/scss/components/_switch.scss +13 -5
- package/scss/components/_tabs.scss +1 -1
- package/scss/components/sidebar/_base.scss +93 -0
- package/scss/components/sidebar/_collapsed.scss +9 -90
- package/scss/foundations/_backdrop.scss +128 -0
- package/scss/foundations/_scope.scss +8 -0
- package/scss/layouts/_app.scss +77 -0
- package/scss/layouts/app/sidebar/_base.scss +117 -0
- package/scss/layouts/app/sidebar/_default.scss +26 -0
- package/scss/layouts/app/sidebar/_floating.scss +44 -0
- package/scss/layouts/app/sidebar/_inset.scss +29 -0
- package/scss/mixins/_banner.scss +3 -0
- package/scss/moo-core.scss +6 -34
- package/scss/moo-ui.scss +6 -6
- package/scss/settings/_bootstrap_overrides.scss +4 -0
- package/scss/settings/_component_variables.scss +20 -1
- package/scss/settings/_options.scss +2 -0
- package/scss/settings/_palette.scss +1 -1
- package/scss/themes/_forms.scss +15 -0
- package/scss/themes/_root.scss +16 -0
- package/scss/themes/_standalone.scss +5 -0
- package/scss/themes/{_scoped_core.scss → _theme.scss} +1 -0
- package/scss/components/sidebar/_inset.scss +0 -59
- package/scss/components/sidebar/_layout.scss +0 -176
- package/scss/foundations/_core_state_layer.scss +0 -25
- package/scss/foundations/_overlay_backdrop.scss +0 -19
- package/scss/themes/_standalone_root.scss +0 -119
- /package/scss/foundations/{_core_global_primitives.scss → _globals.scss} +0 -0
package/dist/js/datatable.js
CHANGED
|
@@ -1,23 +1,60 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* Moo UI datatable.js v1.0.0-rc.
|
|
2
|
+
* Moo UI datatable.js v1.0.0-rc.8 (https://ui.wpmoo.org/)
|
|
3
3
|
* Copyright 2026 WPMoo (https://wpmoo.org)
|
|
4
4
|
* Licensed under MIT (https://github.com/wpmoo-org/ui/blob/main/LICENSE)
|
|
5
5
|
*/
|
|
6
|
-
|
|
6
|
+
var __defProp = Object.defineProperty;
|
|
7
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
8
|
+
|
|
9
|
+
// src/js/theme-owner.js
|
|
10
|
+
var OWNER_SELECTOR = '.moo-ui[data-bs-theme="light"], .moo-ui[data-bs-theme="dark"]';
|
|
11
|
+
var PORTAL_SELECTOR = "[data-moo-overlay-portal-host]";
|
|
12
|
+
function documentFor(node) {
|
|
13
|
+
if (node?.nodeType === 9) return node;
|
|
14
|
+
if (node?.ownerDocument) return node.ownerDocument;
|
|
15
|
+
return typeof document === "undefined" ? null : document;
|
|
16
|
+
}
|
|
17
|
+
__name(documentFor, "documentFor");
|
|
18
|
+
function isResolvedOwner(node) {
|
|
19
|
+
return Boolean(node?.matches?.(OWNER_SELECTOR));
|
|
20
|
+
}
|
|
21
|
+
__name(isResolvedOwner, "isResolvedOwner");
|
|
22
|
+
function ownerRootFor(node) {
|
|
23
|
+
const ownerDocument = documentFor(node);
|
|
24
|
+
if (node?.nodeType === 9 || node === ownerDocument?.body) {
|
|
25
|
+
return ownerDocument?.body?.firstElementChild || null;
|
|
26
|
+
}
|
|
27
|
+
return node;
|
|
28
|
+
}
|
|
29
|
+
__name(ownerRootFor, "ownerRootFor");
|
|
30
|
+
function findThemeOwner(node = typeof document === "undefined" ? null : document) {
|
|
31
|
+
const start = ownerRootFor(node);
|
|
32
|
+
if (!start) return null;
|
|
33
|
+
if (isResolvedOwner(start)) return start;
|
|
34
|
+
return start.closest?.(OWNER_SELECTOR) || null;
|
|
35
|
+
}
|
|
36
|
+
__name(findThemeOwner, "findThemeOwner");
|
|
37
|
+
function ownerPortalRoot(owner) {
|
|
38
|
+
if (!owner) return null;
|
|
39
|
+
return Array.from(owner.children || []).find(
|
|
40
|
+
(child) => child.matches?.(PORTAL_SELECTOR)
|
|
41
|
+
) || owner;
|
|
42
|
+
}
|
|
43
|
+
__name(ownerPortalRoot, "ownerPortalRoot");
|
|
7
44
|
|
|
45
|
+
// src/js/components/datatable.js
|
|
46
|
+
var instances = /* @__PURE__ */ new WeakMap();
|
|
8
47
|
function normalize(value) {
|
|
9
48
|
return (value ?? "").toString().trim().toLowerCase();
|
|
10
49
|
}
|
|
11
|
-
|
|
12
|
-
|
|
50
|
+
__name(normalize, "normalize");
|
|
51
|
+
var _DataTable = class _DataTable {
|
|
13
52
|
static getInstance(element) {
|
|
14
53
|
return element?.nodeType === 1 ? instances.get(element) || null : null;
|
|
15
54
|
}
|
|
16
|
-
|
|
17
55
|
static getOrCreateInstance(element, config = {}) {
|
|
18
|
-
return
|
|
56
|
+
return _DataTable.getInstance(element) || new _DataTable(element, config);
|
|
19
57
|
}
|
|
20
|
-
|
|
21
58
|
constructor(element, config = {}) {
|
|
22
59
|
if (element?.nodeType !== 1 || !element.matches(".datatable")) {
|
|
23
60
|
throw new TypeError("DataTable requires a .datatable root element.");
|
|
@@ -26,7 +63,6 @@ export default class DataTable {
|
|
|
26
63
|
if (existing) {
|
|
27
64
|
return existing;
|
|
28
65
|
}
|
|
29
|
-
|
|
30
66
|
this._element = element;
|
|
31
67
|
this._document = element.ownerDocument;
|
|
32
68
|
this._window = this._document.defaultView;
|
|
@@ -39,34 +75,31 @@ export default class DataTable {
|
|
|
39
75
|
const cardById = new Map(
|
|
40
76
|
Array.from(element.querySelectorAll("[data-datatable-card]")).map((card) => [card.dataset.datatableCardFor, card])
|
|
41
77
|
);
|
|
42
|
-
|
|
43
78
|
this._config = { ...config };
|
|
44
79
|
this._listeners = [];
|
|
45
80
|
this._pageSize = Number(element.dataset.datatablePageSize) || 10;
|
|
46
81
|
this._currentPage = 1;
|
|
47
82
|
this._sortKey = null;
|
|
48
83
|
this._sortDirection = null;
|
|
49
|
-
this._selectedIds = new Set();
|
|
50
|
-
this._facetSelections = new Map();
|
|
51
|
-
this._visibleFacets = new Map();
|
|
84
|
+
this._selectedIds = /* @__PURE__ */ new Set();
|
|
85
|
+
this._facetSelections = /* @__PURE__ */ new Map();
|
|
86
|
+
this._visibleFacets = /* @__PURE__ */ new Map();
|
|
52
87
|
this._searchTerm = "";
|
|
53
88
|
this._tooltips = [];
|
|
54
89
|
this._filterMode = element.dataset.datatableFilterMode || "inline";
|
|
55
|
-
this._reparentedRowMenus = new Map();
|
|
56
|
-
this._reparentedRowMenuByTrigger = new WeakMap();
|
|
57
|
-
this._reparentedSortMenus = new Map();
|
|
58
|
-
this._reparentedSortMenuByTrigger = new WeakMap();
|
|
59
|
-
|
|
90
|
+
this._reparentedRowMenus = /* @__PURE__ */ new Map();
|
|
91
|
+
this._reparentedRowMenuByTrigger = /* @__PURE__ */ new WeakMap();
|
|
92
|
+
this._reparentedSortMenus = /* @__PURE__ */ new Map();
|
|
93
|
+
this._reparentedSortMenuByTrigger = /* @__PURE__ */ new WeakMap();
|
|
60
94
|
this._rows = Array.from(this._tbody.querySelectorAll(":scope > tr[data-datatable-row]")).map((tr, index) => ({
|
|
61
95
|
element: tr,
|
|
62
96
|
cardElement: cardById.get(tr.id) || null,
|
|
63
97
|
index,
|
|
64
98
|
search: normalize(tr.dataset.datatableSearch),
|
|
65
|
-
facets: this._readFacets(tr)
|
|
99
|
+
facets: this._readFacets(tr)
|
|
66
100
|
}));
|
|
67
101
|
this._readInitialFacetVisibility();
|
|
68
102
|
this._readInitialSort();
|
|
69
|
-
|
|
70
103
|
instances.set(element, this);
|
|
71
104
|
this._bindEvents();
|
|
72
105
|
this._render();
|
|
@@ -75,7 +108,6 @@ export default class DataTable {
|
|
|
75
108
|
this._initRowActionDropdowns();
|
|
76
109
|
this._initSortDropdowns();
|
|
77
110
|
}
|
|
78
|
-
|
|
79
111
|
dispose() {
|
|
80
112
|
this._disposeRowActionDropdowns();
|
|
81
113
|
this._disposeSortDropdowns();
|
|
@@ -89,11 +121,9 @@ export default class DataTable {
|
|
|
89
121
|
this._tooltips = [];
|
|
90
122
|
instances.delete(this._element);
|
|
91
123
|
}
|
|
92
|
-
|
|
93
124
|
getSelectedIds() {
|
|
94
125
|
return Array.from(this._selectedIds);
|
|
95
126
|
}
|
|
96
|
-
|
|
97
127
|
_listen(target, type, handler, options) {
|
|
98
128
|
if (!target) {
|
|
99
129
|
return;
|
|
@@ -101,9 +131,9 @@ export default class DataTable {
|
|
|
101
131
|
target.addEventListener(type, handler, options);
|
|
102
132
|
this._listeners.push({ target, type, handler, options });
|
|
103
133
|
}
|
|
104
|
-
|
|
105
134
|
// Row menus are authored next to their trigger so the public HTML stays
|
|
106
|
-
// inspectable, but when opened they are temporarily moved
|
|
135
|
+
// inspectable, but when opened they are temporarily moved to their nearest
|
|
136
|
+
// Moo owner portal.
|
|
107
137
|
// That keeps the menu out of the scroll wrapper's layout math, so Safari
|
|
108
138
|
// cannot clip it at the rounded frame edge or shift the visible table
|
|
109
139
|
// slice while Popper positions it against the viewport.
|
|
@@ -112,10 +142,9 @@ export default class DataTable {
|
|
|
112
142
|
// selected separately so both views get the same fixed Popper config.
|
|
113
143
|
_rowActionTriggers() {
|
|
114
144
|
return this._element.querySelectorAll(
|
|
115
|
-
|
|
145
|
+
'.table-responsive .table-row-actions [data-bs-toggle="dropdown"], [data-datatable-card] .table-row-actions [data-bs-toggle="dropdown"]'
|
|
116
146
|
);
|
|
117
147
|
}
|
|
118
|
-
|
|
119
148
|
_initRowActionDropdowns() {
|
|
120
149
|
const Dropdown = this._bootstrap("Dropdown");
|
|
121
150
|
if (!Dropdown) {
|
|
@@ -123,17 +152,15 @@ export default class DataTable {
|
|
|
123
152
|
}
|
|
124
153
|
this._rowActionTriggers().forEach((trigger) => {
|
|
125
154
|
Dropdown.getOrCreateInstance(trigger, {
|
|
126
|
-
popperConfig: (defaultConfig) => this._clippingSafePopperConfig(defaultConfig),
|
|
155
|
+
popperConfig: /* @__PURE__ */ __name((defaultConfig) => this._clippingSafePopperConfig(defaultConfig), "popperConfig")
|
|
127
156
|
});
|
|
128
157
|
});
|
|
129
158
|
}
|
|
130
|
-
|
|
131
159
|
_sortTriggers() {
|
|
132
160
|
return this._element.querySelectorAll(
|
|
133
|
-
|
|
161
|
+
'.datatable-sort [data-bs-toggle="dropdown"]'
|
|
134
162
|
);
|
|
135
163
|
}
|
|
136
|
-
|
|
137
164
|
_initSortDropdowns() {
|
|
138
165
|
const Dropdown = this._bootstrap("Dropdown");
|
|
139
166
|
if (!Dropdown) {
|
|
@@ -141,34 +168,32 @@ export default class DataTable {
|
|
|
141
168
|
}
|
|
142
169
|
this._sortTriggers().forEach((trigger) => {
|
|
143
170
|
Dropdown.getOrCreateInstance(trigger, {
|
|
144
|
-
popperConfig: (defaultConfig) => this._clippingSafePopperConfig(defaultConfig),
|
|
171
|
+
popperConfig: /* @__PURE__ */ __name((defaultConfig) => this._clippingSafePopperConfig(defaultConfig), "popperConfig")
|
|
145
172
|
});
|
|
146
173
|
});
|
|
147
174
|
}
|
|
148
|
-
|
|
149
175
|
_clippingSafePopperConfig(defaultConfig) {
|
|
150
176
|
return {
|
|
151
177
|
...defaultConfig,
|
|
152
178
|
strategy: "fixed",
|
|
153
179
|
modifiers: [
|
|
154
|
-
...
|
|
180
|
+
...defaultConfig.modifiers || [],
|
|
155
181
|
{
|
|
156
182
|
name: "flip",
|
|
157
183
|
options: {
|
|
158
|
-
fallbackPlacements: ["top-end", "top-start", "bottom-end", "bottom-start"]
|
|
159
|
-
}
|
|
184
|
+
fallbackPlacements: ["top-end", "top-start", "bottom-end", "bottom-start"]
|
|
185
|
+
}
|
|
160
186
|
},
|
|
161
187
|
{
|
|
162
188
|
name: "preventOverflow",
|
|
163
189
|
options: {
|
|
164
190
|
boundary: "viewport",
|
|
165
|
-
padding: 8
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
]
|
|
191
|
+
padding: 8
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
]
|
|
169
195
|
};
|
|
170
196
|
}
|
|
171
|
-
|
|
172
197
|
// dispose() alone leaves any open row-action Dropdown's show/aria-expanded/
|
|
173
198
|
// data-bs-popper state and Bootstrap instance behind; hide and dispose each
|
|
174
199
|
// one first so a subsequent re-init starts from a clean state.
|
|
@@ -186,7 +211,6 @@ export default class DataTable {
|
|
|
186
211
|
instance.dispose();
|
|
187
212
|
});
|
|
188
213
|
}
|
|
189
|
-
|
|
190
214
|
_disposeSortDropdowns() {
|
|
191
215
|
const Dropdown = this._bootstrap("Dropdown");
|
|
192
216
|
if (!Dropdown) {
|
|
@@ -201,14 +225,12 @@ export default class DataTable {
|
|
|
201
225
|
instance.dispose();
|
|
202
226
|
});
|
|
203
227
|
}
|
|
204
|
-
|
|
205
228
|
_rowActionMenuForTrigger(trigger) {
|
|
206
229
|
if (!trigger?.closest?.(".table-row-actions")) {
|
|
207
230
|
return null;
|
|
208
231
|
}
|
|
209
232
|
return trigger.closest(".dropdown")?.querySelector(":scope > .dropdown-menu") || null;
|
|
210
233
|
}
|
|
211
|
-
|
|
212
234
|
_rowActionOwnerIdForTrigger(trigger) {
|
|
213
235
|
const rowId = trigger?.closest?.("tr[data-datatable-row]")?.id;
|
|
214
236
|
if (rowId) {
|
|
@@ -216,7 +238,6 @@ export default class DataTable {
|
|
|
216
238
|
}
|
|
217
239
|
return trigger?.closest?.("[data-datatable-card]")?.getAttribute("data-datatable-card-for") || "";
|
|
218
240
|
}
|
|
219
|
-
|
|
220
241
|
_reparentRowActionMenu(trigger) {
|
|
221
242
|
const menu = this._rowActionMenuForTrigger(trigger);
|
|
222
243
|
if (!menu || this._reparentedRowMenus.has(menu)) {
|
|
@@ -233,25 +254,26 @@ export default class DataTable {
|
|
|
233
254
|
parent: menu.parentNode,
|
|
234
255
|
nextSibling: menu.nextSibling,
|
|
235
256
|
trigger,
|
|
257
|
+
owner: findThemeOwner(trigger)
|
|
236
258
|
});
|
|
237
259
|
this._reparentedRowMenuByTrigger.set(trigger, menu);
|
|
238
|
-
this.
|
|
260
|
+
this._portalRoot(trigger).appendChild(menu);
|
|
239
261
|
}
|
|
240
|
-
|
|
241
262
|
_restoreRowActionMenuForTrigger(trigger) {
|
|
242
263
|
const menu = this._reparentedRowMenuByTrigger.get(trigger) || this._rowActionMenuForTrigger(trigger);
|
|
243
264
|
if (menu) {
|
|
244
265
|
this._restoreRowActionMenu(menu);
|
|
245
266
|
}
|
|
246
267
|
}
|
|
247
|
-
|
|
248
268
|
_restoreRowActionMenu(menu) {
|
|
249
269
|
const original = this._reparentedRowMenus.get(menu);
|
|
250
270
|
if (!original) {
|
|
251
271
|
return;
|
|
252
272
|
}
|
|
253
|
-
const { parent, nextSibling, trigger } = original;
|
|
254
|
-
if (
|
|
273
|
+
const { parent, nextSibling, trigger, owner } = original;
|
|
274
|
+
if (owner?.isConnected === false) {
|
|
275
|
+
menu.remove();
|
|
276
|
+
} else if (parent?.isConnected) {
|
|
255
277
|
if (nextSibling?.parentNode === parent) {
|
|
256
278
|
parent.insertBefore(menu, nextSibling);
|
|
257
279
|
} else {
|
|
@@ -267,24 +289,17 @@ export default class DataTable {
|
|
|
267
289
|
menu.removeAttribute("data-datatable-row-action-trigger");
|
|
268
290
|
this._reparentedRowMenus.delete(menu);
|
|
269
291
|
}
|
|
270
|
-
|
|
271
292
|
_restoreRowActionMenus() {
|
|
272
293
|
Array.from(this._reparentedRowMenus.keys()).forEach((menu) => {
|
|
273
294
|
this._restoreRowActionMenu(menu);
|
|
274
295
|
});
|
|
275
296
|
}
|
|
276
|
-
|
|
277
297
|
_sortMenuForTrigger(trigger) {
|
|
278
298
|
if (!trigger?.closest?.(".datatable-sort")) {
|
|
279
299
|
return null;
|
|
280
300
|
}
|
|
281
|
-
return (
|
|
282
|
-
this._reparentedSortMenuByTrigger.get(trigger) ||
|
|
283
|
-
trigger?.closest?.(".dropdown")?.querySelector(":scope > .dropdown-menu") ||
|
|
284
|
-
null
|
|
285
|
-
);
|
|
301
|
+
return this._reparentedSortMenuByTrigger.get(trigger) || trigger?.closest?.(".dropdown")?.querySelector(":scope > .dropdown-menu") || null;
|
|
286
302
|
}
|
|
287
|
-
|
|
288
303
|
// Sort menus are authored inside their table header, but must leave the
|
|
289
304
|
// overflow frame while open just like row-action menus do.
|
|
290
305
|
_reparentSortMenu(trigger) {
|
|
@@ -297,25 +312,26 @@ export default class DataTable {
|
|
|
297
312
|
nextSibling: menu.nextSibling,
|
|
298
313
|
trigger,
|
|
299
314
|
owner: trigger.closest(".datatable-sort"),
|
|
315
|
+
themeOwner: findThemeOwner(trigger)
|
|
300
316
|
});
|
|
301
317
|
this._reparentedSortMenuByTrigger.set(trigger, menu);
|
|
302
|
-
this.
|
|
318
|
+
this._portalRoot(trigger).appendChild(menu);
|
|
303
319
|
}
|
|
304
|
-
|
|
305
320
|
_restoreSortMenuForTrigger(trigger) {
|
|
306
321
|
const menu = this._reparentedSortMenuByTrigger.get(trigger) || this._sortMenuForTrigger(trigger);
|
|
307
322
|
if (menu) {
|
|
308
323
|
this._restoreSortMenu(menu);
|
|
309
324
|
}
|
|
310
325
|
}
|
|
311
|
-
|
|
312
326
|
_restoreSortMenu(menu) {
|
|
313
327
|
const original = this._reparentedSortMenus.get(menu);
|
|
314
328
|
if (!original) {
|
|
315
329
|
return;
|
|
316
330
|
}
|
|
317
|
-
const { parent, nextSibling, trigger } = original;
|
|
318
|
-
if (
|
|
331
|
+
const { parent, nextSibling, trigger, themeOwner } = original;
|
|
332
|
+
if (themeOwner?.isConnected === false) {
|
|
333
|
+
menu.remove();
|
|
334
|
+
} else if (parent?.isConnected) {
|
|
319
335
|
if (nextSibling?.parentNode === parent) {
|
|
320
336
|
parent.insertBefore(menu, nextSibling);
|
|
321
337
|
} else {
|
|
@@ -329,17 +345,17 @@ export default class DataTable {
|
|
|
329
345
|
}
|
|
330
346
|
this._reparentedSortMenus.delete(menu);
|
|
331
347
|
}
|
|
332
|
-
|
|
333
348
|
_restoreSortMenus() {
|
|
334
349
|
Array.from(this._reparentedSortMenus.keys()).forEach((menu) => {
|
|
335
350
|
this._restoreSortMenu(menu);
|
|
336
351
|
});
|
|
337
352
|
}
|
|
338
|
-
|
|
339
353
|
_bootstrap(name) {
|
|
340
354
|
return this._window.bootstrap?.[name] || null;
|
|
341
355
|
}
|
|
342
|
-
|
|
356
|
+
_portalRoot(trigger = this._element) {
|
|
357
|
+
return ownerPortalRoot(findThemeOwner(trigger)) || this._document.body || this._document.documentElement;
|
|
358
|
+
}
|
|
343
359
|
// The bulk-actions bar's icon-only buttons carry data-bs-title instead of
|
|
344
360
|
// a bare title attribute so Bootstrap's own Tooltip owns the hover/focus
|
|
345
361
|
// affordance (matching the rest of Moo's icon-button contracts) rather
|
|
@@ -356,36 +372,25 @@ export default class DataTable {
|
|
|
356
372
|
if (!Tooltip) {
|
|
357
373
|
return;
|
|
358
374
|
}
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
// aria-label already gives it an accessible name without the hover
|
|
366
|
-
// affordance.
|
|
367
|
-
this._element
|
|
368
|
-
.querySelectorAll("[data-datatable-bulk-actions] [data-bs-title]:not([data-bs-toggle=\"dropdown\"])")
|
|
369
|
-
.forEach((trigger) => {
|
|
370
|
-
this._tooltips.push(Tooltip.getOrCreateInstance(trigger, { animation: false }));
|
|
371
|
-
});
|
|
375
|
+
this._element.querySelectorAll('[data-datatable-bulk-actions] [data-bs-title]:not([data-bs-toggle="dropdown"])').forEach((trigger) => {
|
|
376
|
+
this._tooltips.push(Tooltip.getOrCreateInstance(trigger, {
|
|
377
|
+
animation: false,
|
|
378
|
+
container: this._portalRoot(trigger)
|
|
379
|
+
}));
|
|
380
|
+
});
|
|
372
381
|
}
|
|
373
|
-
|
|
374
382
|
_hideBulkTooltips({ blur = false } = {}) {
|
|
375
383
|
this._tooltips.forEach((tooltip) => {
|
|
376
384
|
tooltip.hide();
|
|
377
385
|
});
|
|
378
|
-
|
|
379
386
|
if (!blur) {
|
|
380
387
|
return;
|
|
381
388
|
}
|
|
382
|
-
|
|
383
389
|
const active = this._document.activeElement;
|
|
384
390
|
if (active?.closest?.("[data-datatable-bulk-actions]")) {
|
|
385
391
|
active.blur();
|
|
386
392
|
}
|
|
387
393
|
}
|
|
388
|
-
|
|
389
394
|
// responsive_mode="toggle" renders both the table and the card list and
|
|
390
395
|
// lets the reader pick between them (Odoo's List/Kanban switcher, not a
|
|
391
396
|
// developer-chosen breakpoint), so the choice belongs to the reader across
|
|
@@ -397,7 +402,7 @@ export default class DataTable {
|
|
|
397
402
|
}
|
|
398
403
|
const inputs = toggles.flatMap((toggle) => Array.from(toggle.querySelectorAll("input")));
|
|
399
404
|
const storageKey = `moo-datatable-view:${this._element.id}`;
|
|
400
|
-
const setView = (value, { persist = false } = {}) => {
|
|
405
|
+
const setView = /* @__PURE__ */ __name((value, { persist = false } = {}) => {
|
|
401
406
|
this._element.dataset.datatableView = value;
|
|
402
407
|
inputs.forEach((input) => {
|
|
403
408
|
input.checked = input.value === value;
|
|
@@ -406,10 +411,9 @@ export default class DataTable {
|
|
|
406
411
|
try {
|
|
407
412
|
this._window.localStorage.setItem(storageKey, value);
|
|
408
413
|
} catch {
|
|
409
|
-
// Storage may be unavailable (private browsing); the toggle still works for this session.
|
|
410
414
|
}
|
|
411
415
|
}
|
|
412
|
-
};
|
|
416
|
+
}, "setView");
|
|
413
417
|
let stored = null;
|
|
414
418
|
try {
|
|
415
419
|
stored = this._window.localStorage.getItem(storageKey);
|
|
@@ -429,7 +433,6 @@ export default class DataTable {
|
|
|
429
433
|
});
|
|
430
434
|
});
|
|
431
435
|
}
|
|
432
|
-
|
|
433
436
|
_readFacets(tr) {
|
|
434
437
|
const facets = {};
|
|
435
438
|
Array.from(tr.attributes).forEach((attr) => {
|
|
@@ -440,7 +443,6 @@ export default class DataTable {
|
|
|
440
443
|
});
|
|
441
444
|
return facets;
|
|
442
445
|
}
|
|
443
|
-
|
|
444
446
|
_readInitialFacetVisibility() {
|
|
445
447
|
this._element.querySelectorAll("[data-datatable-facet]").forEach((facetRoot) => {
|
|
446
448
|
const key = facetRoot.dataset.datatableFacet;
|
|
@@ -461,7 +463,6 @@ export default class DataTable {
|
|
|
461
463
|
}
|
|
462
464
|
});
|
|
463
465
|
}
|
|
464
|
-
|
|
465
466
|
_readInitialSort() {
|
|
466
467
|
const th = this._element.querySelector("th[data-datatable-initial-sort][data-datatable-column]");
|
|
467
468
|
const direction = th?.dataset.datatableInitialSort;
|
|
@@ -471,16 +472,14 @@ export default class DataTable {
|
|
|
471
472
|
this._sortKey = th.dataset.datatableColumn || null;
|
|
472
473
|
this._sortDirection = this._sortKey ? direction : null;
|
|
473
474
|
}
|
|
474
|
-
|
|
475
475
|
_trigger(name, detail = {}) {
|
|
476
476
|
this._element.dispatchEvent(
|
|
477
477
|
new this._window.CustomEvent(`${name}.moo.datatable`, {
|
|
478
478
|
bubbles: true,
|
|
479
|
-
detail
|
|
479
|
+
detail
|
|
480
480
|
})
|
|
481
481
|
);
|
|
482
482
|
}
|
|
483
|
-
|
|
484
483
|
_sortValue(row, key) {
|
|
485
484
|
const cell = row.element.querySelector(`:scope > [data-datatable-column="${key}"]`);
|
|
486
485
|
if (!cell) {
|
|
@@ -488,7 +487,6 @@ export default class DataTable {
|
|
|
488
487
|
}
|
|
489
488
|
return normalize(cell.dataset.datatableSortValue ?? cell.textContent);
|
|
490
489
|
}
|
|
491
|
-
|
|
492
490
|
_matchesFilters(row) {
|
|
493
491
|
if (this._searchTerm && !row.search.includes(this._searchTerm)) {
|
|
494
492
|
return false;
|
|
@@ -503,7 +501,6 @@ export default class DataTable {
|
|
|
503
501
|
}
|
|
504
502
|
return true;
|
|
505
503
|
}
|
|
506
|
-
|
|
507
504
|
_visibleRows() {
|
|
508
505
|
const filtered = this._rows.filter((row) => this._matchesFilters(row));
|
|
509
506
|
if (this._sortKey) {
|
|
@@ -521,11 +518,9 @@ export default class DataTable {
|
|
|
521
518
|
}
|
|
522
519
|
return filtered;
|
|
523
520
|
}
|
|
524
|
-
|
|
525
521
|
_pageCount(rowCount) {
|
|
526
522
|
return Math.max(1, Math.ceil(rowCount / this._pageSize));
|
|
527
523
|
}
|
|
528
|
-
|
|
529
524
|
_render() {
|
|
530
525
|
const filtered = this._visibleRows();
|
|
531
526
|
const pageCount = this._pageCount(filtered.length);
|
|
@@ -533,7 +528,6 @@ export default class DataTable {
|
|
|
533
528
|
const start = (this._currentPage - 1) * this._pageSize;
|
|
534
529
|
const pageRows = filtered.slice(start, start + this._pageSize);
|
|
535
530
|
const pageRowIds = new Set(pageRows.map((row) => row.element.id));
|
|
536
|
-
|
|
537
531
|
this._rows.forEach((row) => {
|
|
538
532
|
const isVisible = pageRowIds.has(row.element.id);
|
|
539
533
|
row.element.hidden = !isVisible;
|
|
@@ -541,19 +535,9 @@ export default class DataTable {
|
|
|
541
535
|
row.cardElement.hidden = !isVisible;
|
|
542
536
|
}
|
|
543
537
|
});
|
|
544
|
-
|
|
545
|
-
// appendChild() always detaches-and-reinserts, which blurs a focused
|
|
546
|
-
// descendant (e.g. a row checkbox) even when the node is only moved to
|
|
547
|
-
// the position it already occupies. Selecting/deselecting a row never
|
|
548
|
-
// changes row order, so skip the reorder entirely unless the DOM order
|
|
549
|
-
// actually disagrees with the desired page order.
|
|
550
|
-
const currentOrder = Array.from(this._tbody.children)
|
|
551
|
-
.filter((element) => pageRowIds.has(element.id))
|
|
552
|
-
.map((element) => element.id);
|
|
538
|
+
const currentOrder = Array.from(this._tbody.children).filter((element) => pageRowIds.has(element.id)).map((element) => element.id);
|
|
553
539
|
const desiredOrder = pageRows.map((row) => row.element.id);
|
|
554
|
-
const orderChanged =
|
|
555
|
-
currentOrder.length !== desiredOrder.length ||
|
|
556
|
-
currentOrder.some((id, index) => id !== desiredOrder[index]);
|
|
540
|
+
const orderChanged = currentOrder.length !== desiredOrder.length || currentOrder.some((id, index) => id !== desiredOrder[index]);
|
|
557
541
|
if (orderChanged) {
|
|
558
542
|
pageRows.forEach((row) => {
|
|
559
543
|
this._tbody.appendChild(row.element);
|
|
@@ -562,7 +546,6 @@ export default class DataTable {
|
|
|
562
546
|
}
|
|
563
547
|
});
|
|
564
548
|
}
|
|
565
|
-
|
|
566
549
|
this._renderToolbarState();
|
|
567
550
|
this._renderSortHeaders();
|
|
568
551
|
this._renderSelection(pageRows);
|
|
@@ -572,7 +555,6 @@ export default class DataTable {
|
|
|
572
555
|
this._renderPageSize();
|
|
573
556
|
this._renderBulkActions();
|
|
574
557
|
}
|
|
575
|
-
|
|
576
558
|
_renderToolbarState() {
|
|
577
559
|
const hasSearch = Boolean(this._searchTerm);
|
|
578
560
|
const hasFacets = Array.from(this._facetSelections.values()).some((set) => set.size > 0);
|
|
@@ -580,10 +562,9 @@ export default class DataTable {
|
|
|
580
562
|
if (resetButton) {
|
|
581
563
|
resetButton.hidden = !(hasSearch || hasFacets);
|
|
582
564
|
}
|
|
583
|
-
|
|
584
565
|
this._element.querySelectorAll("[data-datatable-facet]").forEach((facetRoot) => {
|
|
585
566
|
const key = facetRoot.dataset.datatableFacet;
|
|
586
|
-
const selected = this._facetSelections.get(key) || new Set();
|
|
567
|
+
const selected = this._facetSelections.get(key) || /* @__PURE__ */ new Set();
|
|
587
568
|
if (this._visibleFacets.has(key)) {
|
|
588
569
|
facetRoot.hidden = !this._visibleFacets.get(key);
|
|
589
570
|
}
|
|
@@ -609,36 +590,31 @@ export default class DataTable {
|
|
|
609
590
|
option.setAttribute("aria-pressed", String(isSelected));
|
|
610
591
|
});
|
|
611
592
|
});
|
|
612
|
-
|
|
613
593
|
this._element.querySelectorAll("[data-datatable-filter-toggle]").forEach((toggle) => {
|
|
614
594
|
const key = toggle.dataset.datatableFilterToggle;
|
|
615
595
|
const visible = this._visibleFacets.get(key) ?? true;
|
|
616
596
|
toggle.classList.toggle("active", visible);
|
|
617
597
|
toggle.setAttribute("aria-pressed", visible ? "true" : "false");
|
|
618
598
|
});
|
|
619
|
-
|
|
620
599
|
this._element.querySelectorAll("[data-datatable-filter-option]").forEach((option) => {
|
|
621
600
|
const key = option.dataset.datatableFilterOptionKey;
|
|
622
|
-
const selected = this._facetSelections.get(key) || new Set();
|
|
601
|
+
const selected = this._facetSelections.get(key) || /* @__PURE__ */ new Set();
|
|
623
602
|
const active = selected.has(option.dataset.datatableFilterOption);
|
|
624
603
|
option.classList.toggle("active", active);
|
|
625
604
|
option.setAttribute("aria-pressed", active ? "true" : "false");
|
|
626
605
|
});
|
|
627
|
-
|
|
628
606
|
this._element.querySelectorAll("[data-datatable-filter-group-summary]").forEach((summary) => {
|
|
629
|
-
const selected = this._facetSelections.get(summary.dataset.datatableFilterGroupSummary) || new Set();
|
|
607
|
+
const selected = this._facetSelections.get(summary.dataset.datatableFilterGroupSummary) || /* @__PURE__ */ new Set();
|
|
630
608
|
summary.hidden = selected.size === 0;
|
|
631
609
|
summary.textContent = selected.size > 0 ? `${selected.size} selected` : "";
|
|
632
610
|
});
|
|
633
611
|
}
|
|
634
|
-
|
|
635
612
|
_createFacetBadge(text) {
|
|
636
613
|
const badge = this._document.createElement("span");
|
|
637
614
|
badge.className = "datatable-facet-badge";
|
|
638
615
|
badge.textContent = text;
|
|
639
616
|
return badge;
|
|
640
617
|
}
|
|
641
|
-
|
|
642
618
|
_renderSelection(pageRows) {
|
|
643
619
|
const selectAllControls = Array.from(this._element.querySelectorAll("[data-datatable-select-all]"));
|
|
644
620
|
pageRows.forEach((row) => {
|
|
@@ -657,7 +633,6 @@ export default class DataTable {
|
|
|
657
633
|
control.indeterminate = checked > 0 && checked < total;
|
|
658
634
|
});
|
|
659
635
|
}
|
|
660
|
-
|
|
661
636
|
_renderBulkActions() {
|
|
662
637
|
const bar = this._element.querySelector("[data-datatable-bulk-actions]");
|
|
663
638
|
if (!bar) {
|
|
@@ -669,14 +644,12 @@ export default class DataTable {
|
|
|
669
644
|
count.textContent = String(this._selectedIds.size);
|
|
670
645
|
}
|
|
671
646
|
}
|
|
672
|
-
|
|
673
647
|
_renderFrameState(totalRows) {
|
|
674
648
|
const isEmpty = totalRows === 0;
|
|
675
649
|
this._element.querySelectorAll(".datatable-frame, .datatable-card-frame").forEach((frame) => {
|
|
676
650
|
frame.hidden = isEmpty;
|
|
677
651
|
});
|
|
678
652
|
}
|
|
679
|
-
|
|
680
653
|
_renderEmptyState(totalRows) {
|
|
681
654
|
const empty = this._element.querySelector("[data-datatable-empty]");
|
|
682
655
|
if (!empty) {
|
|
@@ -696,7 +669,6 @@ export default class DataTable {
|
|
|
696
669
|
reset.hidden = !hasRows;
|
|
697
670
|
}
|
|
698
671
|
}
|
|
699
|
-
|
|
700
672
|
_sortAriaValue(direction) {
|
|
701
673
|
if (direction === "asc") {
|
|
702
674
|
return "ascending";
|
|
@@ -706,7 +678,6 @@ export default class DataTable {
|
|
|
706
678
|
}
|
|
707
679
|
return "none";
|
|
708
680
|
}
|
|
709
|
-
|
|
710
681
|
_renderSortHeaders() {
|
|
711
682
|
this._element.querySelectorAll("th[data-datatable-column]").forEach((th) => {
|
|
712
683
|
const trigger = th.querySelector("[data-datatable-sort-key]");
|
|
@@ -727,7 +698,6 @@ export default class DataTable {
|
|
|
727
698
|
}
|
|
728
699
|
});
|
|
729
700
|
}
|
|
730
|
-
|
|
731
701
|
_renderPagination(totalRows, pageCount) {
|
|
732
702
|
const first = this._element.querySelector("[data-datatable-page-first]");
|
|
733
703
|
const prev = this._element.querySelector("[data-datatable-page-prev]");
|
|
@@ -737,7 +707,6 @@ export default class DataTable {
|
|
|
737
707
|
const atEnd = this._currentPage >= pageCount;
|
|
738
708
|
[first, prev].forEach((button) => this._setPageItemDisabled(button, atStart));
|
|
739
709
|
[next, last].forEach((button) => this._setPageItemDisabled(button, atEnd));
|
|
740
|
-
|
|
741
710
|
const summary = this._element.querySelector("[data-datatable-results-summary]");
|
|
742
711
|
if (summary) {
|
|
743
712
|
if (totalRows === 0) {
|
|
@@ -748,43 +717,29 @@ export default class DataTable {
|
|
|
748
717
|
summary.textContent = `Showing ${start}-${end} of ${totalRows}`;
|
|
749
718
|
}
|
|
750
719
|
}
|
|
751
|
-
|
|
752
720
|
const template = this._element.querySelector("template[data-datatable-page-numbers]");
|
|
753
721
|
if (!template) {
|
|
754
722
|
return;
|
|
755
723
|
}
|
|
756
|
-
|
|
757
724
|
const pages = this._pageWindow(this._currentPage, pageCount);
|
|
758
725
|
const existing = Array.from(
|
|
759
726
|
template.parentNode.querySelectorAll(
|
|
760
727
|
"[data-datatable-page-number], [data-datatable-page-ellipsis]"
|
|
761
728
|
)
|
|
762
729
|
);
|
|
763
|
-
const existingWindow = existing.map(
|
|
764
|
-
node.dataset.datatablePageEllipsis ===
|
|
765
|
-
? Number(node.dataset.datatablePageNumber)
|
|
766
|
-
: "…"
|
|
730
|
+
const existingWindow = existing.map(
|
|
731
|
+
(node) => node.dataset.datatablePageEllipsis === void 0 ? Number(node.dataset.datatablePageNumber) : "\u2026"
|
|
767
732
|
);
|
|
768
|
-
|
|
769
|
-
// every page-number button on each click destroys and recreates the one
|
|
770
|
-
// the user just clicked, which blurs it (losing the focus ring and any
|
|
771
|
-
// keyboard position). The page window is unchanged on most clicks (any
|
|
772
|
-
// dataset small enough to show every page, or a prev/next inside an
|
|
773
|
-
// already-visible window), so only rebuild when the window itself
|
|
774
|
-
// differs; otherwise just resync which node is active below.
|
|
775
|
-
const windowChanged =
|
|
776
|
-
existingWindow.length !== pages.length ||
|
|
777
|
-
existingWindow.some((page, index) => page !== pages[index]);
|
|
778
|
-
|
|
733
|
+
const windowChanged = existingWindow.length !== pages.length || existingWindow.some((page, index) => page !== pages[index]);
|
|
779
734
|
if (windowChanged) {
|
|
780
735
|
existing.forEach((node) => node.remove());
|
|
781
736
|
const fragment = this._document.createDocumentFragment();
|
|
782
737
|
pages.forEach((page) => {
|
|
783
738
|
const li = this._document.createElement("li");
|
|
784
739
|
li.className = "page-item";
|
|
785
|
-
if (page === "
|
|
740
|
+
if (page === "\u2026") {
|
|
786
741
|
li.dataset.datatablePageEllipsis = "";
|
|
787
|
-
li.innerHTML = '<span class="page-link"
|
|
742
|
+
li.innerHTML = '<span class="page-link">\u2026</span>';
|
|
788
743
|
} else {
|
|
789
744
|
li.dataset.datatablePageNumber = String(page);
|
|
790
745
|
const button = this._document.createElement("button");
|
|
@@ -799,7 +754,6 @@ export default class DataTable {
|
|
|
799
754
|
});
|
|
800
755
|
template.parentNode.insertBefore(fragment, template);
|
|
801
756
|
}
|
|
802
|
-
|
|
803
757
|
template.parentNode.querySelectorAll("[data-datatable-page-number]").forEach((li) => {
|
|
804
758
|
const isActive = Number(li.dataset.datatablePageNumber) === this._currentPage;
|
|
805
759
|
li.classList.toggle("active", isActive);
|
|
@@ -810,7 +764,6 @@ export default class DataTable {
|
|
|
810
764
|
}
|
|
811
765
|
});
|
|
812
766
|
}
|
|
813
|
-
|
|
814
767
|
_renderPageSize() {
|
|
815
768
|
const currentSize = String(this._pageSize);
|
|
816
769
|
const value = this._element.querySelector("[data-datatable-page-size-value]");
|
|
@@ -827,7 +780,6 @@ export default class DataTable {
|
|
|
827
780
|
option.setAttribute("aria-pressed", active ? "true" : "false");
|
|
828
781
|
});
|
|
829
782
|
}
|
|
830
|
-
|
|
831
783
|
_setPageItemDisabled(button, disabled) {
|
|
832
784
|
if (!button) {
|
|
833
785
|
return;
|
|
@@ -835,31 +787,24 @@ export default class DataTable {
|
|
|
835
787
|
button.disabled = disabled;
|
|
836
788
|
button.closest(".page-item")?.classList.toggle("disabled", disabled);
|
|
837
789
|
}
|
|
838
|
-
|
|
839
790
|
_pageWindow(current, total) {
|
|
840
791
|
if (total <= 7) {
|
|
841
792
|
return Array.from({ length: total }, (_, index) => index + 1);
|
|
842
793
|
}
|
|
843
|
-
const pages = new Set([1, total, current - 1, current, current + 1]);
|
|
844
|
-
const sorted = Array.from(pages)
|
|
845
|
-
.filter((page) => page >= 1 && page <= total)
|
|
846
|
-
.sort((a, b) => a - b);
|
|
794
|
+
const pages = /* @__PURE__ */ new Set([1, total, current - 1, current, current + 1]);
|
|
795
|
+
const sorted = Array.from(pages).filter((page) => page >= 1 && page <= total).sort((a, b) => a - b);
|
|
847
796
|
const withEllipsis = [];
|
|
848
797
|
sorted.forEach((page, index) => {
|
|
849
798
|
if (index > 0 && page - sorted[index - 1] > 1) {
|
|
850
|
-
withEllipsis.push("
|
|
799
|
+
withEllipsis.push("\u2026");
|
|
851
800
|
}
|
|
852
801
|
withEllipsis.push(page);
|
|
853
802
|
});
|
|
854
803
|
return withEllipsis;
|
|
855
804
|
}
|
|
856
|
-
|
|
857
805
|
_isColumnFixed(key) {
|
|
858
|
-
return this._element
|
|
859
|
-
.querySelector(`th[data-datatable-column="${key}"]`)
|
|
860
|
-
?.hasAttribute("data-datatable-column-fixed") || false;
|
|
806
|
+
return this._element.querySelector(`th[data-datatable-column="${key}"]`)?.hasAttribute("data-datatable-column-fixed") || false;
|
|
861
807
|
}
|
|
862
|
-
|
|
863
808
|
_setColumnVisible(key, visible, { syncViewToggle = true } = {}) {
|
|
864
809
|
if (!visible && this._isColumnFixed(key)) {
|
|
865
810
|
return;
|
|
@@ -874,7 +819,6 @@ export default class DataTable {
|
|
|
874
819
|
});
|
|
875
820
|
}
|
|
876
821
|
}
|
|
877
|
-
|
|
878
822
|
_setSort(key, direction) {
|
|
879
823
|
const validDirection = direction === "asc" || direction === "desc" ? direction : null;
|
|
880
824
|
this._sortKey = validDirection ? key : null;
|
|
@@ -882,16 +826,13 @@ export default class DataTable {
|
|
|
882
826
|
this._render();
|
|
883
827
|
this._trigger("sort", { key: this._sortKey, direction: this._sortDirection });
|
|
884
828
|
}
|
|
885
|
-
|
|
886
829
|
_handleSortAction(event) {
|
|
887
830
|
const trigger = event.target.closest("[data-datatable-sort-action]");
|
|
888
831
|
if (!trigger) {
|
|
889
832
|
return;
|
|
890
833
|
}
|
|
891
834
|
const menu = trigger.closest(".dropdown-menu");
|
|
892
|
-
const sort =
|
|
893
|
-
menu?.closest(".datatable-sort") ||
|
|
894
|
-
this._reparentedSortMenus.get(menu)?.owner;
|
|
835
|
+
const sort = menu?.closest(".datatable-sort") || this._reparentedSortMenus.get(menu)?.owner;
|
|
895
836
|
if (!sort || !this._element.contains(sort)) {
|
|
896
837
|
return;
|
|
897
838
|
}
|
|
@@ -906,7 +847,6 @@ export default class DataTable {
|
|
|
906
847
|
}
|
|
907
848
|
this._setSort(key, action);
|
|
908
849
|
}
|
|
909
|
-
|
|
910
850
|
_handleFacetClick(event) {
|
|
911
851
|
const option = event.target.closest("[data-datatable-facet-option]");
|
|
912
852
|
const clear = event.target.closest("[data-datatable-facet-clear]");
|
|
@@ -918,7 +858,7 @@ export default class DataTable {
|
|
|
918
858
|
if (!key) {
|
|
919
859
|
return;
|
|
920
860
|
}
|
|
921
|
-
const selected = this._facetSelections.get(key) || new Set();
|
|
861
|
+
const selected = this._facetSelections.get(key) || /* @__PURE__ */ new Set();
|
|
922
862
|
if (clear) {
|
|
923
863
|
selected.clear();
|
|
924
864
|
} else {
|
|
@@ -937,7 +877,6 @@ export default class DataTable {
|
|
|
937
877
|
this._render();
|
|
938
878
|
this._trigger("filter");
|
|
939
879
|
}
|
|
940
|
-
|
|
941
880
|
_handleFacetSearch(event) {
|
|
942
881
|
const search = event.target.closest("[data-datatable-facet-search]");
|
|
943
882
|
if (!search) {
|
|
@@ -950,7 +889,6 @@ export default class DataTable {
|
|
|
950
889
|
option.closest("li")?.classList.toggle("datatable-facet-search-hidden", query.length > 0 && !label.includes(query));
|
|
951
890
|
});
|
|
952
891
|
}
|
|
953
|
-
|
|
954
892
|
// Bootstrap's own dropdown keyboard navigation moves focus between
|
|
955
893
|
// .dropdown-item siblings, but it deliberately leaves focus alone while an
|
|
956
894
|
// <input> has it (arrow keys inside a text field move the caret, not a
|
|
@@ -974,7 +912,6 @@ export default class DataTable {
|
|
|
974
912
|
firstVisible.focus();
|
|
975
913
|
}
|
|
976
914
|
}
|
|
977
|
-
|
|
978
915
|
_handleFilterOptionClick(event) {
|
|
979
916
|
const option = event.target.closest("[data-datatable-filter-option]");
|
|
980
917
|
if (!option) {
|
|
@@ -986,7 +923,7 @@ export default class DataTable {
|
|
|
986
923
|
return;
|
|
987
924
|
}
|
|
988
925
|
this._visibleFacets.set(key, true);
|
|
989
|
-
const selected = this._facetSelections.get(key) || new Set();
|
|
926
|
+
const selected = this._facetSelections.get(key) || /* @__PURE__ */ new Set();
|
|
990
927
|
if (selected.has(value)) {
|
|
991
928
|
selected.delete(value);
|
|
992
929
|
} else {
|
|
@@ -1000,18 +937,14 @@ export default class DataTable {
|
|
|
1000
937
|
this._render();
|
|
1001
938
|
this._trigger("filter");
|
|
1002
939
|
}
|
|
1003
|
-
|
|
1004
940
|
_showFilterPickerPanel(key = null) {
|
|
1005
941
|
this._element.querySelectorAll("[data-datatable-filter-panel]").forEach((panel) => {
|
|
1006
942
|
const isFacetList = panel.dataset.datatableFilterPanel === "facets";
|
|
1007
943
|
const isRequestedOptions = panel.dataset.datatableFilterPanelKey === key;
|
|
1008
944
|
panel.hidden = key ? !isRequestedOptions : !isFacetList;
|
|
1009
945
|
});
|
|
1010
|
-
this._element
|
|
1011
|
-
.querySelector(".datatable-search-filter-menu")
|
|
1012
|
-
?.setAttribute("data-datatable-filter-menu-panel", key ? "options" : "facets");
|
|
946
|
+
this._element.querySelector(".datatable-search-filter-menu")?.setAttribute("data-datatable-filter-menu-panel", key ? "options" : "facets");
|
|
1013
947
|
}
|
|
1014
|
-
|
|
1015
948
|
_handleFilterPickerClick(event) {
|
|
1016
949
|
const group = event.target.closest("[data-datatable-filter-group]");
|
|
1017
950
|
if (group) {
|
|
@@ -1026,7 +959,6 @@ export default class DataTable {
|
|
|
1026
959
|
this._showFilterPickerPanel();
|
|
1027
960
|
}
|
|
1028
961
|
}
|
|
1029
|
-
|
|
1030
962
|
_handleFilterOptionSearch(event) {
|
|
1031
963
|
const search = event.target.closest("[data-datatable-filter-option-search]");
|
|
1032
964
|
if (!search) {
|
|
@@ -1039,7 +971,6 @@ export default class DataTable {
|
|
|
1039
971
|
option.closest("li")?.classList.toggle("datatable-filter-option-search-hidden", query.length > 0 && !label.includes(query));
|
|
1040
972
|
});
|
|
1041
973
|
}
|
|
1042
|
-
|
|
1043
974
|
// Same bridge as _handleFacetSearchKeydown, for the filter-picker's
|
|
1044
975
|
// drill-down option search box.
|
|
1045
976
|
_handleFilterOptionSearchKeydown(event) {
|
|
@@ -1062,7 +993,6 @@ export default class DataTable {
|
|
|
1062
993
|
firstVisible.focus();
|
|
1063
994
|
}
|
|
1064
995
|
}
|
|
1065
|
-
|
|
1066
996
|
_handleFilterToggleClick(event) {
|
|
1067
997
|
const toggle = event.target.closest("[data-datatable-filter-toggle]");
|
|
1068
998
|
if (!toggle) {
|
|
@@ -1081,7 +1011,6 @@ export default class DataTable {
|
|
|
1081
1011
|
}
|
|
1082
1012
|
this._render();
|
|
1083
1013
|
}
|
|
1084
|
-
|
|
1085
1014
|
_handleColumnToggleClick(event) {
|
|
1086
1015
|
const toggle = event.target.closest("[data-datatable-column-toggle]");
|
|
1087
1016
|
if (!toggle) {
|
|
@@ -1091,7 +1020,6 @@ export default class DataTable {
|
|
|
1091
1020
|
const visible = toggle.getAttribute("aria-pressed") === "true";
|
|
1092
1021
|
this._setColumnVisible(key, visible, { syncViewToggle: false });
|
|
1093
1022
|
}
|
|
1094
|
-
|
|
1095
1023
|
_handleReset() {
|
|
1096
1024
|
const search = this._element.querySelector("[data-datatable-search]");
|
|
1097
1025
|
if (search) {
|
|
@@ -1108,7 +1036,6 @@ export default class DataTable {
|
|
|
1108
1036
|
this._render();
|
|
1109
1037
|
this._trigger("filter");
|
|
1110
1038
|
}
|
|
1111
|
-
|
|
1112
1039
|
_handleSelectAll(event) {
|
|
1113
1040
|
const checked = event.target.checked;
|
|
1114
1041
|
const filtered = this._visibleRows();
|
|
@@ -1124,7 +1051,6 @@ export default class DataTable {
|
|
|
1124
1051
|
this._render();
|
|
1125
1052
|
this._trigger("select");
|
|
1126
1053
|
}
|
|
1127
|
-
|
|
1128
1054
|
_handleSelectRow(event) {
|
|
1129
1055
|
const checkbox = event.target.closest("[data-datatable-select-row]");
|
|
1130
1056
|
if (!checkbox) {
|
|
@@ -1144,7 +1070,6 @@ export default class DataTable {
|
|
|
1144
1070
|
this._render();
|
|
1145
1071
|
this._trigger("select");
|
|
1146
1072
|
}
|
|
1147
|
-
|
|
1148
1073
|
_handleBulkClick(event) {
|
|
1149
1074
|
if (event.target.closest("[data-datatable-bulk-clear]")) {
|
|
1150
1075
|
this._clearSelection();
|
|
@@ -1167,14 +1092,12 @@ export default class DataTable {
|
|
|
1167
1092
|
this._trigger(`bulk-${action}`, { ids: this.getSelectedIds() });
|
|
1168
1093
|
}
|
|
1169
1094
|
}
|
|
1170
|
-
|
|
1171
1095
|
_clearSelection() {
|
|
1172
1096
|
this._hideBulkTooltips({ blur: true });
|
|
1173
1097
|
this._selectedIds.clear();
|
|
1174
1098
|
this._render();
|
|
1175
1099
|
this._trigger("select");
|
|
1176
1100
|
}
|
|
1177
|
-
|
|
1178
1101
|
_applyBulkUpdate(key, value, trigger) {
|
|
1179
1102
|
const icon = trigger.querySelector("svg")?.cloneNode(true);
|
|
1180
1103
|
const label = trigger.querySelector("span")?.textContent?.trim() ?? value;
|
|
@@ -1207,7 +1130,6 @@ export default class DataTable {
|
|
|
1207
1130
|
this._render();
|
|
1208
1131
|
this._trigger("bulk-update", { key, value, ids: this.getSelectedIds() });
|
|
1209
1132
|
}
|
|
1210
|
-
|
|
1211
1133
|
_applyBulkDelete() {
|
|
1212
1134
|
const ids = this.getSelectedIds();
|
|
1213
1135
|
ids.forEach((id) => {
|
|
@@ -1222,7 +1144,6 @@ export default class DataTable {
|
|
|
1222
1144
|
this._render();
|
|
1223
1145
|
this._trigger("bulk-delete", { ids });
|
|
1224
1146
|
}
|
|
1225
|
-
|
|
1226
1147
|
_handlePageClick(event) {
|
|
1227
1148
|
const goButton = event.target.closest("[data-datatable-page-go]");
|
|
1228
1149
|
if (goButton) {
|
|
@@ -1250,7 +1171,6 @@ export default class DataTable {
|
|
|
1250
1171
|
this._render();
|
|
1251
1172
|
}
|
|
1252
1173
|
}
|
|
1253
|
-
|
|
1254
1174
|
_setPageSize(value) {
|
|
1255
1175
|
const nextPageSize = Number(value);
|
|
1256
1176
|
if (!Number.isFinite(nextPageSize) || nextPageSize <= 0) {
|
|
@@ -1261,7 +1181,6 @@ export default class DataTable {
|
|
|
1261
1181
|
this._currentPage = 1;
|
|
1262
1182
|
this._render();
|
|
1263
1183
|
}
|
|
1264
|
-
|
|
1265
1184
|
_bindEvents() {
|
|
1266
1185
|
const search = this._element.querySelector("[data-datatable-search]");
|
|
1267
1186
|
this._listen(search, "input", (event) => {
|
|
@@ -1281,7 +1200,6 @@ export default class DataTable {
|
|
|
1281
1200
|
Dropdown.getOrCreateInstance(trigger).hide();
|
|
1282
1201
|
}
|
|
1283
1202
|
});
|
|
1284
|
-
|
|
1285
1203
|
this._listen(this._element, "click", (event) => {
|
|
1286
1204
|
this._handleFilterPickerClick(event);
|
|
1287
1205
|
this._handleFilterOptionClick(event);
|
|
@@ -1298,27 +1216,11 @@ export default class DataTable {
|
|
|
1298
1216
|
}
|
|
1299
1217
|
});
|
|
1300
1218
|
this._listen(this._document, "click", (event) => this._handleSortAction(event));
|
|
1301
|
-
|
|
1302
|
-
// Bound to the document, not this._element: a checkbox click does not
|
|
1303
|
-
// reliably move focus into the table (WebKit never focuses form
|
|
1304
|
-
// controls on click, and even where it does the bulk-actions bar itself
|
|
1305
|
-
// sits outside the table's DOM flow), so a listener scoped to the table
|
|
1306
|
-
// would miss Escape whenever focus is elsewhere on the page.
|
|
1307
1219
|
this._listen(this._document, "keydown", (event) => {
|
|
1308
1220
|
if (event.key === "Escape" && this._selectedIds.size > 0) {
|
|
1309
1221
|
this._clearSelection();
|
|
1310
1222
|
}
|
|
1311
1223
|
});
|
|
1312
|
-
|
|
1313
|
-
// A hover-triggered tooltip does not hide itself when a click opens the
|
|
1314
|
-
// same button's dropdown (Bootstrap Tooltip only listens for
|
|
1315
|
-
// mouseleave/blur), so it would otherwise sit on top of the open menu.
|
|
1316
|
-
// hide() alone is not enough: opening the dropdown shifts layout under
|
|
1317
|
-
// the still-hovered cursor, which makes the browser refire mouseenter
|
|
1318
|
-
// and the tooltip re-show a moment later. disable()/enable() -- not
|
|
1319
|
-
// hide() -- is Bootstrap's own way to suppress that: it makes show() a
|
|
1320
|
-
// no-op for as long as the dropdown stays open, however it gets
|
|
1321
|
-
// re-triggered.
|
|
1322
1224
|
this._listen(this._element, "show.bs.dropdown", (event) => {
|
|
1323
1225
|
this._reparentRowActionMenu(event.target);
|
|
1324
1226
|
this._reparentSortMenu(event.target);
|
|
@@ -1334,31 +1236,30 @@ export default class DataTable {
|
|
|
1334
1236
|
this._showFilterPickerPanel();
|
|
1335
1237
|
}
|
|
1336
1238
|
});
|
|
1337
|
-
|
|
1338
1239
|
this._element.querySelectorAll("[data-datatable-filter-option-search]").forEach((searchInput) => {
|
|
1339
1240
|
this._listen(searchInput, "input", (event) => this._handleFilterOptionSearch(event));
|
|
1340
1241
|
this._listen(searchInput, "keydown", (event) => this._handleFilterOptionSearchKeydown(event));
|
|
1341
1242
|
});
|
|
1342
|
-
|
|
1343
1243
|
this._element.querySelectorAll("[data-datatable-facet-search]").forEach((searchInput) => {
|
|
1344
1244
|
this._listen(searchInput, "input", (event) => this._handleFacetSearch(event));
|
|
1345
1245
|
this._listen(searchInput, "keydown", (event) => this._handleFacetSearchKeydown(event));
|
|
1346
1246
|
});
|
|
1347
|
-
|
|
1348
1247
|
const resetButton = this._element.querySelector("[data-datatable-reset]");
|
|
1349
1248
|
this._listen(resetButton, "click", () => this._handleReset());
|
|
1350
|
-
|
|
1351
1249
|
this._element.querySelectorAll("[data-datatable-select-all]").forEach((selectAll) => {
|
|
1352
1250
|
this._listen(selectAll, "change", (event) => this._handleSelectAll(event));
|
|
1353
1251
|
});
|
|
1354
|
-
|
|
1355
1252
|
const pageSizeSelect = this._element.querySelector("[data-datatable-page-size-select]");
|
|
1356
1253
|
this._listen(pageSizeSelect, "change", (event) => this._setPageSize(event.target.value));
|
|
1357
|
-
|
|
1358
1254
|
this._element.querySelectorAll("[data-datatable-page-size-option]").forEach((option) => {
|
|
1359
1255
|
this._listen(option, "click", () => {
|
|
1360
1256
|
this._setPageSize(option.dataset.datatablePageSizeOption);
|
|
1361
1257
|
});
|
|
1362
1258
|
});
|
|
1363
1259
|
}
|
|
1364
|
-
}
|
|
1260
|
+
};
|
|
1261
|
+
__name(_DataTable, "DataTable");
|
|
1262
|
+
var DataTable = _DataTable;
|
|
1263
|
+
export {
|
|
1264
|
+
DataTable as default
|
|
1265
|
+
};
|