@nanoporetech-digital/components 3.4.0 → 3.5.0
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/CHANGELOG.md +12 -0
- package/dist/cjs/index-41582c2a.js +16 -12
- package/dist/cjs/index.cjs.js.map +1 -1
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/nano-components.cjs.js +1 -1
- package/dist/cjs/nano-demo.cjs.entry.js +291 -0
- package/dist/cjs/nano-demo.cjs.entry.js.map +1 -0
- package/dist/cjs/{nano-table-b9cdafab.js → nano-table-83e46f68.js} +486 -202
- package/dist/cjs/nano-table-83e46f68.js.map +1 -0
- package/dist/cjs/nano-table.cjs.entry.js +1 -1
- package/dist/cjs/{table.worker-291904c9.js → table.worker-525ec230.js} +3 -3
- package/dist/cjs/table.worker-525ec230.js.map +1 -0
- package/dist/cjs/table.worker-e9fb087e.js +4 -0
- package/dist/collection/collection-manifest.json +1 -0
- package/dist/collection/components/alert/alert.helpers.js.map +1 -1
- package/dist/collection/components/demo/demo.js +284 -0
- package/dist/collection/components/demo/demo.js.map +1 -0
- package/dist/collection/components/dialog/dialog.helpers.js.map +1 -1
- package/dist/collection/components/table/table-interface.js.map +1 -1
- package/dist/collection/components/table/table.cell.js +65 -0
- package/dist/collection/components/table/table.cell.js.map +1 -0
- package/dist/collection/components/table/table.css +98 -20
- package/dist/collection/components/table/table.header.js +156 -0
- package/dist/collection/components/table/table.header.js.map +1 -0
- package/dist/collection/components/table/table.js +170 -18
- package/dist/collection/components/table/table.js.map +1 -1
- package/dist/collection/components/table/table.row.js +113 -0
- package/dist/collection/components/table/table.row.js.map +1 -0
- package/dist/collection/components/table/table.store.js +46 -9
- package/dist/collection/components/table/table.store.js.map +1 -1
- package/dist/collection/components/table/table.utils.js +230 -0
- package/dist/collection/components/table/table.utils.js.map +1 -1
- package/dist/collection/components/table/table.worker.js +1 -0
- package/dist/collection/components/table/table.worker.js.map +1 -1
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.js +1 -0
- package/dist/components/index.js.map +1 -1
- package/dist/components/nano-demo.d.ts +11 -0
- package/dist/components/nano-demo.js +341 -0
- package/dist/components/nano-demo.js.map +1 -0
- package/dist/components/nano-table.js +2 -1247
- package/dist/components/nano-table.js.map +1 -1
- package/dist/components/table.js +1539 -0
- package/dist/components/table.js.map +1 -0
- package/dist/components/table.worker.js +2 -2
- package/dist/custom-elements/index.d.ts +6 -0
- package/dist/custom-elements/index.js +772 -204
- package/dist/custom-elements/index.js.map +1 -1
- package/dist/esm/index-3c280603.js +16 -12
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/loader.js +1 -1
- package/dist/esm/nano-components.js +1 -1
- package/dist/esm/nano-demo.entry.js +287 -0
- package/dist/esm/nano-demo.entry.js.map +1 -0
- package/dist/esm/{nano-table-c8ef2276.js → nano-table-e2405350.js} +487 -203
- package/dist/esm/nano-table-e2405350.js.map +1 -0
- package/dist/esm/nano-table.entry.js +1 -1
- package/dist/esm/{table.worker-65438fa0.js → table.worker-739c193f.js} +3 -3
- package/dist/esm/table.worker-739c193f.js.map +1 -0
- package/dist/esm/table.worker-e9fb087e.js +4 -0
- package/dist/nano-components/index.esm.js.map +1 -1
- package/dist/nano-components/nano-components.esm.js +1 -1
- package/dist/nano-components/nano-components.esm.js.map +1 -1
- package/dist/nano-components/p-28fdfa6b.js +5 -0
- package/dist/nano-components/p-28fdfa6b.js.map +1 -0
- package/dist/nano-components/p-85cfb0af.entry.js +5 -0
- package/dist/nano-components/p-85cfb0af.entry.js.map +1 -0
- package/dist/nano-components/p-a71989f3.js +5 -0
- package/dist/nano-components/{p-14218d23.entry.js.map → p-a71989f3.js.map} +0 -0
- package/dist/nano-components/{p-14218d23.entry.js → p-e4a28360.entry.js} +2 -2
- package/dist/nano-components/{p-fe1f8360.js.map → p-e4a28360.entry.js.map} +0 -0
- package/dist/nano-components/p-e9fb087e.js +4 -0
- package/dist/types/components/alert/alert.helpers.d.ts +1 -1
- package/dist/types/components/demo/demo.d.ts +6 -0
- package/dist/types/components/dialog/dialog.helpers.d.ts +1 -1
- package/dist/types/components/table/table-interface.d.ts +38 -23
- package/dist/types/components/table/table.cell.d.ts +18 -0
- package/dist/types/components/table/table.d.ts +36 -1
- package/dist/types/components/table/table.header.d.ts +16 -0
- package/dist/types/components/table/table.row.d.ts +15 -0
- package/dist/types/components/table/table.utils.d.ts +99 -0
- package/dist/types/components.d.ts +50 -0
- package/docs-json.json +124 -3
- package/docs-vscode.json +17 -1
- package/package.json +2 -2
- package/dist/cjs/nano-table-b9cdafab.js.map +0 -1
- package/dist/cjs/table.worker-1fd13775.js +0 -4
- package/dist/cjs/table.worker-291904c9.js.map +0 -1
- package/dist/collection/components/table/table.children.js +0 -224
- package/dist/collection/components/table/table.children.js.map +0 -1
- package/dist/collection/components/table/table.service.js +0 -121
- package/dist/collection/components/table/table.service.js.map +0 -1
- package/dist/esm/nano-table-c8ef2276.js.map +0 -1
- package/dist/esm/table.worker-1fd13775.js +0 -4
- package/dist/esm/table.worker-65438fa0.js.map +0 -1
- package/dist/nano-components/p-1fd13775.js +0 -4
- package/dist/nano-components/p-f9349146.js +0 -5
- package/dist/nano-components/p-f9349146.js.map +0 -1
- package/dist/nano-components/p-fe1f8360.js +0 -5
- package/dist/types/components/table/table.children.d.ts +0 -30
- package/dist/types/components/table/table.service.d.ts +0 -42
@@ -1,7 +1,7 @@
|
|
1
1
|
/*!
|
2
2
|
* Web Components for Nanopore digital Web Apps
|
3
3
|
*/
|
4
|
-
import { j as consoleError,
|
4
|
+
import { j as consoleError, g as getElement, e as getRenderingRef, h, F as Fragment, r as registerInstance, c as createEvent, d as readTask, a as Host } from './index-3c280603.js';
|
5
5
|
import { a as cyrb53 } from './math-c02ddfda.js';
|
6
6
|
import { d as debounce } from './throttle-7836544e.js';
|
7
7
|
import { c as createStore } from './index-c752dae1.js';
|
@@ -110,7 +110,7 @@ const createWorkerProxy = (worker, workerMsgId, exportedMethod) => (
|
|
110
110
|
})
|
111
111
|
);
|
112
112
|
|
113
|
-
const workerPromise = import('./table.worker-
|
113
|
+
const workerPromise = import('./table.worker-739c193f.js').then(m => m.worker);
|
114
114
|
const createWorkerStore = /*@__PURE__*/createWorkerProxy(workerPromise, 'stencil.table.worker', 'createWorkerStore');
|
115
115
|
const syncConfigToWorker = /*@__PURE__*/createWorkerProxy(workerPromise, 'stencil.table.worker', 'syncConfigToWorker');
|
116
116
|
const syncDataToWorker = /*@__PURE__*/createWorkerProxy(workerPromise, 'stencil.table.worker', 'syncDataToWorker');
|
@@ -164,16 +164,53 @@ async function generateStore(host, columns, scrollParent) {
|
|
164
164
|
function getStore(host) {
|
165
165
|
return stores.get(host);
|
166
166
|
}
|
167
|
+
function getDataType(value) {
|
168
|
+
if (value instanceof Date) {
|
169
|
+
return 'date';
|
170
|
+
}
|
171
|
+
if (['number', 'string'].includes(typeof value)) {
|
172
|
+
return typeof value;
|
173
|
+
}
|
174
|
+
return 'unknown';
|
175
|
+
}
|
167
176
|
function storeSetData(host, rows) {
|
168
177
|
const store = stores.get(host);
|
169
178
|
if (!store)
|
170
179
|
return;
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
})
|
180
|
+
const cols = store.config.state.columns;
|
181
|
+
const dateCols = cols
|
182
|
+
.filter((col) => col.type === 'date')
|
183
|
+
.reduce((prev, curr) => {
|
184
|
+
return [...prev, curr.prop];
|
185
|
+
}, []);
|
186
|
+
const unknownCols = cols.filter((col) => !col.type);
|
187
|
+
// augments data with some internal.
|
188
|
+
// discern unknown column types
|
189
|
+
// convert dates to numbers for worker
|
190
|
+
rows = rows.map((row, i) => {
|
191
|
+
// try our best to discern the column type (from first row) if unset
|
192
|
+
if (unknownCols.length && i === 0) {
|
193
|
+
store.config.state.columns = cols.map((col) => {
|
194
|
+
if (unknownCols.includes(col) && row[col.prop] && !col.type) {
|
195
|
+
col.type = getDataType(row[col.prop]);
|
196
|
+
if (col.type === 'date')
|
197
|
+
dateCols.push(col.prop);
|
198
|
+
}
|
199
|
+
return col;
|
200
|
+
});
|
201
|
+
}
|
202
|
+
// convert date columns into numbers to send to our worker
|
203
|
+
dateCols.forEach((colName) => {
|
204
|
+
// coerce any date type;
|
205
|
+
// Date(), timestamp, valid date string
|
206
|
+
const coerceDate = new Date(row[colName]) ?? null;
|
207
|
+
if (!!coerceDate && Number(coerceDate))
|
208
|
+
row[colName] = Number(coerceDate);
|
209
|
+
});
|
210
|
+
row['__index'] = i;
|
211
|
+
row['__uuid'] = cyrb53(Object.values(row).join());
|
212
|
+
return row;
|
213
|
+
});
|
177
214
|
store.data.state.rows = rows;
|
178
215
|
if (store.general.state.workerId)
|
179
216
|
return syncDataToWorker(store.general.state.workerId, rows);
|
@@ -194,7 +231,7 @@ async function storeSearch(host, term) {
|
|
194
231
|
store.data.state.rows = await workerSearch(store.general.state.workerId, term);
|
195
232
|
}
|
196
233
|
catch (e) {
|
197
|
-
console.
|
234
|
+
console.warn(e);
|
198
235
|
}
|
199
236
|
}
|
200
237
|
async function storeFilter(host, filters) {
|
@@ -205,7 +242,7 @@ async function storeFilter(host, filters) {
|
|
205
242
|
store.data.state.rows = await workerFilter(store.general.state.workerId, filters);
|
206
243
|
}
|
207
244
|
catch (e) {
|
208
|
-
console.
|
245
|
+
console.warn(e);
|
209
246
|
}
|
210
247
|
}
|
211
248
|
async function storeSort(host, prop, order) {
|
@@ -216,7 +253,7 @@ async function storeSort(host, prop, order) {
|
|
216
253
|
store.data.state.rows = await workerSort(store.general.state.workerId, prop, order);
|
217
254
|
}
|
218
255
|
catch (e) {
|
219
|
-
console.
|
256
|
+
console.warn(e);
|
220
257
|
}
|
221
258
|
}
|
222
259
|
|
@@ -313,19 +350,6 @@ function mergeCellProperties(rowIndex, colIndex, defaultProps) {
|
|
313
350
|
return props;
|
314
351
|
return mergeProperties(props, extra);
|
315
352
|
}
|
316
|
-
/**
|
317
|
-
* Renders a cell using a custom renderer if set.
|
318
|
-
* @param rowIndex - the current row index being rendered
|
319
|
-
* @param colIndex - the current column index being rendered
|
320
|
-
* @returns - a JSX node
|
321
|
-
*/
|
322
|
-
function cellRender(rowIndex, colIndex) {
|
323
|
-
const store = fetchStores();
|
324
|
-
const columns = store.config.state.columns;
|
325
|
-
const tpl = columns[colIndex]?.cellTemplate;
|
326
|
-
const model = colDataModel(rowIndex, colIndex);
|
327
|
-
return tpl ? (tpl(h, model)) : (h(Fragment, null, model.cellModel.toString()));
|
328
|
-
}
|
329
353
|
/**
|
330
354
|
* Renders a table header (within a thead) using a custom template if set.
|
331
355
|
* @param col - the current column config object
|
@@ -335,26 +359,14 @@ function colheadFootRender(col) {
|
|
335
359
|
const tpl = col?.colTemplate;
|
336
360
|
return tpl ? (tpl(h, col)) : (h(Fragment, null, col.title));
|
337
361
|
}
|
338
|
-
|
339
|
-
function baseClasses(type, vPinned, toString = false) {
|
340
|
-
const classes = {
|
341
|
-
[`${CSSNAMESPACE}__${type}`]: true,
|
342
|
-
[`${CSSNAMESPACE}__pin`]: !!vPinned,
|
343
|
-
[`${CSSNAMESPACE}__pin--top`]: vPinned === 'top',
|
344
|
-
[`${CSSNAMESPACE}__pin--bottom`]: vPinned === 'bottom',
|
345
|
-
};
|
346
|
-
if (toString) {
|
347
|
-
let classString = '';
|
348
|
-
Object.entries(classes).forEach(([className, on]) => {
|
349
|
-
if (on)
|
350
|
-
classString += className + ' ';
|
351
|
-
});
|
352
|
-
return classString;
|
353
|
-
}
|
354
|
-
return classes;
|
355
|
-
}
|
356
362
|
const stickyHIOs = new WeakMap();
|
357
363
|
const stickyVIOs = new WeakMap();
|
364
|
+
/**
|
365
|
+
* Adds element to Intersection Observer. Fires when element changes on the x axis
|
366
|
+
* @param el - an element to observe
|
367
|
+
* @param pos - the edge to watch (start or end)
|
368
|
+
* @param cb - callback when an intersection state changes.
|
369
|
+
*/
|
358
370
|
function addHObserver(el, pos, cb) {
|
359
371
|
if (stickyHIOs.get(el))
|
360
372
|
return;
|
@@ -369,13 +381,13 @@ function addHObserver(el, pos, cb) {
|
|
369
381
|
!e.isIntersecting;
|
370
382
|
}
|
371
383
|
if (pos === 'end') {
|
372
|
-
// console.log('refe', store.general.state.host)
|
373
384
|
// TODO - sort these out for RtL
|
374
385
|
positions.end =
|
375
386
|
e.boundingClientRect.right > e.boundingClientRect.width &&
|
376
387
|
!e.isIntersecting;
|
377
388
|
}
|
378
|
-
cb
|
389
|
+
if (!!cb)
|
390
|
+
cb(positions);
|
379
391
|
}, {
|
380
392
|
threshold: [1],
|
381
393
|
rootMargin: '1px 0px 100px 0px',
|
@@ -385,6 +397,12 @@ function addHObserver(el, pos, cb) {
|
|
385
397
|
// dirty fix - wait a tick 'cos nano-size-observer isn't always ready in-time
|
386
398
|
setTimeout(() => observer.observe(el), 300);
|
387
399
|
}
|
400
|
+
/**
|
401
|
+
* Adds element to Intersection Observer. Fires when element changes on the y axis
|
402
|
+
* @param el - an element to observe
|
403
|
+
* @param pos - the edge to watch (start or end)
|
404
|
+
* @param cb - callback when an intersection state changes.
|
405
|
+
*/
|
388
406
|
function addVObserver(el, pos, cb) {
|
389
407
|
if (stickyVIOs.get(el))
|
390
408
|
return;
|
@@ -398,11 +416,14 @@ function addVObserver(el, pos, cb) {
|
|
398
416
|
e.boundingClientRect.y - (rootBounds.y + root.scrollTop) < 0 &&
|
399
417
|
!e.isIntersecting;
|
400
418
|
}
|
401
|
-
if (pos === 'bottom')
|
419
|
+
if (pos === 'bottom') {
|
420
|
+
const boundingClientRect = e.target.getBoundingClientRect();
|
402
421
|
positions.bottom =
|
403
|
-
|
404
|
-
!e.isIntersecting;
|
405
|
-
|
422
|
+
boundingClientRect.height + boundingClientRect.y >
|
423
|
+
rootBounds.height && !e.isIntersecting;
|
424
|
+
}
|
425
|
+
if (!!cb)
|
426
|
+
cb(positions);
|
406
427
|
}, {
|
407
428
|
threshold: [1],
|
408
429
|
rootMargin: '0px 100px 0px 100px',
|
@@ -411,64 +432,183 @@ function addVObserver(el, pos, cb) {
|
|
411
432
|
stickyVIOs.set(el, observer);
|
412
433
|
requestAnimationFrame(() => observer.observe(el));
|
413
434
|
}
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
435
|
+
function headerPinClasses(type, vPinned, toString = false) {
|
436
|
+
const classes = {
|
437
|
+
[`${CSSNAMESPACE}__${type}`]: true,
|
438
|
+
[`${CSSNAMESPACE}__pin`]: !!vPinned,
|
439
|
+
[`${CSSNAMESPACE}__pin--top`]: vPinned === 'top',
|
440
|
+
[`${CSSNAMESPACE}__pin--bottom`]: vPinned === 'bottom',
|
441
|
+
};
|
442
|
+
if (toString)
|
443
|
+
return classListToStr(classes);
|
444
|
+
return classes;
|
445
|
+
}
|
446
|
+
/**
|
447
|
+
* Turns a class map {'string': boolean} to class string
|
448
|
+
* @param classes - the class map to convert
|
449
|
+
* @returns a class string
|
450
|
+
*/
|
451
|
+
function classListToStr(classes) {
|
452
|
+
let classString = '';
|
453
|
+
Object.entries(classes).forEach(([className, on]) => {
|
454
|
+
if (on)
|
455
|
+
classString += className + ' ';
|
456
|
+
});
|
457
|
+
return classString;
|
458
|
+
}
|
459
|
+
/**
|
460
|
+
* Detects the current scroll speed as a number.
|
461
|
+
* Use within a scroll listener
|
462
|
+
*/
|
463
|
+
const detectScrollSpeed = (() => {
|
464
|
+
let lastPos;
|
465
|
+
let newPos;
|
466
|
+
let timer;
|
467
|
+
let delta;
|
468
|
+
const delay = 60; // in "ms" (higher means lower fidelity )
|
469
|
+
const clear = () => {
|
470
|
+
lastPos = null;
|
471
|
+
delta = 0;
|
472
|
+
};
|
473
|
+
clear();
|
474
|
+
return () => {
|
475
|
+
newPos = window.scrollY;
|
476
|
+
if (lastPos != null)
|
477
|
+
delta = newPos - lastPos;
|
478
|
+
lastPos = newPos;
|
479
|
+
window.clearTimeout(timer);
|
480
|
+
timer = window.setTimeout(clear, delay);
|
481
|
+
return delta;
|
482
|
+
};
|
483
|
+
})();
|
484
|
+
/**
|
485
|
+
* Attempts to find the closes scrolling parental element
|
486
|
+
* @param element - the element from which to traverse up the DOM
|
487
|
+
* @returns - the closest scrolling parental element
|
488
|
+
*/
|
489
|
+
function findScrollParent(element) {
|
490
|
+
let style = getComputedStyle(element);
|
491
|
+
const excludeStaticParent = style.position === 'absolute';
|
492
|
+
const overflowRegex = /(auto|scroll)/;
|
493
|
+
if (style.position === 'fixed')
|
494
|
+
return document.documentElement;
|
495
|
+
for (let parent = element; (parent = parent.parentElement);) {
|
496
|
+
style = getComputedStyle(parent);
|
497
|
+
if (excludeStaticParent && style.position === 'static') {
|
498
|
+
continue;
|
499
|
+
}
|
500
|
+
if (overflowRegex.test(style.overflow + style.overflowY + style.overflowX))
|
501
|
+
return parent;
|
423
502
|
}
|
424
|
-
|
425
|
-
|
426
|
-
|
503
|
+
return document.documentElement;
|
504
|
+
}
|
505
|
+
/**
|
506
|
+
* Checks whether an element is currently viewable within the viewport
|
507
|
+
* @param el - element to check
|
508
|
+
* @param percentVisible - the percentage of the element that should be within the viewport
|
509
|
+
* @returns true if the element's area percentage is visible
|
510
|
+
*/
|
511
|
+
function isInViewport(el, percentVisible = 100) {
|
512
|
+
const r = el.getBoundingClientRect();
|
513
|
+
const windowHeight = window.innerHeight || document.documentElement.clientHeight;
|
514
|
+
if (!r.bottom &&
|
515
|
+
!r.top &&
|
516
|
+
!r.left &&
|
517
|
+
!r.right &&
|
518
|
+
!r.height &&
|
519
|
+
!r.width &&
|
520
|
+
!r.x &&
|
521
|
+
!r.y)
|
522
|
+
return false;
|
523
|
+
return !(Math.floor(100 - ((r.top >= 0 ? 0 : r.top) / +-r.height) * 100) <
|
524
|
+
percentVisible ||
|
525
|
+
Math.floor(100 - ((r.bottom - windowHeight) / r.height) * 100) <
|
526
|
+
percentVisible);
|
527
|
+
}
|
528
|
+
/**
|
529
|
+
* Immutable array re-order
|
530
|
+
* @param from - the index to move from
|
531
|
+
* @param to - the index to move to
|
532
|
+
* @param arr - the array to re-order
|
533
|
+
* @returns - a new, re-orderd array
|
534
|
+
*/
|
535
|
+
function arrMove(from, to, arr) {
|
536
|
+
const newArr = [...arr];
|
537
|
+
const item = newArr.splice(from, 1)[0];
|
538
|
+
newArr.splice(to, 0, item);
|
539
|
+
return newArr;
|
540
|
+
}
|
541
|
+
|
542
|
+
// TABLE HEADERS
|
543
|
+
// (thead > tr > th, tfoot > tr > th)
|
544
|
+
let draggingCol;
|
545
|
+
let draggingColEle;
|
546
|
+
let dragEnterEle;
|
547
|
+
let draggingParent;
|
548
|
+
const TableColHead = ({ column, headRenderer, onColumnSortClick, onColumnPinned, onColumnDrag, onColumnDrop, defaults, }) => {
|
549
|
+
const store = fetchStores();
|
550
|
+
// Drag to re-order columns handling
|
551
|
+
function handleDragStart(e, column) {
|
552
|
+
draggingCol = column;
|
553
|
+
draggingColEle = dragEnterEle = e.target;
|
554
|
+
draggingParent = draggingColEle.closest('.' + `${CSSNAMESPACE}__tr`);
|
555
|
+
draggingParent.classList.add(`${CSSNAMESPACE}__dragging`);
|
556
|
+
draggingColEle.classList.add(`${CSSNAMESPACE}__drag--start`);
|
557
|
+
e.dataTransfer.effectAllowed = 'move';
|
558
|
+
e.dataTransfer.setData('text/html', draggingColEle.innerHTML);
|
559
|
+
onColumnDrag(column.prop, draggingColEle);
|
427
560
|
}
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
561
|
+
function handleDragEnd() {
|
562
|
+
draggingParent.classList.remove(`${CSSNAMESPACE}__dragging`);
|
563
|
+
draggingColEle.classList.remove(`${CSSNAMESPACE}__drag--start`);
|
564
|
+
draggingParent
|
565
|
+
.querySelectorAll(`.${CSSNAMESPACE}__drag-mask--active`)
|
566
|
+
.forEach((el) => {
|
567
|
+
el.classList.remove(`${CSSNAMESPACE}__drag-mask--active`);
|
568
|
+
});
|
569
|
+
draggingColEle = null;
|
570
|
+
draggingCol = null;
|
571
|
+
draggingParent = null;
|
572
|
+
dragEnterEle = null;
|
436
573
|
}
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
574
|
+
function handleDragEnter(e) {
|
575
|
+
if (dragEnterEle === e.target)
|
576
|
+
return;
|
577
|
+
e.preventDefault();
|
578
|
+
e.stopImmediatePropagation();
|
579
|
+
e.dataTransfer.dropEffect = 'move';
|
580
|
+
draggingParent
|
581
|
+
.querySelectorAll(`.${CSSNAMESPACE}__drag-mask--active`)
|
582
|
+
.forEach((el) => {
|
583
|
+
el.classList.remove(`${CSSNAMESPACE}__drag-mask--active`);
|
444
584
|
});
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
if (!!node.vchildren) {
|
450
|
-
node.vchildren = utils.map(node.vchildren, (cNode) => {
|
451
|
-
if (['td', 'th'].includes(cNode.vtag.toString())) {
|
452
|
-
cNode.vattrs = mergeProperties({
|
453
|
-
class: baseClasses(cNode.vtag.toString(), pinned, true),
|
454
|
-
ref: (th) => {
|
455
|
-
addVObserver(th, pinned, onColumnPinned);
|
456
|
-
},
|
457
|
-
}, cNode.vattrs);
|
458
|
-
}
|
459
|
-
return cNode;
|
460
|
-
});
|
461
|
-
}
|
462
|
-
}
|
463
|
-
return node;
|
464
|
-
});
|
585
|
+
dragEnterEle = e.target;
|
586
|
+
if (!dragEnterEle.classList.contains(`${CSSNAMESPACE}__drag-mask`)) {
|
587
|
+
e.dataTransfer.dropEffect = 'none';
|
588
|
+
return;
|
465
589
|
}
|
466
|
-
|
590
|
+
dragEnterEle.classList.add(`${CSSNAMESPACE}__drag-mask--active`);
|
467
591
|
}
|
468
|
-
|
469
|
-
|
470
|
-
const
|
471
|
-
|
592
|
+
function handleDrop(e) {
|
593
|
+
e.stopPropagation();
|
594
|
+
const { colName } = this.dataset;
|
595
|
+
if (colName === draggingCol.prop)
|
596
|
+
return;
|
597
|
+
const cols = store.config.state.columns;
|
598
|
+
let toIndex = cols.findIndex((col) => col.prop === colName);
|
599
|
+
const fromIndex = cols.findIndex((col) => col === draggingCol);
|
600
|
+
if (toIndex < fromIndex &&
|
601
|
+
this.classList.contains(`${CSSNAMESPACE}__drag-mask--end`))
|
602
|
+
toIndex++;
|
603
|
+
if (toIndex > fromIndex &&
|
604
|
+
this.classList.contains(`${CSSNAMESPACE}__drag-mask--start`))
|
605
|
+
toIndex--;
|
606
|
+
if (toIndex === fromIndex)
|
607
|
+
return;
|
608
|
+
onColumnDrop(draggingCol.prop, store.config.state.columns[toIndex].prop, draggingColEle);
|
609
|
+
}
|
610
|
+
// Sort handling
|
611
|
+
function handleColumnSortClick(e) {
|
472
612
|
let order;
|
473
613
|
switch (column.order) {
|
474
614
|
case 'asc':
|
@@ -480,7 +620,15 @@ const TableColHead = ({ column, headRenderer, onColumnOrderClick, onColumnPinned
|
|
480
620
|
default:
|
481
621
|
order = 'asc';
|
482
622
|
}
|
483
|
-
|
623
|
+
onColumnSortClick(order, column.prop, e.target.closest('th'));
|
624
|
+
}
|
625
|
+
function isSortable() {
|
626
|
+
return ((!!defaults.sortable && column.sortable !== false) ||
|
627
|
+
(!defaults.sortable && column.sortable === true));
|
628
|
+
}
|
629
|
+
function isDraggable() {
|
630
|
+
return ((!!defaults.draggable && column.draggable !== false) ||
|
631
|
+
(!defaults.draggable && column.draggable === true));
|
484
632
|
}
|
485
633
|
let extraProps = {};
|
486
634
|
if (column.columnProperties) {
|
@@ -488,7 +636,7 @@ const TableColHead = ({ column, headRenderer, onColumnOrderClick, onColumnPinned
|
|
488
636
|
}
|
489
637
|
const baseProps = {
|
490
638
|
class: {
|
491
|
-
...
|
639
|
+
...headerPinClasses('th', headRenderer?.pinned),
|
492
640
|
[`${CSSNAMESPACE}__pin--start`]: column.pinned === 'start',
|
493
641
|
[`${CSSNAMESPACE}__pin--end`]: column.pinned === 'end',
|
494
642
|
[`${CSSNAMESPACE}__ordered`]: !!column.order,
|
@@ -500,60 +648,106 @@ const TableColHead = ({ column, headRenderer, onColumnOrderClick, onColumnPinned
|
|
500
648
|
if (!content)
|
501
649
|
return h(Fragment, null);
|
502
650
|
props =
|
503
|
-
Number(props.
|
651
|
+
Number(props.colSpan) > 1
|
504
652
|
? { ...props, scope: 'colgroup' }
|
505
653
|
: { ...props, scope: 'col' };
|
506
|
-
if (
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
!!column.filter && h("nano-icon", { name: "light/filter" }),
|
523
|
-
!!column.order &&
|
524
|
-
(column.order === 'desc' ? (h("nano-icon", { name: "solid/long-arrow-down" })) : (h("nano-icon", { name: "solid/long-arrow-up" }))),
|
525
|
-
h("div", { class: `${CSSNAMESPACE}__status-icons` },
|
526
|
-
h("nano-icon", { name: "light/chevron-down" })))));
|
654
|
+
if (isSortable()) {
|
655
|
+
const sort = column.order
|
656
|
+
? column.order === 'asc'
|
657
|
+
? 'ascending'
|
658
|
+
: 'descending'
|
659
|
+
: 'none';
|
660
|
+
props = { ...props, 'aria-sort': sort };
|
661
|
+
}
|
662
|
+
if (isDraggable()) {
|
663
|
+
props = {
|
664
|
+
...props,
|
665
|
+
draggable: true,
|
666
|
+
onDragStart: (e) => handleDragStart(e, column),
|
667
|
+
onDragOver: (e) => e.preventDefault(),
|
668
|
+
onDragEnd: () => handleDragEnd(),
|
669
|
+
};
|
527
670
|
}
|
528
671
|
return (h("th", { ...props, ref: (th) => {
|
529
672
|
if (['end', 'start'].includes(column.pinned))
|
530
673
|
addHObserver(th, column.pinned, onColumnPinned);
|
531
674
|
if (['top', 'bottom'].includes(headRenderer.pinned))
|
532
675
|
addVObserver(th, headRenderer.pinned, onColumnPinned);
|
533
|
-
} },
|
534
|
-
|
676
|
+
}, key: column.prop },
|
677
|
+
isDraggable() && [
|
678
|
+
h("div", { class: {
|
679
|
+
[`${CSSNAMESPACE}__drag-mask`]: true,
|
680
|
+
[`${CSSNAMESPACE}__drag-mask--start`]: true,
|
681
|
+
}, "data-col-name": column.prop, onDragEnter: handleDragEnter, onDrop: handleDrop, onDragOver: (e) => e.preventDefault() }),
|
682
|
+
h("div", { class: {
|
683
|
+
[`${CSSNAMESPACE}__drag-mask`]: true,
|
684
|
+
[`${CSSNAMESPACE}__drag-mask--end`]: true,
|
685
|
+
}, "data-col-name": column.prop, onDragEnter: handleDragEnter, onDrop: handleDrop, onDragOver: (e) => e.preventDefault() }),
|
686
|
+
],
|
687
|
+
isSortable() ? (h("button", { class: {
|
688
|
+
[`${CSSNAMESPACE}__order-btn`]: true,
|
689
|
+
[`${CSSNAMESPACE}__cell-content`]: true,
|
690
|
+
}, onClick: handleColumnSortClick },
|
691
|
+
colheadFootRender(column),
|
692
|
+
!!column.filter && h("nano-icon", { name: "light/filter" }),
|
693
|
+
!!column.order &&
|
694
|
+
(column.order === 'desc' ? (h("nano-icon", { name: "solid/long-arrow-down" })) : (h("nano-icon", { name: "solid/long-arrow-up" }))),
|
695
|
+
h("div", { class: `${CSSNAMESPACE}__status-icons` },
|
696
|
+
h("nano-icon", { name: "light/chevron-down" })))) : (h("div", { class: `${CSSNAMESPACE}__cell-content` },
|
535
697
|
colheadFootRender(column),
|
536
|
-
!!column.filter && h("nano-icon", { name: "light/bars-filter" }))));
|
698
|
+
!!column.filter && h("nano-icon", { name: "light/bars-filter" })))));
|
699
|
+
};
|
700
|
+
|
701
|
+
// TABLE CELL
|
702
|
+
// (tbody > tr > td, tbody > tr > th)
|
703
|
+
/**
|
704
|
+
* Renders a cell using a custom renderer if set.
|
705
|
+
* @param rowIndex - the current row index being rendered
|
706
|
+
* @param colIndex - the current column index being rendered
|
707
|
+
* @returns - a JSX node
|
708
|
+
*/
|
709
|
+
function cellRender(rowIndex, colIndex) {
|
710
|
+
const store = fetchStores();
|
711
|
+
const columns = store.config.state.columns;
|
712
|
+
const tpl = columns[colIndex]?.cellTemplate;
|
713
|
+
const model = colDataModel(rowIndex, colIndex);
|
714
|
+
if (!!model.cellModel && columns[colIndex].type === 'date') {
|
715
|
+
const d = new Date(model.cellModel);
|
716
|
+
if (d instanceof Date && !isNaN(d)) {
|
717
|
+
model.cellModel = !tpl
|
718
|
+
? `${new Date(model.cellModel).toLocaleDateString()} ${new Date(model.cellModel).toLocaleTimeString()}`
|
719
|
+
: d;
|
720
|
+
}
|
721
|
+
}
|
722
|
+
return tpl ? (tpl(h, model)) : (h(Fragment, null, model.cellModel?.toString()));
|
723
|
+
}
|
724
|
+
const baseCellClasses = (colIndex, toString = false) => {
|
725
|
+
const store = fetchStores();
|
726
|
+
const column = store.config.state.columns[colIndex];
|
727
|
+
const classes = {
|
728
|
+
[`${CSSNAMESPACE}__td`]: true,
|
729
|
+
[`${CSSNAMESPACE}__ordered`]: !!column.order,
|
730
|
+
[`${CSSNAMESPACE}__pin`]: !!column.pinned,
|
731
|
+
[`${CSSNAMESPACE}__pin--start`]: column.pinned === 'start',
|
732
|
+
[`${CSSNAMESPACE}__pin--end`]: column.pinned === 'end',
|
733
|
+
};
|
734
|
+
if (toString)
|
735
|
+
return classListToStr(classes);
|
736
|
+
return classes;
|
537
737
|
};
|
538
738
|
const TableCell = ({ rowIndex, colIndex, nestedContent, }) => {
|
539
739
|
const content = nestedContent || cellRender(rowIndex, colIndex);
|
540
740
|
if (!content)
|
541
741
|
return h(Fragment, null);
|
742
|
+
let CellType = 'td';
|
542
743
|
const store = fetchStores();
|
543
744
|
const column = store.config.state.columns[colIndex];
|
544
|
-
let CellType = 'td';
|
545
745
|
let props = mergeCellProperties(rowIndex, colIndex, {
|
546
|
-
class:
|
547
|
-
[`${CSSNAMESPACE}__td`]: true,
|
548
|
-
[`${CSSNAMESPACE}__ordered`]: !!column.order,
|
549
|
-
[`${CSSNAMESPACE}__pin`]: !!column.pinned,
|
550
|
-
[`${CSSNAMESPACE}__pin--start`]: column.pinned === 'start',
|
551
|
-
[`${CSSNAMESPACE}__pin--end`]: column.pinned === 'end',
|
552
|
-
},
|
746
|
+
class: baseCellClasses(colIndex),
|
553
747
|
});
|
554
748
|
if (column.rowHeader) {
|
555
749
|
props =
|
556
|
-
Number(props.
|
750
|
+
Number(props.rowSpan) > 1
|
557
751
|
? { ...props, scope: 'rowgroup' }
|
558
752
|
: { ...props, scope: 'row' };
|
559
753
|
CellType = 'th';
|
@@ -564,62 +758,113 @@ const TableCell = ({ rowIndex, colIndex, nestedContent, }) => {
|
|
564
758
|
h("div", { class: `${CSSNAMESPACE}__cell-content` }, content)));
|
565
759
|
};
|
566
760
|
|
567
|
-
const
|
568
|
-
let
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
const delay = 60; // in "ms" (higher means lower fidelity )
|
573
|
-
const clear = () => {
|
574
|
-
lastPos = null;
|
575
|
-
delta = 0;
|
761
|
+
const TableRow = ({ rowRenderer, rowIndex, row, onColumnPinned }, children, utils) => {
|
762
|
+
let extraProps = {};
|
763
|
+
const TableCell = ({ header }, children) => {
|
764
|
+
const cell = h("div", { class: CSSNAMESPACE + '__cell-content' }, children);
|
765
|
+
return header ? h("th", { scope: "row" }, cell) : h("td", null, cell);
|
576
766
|
};
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
767
|
+
if (!row) {
|
768
|
+
const model = rowDataModel(rowIndex);
|
769
|
+
row = model.row;
|
770
|
+
}
|
771
|
+
if (rowRenderer?.rowProperties) {
|
772
|
+
extraProps = rowRenderer.rowProperties({ row, rowIndex }) || extraProps;
|
773
|
+
}
|
774
|
+
let pinned;
|
775
|
+
if (rowRenderer?.pinned && typeof rowRenderer.pinned === 'function') {
|
776
|
+
pinned = rowRenderer.pinned();
|
777
|
+
}
|
778
|
+
const baseProps = { class: headerPinClasses('tr', pinned) };
|
779
|
+
const props = extraProps ? mergeProperties(baseProps, extraProps) : baseProps;
|
780
|
+
const tpl = rowRenderer?.template;
|
781
|
+
if (tpl) {
|
782
|
+
let toRender = tpl(h, {
|
783
|
+
renderedRow: (h("tr", { ...props, key: row.__uuid }, children)),
|
784
|
+
row,
|
785
|
+
rowIndex,
|
786
|
+
}, TableCell);
|
787
|
+
if (Array.isArray(toRender)) {
|
788
|
+
toRender = utils.map(toRender, (node, i) => {
|
789
|
+
if (node.vtag === 'tr') {
|
790
|
+
if (!node.vkey)
|
791
|
+
node.vkey = `${row.__uuid}_${i}`;
|
792
|
+
node.vattrs = mergeProperties({ class: headerPinClasses('tr', pinned, true) }, node.vattrs);
|
793
|
+
if (!!node.vchildren) {
|
794
|
+
node.vchildren = utils.map(node.vchildren, (cNode, i) => {
|
795
|
+
if (['td', 'th'].includes(cNode.vtag.toString())) {
|
796
|
+
cNode.vattrs = mergeProperties({
|
797
|
+
class: headerPinClasses(cNode.vtag.toString(), pinned, true) + baseCellClasses(i, true),
|
798
|
+
ref: (th) => {
|
799
|
+
if ((!!th && pinned === 'top') || pinned === 'bottom')
|
800
|
+
addVObserver(th, pinned, onColumnPinned);
|
801
|
+
if (!!th && th.classList.contains('nano-tbl__pin--end'))
|
802
|
+
addHObserver(th, 'end', onColumnPinned);
|
803
|
+
if (!!th && th.classList.contains('nano-tbl__pin--start'))
|
804
|
+
addHObserver(th, 'start', onColumnPinned);
|
805
|
+
},
|
806
|
+
}, cNode.vattrs);
|
807
|
+
}
|
808
|
+
return cNode;
|
809
|
+
});
|
810
|
+
}
|
811
|
+
}
|
812
|
+
return node;
|
813
|
+
});
|
814
|
+
}
|
815
|
+
return toRender;
|
816
|
+
}
|
817
|
+
return (h("tr", { ...props, key: row.__uuid }, children));
|
818
|
+
};
|
819
|
+
const TableHeadFootRow = ({ rowRenderer, onColumnPinned }, children, utils) => {
|
820
|
+
let extraProps = {};
|
821
|
+
if (rowRenderer.rowProperties) {
|
822
|
+
extraProps = rowRenderer.rowProperties() || {};
|
823
|
+
}
|
824
|
+
const TableCell = ({ header }, children) => {
|
825
|
+
const cell = h("div", { class: CSSNAMESPACE + '__cell-content' }, children);
|
826
|
+
return header !== false ? h("th", { scope: "col" }, cell) : h("td", null, cell);
|
586
827
|
};
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
const
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
828
|
+
const pinned = rowRenderer.pinned || null;
|
829
|
+
const baseProps = { class: headerPinClasses('tr', null) };
|
830
|
+
const props = extraProps ? mergeProperties(baseProps, extraProps) : baseProps;
|
831
|
+
const tpl = rowRenderer?.template;
|
832
|
+
if (tpl) {
|
833
|
+
let toRender = tpl(h, {
|
834
|
+
renderedRow: h("tr", { ...props }, children),
|
835
|
+
}, TableCell);
|
836
|
+
if (Array.isArray(toRender)) {
|
837
|
+
toRender = utils.map(toRender, (node) => {
|
838
|
+
if (node.vtag === 'tr') {
|
839
|
+
node.vattrs = mergeProperties({ class: headerPinClasses('tr', pinned, true) }, node.vattrs);
|
840
|
+
if (!!node.vchildren) {
|
841
|
+
node.vchildren = utils.map(node.vchildren, (cNode) => {
|
842
|
+
if (['td', 'th'].includes(cNode.vtag.toString())) {
|
843
|
+
cNode.vattrs = mergeProperties({
|
844
|
+
class: headerPinClasses(cNode.vtag.toString(), pinned, true),
|
845
|
+
ref: (th) => {
|
846
|
+
if ((!!th && pinned === 'top') || pinned === 'bottom')
|
847
|
+
addVObserver(th, pinned, onColumnPinned);
|
848
|
+
if (!!th && th.classList.contains('nano-tbl__pin--end'))
|
849
|
+
addHObserver(th, 'end', onColumnPinned);
|
850
|
+
if (!!th && th.classList.contains('nano-tbl__pin--start'))
|
851
|
+
addHObserver(th, 'start', onColumnPinned);
|
852
|
+
},
|
853
|
+
}, cNode.vattrs);
|
854
|
+
}
|
855
|
+
return cNode;
|
856
|
+
});
|
857
|
+
}
|
858
|
+
}
|
859
|
+
return node;
|
860
|
+
});
|
598
861
|
}
|
599
|
-
|
600
|
-
return parent;
|
862
|
+
return toRender;
|
601
863
|
}
|
602
|
-
return
|
603
|
-
}
|
604
|
-
function isInViewport(el, percentVisible = 100) {
|
605
|
-
const r = el.getBoundingClientRect();
|
606
|
-
const windowHeight = window.innerHeight || document.documentElement.clientHeight;
|
607
|
-
if (!r.bottom &&
|
608
|
-
!r.top &&
|
609
|
-
!r.left &&
|
610
|
-
!r.right &&
|
611
|
-
!r.height &&
|
612
|
-
!r.width &&
|
613
|
-
!r.x &&
|
614
|
-
!r.y)
|
615
|
-
return false;
|
616
|
-
return !(Math.floor(100 - ((r.top >= 0 ? 0 : r.top) / +-r.height) * 100) <
|
617
|
-
percentVisible ||
|
618
|
-
Math.floor(100 - ((r.bottom - windowHeight) / r.height) * 100) <
|
619
|
-
percentVisible);
|
620
|
-
}
|
864
|
+
return h("tr", { ...props }, children);
|
865
|
+
};
|
621
866
|
|
622
|
-
const tableCss = ":host{box-sizing:border-box}*,*::before,*::after{box-sizing:border-box}[hidden]{display:none !important}
|
867
|
+
const tableCss = ":host{box-sizing:border-box}*,*::before,*::after{box-sizing:border-box}[hidden]{display:none !important}nano-table{display:block;width:100%;--max-col-width:clamp(200px, 30%, 20vw);--color:var(--nano-color-mediumgrey, #68767e);--font-size:0.87rem;--cell-line-height:1.5;--thead-font-size:0.95rem;--thead-color:#455560;--tfoot-color:#455560;--border-color:#dddbda;--border-style:thin solid var(--border-color);--border-tint-color:#0084a9;--border-tint-style:3px solid var(--border-tint-color);--cell-bg-rgb:var(--nano-color-white-rgb, 255 255 255);--head-bg-rgb:250, 250, 249;--foot-bg-rgb:var(--head-bg-rgb);--th-row-bg-rgb:var(--cell-bg-rgb);--ordered-bg-rgb:var(--nano-color-offwhite-rgb, 249 249 251);--td-padding-start:0.625rem;--td-padding-end:0.625rem;--td-padding-top:0.5rem;--td-padding-bottom:0.4125rem;--th-padding-start:0.625rem;--th-padding-end:0.625rem;--th-padding-top:0.875rem;--th-padding-bottom:0.6875rem;--td-padding-v:var(--td-padding-top) var(--td-padding-bottom);--td-padding-h:var(--td-padding-start) var(--td-padding-end);--th-padding-v:var(--th-padding-top) var(--th-padding-bottom);--th-padding-h:var(--th-padding-start) var(--th-padding-end);--foot-th-padding-v:var(--td-padding-top) var(--td-padding-bottom);--foot-th-padding-h:var(--td-padding-start) var(--td-padding-end);--head-th-padding-v:var(--th-padding-top) var(--th-padding-bottom);--head-th-padding-h:var(--th-padding-start) var(--th-padding-end);--bookend-col-padding:2rem}.nano-tbl{color:var(--color);text-align:start;width:100%;font-size:var(--font-size);border-spacing:0 0;border-collapse:separate;background:rgb(var(--cell-bg-rgb));border-inline-end:1px solid transparent;border-block-start:1px solid transparent;position:relative;z-index:1}.nano-tbl__wrap{display:table;min-width:100%}.nano-tbl__top-anchor{clip:rect(1px, 1px, 1px, 1px);-webkit-clip-path:inset(50%);clip-path:inset(50%);block-size:1px;inline-size:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;position:relative}.nano-tbl__ordered{background-color:var(--ordered-bg);border-inline-start:var(--border-style);border-inline-end:var(--border-style)}.nano-tbl__drag-mask{display:none;position:absolute;inset-block:-2px -2px;z-index:10;opacity:0;transition:0.2s ease opacity}.nano-tbl__drag-mask--start{width:calc(50% + 2px);inset-inline-start:-2px;border-inline-start:2px dashed var(--border-tint-color)}.nano-tbl__drag-mask--end{width:50%;inset-inline-end:0;border-inline-end:2px dashed var(--border-tint-color)}.nano-tbl__drag-mask--active{opacity:1}.nano-tbl__dragging .nano-tbl__drag-mask{display:block}.nano-tbl__drag--start{opacity:0.4}.nano-tbl__dragging .nano-tbl__td,.nano-tbl__dragging .nano-tbl__th{cursor:no-drop}.nano-tbl__dragging .nano-tbl__td .nano-tbl__cell-content,.nano-tbl__dragging .nano-tbl__th .nano-tbl__cell-content{pointer-events:none}.nano-tbl__order-btn{padding:0;border:none;outline:none;font:inherit;background:none;-webkit-appearance:none;appearance:none;color:inherit;display:flex;gap:10px;align-items:center;width:100%}.nano-tbl__status-icons{margin-inline:auto 10px;display:flex;gap:10px}.nano-tbl__progress-bar{font-size:0.2rem;position:sticky;inset-block-start:0;inset-inline:0;z-index:10;transition:scale 0.25s;scale:0;width:100%;height:0}.nano-tbl__progress-bar--show{scale:1;height:auto}.nano-tbl__caption--hide{clip:rect(1px, 1px, 1px, 1px);-webkit-clip-path:inset(50%);clip-path:inset(50%);block-size:1px;inline-size:1px;margin:-1px;overflow:hidden;padding:0;position:absolute}.nano-tbl__td,.nano-tbl__th{line-height:var(--cell-line-height);text-align:start;border-block-start:var(--border-style);max-width:var(--max-col-width);background-color:rgb(var(--cell-bg-rgb))}tbody:first-of-type tr:first-child .nano-tbl__td,tbody:first-of-type tr:first-child .nano-tbl__th{border-block-start:none}tbody:last-of-type tr:last-child .nano-tbl__td,tbody:last-of-type tr:last-child .nano-tbl__th{border-block-end:var(--border-style)}.md .nano-tbl__td:first-child .nano-tbl__cell-content,.md .nano-tbl__th:first-child .nano-tbl__cell-content{padding-inline-start:var(--bookend-col-padding)}.md .nano-tbl__td:last-child .nano-tbl__cell-content,.md .nano-tbl__th:last-child .nano-tbl__cell-content{padding-inline-end:var(--bookend-col-padding)}@media (max-width: 768px){.nano-tbl__td:first-child .nano-tbl__cell-content,.nano-tbl__th:first-child .nano-tbl__cell-content{padding-inline-start:var(--td-padding-start) !important}.nano-tbl__td:last-child .nano-tbl__cell-content,.nano-tbl__th:last-child .nano-tbl__cell-content{padding-inline-end:var(--td-padding-end) !important}}thead .nano-tbl__td,thead .nano-tbl__th{color:var(--thead-color);font-weight:800;background:rgba(var(--head-bg-rgb), 90%);font-size:var(--thead-font-size);border-block-start:none !important;transition:all 0.2s ease}thead .nano-tbl__td .nano-tbl__cell-content,thead .nano-tbl__th .nano-tbl__cell-content{padding-block:var(--head-th-padding-v);padding-inline:var(--head-th-padding-h)}tfoot .nano-tbl__td,tfoot .nano-tbl__th{color:var(--tfoot-color);font-weight:800;border-block-start:none;background:rgba(var(--foot-bg-rgb), 90%);font-size:var(--thead-font-size)}tfoot .nano-tbl__td .nano-tbl__cell-content,tfoot .nano-tbl__th .nano-tbl__cell-content{padding-block:var(--foot-th-padding-v);padding-inline:var(--foot-th-padding-h)}.nano-tbl__td.nano-tbl__ordered,.nano-tbl__th.nano-tbl__ordered{background-color:rgba(var(--ordered-bg-rgb), 0.8) !important}.nano-tbl__cell-content{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding-block:var(--td-padding-v);padding-inline:var(--td-padding-h)}.nano-tbl__cell-content--no-result{padding-block:2rem}.nano-tbl tbody{will-change:scroll-position;visibility:visible}.nano-tbl tbody.nano-tbl__inactive{visibility:hidden}.nano-tbl th[scope=row]{font-weight:800;margin:0}.nano-tbl__pin{position:sticky;z-index:1}.nano-tbl__pin--start{inset-inline:-1px auto;transition:max-width 0.25s ease;z-index:2}.nano-tbl__pin--start::after{content:\"\";position:absolute;inset:0;box-shadow:5px 1px 4px 0 rgba(0, 0, 0, 0.2);opacity:0;z-index:-1}.nano-tbl__pinned--start .nano-tbl__pin--start{z-index:2;max-width:125px !important}.sm .nano-tbl__pinned--start .nano-tbl__pin--start{max-width:var(--max-col-width) !important}.nano-tbl__pinned--start .nano-tbl__pin--start::after{opacity:1}.nano-tbl__pin--end{z-index:2;}.nano-tbl__pin--start+.nano-tbl__pin--end{inset-inline:auto auto}.nano-tbl__pin--start+.nano-tbl__pin--end::after{display:none}.sm .nano-tbl__pin--end{inset-inline:auto -1px !important;max-width:min(50vw, 200px)}.sm .nano-tbl__pin--end::after{display:block !important;content:\"\";position:absolute;inset:0;box-shadow:-5px 1px 4px 0 rgba(0, 0, 0, 0.2);opacity:0;z-index:-1}.sm .nano-tbl__pinned--end .nano-tbl__pin--end{z-index:3}.sm .nano-tbl__pinned--end .nano-tbl__pin--end::after{opacity:1}.nano-tbl__pin--top{inset-block:-1px auto;z-index:3}.nano-tbl__pinned--top .nano-tbl__pin--top{z-index:4 !important}.nano-tbl__pin--bottom{inset-block:auto -1px;z-index:3}.nano-tbl__pinned--bottom .nano-tbl__pin--bottom{z-index:5 !important}.nano-tbl__pin--top.nano-tbl__pin--start{z-index:4}.nano-tbl__pinned--start .nano-tbl__pin--top.nano-tbl__pin--start{z-index:5 !important}.nano-tbl__pinned--top.nano-tbl__pinned--start .nano-tbl__pin--top.nano-tbl__pin--start{z-index:6 !important}.nano-tbl__pin--top.nano-tbl__pin--end{z-index:4}.nano-tbl__pinned--end .nano-tbl__pin--top.nano-tbl__pin--end{z-index:5 !important}.nano-tbl__pinned--top.nano-tbl__pinned--end .nano-tbl__pin--top.nano-tbl__pin--end{z-index:6 !important}.nano-tbl__pin--bottom.nano-tbl__pin--start{z-index:4}.nano-tbl__pinned--start .nano-tbl__pin--bottom.nano-tbl__pin--start{z-index:5 !important}.nano-tbl__pinned--bottom.nano-tbl__pinned--start .nano-tbl__pin--bottom.nano-tbl__pin--start{z-index:6 !important}.nano-tbl__pin--bottom.nano-tbl__pin--end{z-index:4}.nano-tbl__pinned--end .nano-tbl__pin--bottom.nano-tbl__pin--end{z-index:5 !important}.nano-tbl__pinned--bottom.nano-tbl__pinned--end .nano-tbl__pin--bottom.nano-tbl__pin--end{z-index:6 !important}.nano-tbl thead tr:last-of-type td,.nano-tbl thead tr:last-of-type th{border-block-end:var(--border-tint-style)}.nano-tbl tfoot tr:first-of-type td,.nano-tbl tfoot tr:first-of-type th{border-block-start:none}.nano-tbl tfoot tr:last-of-type td,.nano-tbl tfoot tr:last-of-type th{border-block-end:var(--border-tint-style)}.nano-tbl__pinned--bottom .nano-tbl tfoot tr.nano-tbl__pin--bottom:first-of-type td,.nano-tbl__pinned--bottom .nano-tbl tfoot tr.nano-tbl__pin--bottom:first-of-type th{border-block-start:var(--border-tint-style) !important}.nano-tbl__pinned--bottom .nano-tbl tfoot tr.nano-tbl__pin--bottom:last-of-type td,.nano-tbl__pinned--bottom .nano-tbl tfoot tr.nano-tbl__pin--bottom:last-of-type th{border-block-end:none !important}.nano-tbl .unlimited-width{max-width:none}.nano-tbl__spinner{font-size:1.5rem;transition:scale 0.25s;scale:0;padding:0.5rem;position:absolute;inset-block-end:0;inset-inline-start:calc(50% - 0.75rem);z-index:0}.nano-tbl__spinner--show{scale:1;position:sticky}.nano-tbl nano-skeleton{line-height:var(--cell-line-height)}";
|
623
868
|
|
624
869
|
let id = 0;
|
625
870
|
const Table = class {
|
@@ -629,16 +874,18 @@ const Table = class {
|
|
629
874
|
this.nanoTblReady = createEvent(this, "nanoTblReady", 7);
|
630
875
|
this.nanoTblBeforeSort = createEvent(this, "nanoTblBeforeSort", 7);
|
631
876
|
this.nanoTblAfterSort = createEvent(this, "nanoTblAfterSort", 7);
|
877
|
+
this.nanoTblColDrag = createEvent(this, "nanoTblColDrag", 7);
|
878
|
+
this.nanoTblColDrop = createEvent(this, "nanoTblColDrop", 7);
|
632
879
|
this.nanoTblBeforeFilter = createEvent(this, "nanoTblBeforeFilter", 7);
|
633
880
|
this.nanoTblAfterFilter = createEvent(this, "nanoTblAfterFilter", 7);
|
634
881
|
this.nanoTblBeforeSearch = createEvent(this, "nanoTblBeforeSearch", 7);
|
635
882
|
this.nanoTblAfterSearch = createEvent(this, "nanoTblAfterSearch", 7);
|
636
883
|
this.debounceSetLoading = (l) => {
|
637
|
-
this._loading =
|
884
|
+
this._loading = l;
|
638
885
|
};
|
639
886
|
this.renderId = 'tbl-' + id++;
|
640
887
|
this.filters = [];
|
641
|
-
this.currentFilters = '';
|
888
|
+
this.currentFilters = '[]';
|
642
889
|
this.currentSort = '';
|
643
890
|
this.blockIos = new WeakMap();
|
644
891
|
this.blockHeights = [];
|
@@ -646,6 +893,23 @@ const Table = class {
|
|
646
893
|
// Scroll / IO used for hiding / showing blocks
|
647
894
|
this.ignoreIO = true;
|
648
895
|
this._isReady = false;
|
896
|
+
this.colDrag = (column) => {
|
897
|
+
this.nanoTblColDrag.emit({ column });
|
898
|
+
};
|
899
|
+
this.colDrop = (fromCol, toCol) => {
|
900
|
+
const cols = this.store.config.state.columns;
|
901
|
+
const toIndex = cols.findIndex((col) => col.prop === toCol);
|
902
|
+
const fromIndex = cols.findIndex((col) => col.prop === fromCol);
|
903
|
+
const dropEvent = this.nanoTblColDrop.emit({
|
904
|
+
fromCol,
|
905
|
+
toCol,
|
906
|
+
fromIndex,
|
907
|
+
toIndex,
|
908
|
+
});
|
909
|
+
if (dropEvent.defaultPrevented)
|
910
|
+
return;
|
911
|
+
this.store.config.state.columns = arrMove(fromIndex, toIndex, cols);
|
912
|
+
};
|
649
913
|
/**
|
650
914
|
* Start a sort - can be cancelled by `preventDefault`
|
651
915
|
* @param order - column order
|
@@ -701,7 +965,7 @@ const Table = class {
|
|
701
965
|
// This is a bit gross
|
702
966
|
// The Intersection Observer (IO) fires in an incorrect order when the scrolling is very fast
|
703
967
|
// i.e. we go past blocks 3, 2, 1 and land on 0, but 3 can fire as 'intersecting' after 0.
|
704
|
-
// To fix that, we check - for
|
968
|
+
// To fix that, we check - for realzies - if the block IS visible.
|
705
969
|
// BUT that test is not as sensitive to a block being visible via the IO,
|
706
970
|
// so doesn't always fire if scrolling slowly
|
707
971
|
// *sigh*
|
@@ -734,6 +998,10 @@ const Table = class {
|
|
734
998
|
this.tableEle.classList.toggle(`${CSSNAMESPACE}__pinned--${key}`, applied);
|
735
999
|
});
|
736
1000
|
};
|
1001
|
+
this.handleResizeChange = (e) => {
|
1002
|
+
this.tableWrapperEle.className = '';
|
1003
|
+
this.tableWrapperEle.classList.add(...(e.target.className + ' ' + `${CSSNAMESPACE}__wrap`).split(' '));
|
1004
|
+
};
|
737
1005
|
this.type = 'table';
|
738
1006
|
this.caption = undefined;
|
739
1007
|
this.showCaption = false;
|
@@ -749,6 +1017,8 @@ const Table = class {
|
|
749
1017
|
this.searchTerm = undefined;
|
750
1018
|
this.customFilterFn = undefined;
|
751
1019
|
this.customSortFn = undefined;
|
1020
|
+
this.defaultSort = true;
|
1021
|
+
this.defaultColDraggable = false;
|
752
1022
|
this.blocks = [];
|
753
1023
|
this.activeBlocks = [0, 1, 2];
|
754
1024
|
this.measureHeight = 0;
|
@@ -775,9 +1045,8 @@ const Table = class {
|
|
775
1045
|
this.currentFilters = '';
|
776
1046
|
this.currentSort = '';
|
777
1047
|
await this.columnInit();
|
778
|
-
if (!this.isReady)
|
1048
|
+
if (!this.isReady)
|
779
1049
|
this.setInitialBlockDimension();
|
780
|
-
}
|
781
1050
|
this.loading = false;
|
782
1051
|
});
|
783
1052
|
}
|
@@ -825,6 +1094,14 @@ const Table = class {
|
|
825
1094
|
this.filters = [];
|
826
1095
|
return this.filterStart(filters, additive);
|
827
1096
|
}
|
1097
|
+
/** Remove filters from a column
|
1098
|
+
* @param columnNames - the filters to apply
|
1099
|
+
* @returns a promise which resolves when complete
|
1100
|
+
*/
|
1101
|
+
async removeFilters(columnNames) {
|
1102
|
+
this.filters = this.filters.filter((f) => !columnNames.includes(f.prop));
|
1103
|
+
return this.filterStart();
|
1104
|
+
}
|
828
1105
|
// uses the first 'tr' of an active block as our yard stick
|
829
1106
|
set measureEle(el) {
|
830
1107
|
if (!el)
|
@@ -844,13 +1121,13 @@ const Table = class {
|
|
844
1121
|
if (this.isReady)
|
845
1122
|
requestAnimationFrame(() => this.handleReady());
|
846
1123
|
}
|
1124
|
+
// Private Logic
|
847
1125
|
// Listeners
|
848
1126
|
scrollListener() {
|
849
1127
|
// see explanation in `setupBlockIO`
|
850
1128
|
const speed = detectScrollSpeed();
|
851
1129
|
this.scrollSpeed = speed < 0 ? speed * -1 : speed;
|
852
1130
|
}
|
853
|
-
// Logic
|
854
1131
|
handleReady() {
|
855
1132
|
const hash = window.location.hash;
|
856
1133
|
if (hash.length > 1) {
|
@@ -1084,19 +1361,20 @@ const Table = class {
|
|
1084
1361
|
processSlots() {
|
1085
1362
|
// see if we have slot content
|
1086
1363
|
if (!this.caption && !this.host.querySelector('[slot="caption"]')) {
|
1087
|
-
console.error('For accessibility you must set a `
|
1364
|
+
console.error('For accessibility you must set a `caption` prop or use the `caption` slot');
|
1088
1365
|
}
|
1089
1366
|
}
|
1090
1367
|
// Component lifecycle
|
1091
1368
|
async componentWillLoad() {
|
1369
|
+
this.scrollParent = findScrollParent(this.host);
|
1092
1370
|
this.store = await generateStore(this.host, this.columns, this.scrollParent);
|
1093
1371
|
await this.handleRowsChange();
|
1094
1372
|
this.processSlots();
|
1095
|
-
this.setBlocks();
|
1096
1373
|
this.store.data.onChange('rows', () => this.setBlocks());
|
1374
|
+
this.setBlocks();
|
1097
1375
|
}
|
1098
1376
|
connectedCallback() {
|
1099
|
-
|
1377
|
+
this.scrollParent = findScrollParent(this.host);
|
1100
1378
|
}
|
1101
1379
|
componentDidLoad() {
|
1102
1380
|
this.setInitialBlockDimension();
|
@@ -1116,15 +1394,18 @@ const Table = class {
|
|
1116
1394
|
}
|
1117
1395
|
render() {
|
1118
1396
|
this.blockElements = [];
|
1119
|
-
return (h(Host, null, h("div", { class: `${CSSNAMESPACE}__top-anchor`, ref: (a) => (this.topAnchorEle = a) }, "\u00A0"), h("nano-resize-observe", { "aria-labelledby": 'table-caption-' + this.renderId, tabindex: this.type === 'grid' ? '0' : undefined, states: "576w sm, 768w md", class: "sm md" }, h("div", { class: `${CSSNAMESPACE}__wrap
|
1397
|
+
return (h(Host, null, h("div", { class: `${CSSNAMESPACE}__top-anchor`, ref: (a) => (this.topAnchorEle = a) }, "\u00A0"), h("nano-resize-observe", { "aria-labelledby": 'table-caption-' + this.renderId, tabindex: this.type === 'grid' ? '0' : undefined, states: "576w sm, 768w md", class: "sm md", onNanoResizeStateChange: this.handleResizeChange }), h("div", { class: `${CSSNAMESPACE}__wrap sm md`, ref: (div) => (this.tableWrapperEle = div) }, h("nano-progress-bar", { indeterminate: true, class: {
|
1120
1398
|
[`${CSSNAMESPACE}__progress-bar`]: true,
|
1121
1399
|
[`${CSSNAMESPACE}__progress-bar--show`]: this._loading,
|
1122
1400
|
} }), h("table", { role: this.type === 'grid' ? 'grid' : undefined, "aria-readonly": this.type === 'table' ? 'true' : undefined, "aria-rowcount": this.store.data.state.rows.length, "aria-colcount": this.store.config.state.columns.length, class: `${CSSNAMESPACE}`, ref: (tbl) => (this.tableEle = tbl) }, h("caption", { class: {
|
1123
1401
|
[`${CSSNAMESPACE}__caption`]: true,
|
1124
1402
|
[`${CSSNAMESPACE}__caption--hide`]: !this.showCaption,
|
1125
1403
|
}, id: 'table-caption-' + this.renderId }, h("slot", { name: "caption" }, this.caption)), h("thead", null, h(TableHeadFootRow, { rowRenderer: this.headRender, onColumnPinned: this.handleColumnPinned }, this.store.config.state.columns.map((colModel) => [
|
1126
|
-
h(TableColHead, { column: colModel, headRenderer: this.headRender,
|
1127
|
-
|
1404
|
+
h(TableColHead, { column: colModel, headRenderer: this.headRender, onColumnSortClick: this.sortStart, onColumnPinned: this.handleColumnPinned, onColumnDrag: this.colDrag, onColumnDrop: this.colDrop, defaults: {
|
1405
|
+
sortable: this.defaultSort,
|
1406
|
+
draggable: this.defaultColDraggable,
|
1407
|
+
} }),
|
1408
|
+
]))), this._loading && !this.blocks.length && (h("tbody", { class: `${CSSNAMESPACE}__active` }, [...Array(10).keys()].map((rowIndex) => (h("tr", null, this.store.config.state.columns.map((_colModel, colIndex) => (h(TableCell, { rowIndex: rowIndex, colIndex: colIndex, nestedContent: h("nano-skeleton", null) })))))))), !this._loading && !this.blocks.length && (h("tr", null, h("th", { class: `${CSSNAMESPACE}__th`, colSpan: this.store.config.state.columns.length }, h("div", { class: "nano-tbl__cell-content nano-tbl__cell-content--no-result" }, h("slot", { name: "no-results" }, "No results found"))))), this.blocks.map((block, blockIndex) => (h("tbody", { key: block.__uuid, id: `tbody-${this.renderId}-${blockIndex}`, ref: (tb) => {
|
1128
1409
|
this.blockElements.push(tb);
|
1129
1410
|
this.setupBlockIO(tb, blockIndex);
|
1130
1411
|
}, class: {
|
@@ -1132,15 +1413,18 @@ const Table = class {
|
|
1132
1413
|
[`${CSSNAMESPACE}__active`]: this.activeBlocks.includes(blockIndex),
|
1133
1414
|
} }, this.activeBlocks.includes(blockIndex) ? (block.rows.map((row, i) => {
|
1134
1415
|
const rowIndex = blockIndex > 0 ? blockIndex * this.perBlock + i : i;
|
1135
|
-
return (h(TableRow, { rowRenderer: this.rowRender, row: row }, this.store.config.state.columns.map((_colModel, colIndex) => (h(TableCell, { rowIndex: rowIndex, colIndex: colIndex })))));
|
1416
|
+
return (h(TableRow, { rowRenderer: this.rowRender, row: row, rowIndex: rowIndex }, this.store.config.state.columns.map((_colModel, colIndex) => (h(TableCell, { rowIndex: rowIndex, colIndex: colIndex })))));
|
1136
1417
|
})) : (h("td", { colSpan: this.store.config.state.columns.length, style: {
|
1137
1418
|
height: this.getBlockHeight(blockIndex),
|
1138
1419
|
} }))))), this.showFooter && (h("tfoot", null, h(TableHeadFootRow, { rowRenderer: this.footRender, onColumnPinned: this.handleColumnPinned }, this.store.config.state.columns.map((colModel) => [
|
1139
|
-
h(TableColHead, { column: colModel, headRenderer: this.footRender, onColumnPinned: this.handleColumnPinned,
|
1420
|
+
h(TableColHead, { column: colModel, headRenderer: this.footRender, onColumnPinned: this.handleColumnPinned, onColumnSortClick: this.sortStart, defaults: {
|
1421
|
+
sortable: this.defaultSort,
|
1422
|
+
draggable: this.defaultColDraggable,
|
1423
|
+
} }),
|
1140
1424
|
]))))), !!this.blocks.length && (h("nano-spinner", { type: "circle", class: {
|
1141
1425
|
[`${CSSNAMESPACE}__spinner`]: true,
|
1142
1426
|
[`${CSSNAMESPACE}__spinner--show`]: this._loading,
|
1143
|
-
} })))))
|
1427
|
+
} })))));
|
1144
1428
|
}
|
1145
1429
|
get host() { return getElement(this); }
|
1146
1430
|
static get watchers() { return {
|
@@ -1153,4 +1437,4 @@ Table.style = tableCss;
|
|
1153
1437
|
|
1154
1438
|
export { Table as T, createWorker as c };
|
1155
1439
|
|
1156
|
-
//# sourceMappingURL=nano-table-
|
1440
|
+
//# sourceMappingURL=nano-table-e2405350.js.map
|