@nanoporetech-digital/components 5.1.2 → 5.2.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 +35 -0
- package/dist/cjs/{component-store-74d25f63.js → component-store-f1dc1276.js} +2 -2
- package/dist/cjs/{component-store-74d25f63.js.map → component-store-f1dc1276.js.map} +1 -1
- package/dist/cjs/index.cjs.js +1 -1
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/nano-algolia-filter.cjs.entry.js +2 -2
- package/dist/cjs/nano-algolia-input.cjs.entry.js +2 -2
- package/dist/cjs/nano-algolia.cjs.entry.js +2 -2
- package/dist/cjs/nano-checkbox-group.cjs.entry.js +5 -1
- package/dist/cjs/nano-checkbox-group.cjs.entry.js.map +1 -1
- package/dist/cjs/nano-components.cjs.js +1 -1
- package/dist/cjs/nano-datalist_3.cjs.entry.js +14 -5
- package/dist/cjs/nano-datalist_3.cjs.entry.js.map +1 -1
- package/dist/cjs/nano-dialog.cjs.entry.js +2 -2
- package/dist/cjs/nano-global-nav-user-profile_3.cjs.entry.js +8 -5
- package/dist/cjs/nano-global-nav-user-profile_3.cjs.entry.js.map +1 -1
- package/dist/cjs/nano-global-nav.cjs.entry.js +2 -2
- package/dist/cjs/nano-input.cjs.entry.js +3 -3
- package/dist/cjs/nano-input.cjs.entry.js.map +1 -1
- package/dist/cjs/nano-overflow-nav.cjs.entry.js +1 -1
- package/dist/cjs/nano-range.cjs.entry.js +1 -1
- package/dist/cjs/nano-resize-observe_2.cjs.entry.js +3 -1
- package/dist/cjs/nano-resize-observe_2.cjs.entry.js.map +1 -1
- package/dist/cjs/nano-sortable.cjs.entry.js +18 -8
- package/dist/cjs/nano-sortable.cjs.entry.js.map +1 -1
- package/dist/cjs/nano-split-pane.cjs.entry.js +1 -1
- package/dist/cjs/nano-sticker.cjs.entry.js +4 -2
- package/dist/cjs/nano-sticker.cjs.entry.js.map +1 -1
- package/dist/cjs/nano-tab-group.cjs.entry.js +2 -2
- package/dist/cjs/{nano-table-0a720c5f.js → nano-table-04993bb4.js} +560 -186
- package/dist/cjs/nano-table-04993bb4.js.map +1 -0
- package/dist/cjs/nano-table.cjs.entry.js +2 -2
- package/dist/cjs/{table.worker-347d4d31.js → table.worker-85877b23.js} +4 -4
- package/dist/cjs/table.worker-85877b23.js.map +1 -0
- package/dist/cjs/{table.worker-bd51e29f.js → table.worker-f258383d.js} +1 -1
- package/dist/cjs/{throttle-f55496c8.js → throttle-dfa64b9e.js} +17 -20
- package/dist/cjs/throttle-dfa64b9e.js.map +1 -0
- package/dist/collection/components/checkbox/checkbox-group.js +4 -0
- package/dist/collection/components/checkbox/checkbox-group.js.map +1 -1
- package/dist/collection/components/datalist/datalist.js +13 -4
- package/dist/collection/components/datalist/datalist.js.map +1 -1
- package/dist/collection/components/input/input.css +1 -1
- package/dist/collection/components/input/input.js +1 -1
- package/dist/collection/components/input/input.js.map +1 -1
- package/dist/collection/components/nav-item/nav-item.js +6 -3
- package/dist/collection/components/nav-item/nav-item.js.map +1 -1
- package/dist/collection/components/resize-observe/resize-observe.js +21 -1
- package/dist/collection/components/resize-observe/resize-observe.js.map +1 -1
- package/dist/collection/components/select/select.css +1 -2
- package/dist/collection/components/sortable/sortable.js +5 -7
- package/dist/collection/components/sortable/sortable.js.map +1 -1
- package/dist/collection/components/sticker/sticker.js +11 -5
- package/dist/collection/components/sticker/sticker.js.map +1 -1
- package/dist/collection/components/table/table-interface.js.map +1 -1
- package/dist/collection/components/table/table.cell.js +43 -10
- package/dist/collection/components/table/table.cell.js.map +1 -1
- package/dist/collection/components/table/table.css +38 -55
- package/dist/collection/components/table/table.header.js +4 -9
- package/dist/collection/components/table/table.header.js.map +1 -1
- package/dist/collection/components/table/table.js +104 -48
- package/dist/collection/components/table/table.js.map +1 -1
- package/dist/collection/components/table/table.pin-service.js +382 -0
- package/dist/collection/components/table/table.pin-service.js.map +1 -0
- package/dist/collection/components/table/table.row.js +39 -46
- package/dist/collection/components/table/table.row.js.map +1 -1
- package/dist/collection/components/table/table.utils.js +0 -124
- 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/collection/utils/events.js +27 -0
- package/dist/collection/utils/events.js.map +1 -0
- package/dist/collection/utils/throttle.js +16 -19
- package/dist/collection/utils/throttle.js.map +1 -1
- package/dist/components/datalist.js +13 -4
- package/dist/components/datalist.js.map +1 -1
- package/dist/components/input.js +2 -2
- package/dist/components/input.js.map +1 -1
- package/dist/components/nano-checkbox-group.js +4 -0
- package/dist/components/nano-checkbox-group.js.map +1 -1
- package/dist/components/nano-sortable.js +17 -7
- package/dist/components/nano-sortable.js.map +1 -1
- package/dist/components/nav-item.js +6 -3
- package/dist/components/nav-item.js.map +1 -1
- package/dist/components/resize-observe.js +3 -1
- package/dist/components/resize-observe.js.map +1 -1
- package/dist/components/select.js +1 -1
- package/dist/components/select.js.map +1 -1
- package/dist/components/sticker.js +3 -1
- package/dist/components/sticker.js.map +1 -1
- package/dist/components/table.js +533 -188
- package/dist/components/table.js.map +1 -1
- package/dist/components/table.worker.js +1 -1
- package/dist/components/throttle.js +16 -19
- package/dist/components/throttle.js.map +1 -1
- package/dist/esm/{component-store-244a8431.js → component-store-c23ebc9c.js} +2 -2
- package/dist/esm/{component-store-244a8431.js.map → component-store-c23ebc9c.js.map} +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/loader.js +1 -1
- package/dist/esm/nano-algolia-filter.entry.js +2 -2
- package/dist/esm/nano-algolia-input.entry.js +2 -2
- package/dist/esm/nano-algolia.entry.js +2 -2
- package/dist/esm/nano-checkbox-group.entry.js +5 -1
- package/dist/esm/nano-checkbox-group.entry.js.map +1 -1
- package/dist/esm/nano-components.js +1 -1
- package/dist/esm/nano-datalist_3.entry.js +14 -5
- package/dist/esm/nano-datalist_3.entry.js.map +1 -1
- package/dist/esm/nano-dialog.entry.js +2 -2
- package/dist/esm/nano-global-nav-user-profile_3.entry.js +8 -5
- package/dist/esm/nano-global-nav-user-profile_3.entry.js.map +1 -1
- package/dist/esm/nano-global-nav.entry.js +2 -2
- package/dist/esm/nano-input.entry.js +3 -3
- package/dist/esm/nano-input.entry.js.map +1 -1
- package/dist/esm/nano-overflow-nav.entry.js +1 -1
- package/dist/esm/nano-range.entry.js +1 -1
- package/dist/esm/nano-resize-observe_2.entry.js +3 -1
- package/dist/esm/nano-resize-observe_2.entry.js.map +1 -1
- package/dist/esm/nano-sortable.entry.js +18 -8
- package/dist/esm/nano-sortable.entry.js.map +1 -1
- package/dist/esm/nano-split-pane.entry.js +1 -1
- package/dist/esm/nano-sticker.entry.js +4 -2
- package/dist/esm/nano-sticker.entry.js.map +1 -1
- package/dist/esm/nano-tab-group.entry.js +2 -2
- package/dist/esm/{nano-table-9767860f.js → nano-table-91f09583.js} +561 -187
- package/dist/esm/nano-table-91f09583.js.map +1 -0
- package/dist/esm/nano-table.entry.js +2 -2
- package/dist/esm/{table.worker-d252307c.js → table.worker-625475ba.js} +4 -4
- package/dist/esm/table.worker-625475ba.js.map +1 -0
- package/dist/esm/{table.worker-bd51e29f.js → table.worker-f258383d.js} +1 -1
- package/dist/esm/{throttle-7836544e.js → throttle-ac4fcefa.js} +17 -20
- package/dist/esm/throttle-ac4fcefa.js.map +1 -0
- package/dist/nano-components/index.esm.js +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-7d6065c6.entry.js → p-0697795a.entry.js} +2 -2
- package/dist/nano-components/p-0697795a.entry.js.map +1 -0
- package/dist/nano-components/p-17ee0c07.entry.js +5 -0
- package/dist/nano-components/{p-6975f110.entry.js → p-192902e0.entry.js} +2 -2
- package/dist/nano-components/{p-a6ff5ca6.js → p-1a0b5bc3.js} +2 -2
- package/dist/nano-components/{p-3a761d77.entry.js → p-1b791810.entry.js} +2 -2
- package/dist/nano-components/p-3de3449e.js +5 -0
- package/dist/nano-components/p-3de3449e.js.map +1 -0
- package/dist/nano-components/p-3eb6d833.entry.js +5 -0
- package/dist/nano-components/p-3eb6d833.entry.js.map +1 -0
- package/dist/nano-components/{p-a1c0afb6.entry.js → p-4884b65a.entry.js} +2 -2
- package/dist/nano-components/{p-75735a91.entry.js → p-565793a2.entry.js} +2 -2
- package/dist/nano-components/p-565793a2.entry.js.map +1 -0
- package/dist/nano-components/p-5aae2588.entry.js +5 -0
- package/dist/nano-components/p-5aae2588.entry.js.map +1 -0
- package/dist/nano-components/{p-935aef3d.entry.js → p-6920ad69.entry.js} +2 -2
- package/dist/nano-components/{p-1c6c94cb.entry.js → p-7baa9e14.entry.js} +2 -2
- package/dist/nano-components/p-7bff5224.js +5 -0
- package/dist/nano-components/p-7bff5224.js.map +1 -0
- package/dist/nano-components/{p-f60fe933.entry.js → p-898cbac7.entry.js} +2 -2
- package/dist/nano-components/{p-ace1ffc2.entry.js → p-a362bd23.entry.js} +2 -2
- package/dist/nano-components/{p-eb6c9191.entry.js → p-b72df1aa.entry.js} +2 -2
- package/dist/nano-components/p-bf18e298.entry.js +5 -0
- package/dist/nano-components/p-bf18e298.entry.js.map +1 -0
- package/dist/nano-components/p-ce5efc3f.entry.js +5 -0
- package/dist/nano-components/p-ce5efc3f.entry.js.map +1 -0
- package/dist/nano-components/{p-1b687f96.entry.js → p-d0eefd52.entry.js} +2 -2
- package/dist/nano-components/{p-2d43a82b.entry.js → p-d74e2642.entry.js} +2 -2
- package/dist/nano-components/p-d74e2642.entry.js.map +1 -0
- package/dist/nano-components/p-dfbf0d56.js +5 -0
- package/dist/nano-components/{p-bd51e29f.js → p-f258383d.js} +1 -1
- package/dist/types/components/datalist/datalist.d.ts +1 -0
- package/dist/types/components/nav-item/nav-item.d.ts +1 -1
- package/dist/types/components/resize-observe/resize-observe.d.ts +2 -0
- package/dist/types/components/sortable/sortable.d.ts +0 -1
- package/dist/types/components/sticker/sticker.d.ts +2 -2
- package/dist/types/components/table/table-interface.d.ts +23 -11
- package/dist/types/components/table/table.cell.d.ts +0 -7
- package/dist/types/components/table/table.d.ts +10 -7
- package/dist/types/components/table/table.header.d.ts +0 -1
- package/dist/types/components/table/table.pin-service.d.ts +90 -0
- package/dist/types/components/table/table.row.d.ts +3 -2
- package/dist/types/components/table/table.utils.d.ts +0 -27
- package/dist/types/components.d.ts +29 -11
- package/dist/types/utils/events.d.ts +15 -0
- package/dist/types/utils/throttle.d.ts +1 -1
- package/docs-json.json +59 -24
- package/docs-vscode.json +2 -2
- package/hydrate/index.js +610 -204
- package/package.json +2 -2
- package/dist/cjs/nano-table-0a720c5f.js.map +0 -1
- package/dist/cjs/table.worker-347d4d31.js.map +0 -1
- package/dist/cjs/throttle-f55496c8.js.map +0 -1
- package/dist/esm/nano-table-9767860f.js.map +0 -1
- package/dist/esm/table.worker-d252307c.js.map +0 -1
- package/dist/esm/throttle-7836544e.js.map +0 -1
- package/dist/nano-components/p-15217442.entry.js +0 -5
- package/dist/nano-components/p-15217442.entry.js.map +0 -1
- package/dist/nano-components/p-2d43a82b.entry.js.map +0 -1
- package/dist/nano-components/p-633c778c.js +0 -5
- package/dist/nano-components/p-633c778c.js.map +0 -1
- package/dist/nano-components/p-66631f50.js +0 -5
- package/dist/nano-components/p-75735a91.entry.js.map +0 -1
- package/dist/nano-components/p-7d6065c6.entry.js.map +0 -1
- package/dist/nano-components/p-8a79a7ca.entry.js +0 -5
- package/dist/nano-components/p-9746b0a5.js +0 -5
- package/dist/nano-components/p-9746b0a5.js.map +0 -1
- package/dist/nano-components/p-b0c60290.entry.js +0 -5
- package/dist/nano-components/p-b0c60290.entry.js.map +0 -1
- package/dist/nano-components/p-c8ccb57a.entry.js +0 -5
- package/dist/nano-components/p-c8ccb57a.entry.js.map +0 -1
- package/dist/nano-components/p-d1a5326f.entry.js +0 -5
- package/dist/nano-components/p-d1a5326f.entry.js.map +0 -1
- /package/dist/nano-components/{p-66631f50.js.map → p-17ee0c07.entry.js.map} +0 -0
- /package/dist/nano-components/{p-6975f110.entry.js.map → p-192902e0.entry.js.map} +0 -0
- /package/dist/nano-components/{p-a6ff5ca6.js.map → p-1a0b5bc3.js.map} +0 -0
- /package/dist/nano-components/{p-3a761d77.entry.js.map → p-1b791810.entry.js.map} +0 -0
- /package/dist/nano-components/{p-a1c0afb6.entry.js.map → p-4884b65a.entry.js.map} +0 -0
- /package/dist/nano-components/{p-935aef3d.entry.js.map → p-6920ad69.entry.js.map} +0 -0
- /package/dist/nano-components/{p-1c6c94cb.entry.js.map → p-7baa9e14.entry.js.map} +0 -0
- /package/dist/nano-components/{p-f60fe933.entry.js.map → p-898cbac7.entry.js.map} +0 -0
- /package/dist/nano-components/{p-ace1ffc2.entry.js.map → p-a362bd23.entry.js.map} +0 -0
- /package/dist/nano-components/{p-eb6c9191.entry.js.map → p-b72df1aa.entry.js.map} +0 -0
- /package/dist/nano-components/{p-1b687f96.entry.js.map → p-d0eefd52.entry.js.map} +0 -0
- /package/dist/nano-components/{p-8a79a7ca.entry.js.map → p-dfbf0d56.js.map} +0 -0
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
const index = require('./index-71f899a7.js');
|
7
7
|
const math = require('./math-a8123703.js');
|
8
|
-
const throttle = require('./throttle-
|
8
|
+
const throttle = require('./throttle-dfa64b9e.js');
|
9
9
|
const index$1 = require('./index-99649bef.js');
|
10
10
|
|
11
11
|
const CSSNAMESPACE = 'nano-tbl';
|
@@ -112,7 +112,7 @@ const createWorkerProxy = (worker, workerMsgId, exportedMethod) => (
|
|
112
112
|
})
|
113
113
|
);
|
114
114
|
|
115
|
-
const workerPromise = Promise.resolve().then(function () { return require('./table.worker-
|
115
|
+
const workerPromise = Promise.resolve().then(function () { return require('./table.worker-85877b23.js'); }).then(m => m.worker);
|
116
116
|
const createWorkerStore = /*@__PURE__*/createWorkerProxy(workerPromise, 'stencil.table.worker', 'createWorkerStore');
|
117
117
|
const syncConfigToWorker = /*@__PURE__*/createWorkerProxy(workerPromise, 'stencil.table.worker', 'syncConfigToWorker');
|
118
118
|
const syncDataToWorker = /*@__PURE__*/createWorkerProxy(workerPromise, 'stencil.table.worker', 'syncDataToWorker');
|
@@ -363,92 +363,6 @@ function colheadFootRender(col) {
|
|
363
363
|
const tpl = col === null || col === void 0 ? void 0 : col.columnTemplate;
|
364
364
|
return tpl ? (tpl(index.h, col)) : (index.h(index.Fragment, null, col.title));
|
365
365
|
}
|
366
|
-
const stickyHIOs = new WeakMap();
|
367
|
-
const stickyVIOs = new WeakMap();
|
368
|
-
/**
|
369
|
-
* Adds element to Intersection Observer. Fires when element changes on the x axis
|
370
|
-
* @param el - an element to observe
|
371
|
-
* @param pos - the edge to watch (start or end)
|
372
|
-
* @param cb - callback when an intersection state changes.
|
373
|
-
*/
|
374
|
-
function addHObserver(el, pos, cb) {
|
375
|
-
if (stickyHIOs.get(el))
|
376
|
-
return;
|
377
|
-
const store = fetchStores();
|
378
|
-
const root = store.general.state.scrollParent;
|
379
|
-
const observer = new IntersectionObserver(([e]) => {
|
380
|
-
const rootBounds = e.rootBounds || document.scrollingElement.getBoundingClientRect();
|
381
|
-
const positions = {};
|
382
|
-
if (pos === 'start') {
|
383
|
-
positions.start =
|
384
|
-
e.boundingClientRect.x - (rootBounds.x + root.scrollLeft) < 0 &&
|
385
|
-
!e.isIntersecting;
|
386
|
-
}
|
387
|
-
if (pos === 'end') {
|
388
|
-
// TODO - sort these out for RtL
|
389
|
-
positions.end =
|
390
|
-
e.boundingClientRect.right > e.boundingClientRect.width &&
|
391
|
-
!e.isIntersecting;
|
392
|
-
}
|
393
|
-
if (!!cb)
|
394
|
-
cb(positions);
|
395
|
-
}, {
|
396
|
-
threshold: [1],
|
397
|
-
rootMargin: '1px 0px 100px 0px',
|
398
|
-
root: root === document.scrollingElement ? null : root,
|
399
|
-
});
|
400
|
-
stickyHIOs.set(el, observer);
|
401
|
-
if (store.general.state.isReady) {
|
402
|
-
observer.observe(el);
|
403
|
-
}
|
404
|
-
else {
|
405
|
-
store.general.state.host.addEventListener('nanoTblReady', () => {
|
406
|
-
observer.observe(el);
|
407
|
-
}, { once: true });
|
408
|
-
}
|
409
|
-
}
|
410
|
-
/**
|
411
|
-
* Adds element to Intersection Observer. Fires when element changes on the y axis
|
412
|
-
* @param el - an element to observe
|
413
|
-
* @param pos - the edge to watch (start or end)
|
414
|
-
* @param cb - callback when an intersection state changes.
|
415
|
-
*/
|
416
|
-
function addVObserver(el, pos, cb) {
|
417
|
-
if (stickyVIOs.get(el))
|
418
|
-
return;
|
419
|
-
const store = fetchStores();
|
420
|
-
const root = store.general.state.scrollParent;
|
421
|
-
const observer = new IntersectionObserver(([e]) => {
|
422
|
-
const rootBounds = e.rootBounds || document.scrollingElement.getBoundingClientRect();
|
423
|
-
const positions = {};
|
424
|
-
if (pos === 'top') {
|
425
|
-
positions.top =
|
426
|
-
e.boundingClientRect.y - (rootBounds.y + root.scrollTop) < 0 &&
|
427
|
-
!e.isIntersecting;
|
428
|
-
}
|
429
|
-
if (pos === 'bottom') {
|
430
|
-
const boundingClientRect = e.target.getBoundingClientRect();
|
431
|
-
positions.bottom =
|
432
|
-
boundingClientRect.height + boundingClientRect.y >
|
433
|
-
rootBounds.height && !e.isIntersecting;
|
434
|
-
}
|
435
|
-
if (!!cb)
|
436
|
-
cb(positions);
|
437
|
-
}, {
|
438
|
-
threshold: [1],
|
439
|
-
rootMargin: '0px 100px 0px 100px',
|
440
|
-
root: root === document.scrollingElement ? null : root,
|
441
|
-
});
|
442
|
-
stickyVIOs.set(el, observer);
|
443
|
-
if (store.general.state.isReady) {
|
444
|
-
observer.observe(el);
|
445
|
-
}
|
446
|
-
else {
|
447
|
-
store.general.state.host.addEventListener('nanoTblReady', () => {
|
448
|
-
observer.observe(el);
|
449
|
-
}, { once: true });
|
450
|
-
}
|
451
|
-
}
|
452
366
|
function headerPinClasses(type, vPinned, toString = false) {
|
453
367
|
const classes = {
|
454
368
|
[`${CSSNAMESPACE}__${type}`]: true,
|
@@ -518,7 +432,7 @@ function isInViewport(el, percentVisible = 100) {
|
|
518
432
|
percentVisible);
|
519
433
|
}
|
520
434
|
|
521
|
-
const TableColHead = ({ column,
|
435
|
+
const TableColHead = ({ column, onColumnSortClick, defaults, }) => {
|
522
436
|
// Sort handling
|
523
437
|
function handleColumnSortClick(e) {
|
524
438
|
let order;
|
@@ -543,7 +457,7 @@ const TableColHead = ({ column, headRenderer, onColumnSortClick, onColumnPinned,
|
|
543
457
|
extraProps = column.columnProperties(column) || extraProps;
|
544
458
|
}
|
545
459
|
const baseProps = {
|
546
|
-
class: Object.assign(Object.assign({}, headerPinClasses('th',
|
460
|
+
class: Object.assign(Object.assign({}, headerPinClasses('th', column.pinned)), { [`${CSSNAMESPACE}__pin--start`]: column.pinned === 'start', [`${CSSNAMESPACE}__pin--end`]: column.pinned === 'end', [`${CSSNAMESPACE}__ordered`]: !!column.order, [`${CSSNAMESPACE}__filtered`]: column.filter !== undefined && column.filter !== null }),
|
547
461
|
};
|
548
462
|
let props = extraProps ? mergeProperties(baseProps, extraProps) : baseProps;
|
549
463
|
const content = colheadFootRender(column);
|
@@ -560,12 +474,7 @@ const TableColHead = ({ column, headRenderer, onColumnSortClick, onColumnPinned,
|
|
560
474
|
: 'none';
|
561
475
|
props = Object.assign(Object.assign({}, props), { 'aria-sort': sort });
|
562
476
|
}
|
563
|
-
return (index.h("th", Object.assign({}, props, {
|
564
|
-
if (['end', 'start'].includes(column.pinned))
|
565
|
-
addHObserver(th, column.pinned, onColumnPinned);
|
566
|
-
if (['top', 'bottom'].includes(headRenderer.pinned))
|
567
|
-
addVObserver(th, headRenderer.pinned, onColumnPinned);
|
568
|
-
}, key: column.prop }), isSortable() ? (index.h("button", { class: {
|
477
|
+
return (index.h("th", Object.assign({}, props, { key: column.prop }), isSortable() ? (index.h("button", { class: {
|
569
478
|
[`${CSSNAMESPACE}__order-btn`]: true,
|
570
479
|
[`${CSSNAMESPACE}__cell-content`]: true,
|
571
480
|
}, onClick: handleColumnSortClick },
|
@@ -593,6 +502,7 @@ function cellRender(rowIndex, colIndex) {
|
|
593
502
|
const columns = store.config.state.columns;
|
594
503
|
const tpl = (_a = columns[colIndex]) === null || _a === void 0 ? void 0 : _a.cellTemplate;
|
595
504
|
const model = colDataModel(rowIndex, colIndex);
|
505
|
+
const tableInstance = index.getRenderingRef();
|
596
506
|
if (!!model.cellModel && columns[colIndex].type === 'date') {
|
597
507
|
const d = new Date(model.cellModel);
|
598
508
|
if (d instanceof Date && !isNaN(d)) {
|
@@ -601,7 +511,28 @@ function cellRender(rowIndex, colIndex) {
|
|
601
511
|
: d;
|
602
512
|
}
|
603
513
|
}
|
604
|
-
|
514
|
+
// Wrap the h pragma, then we can know if we're using Stencil's
|
515
|
+
// jsx renderer or a different one
|
516
|
+
let hCalled = false;
|
517
|
+
const hWrap = (...args) => {
|
518
|
+
hCalled = true;
|
519
|
+
return index.h(...args);
|
520
|
+
};
|
521
|
+
let tplResult = tpl ? tpl(hWrap, model) : undefined;
|
522
|
+
if (tplResult &&
|
523
|
+
tableInstance.customRenderer &&
|
524
|
+
tplResult['$attrs$'] === undefined &&
|
525
|
+
!(tplResult instanceof Element) &&
|
526
|
+
typeof tplResult !== 'string' &&
|
527
|
+
!hCalled) {
|
528
|
+
// template result is jsx *not* from Stencil.
|
529
|
+
// Render it now and output it later.
|
530
|
+
const templateEle = document.createElement('template');
|
531
|
+
// @ts-expect-error
|
532
|
+
tableInstance.customRenderer(tplResult, templateEle.content);
|
533
|
+
tplResult = templateEle;
|
534
|
+
}
|
535
|
+
return tplResult ? (tplResult) : model.cellModel !== undefined && model.cellModel !== null ? (index.h(index.Fragment, null, (_b = model.cellModel) === null || _b === void 0 ? void 0 : _b.toString())) : ('');
|
605
536
|
}
|
606
537
|
const baseCellClasses = (colIndex, toString = false) => {
|
607
538
|
const store = fetchStores();
|
@@ -617,11 +548,12 @@ const baseCellClasses = (colIndex, toString = false) => {
|
|
617
548
|
return classListToStr(classes);
|
618
549
|
return classes;
|
619
550
|
};
|
620
|
-
const TableCell
|
551
|
+
const TableCell = ({ rowIndex, colIndex, nestedContent, }) => {
|
621
552
|
const Content = () => nestedContent
|
622
553
|
? nestedContent()
|
623
554
|
: cellRender(rowIndex, colIndex) || (index.h("span", { class: "placeholder" }, "\u00A0"));
|
624
555
|
let CellType = 'td';
|
556
|
+
const tableInstance = index.getRenderingRef();
|
625
557
|
const store = fetchStores();
|
626
558
|
const column = store.config.state.columns[colIndex];
|
627
559
|
let props = mergeCellProperties(rowIndex, colIndex, {
|
@@ -633,14 +565,23 @@ const TableCell$1 = ({ rowIndex, colIndex, nestedContent, }) => {
|
|
633
565
|
? Object.assign(Object.assign({}, props), { scope: 'rowgroup' }) : Object.assign(Object.assign({}, props), { scope: 'row' });
|
634
566
|
CellType = 'th';
|
635
567
|
}
|
636
|
-
const ContentWrap = (props) =>
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
568
|
+
const ContentWrap = (props) => {
|
569
|
+
const content = Content();
|
570
|
+
return (index.h("div", Object.assign({ ref: (d) => {
|
571
|
+
if (d && content instanceof Element) {
|
572
|
+
d.replaceChildren();
|
573
|
+
d.append(content['content'] || content);
|
574
|
+
}
|
575
|
+
} }, props, { class: {
|
576
|
+
[`${CSSNAMESPACE}__cell-content`]: true,
|
577
|
+
[`${CSSNAMESPACE}__cell-content--wrap`]: !!column.wrap,
|
578
|
+
}, innerHTML: typeof content === 'string' && content.includes('<')
|
579
|
+
? content
|
580
|
+
: undefined }), (typeof content !== 'string' || !content.includes('<')) &&
|
581
|
+
!(content instanceof Element) &&
|
582
|
+
content));
|
583
|
+
};
|
584
|
+
return (index.h(CellType, Object.assign({ role: tableInstance.type === 'grid' ? 'gridcell' : undefined }, props), column.autoTooltip && !column.wrap ? (index.h("nano-resize-observe", { notifyContentFit: "x", onNanoResizeContentFitChange: (e) => (e.target.firstElementChild.disabled =
|
644
585
|
e.detail.x) },
|
645
586
|
index.h("nano-tooltip", { disabled: true, placement: "top", onNanoShow: (e) => (e.target.closest(CellType).style.zIndex = '100'), onNanoHide: (e) => (e.target.closest(CellType).style.zIndex = '') },
|
646
587
|
index.h(ContentWrap, null),
|
@@ -648,14 +589,18 @@ const TableCell$1 = ({ rowIndex, colIndex, nestedContent, }) => {
|
|
648
589
|
index.h(Content, null))))) : (index.h(ContentWrap, null))));
|
649
590
|
};
|
650
591
|
|
651
|
-
const
|
652
|
-
const cell = (index.h("div", { class: {
|
592
|
+
const tableCellContent = (props, children, ctx) => {
|
593
|
+
const cell = (index.h("div", Object.assign({}, props.wrapperProps, { class: {
|
653
594
|
[`${CSSNAMESPACE}__cell-content`]: true,
|
654
|
-
[`${CSSNAMESPACE}__cell-content--wrap`]: wrap,
|
655
|
-
} }, children));
|
656
|
-
return header ? index.h("th", { scope:
|
595
|
+
[`${CSSNAMESPACE}__cell-content--wrap`]: props.wrap,
|
596
|
+
} }), children));
|
597
|
+
return props.header ? (index.h("th", Object.assign({ scope: ctx }, props.cellProps), cell)) : (index.h("td", Object.assign({}, props.cellProps), cell));
|
657
598
|
};
|
658
|
-
const TableRow = ({ rowRenderer, rowIndex, rowModel
|
599
|
+
const TableRow = ({ rowRenderer, rowIndex, rowModel }, children, utils) => {
|
600
|
+
// helper, generates <td> or <th>
|
601
|
+
const TableCell = ({ header, wrap, cellProps, wrapperProps }, children) => {
|
602
|
+
return tableCellContent({ header, wrap, cellProps, wrapperProps }, children, 'row');
|
603
|
+
};
|
659
604
|
let extraProps = {};
|
660
605
|
if (!rowModel) {
|
661
606
|
const model = rowDataModel(rowIndex);
|
@@ -665,13 +610,28 @@ const TableRow = ({ rowRenderer, rowIndex, rowModel, onColumnPinned }, children,
|
|
665
610
|
extraProps =
|
666
611
|
rowRenderer.rowProperties({ rowModel, rowIndex }) || extraProps;
|
667
612
|
}
|
668
|
-
let
|
613
|
+
let rowPinned;
|
669
614
|
if ((rowRenderer === null || rowRenderer === void 0 ? void 0 : rowRenderer.pinned) && typeof rowRenderer.pinned === 'function') {
|
670
|
-
|
615
|
+
rowPinned = rowRenderer.pinned({ rowModel, rowIndex });
|
671
616
|
}
|
672
|
-
const
|
673
|
-
const props = extraProps ? mergeProperties(baseProps, extraProps) : baseProps;
|
617
|
+
const props = mergeProperties({ class: headerPinClasses('tr', rowPinned, true) }, extraProps);
|
674
618
|
const tpl = rowRenderer === null || rowRenderer === void 0 ? void 0 : rowRenderer.template;
|
619
|
+
/**
|
620
|
+
* Applies appropriate classes to td / th VNodes;
|
621
|
+
* which can be supplied by user defined templates
|
622
|
+
* @param children virtual / jsx node array
|
623
|
+
* @returns virtual / jsx node array
|
624
|
+
*/
|
625
|
+
const applyCellClasses = (children) => {
|
626
|
+
return utils.map(children, (cNode, i) => {
|
627
|
+
if (['td', 'th'].includes(cNode.vtag.toString())) {
|
628
|
+
cNode.vattrs = mergeProperties({
|
629
|
+
class: baseCellClasses(i, true),
|
630
|
+
}, cNode.vattrs);
|
631
|
+
}
|
632
|
+
return cNode;
|
633
|
+
});
|
634
|
+
};
|
675
635
|
if (tpl) {
|
676
636
|
let toRender = tpl(index.h, {
|
677
637
|
renderedRow: (index.h("tr", Object.assign({}, props, { key: rowModel.__uuid }), children)),
|
@@ -683,24 +643,9 @@ const TableRow = ({ rowRenderer, rowIndex, rowModel, onColumnPinned }, children,
|
|
683
643
|
if (node.vtag === 'tr') {
|
684
644
|
if (!node.vkey)
|
685
645
|
node.vkey = `${rowModel.__uuid}_${i}`;
|
686
|
-
node.vattrs = mergeProperties({ class: headerPinClasses('tr',
|
646
|
+
node.vattrs = mergeProperties({ class: headerPinClasses('tr', rowPinned, true) }, node.vattrs);
|
687
647
|
if (!!node.vchildren) {
|
688
|
-
node.vchildren =
|
689
|
-
if (['td', 'th'].includes(cNode.vtag.toString())) {
|
690
|
-
cNode.vattrs = mergeProperties({
|
691
|
-
class: headerPinClasses(cNode.vtag.toString(), pinned, true) + baseCellClasses(i, true),
|
692
|
-
ref: (th) => {
|
693
|
-
if ((!!th && pinned === 'top') || pinned === 'bottom')
|
694
|
-
addVObserver(th, pinned, onColumnPinned);
|
695
|
-
if (!!th && th.classList.contains('nano-tbl__pin--end'))
|
696
|
-
addHObserver(th, 'end', onColumnPinned);
|
697
|
-
if (!!th && th.classList.contains('nano-tbl__pin--start'))
|
698
|
-
addHObserver(th, 'start', onColumnPinned);
|
699
|
-
},
|
700
|
-
}, cNode.vattrs);
|
701
|
-
}
|
702
|
-
return cNode;
|
703
|
-
});
|
648
|
+
node.vchildren = applyCellClasses(node.vchildren);
|
704
649
|
}
|
705
650
|
}
|
706
651
|
return node;
|
@@ -708,28 +653,25 @@ const TableRow = ({ rowRenderer, rowIndex, rowModel, onColumnPinned }, children,
|
|
708
653
|
}
|
709
654
|
return toRender;
|
710
655
|
}
|
711
|
-
return (index.h("tr", Object.assign({}, props, { key: rowModel.__uuid }), children));
|
656
|
+
return (index.h("tr", Object.assign({}, props, { key: rowModel.__uuid }), applyCellClasses(children)));
|
712
657
|
};
|
713
|
-
const TableHeadFootRow = ({ rowRenderer
|
658
|
+
const TableHeadFootRow = ({ rowRenderer }, // onRowPinned, onColPinned
|
659
|
+
children, utils) => {
|
714
660
|
let extraProps = {};
|
715
661
|
if (rowRenderer.rowProperties) {
|
716
662
|
extraProps = rowRenderer.rowProperties() || {};
|
717
663
|
}
|
718
|
-
const
|
719
|
-
|
720
|
-
[`${CSSNAMESPACE}__cell-content`]: true,
|
721
|
-
[`${CSSNAMESPACE}__cell-content--wrap`]: wrap,
|
722
|
-
} }, children));
|
723
|
-
return header !== false ? index.h("th", { scope: "col" }, cell) : index.h("td", null, cell);
|
664
|
+
const TableHeadFootCell = ({ header, wrap, cellProps, wrapperProps }, children) => {
|
665
|
+
return tableCellContent({ header, wrap, cellProps, wrapperProps }, children, 'col');
|
724
666
|
};
|
725
667
|
const pinned = rowRenderer.pinned || null;
|
726
|
-
const baseProps = { class: headerPinClasses('tr',
|
668
|
+
const baseProps = { class: headerPinClasses('tr', pinned) };
|
727
669
|
const props = extraProps ? mergeProperties(baseProps, extraProps) : baseProps;
|
728
670
|
const tpl = rowRenderer === null || rowRenderer === void 0 ? void 0 : rowRenderer.template;
|
729
671
|
if (tpl) {
|
730
672
|
let toRender = tpl(index.h, {
|
731
673
|
renderedRow: index.h("tr", Object.assign({}, props), children),
|
732
|
-
},
|
674
|
+
}, TableHeadFootCell);
|
733
675
|
if (Array.isArray(toRender)) {
|
734
676
|
toRender = utils.map(toRender, (node) => {
|
735
677
|
if (node.vtag === 'tr') {
|
@@ -739,14 +681,6 @@ const TableHeadFootRow = ({ rowRenderer, onColumnPinned }, children, utils) => {
|
|
739
681
|
if (['td', 'th'].includes(cNode.vtag.toString())) {
|
740
682
|
cNode.vattrs = mergeProperties({
|
741
683
|
class: headerPinClasses(cNode.vtag.toString(), pinned, true),
|
742
|
-
ref: (th) => {
|
743
|
-
if ((!!th && pinned === 'top') || pinned === 'bottom')
|
744
|
-
addVObserver(th, pinned, onColumnPinned);
|
745
|
-
if (!!th && th.classList.contains('nano-tbl__pin--end'))
|
746
|
-
addHObserver(th, 'end', onColumnPinned);
|
747
|
-
if (!!th && th.classList.contains('nano-tbl__pin--start'))
|
748
|
-
addHObserver(th, 'start', onColumnPinned);
|
749
|
-
},
|
750
684
|
}, cNode.vattrs);
|
751
685
|
}
|
752
686
|
return cNode;
|
@@ -761,8 +695,399 @@ const TableHeadFootRow = ({ rowRenderer, onColumnPinned }, children, utils) => {
|
|
761
695
|
return index.h("tr", Object.assign({}, props), children);
|
762
696
|
};
|
763
697
|
|
764
|
-
|
698
|
+
function addStyleSheet(id, css) {
|
699
|
+
const styleSheet = document.getElementById(id) ||
|
700
|
+
document.createElement('style');
|
701
|
+
styleSheet.id = id;
|
702
|
+
styleSheet.innerHTML = css;
|
703
|
+
if (!styleSheet.isConnected)
|
704
|
+
document.head.append(styleSheet);
|
705
|
+
}
|
706
|
+
/**
|
707
|
+
* Manages the complex business of table 'pinning'; sticking columns and rows to the scrolling parent element.
|
708
|
+
*
|
709
|
+
* *knowing* when an element is pinned is tricky.
|
710
|
+
* Managing the display of multiple, side-by-side pinned elements is trickier still.
|
711
|
+
*
|
712
|
+
* Pinning table columns are very different from pinning table rows:
|
713
|
+
* - Rows are actual elements we can select, measure and apply styles to.
|
714
|
+
* - Columns are disparate collections of elements that are much harder to select, measure and apply styles to.
|
715
|
+
*
|
716
|
+
* With this in mind, how columns and rows are pinned is different:
|
717
|
+
* Rows can have changes applied directly, Columns have changes applied via dynamic stylesheets.
|
718
|
+
*
|
719
|
+
* The service is slightly opinionated on how it pins rows and columns (with some room for override):
|
720
|
+
* - Pinned columns are stuck consecutively, without overlapping.
|
721
|
+
* e.g. If column 'name' and 'surname' are both `pin: 'start'`; 'surname' will display **next** to name.
|
722
|
+
* Both columns are important for context
|
723
|
+
*
|
724
|
+
* - Pinned rows are set to overlap *when* they have the same ancestor,
|
725
|
+
* and stuck consecutively when they have a different ancestor.
|
726
|
+
* e.g. `tbody > tr.pin ~ tr.pin` the second row will **overlap** the first; it's unlikely both rows will be important for context.
|
727
|
+
* `thead > tr.pin`, `tbody > tr.pin`. Both rows are required for context so will require next to each other.
|
728
|
+
*
|
729
|
+
* Devs can override this behaviour by setting `--pin-start`, `--pin-end`, `--pin-top`, `--pin-bottom` custom vars.
|
730
|
+
*/
|
731
|
+
class TablePinService {
|
732
|
+
constructor(table, scrollElement) {
|
733
|
+
// Private state
|
734
|
+
this.cachedColMeta = new WeakMap();
|
735
|
+
this._pinnedStart = [];
|
736
|
+
this._pinnedEnd = [];
|
737
|
+
this._cssColDimensionCacheKey = '';
|
738
|
+
this.cacheX = 0;
|
739
|
+
this.cacheY = 0;
|
740
|
+
this.tableEle = table;
|
741
|
+
this.tableId = this.tableEle.id;
|
742
|
+
this.scrollElement = scrollElement;
|
743
|
+
// Secret sauce - `getElementsByClassName` is a live collection.
|
744
|
+
// An HTMLCollection will keep itself up-to-date as elements come and go
|
745
|
+
// So we can keep assessing on scroll
|
746
|
+
this.startColumns = table
|
747
|
+
.querySelector('thead')
|
748
|
+
.getElementsByClassName(`${CSSNAMESPACE}__pin--start`);
|
749
|
+
this.endColumns = table
|
750
|
+
.querySelector('thead')
|
751
|
+
.getElementsByClassName(`${CSSNAMESPACE}__pin--end`);
|
752
|
+
this.topRows = table.getElementsByClassName(`${CSSNAMESPACE}__pin--top`);
|
753
|
+
this.bottomRows = table.getElementsByClassName(`${CSSNAMESPACE}__pin--bottom`);
|
754
|
+
this.onResize();
|
755
|
+
}
|
756
|
+
// Pinned cols & change detection
|
757
|
+
get pinnedStart() {
|
758
|
+
return this._pinnedStart;
|
759
|
+
}
|
760
|
+
set pinnedStart(cols) {
|
761
|
+
this._pinnedStart = cols;
|
762
|
+
this.handlePinnedStartChange();
|
763
|
+
}
|
764
|
+
/**
|
765
|
+
* Called when columns are either pinned or unpinned.
|
766
|
+
* Attaches a tiny stylesheet to target the 'last' start column.
|
767
|
+
* (e.g. We only want to apply drop shadow on last pinned start column - not all pinned columns)
|
768
|
+
*/
|
769
|
+
handlePinnedStartChange() {
|
770
|
+
index.writeTask(() => {
|
771
|
+
if (this.pinnedStart.length) {
|
772
|
+
this.tableEle.classList.add(`${CSSNAMESPACE}__pinned--start`);
|
773
|
+
const lastActiveCol = this.cachedColMeta.get(this.pinnedStart[this.pinnedStart.length - 1]);
|
774
|
+
addStyleSheet(`${this.tableId}-col-start-active-style`,
|
775
|
+
/* css */ `
|
776
|
+
#${this.tableId} tr > :nth-child(${lastActiveCol.idx + 1}) {
|
777
|
+
--pin-start-active: 1;
|
778
|
+
}
|
779
|
+
`);
|
780
|
+
}
|
781
|
+
else {
|
782
|
+
this.tableEle.classList.remove(`${CSSNAMESPACE}__pinned--start`);
|
783
|
+
addStyleSheet(`${this.tableId}-col-start-active-style`, ``);
|
784
|
+
}
|
785
|
+
});
|
786
|
+
}
|
787
|
+
get pinnedEnd() {
|
788
|
+
return this._pinnedEnd;
|
789
|
+
}
|
790
|
+
set pinnedEnd(cols) {
|
791
|
+
this._pinnedEnd = cols;
|
792
|
+
this.handlePinnedEndChange();
|
793
|
+
}
|
794
|
+
/**
|
795
|
+
* Called when columns are either pinned or unpinned.
|
796
|
+
* Attaches a tiny stylesheet to target the 'first' end column.
|
797
|
+
* (e.g. We only want to apply drop shadow on first pinned end column - not all pinned columns)
|
798
|
+
*/
|
799
|
+
handlePinnedEndChange() {
|
800
|
+
index.writeTask(() => {
|
801
|
+
if (this.pinnedEnd.length) {
|
802
|
+
this.tableEle.classList.add(`${CSSNAMESPACE}__pinned--end`);
|
803
|
+
const firstActiveCol = this.cachedColMeta.get(this.pinnedEnd[0]);
|
804
|
+
addStyleSheet(`${this.tableId}-col-end-active-style`,
|
805
|
+
/* css */ `
|
806
|
+
#${this.tableId} tr > :nth-child(${firstActiveCol.idx + 1}) { --pin-end-active: 1; }
|
807
|
+
`);
|
808
|
+
}
|
809
|
+
else {
|
810
|
+
this.tableEle.classList.remove(`${CSSNAMESPACE}__pinned--end`);
|
811
|
+
addStyleSheet(`${this.tableId}-col-end-active-style`, ``);
|
812
|
+
}
|
813
|
+
});
|
814
|
+
}
|
815
|
+
get cssColDimensionCacheKey() {
|
816
|
+
return this._cssColDimensionCacheKey;
|
817
|
+
}
|
818
|
+
set cssColDimensionCacheKey(key) {
|
819
|
+
if (key === this._cssColDimensionCacheKey)
|
820
|
+
return;
|
821
|
+
this._cssColDimensionCacheKey = key;
|
822
|
+
this.createPinnedColDimensionStyles();
|
823
|
+
}
|
824
|
+
/**
|
825
|
+
* To only generate column dimension styles when necessary we
|
826
|
+
* maintain a cache key string via serialised column meta.
|
827
|
+
* Only when this key changes do we generate a new stylesheet
|
828
|
+
*/
|
829
|
+
generateCssCacheKey() {
|
830
|
+
let key = '';
|
831
|
+
for (const col of this.startColumns) {
|
832
|
+
const colMeta = this.cachedColMeta.get(col);
|
833
|
+
key += `${colMeta.idx}-start-${colMeta.width}`;
|
834
|
+
}
|
835
|
+
for (const col of this.endColumns) {
|
836
|
+
const colMeta = this.cachedColMeta.get(col);
|
837
|
+
key += `${colMeta.idx}-start-${colMeta.width}`;
|
838
|
+
}
|
839
|
+
this.cssColDimensionCacheKey = key;
|
840
|
+
}
|
841
|
+
/**
|
842
|
+
* Generates pinned column width offset styles
|
843
|
+
* so pinned columns can appear stuck together,
|
844
|
+
* then attaches a stylesheet.
|
845
|
+
*/
|
846
|
+
createPinnedColDimensionStyles() {
|
847
|
+
let widthS = 0;
|
848
|
+
let widthE = 0;
|
849
|
+
const startCols = Array.from(this.startColumns);
|
850
|
+
const endCols = Array.from(this.endColumns).reverse();
|
851
|
+
const css = /* css */ `
|
852
|
+
${startCols
|
853
|
+
.map((col) => {
|
854
|
+
const colMeta = this.cachedColMeta.get(col);
|
855
|
+
widthS += colMeta.width || 0;
|
856
|
+
return /* css */ `
|
857
|
+
#${this.tableId} tr > :nth-child(${colMeta.idx + 1}) ~ td,
|
858
|
+
#${this.tableId} tr > :nth-child(${colMeta.idx + 1}) ~ th {
|
859
|
+
--pin-start: ${widthS - 1}px;
|
860
|
+
}
|
861
|
+
`;
|
862
|
+
})
|
863
|
+
.join('')}
|
864
|
+
${endCols
|
865
|
+
.map((col) => {
|
866
|
+
const colMeta = this.cachedColMeta.get(col);
|
867
|
+
widthE += colMeta.width;
|
868
|
+
return /* css */ `
|
869
|
+
#${this.tableId} tr > td:has(~ :nth-child(${colMeta.idx + 1})),
|
870
|
+
#${this.tableId} tr > th:has(~ :nth-child(${colMeta.idx + 1})) {
|
871
|
+
--pin-end: ${widthE - 1}px;
|
872
|
+
}
|
873
|
+
`;
|
874
|
+
})
|
875
|
+
.join('')}
|
876
|
+
`;
|
877
|
+
addStyleSheet(`${this.tableId}-dimension-style`, css);
|
878
|
+
}
|
879
|
+
getParentOffsets() {
|
880
|
+
const { x, y } = this.scrollElement.getBoundingClientRect();
|
881
|
+
let offsetX = x;
|
882
|
+
let offsetY = y;
|
883
|
+
if (this.scrollElement === document.documentElement) {
|
884
|
+
offsetX = this.scrollElement.offsetLeft;
|
885
|
+
offsetY = this.scrollElement.offsetTop;
|
886
|
+
}
|
887
|
+
return { offsetX, offsetY };
|
888
|
+
}
|
889
|
+
/**
|
890
|
+
* Loops through all 'top' & 'bottom' rows (on scroll or resize)
|
891
|
+
* Manages their visual state by applying classes on stuck / unstuck
|
892
|
+
* And their pinned offset / distance
|
893
|
+
*/
|
894
|
+
assessRows() {
|
895
|
+
if (!this.topRows.length && !this.bottomRows.length)
|
896
|
+
return;
|
897
|
+
// top rows
|
898
|
+
if (this.topRows.length) {
|
899
|
+
index.readTask(async () => {
|
900
|
+
let heightAggregate = 0;
|
901
|
+
let cacheParent;
|
902
|
+
const { offsetY } = this.getParentOffsets();
|
903
|
+
for (const topRow of this.topRows) {
|
904
|
+
const { y, height } = topRow.getBoundingClientRect();
|
905
|
+
const currParent = topRow.parentElement;
|
906
|
+
// we'll use the applied `--pin-top` css var to decide row offset.
|
907
|
+
// This allows devs to override this behaviour through selector specificity
|
908
|
+
const pinTop = getComputedStyle(topRow).getPropertyValue('--pin-top');
|
909
|
+
const offset = pinTop !== '' ? parseFloat(pinTop) : heightAggregate;
|
910
|
+
// we need to wait for the row to finish sticking
|
911
|
+
// and generating it's offset (`--pin-top`) so we can see, on
|
912
|
+
// subsequent rows *if* the offset was applied
|
913
|
+
await new Promise((resolve) => index.writeTask(() => {
|
914
|
+
if (y - offsetY <= offset) {
|
915
|
+
topRow.classList.add(`${CSSNAMESPACE}__pinned`, `${CSSNAMESPACE}__pinned--top`);
|
916
|
+
}
|
917
|
+
else {
|
918
|
+
topRow.classList.remove(`${CSSNAMESPACE}__pinned`, `${CSSNAMESPACE}__pinned--top`);
|
919
|
+
}
|
920
|
+
// by default, we only want to stick one row from each parental block (thead, tbody, tfoot)
|
921
|
+
// so only aggregate height / offset when cacheParent is different from current parent.
|
922
|
+
// Devs can override this behaviour by manually setting `--pin-bottom` on the table row
|
923
|
+
if (cacheParent !== currParent) {
|
924
|
+
currParent.style.setProperty('--pin-top', `${heightAggregate}px`);
|
925
|
+
heightAggregate += height;
|
926
|
+
cacheParent = currParent;
|
927
|
+
}
|
928
|
+
resolve();
|
929
|
+
}));
|
930
|
+
}
|
931
|
+
});
|
932
|
+
}
|
933
|
+
// bottom rows
|
934
|
+
if (this.bottomRows.length) {
|
935
|
+
const bottomRows = Array.from(this.bottomRows).reverse();
|
936
|
+
index.readTask(async () => {
|
937
|
+
let cacheParent;
|
938
|
+
let heightAggregate = 0;
|
939
|
+
const { offsetY } = this.getParentOffsets();
|
940
|
+
for (const bottomRow of bottomRows) {
|
941
|
+
if (!bottomRow.isConnected)
|
942
|
+
continue;
|
943
|
+
const { y, height } = bottomRow.getBoundingClientRect();
|
944
|
+
const currParent = bottomRow.parentElement;
|
945
|
+
// we'll use the applied `--pin-bottom` css var to decide row offset.
|
946
|
+
// This allows devs to override this behaviour through selector specificity
|
947
|
+
const pinBottom = getComputedStyle(bottomRow).getPropertyValue('--pin-bottom');
|
948
|
+
const offset = pinBottom !== '' ? parseFloat(pinBottom) : heightAggregate;
|
949
|
+
// we need to wait for the row to finish sticking
|
950
|
+
// and generating it's offset (`--pin-bottom`) to we can see, on
|
951
|
+
// subsequent rows *if* the offset was applied
|
952
|
+
await new Promise((resolve) => index.writeTask(() => {
|
953
|
+
if (this.tableDims.height + offsetY - (y + height) <= offset) {
|
954
|
+
bottomRow.classList.add(`${CSSNAMESPACE}__pinned`, `${CSSNAMESPACE}__pinned--bottom`);
|
955
|
+
}
|
956
|
+
else {
|
957
|
+
bottomRow.classList.remove(`${CSSNAMESPACE}__pinned`, `${CSSNAMESPACE}__pinned--bottom`);
|
958
|
+
}
|
959
|
+
// by default, we only want to stick one row from each parental block (thead, tbody, tfoot)
|
960
|
+
// so only aggregate height / offset when cacheParent is different from current parent.
|
961
|
+
// Devs can override this behaviour by manually setting `--pin-bottom` on the table row
|
962
|
+
if (cacheParent !== currParent) {
|
963
|
+
currParent.style.setProperty('--pin-bottom', `${heightAggregate}px`);
|
964
|
+
heightAggregate += height;
|
965
|
+
cacheParent = currParent;
|
966
|
+
}
|
967
|
+
resolve();
|
968
|
+
}));
|
969
|
+
}
|
970
|
+
});
|
971
|
+
}
|
972
|
+
}
|
973
|
+
/**
|
974
|
+
* Loops through all 'start' & 'end' columns (on scroll or resize)
|
975
|
+
* Caches meta about each column (e.g. size, position-index)
|
976
|
+
* and decides which columns are pinned
|
977
|
+
*/
|
978
|
+
async assessCols() {
|
979
|
+
if (!this.startColumns.length && !this.endColumns.length)
|
980
|
+
return;
|
981
|
+
let boundBox;
|
982
|
+
let currPinned;
|
983
|
+
let parentEles;
|
984
|
+
const done = new Promise((resolve) => {
|
985
|
+
// start cols
|
986
|
+
if (this.startColumns.length) {
|
987
|
+
index.readTask(() => {
|
988
|
+
const { offsetX } = this.getParentOffsets();
|
989
|
+
// cumulatively add widths of columns together
|
990
|
+
// 'cos columns stick together
|
991
|
+
let widthAggregate = offsetX;
|
992
|
+
parentEles = Array.from(this.startColumns[0].parentElement.children);
|
993
|
+
for (const startCol of this.startColumns) {
|
994
|
+
boundBox = startCol.getBoundingClientRect();
|
995
|
+
// cache meta for later
|
996
|
+
this.cachedColMeta.set(startCol, {
|
997
|
+
width: boundBox.width,
|
998
|
+
idx: parentEles.indexOf(startCol),
|
999
|
+
});
|
1000
|
+
currPinned = this.pinnedStart.find((c) => c === startCol);
|
1001
|
+
if (boundBox.x < widthAggregate) {
|
1002
|
+
// this column is pinned
|
1003
|
+
if (!currPinned)
|
1004
|
+
this.pinnedStart = [
|
1005
|
+
...this.pinnedStart,
|
1006
|
+
startCol,
|
1007
|
+
];
|
1008
|
+
}
|
1009
|
+
else if (currPinned) {
|
1010
|
+
// this column is unpinned
|
1011
|
+
this.pinnedStart = this.pinnedStart.filter((c) => c !== startCol);
|
1012
|
+
}
|
1013
|
+
widthAggregate += boundBox.width;
|
1014
|
+
}
|
1015
|
+
if (!this.endColumns.length)
|
1016
|
+
resolve();
|
1017
|
+
});
|
1018
|
+
}
|
1019
|
+
// end cols
|
1020
|
+
if (this.endColumns.length) {
|
1021
|
+
index.readTask(() => {
|
1022
|
+
const endCols = Array.from(this.endColumns).reverse();
|
1023
|
+
parentEles = Array.from(this.endColumns[0].parentElement.children);
|
1024
|
+
const { offsetX } = this.getParentOffsets();
|
1025
|
+
// cumulatively add widths of columns together
|
1026
|
+
// 'cos columns stick together
|
1027
|
+
let widthAggregate = 0;
|
1028
|
+
for (const endCol of endCols) {
|
1029
|
+
boundBox = endCol.getBoundingClientRect();
|
1030
|
+
// cache meta for later
|
1031
|
+
this.cachedColMeta.set(endCol, {
|
1032
|
+
width: boundBox.width,
|
1033
|
+
idx: parentEles.indexOf(endCol),
|
1034
|
+
});
|
1035
|
+
currPinned = this.pinnedEnd.find((c) => c === endCol);
|
1036
|
+
if (this.tableDims.width + offsetX - boundBox.right <=
|
1037
|
+
widthAggregate) {
|
1038
|
+
// this column is pinned
|
1039
|
+
if (!currPinned)
|
1040
|
+
this.pinnedEnd = [endCol, ...this.pinnedEnd];
|
1041
|
+
}
|
1042
|
+
else if (currPinned) {
|
1043
|
+
// this column is unpinned
|
1044
|
+
this.pinnedEnd = this.pinnedEnd.filter((c) => c !== endCol);
|
1045
|
+
}
|
1046
|
+
widthAggregate += boundBox.width;
|
1047
|
+
}
|
1048
|
+
resolve();
|
1049
|
+
});
|
1050
|
+
}
|
1051
|
+
});
|
1052
|
+
await done;
|
1053
|
+
// potentially generate a new css stylesheet if anything changed
|
1054
|
+
this.generateCssCacheKey();
|
1055
|
+
}
|
1056
|
+
onScroll(pos) {
|
1057
|
+
if (this.cacheX !== pos.x) {
|
1058
|
+
this.cacheX = pos.x;
|
1059
|
+
this.assessCols();
|
1060
|
+
}
|
1061
|
+
if (this.cacheY !== pos.y) {
|
1062
|
+
this.cacheY = pos.y;
|
1063
|
+
this.assessRows();
|
1064
|
+
}
|
1065
|
+
}
|
1066
|
+
onResize() {
|
1067
|
+
const width = this.scrollElement.clientWidth;
|
1068
|
+
const height = this.scrollElement.clientHeight;
|
1069
|
+
this.tableDims = { width, height };
|
1070
|
+
this.assessCols();
|
1071
|
+
this.assessRows();
|
1072
|
+
}
|
1073
|
+
}
|
1074
|
+
|
1075
|
+
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, 500px, 50vw);--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.6rem;--td-padding-bottom:0.6125rem;--th-padding-start:0.725rem;--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));-webkit-border-end:1px solid transparent;border-inline-end:1px solid transparent;-webkit-border-before: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);-webkit-border-start:var(--border-style);border-inline-start:var(--border-style);-webkit-border-end:var(--border-style);border-inline-end:var(--border-style)}.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__order-btn:focus-visible{outline:none;box-shadow:var(--nano-control-focus-shadow, 0 0 0 0.1875rem var(--nano-control-focus-color, rgba(144, 198, 231, 0.8))) inset}.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;transform:scale(0);width:100%;height:0}.nano-tbl__progress-bar--show{transform: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;-webkit-border-before:var(--border-style);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{-webkit-border-before:none;border-block-start:none}tbody:last-of-type tr:last-child .nano-tbl__td,tbody:last-of-type tr:last-child .nano-tbl__th{-webkit-border-after:var(--border-style);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{-webkit-padding-start:var(--bookend-col-padding);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{-webkit-padding-end:var(--bookend-col-padding);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{-webkit-padding-start:var(--td-padding-start) !important;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{-webkit-padding-end:var(--td-padding-end) !important;padding-inline-end:var(--td-padding-end) !important}}thead .nano-tbl__td,thead .nano-tbl__th{color:var(--thead-color);font-weight:800;background:rgb(var(--head-bg-rgb)/100%);font-size:var(--thead-font-size);-webkit-border-before:none !important;border-block-start:none !important}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)}thead .nano-tbl__td .nano-sortable__keyboard-handle,thead .nano-tbl__th .nano-sortable__keyboard-handle{position:absolute;inset-inline-end:5px;inset-block-start:50%;transform:translateY(-50%);background:white;z-index:10}tfoot .nano-tbl__td,tfoot .nano-tbl__th{color:var(--tfoot-color);font-weight:800;-webkit-border-before:none;border-block-start:none;background:rgb(var(--foot-bg-rgb)/100%);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:rgb(var(--ordered-bg-rgb)/80%) !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__cell-content--wrap{white-space:normal;overflow:visible}.nano-tbl tbody{will-change:scroll-position;opacity:1;transition:0.1s ease opacity}.nano-tbl tbody.nano-tbl__loading{z-index:-1;position:relative}.nano-tbl tbody.nano-tbl__inactive{opacity:0}.nano-tbl tbody .nano-tbl__tr:has(~.nano-tbl__tr--placeholder){display:none}.nano-tbl tbody .nano-tbl__tr--placeholder~.nano-tbl__tr{display:none}.nano-tbl th[scope=row]{font-weight:800;margin:0}.nano-tbl__pin--start{position:sticky;inset-inline-start:var(--pin-start, -1px)}.nano-tbl__pin--start::after{content:\"\";position:absolute;inset:0;box-shadow:5px 0 4px -1px rgba(0, 0, 0, 0.2);opacity:var(--pin-start-active, 0);z-index:-1}.nano-tbl__pinned--start .nano-tbl__pin--start{z-index:2}.nano-tbl__pin--end{position:sticky}.nano-tbl__pin--start+.nano-tbl__pin--end{inset-inline-end:auto !important}.nano-tbl__pin--start+.nano-tbl__pin--end::after{display:none}.sm .nano-tbl__pin--end{inset-inline-end:var(--pin-end, -1px);max-width:min(50vw, 200px)}.sm .nano-tbl__pin--end::after{display:block !important;content:\"\";position:absolute;inset:0;box-shadow:-5px 1px 4px -1px rgba(0, 0, 0, 0.2);opacity:var(--pin-end-active, 0);z-index:-1}.sm .nano-tbl__pinned--end .nano-tbl__pin--end{z-index:3}.nano-tbl__pin--top .nano-tbl__th,.nano-tbl__pin--top .nano-tbl__td{position:sticky;inset-block-start:var(--pin-top, -1px)}.nano-tbl__pin--top.nano-tbl__pinned--top .nano-tbl__th,.nano-tbl__pin--top.nano-tbl__pinned--top .nano-tbl__td{z-index:4 !important}.nano-tbl__pinned--start .nano-tbl__pin--top.nano-tbl__pinned--top .nano-tbl__pin--start{z-index:6 !important}tbody .nano-tbl__pin--top.nano-tbl__pinned--top .nano-tbl__th,tbody .nano-tbl__pin--top.nano-tbl__pinned--top .nano-tbl__td{box-shadow:1px 3px 4px -1px rgba(0, 0, 0, 0.1)}.nano-tbl__pin--bottom .nano-tbl__th,.nano-tbl__pin--bottom .nano-tbl__td{position:sticky;inset-block-end:var(--pin-bottom, -1px)}.nano-tbl__pin--bottom.nano-tbl__pinned--bottom .nano-tbl__th,.nano-tbl__pin--bottom.nano-tbl__pinned--bottom .nano-tbl__td{z-index:5 !important}.nano-tbl__pin--bottom.nano-tbl__pinned--bottom:has(~.nano-tbl__pin--bottom.nano-tbl__pinned--bottom) .nano-tbl__th,.nano-tbl__pin--bottom.nano-tbl__pinned--bottom:has(~.nano-tbl__pin--bottom.nano-tbl__pinned--bottom) .nano-tbl__td{z-index:6 !important}.nano-tbl__pinned--start .nano-tbl__pin--bottom.nano-tbl__pinned--bottom .nano-tbl__pin--start{z-index:6 !important}tbody .nano-tbl__pin--bottom.nano-tbl__pinned--bottom .nano-tbl__th,tbody .nano-tbl__pin--bottom.nano-tbl__pinned--bottom .nano-tbl__td{box-shadow:1px -3px 4px -1px rgba(0, 0, 0, 0.07)}.nano-tbl thead tr:last-of-type td,.nano-tbl thead tr:last-of-type th{-webkit-border-after:var(--border-tint-style);border-block-end:var(--border-tint-style)}.nano-tbl tfoot tr:first-of-type td,.nano-tbl tfoot tr:first-of-type th{-webkit-border-before:none;border-block-start:none}.nano-tbl tfoot tr:last-of-type td,.nano-tbl tfoot tr:last-of-type th{-webkit-border-before:var(--border-style);border-block-start:var(--border-style);-webkit-border-after:var(--border-tint-style);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{-webkit-border-before:var(--border-tint-style) !important;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{-webkit-border-after:none !important;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)}";
|
765
1076
|
|
1077
|
+
const measurePerf = false;
|
1078
|
+
function perMark(name, end = false) {
|
1079
|
+
if (!performance || !measurePerf)
|
1080
|
+
return;
|
1081
|
+
if (end) {
|
1082
|
+
performance === null || performance === void 0 ? void 0 : performance.mark('end' + name);
|
1083
|
+
performance === null || performance === void 0 ? void 0 : performance.measure(name, 'start' + name, 'end' + name);
|
1084
|
+
const entries = performance === null || performance === void 0 ? void 0 : performance.getEntriesByName(name);
|
1085
|
+
console.log(entries[entries.length ? entries.length - 1 : 0]);
|
1086
|
+
}
|
1087
|
+
else {
|
1088
|
+
performance === null || performance === void 0 ? void 0 : performance.mark('start' + name);
|
1089
|
+
}
|
1090
|
+
}
|
766
1091
|
let id = 0;
|
767
1092
|
const Table = class {
|
768
1093
|
constructor(hostRef) {
|
@@ -799,6 +1124,7 @@ const Table = class {
|
|
799
1124
|
const sortEvent = this.nanoTblBeforeSort.emit({ column: column, order });
|
800
1125
|
if (sortEvent.defaultPrevented)
|
801
1126
|
return;
|
1127
|
+
perMark('sort');
|
802
1128
|
this.currentSort = order + ':' + column;
|
803
1129
|
// doesn't make sense to leave user in place for a sort
|
804
1130
|
this.scrollToTop(element);
|
@@ -842,11 +1168,24 @@ const Table = class {
|
|
842
1168
|
* stop loop - it's on the current active block.
|
843
1169
|
*/
|
844
1170
|
this.scrollHandler = () => {
|
1171
|
+
var _a;
|
1172
|
+
perMark('scrollHandler');
|
845
1173
|
// don't listen if this table isn't in the viewport
|
846
|
-
if (!this.store.general.state.isActive)
|
1174
|
+
if (!((_a = this.store) === null || _a === void 0 ? void 0 : _a.general.state.isActive) || !this.rows)
|
847
1175
|
return;
|
1176
|
+
if (this.primaryBlockIndex === undefined)
|
1177
|
+
this.primaryBlockIndex = 0;
|
848
1178
|
index.readTask(() => {
|
849
|
-
this.cacheScrollPosition =
|
1179
|
+
this.cacheScrollPosition =
|
1180
|
+
typeof this.scrollParent.scrollTop !== 'undefined'
|
1181
|
+
? this.scrollParent.scrollTop
|
1182
|
+
: window.scrollY;
|
1183
|
+
if (this.tablePinnedService) {
|
1184
|
+
this.tablePinnedService.onScroll({
|
1185
|
+
x: this.scrollParent.scrollLeft || window.scrollX,
|
1186
|
+
y: this.cacheScrollPosition,
|
1187
|
+
});
|
1188
|
+
}
|
850
1189
|
let cumulativeHeight = this.host.offsetTop;
|
851
1190
|
let blockIndex = 0;
|
852
1191
|
const blockLen = this.blocks.length;
|
@@ -857,21 +1196,18 @@ const Table = class {
|
|
857
1196
|
const potentialBlocks = [
|
858
1197
|
blockIndex,
|
859
1198
|
blockIndex + 1,
|
860
|
-
|
1199
|
+
this.cacheScrollPosition,
|
1200
|
+
cumulativeHeight,
|
1201
|
+
// Math.max(0, blockIndex - 1),
|
861
1202
|
];
|
862
1203
|
if (potentialBlocks.toString() !== this.activeBlocks.toString()) {
|
863
1204
|
this.activeBlocks = potentialBlocks;
|
864
|
-
this.setBlockHeight();
|
865
1205
|
}
|
866
1206
|
this.primaryBlockIndex = blockIndex;
|
867
1207
|
}
|
868
1208
|
blockIndex++;
|
869
1209
|
}
|
870
|
-
|
871
|
-
};
|
872
|
-
this.handleColumnPinned = (positions) => {
|
873
|
-
Object.entries(positions).forEach(([key, applied]) => {
|
874
|
-
this.tableEle.classList.toggle(`${CSSNAMESPACE}__pinned--${key}`, applied);
|
1210
|
+
perMark('scrollHandler', true);
|
875
1211
|
});
|
876
1212
|
};
|
877
1213
|
this.handleResizeChange = (e) => {
|
@@ -882,12 +1218,12 @@ const Table = class {
|
|
882
1218
|
classes = [...e.target.className.split(' '), ...classes];
|
883
1219
|
this.tableWrapperEle.classList.add(...classes.filter((cl) => !!cl));
|
884
1220
|
};
|
885
|
-
this.
|
1221
|
+
this.customRenderer = undefined;
|
886
1222
|
this.type = 'table';
|
887
1223
|
this.caption = undefined;
|
888
1224
|
this.showCaption = false;
|
889
1225
|
this.loading = undefined;
|
890
|
-
this.internalLoading =
|
1226
|
+
this.internalLoading = true;
|
891
1227
|
this.placeholderSize = 5;
|
892
1228
|
this.rows = undefined;
|
893
1229
|
this.columns = [];
|
@@ -895,14 +1231,14 @@ const Table = class {
|
|
895
1231
|
this.rowRender = undefined;
|
896
1232
|
this.footRender = { pinned: 'bottom' };
|
897
1233
|
this.showFooter = false;
|
898
|
-
this.perBlock =
|
1234
|
+
this.perBlock = 50;
|
899
1235
|
this.searchTerm = undefined;
|
900
1236
|
this.customFilterFn = undefined;
|
901
1237
|
this.customSortFn = undefined;
|
902
1238
|
this.defaultSort = true;
|
903
1239
|
this.virtualTotalItems = 0;
|
904
1240
|
this.blocks = [];
|
905
|
-
this.activeBlocks = [0, 1
|
1241
|
+
this.activeBlocks = [0, 1];
|
906
1242
|
this.debounceSetLoading = throttle.debounce(this.debounceSetLoading.bind(this), 50);
|
907
1243
|
}
|
908
1244
|
get _loading() {
|
@@ -931,6 +1267,8 @@ const Table = class {
|
|
931
1267
|
if (!this.isReady)
|
932
1268
|
requestAnimationFrame(() => this.setInitialBlockDimension());
|
933
1269
|
this._loading = false;
|
1270
|
+
if (this.tablePinnedService)
|
1271
|
+
this.tablePinnedService.assessRows();
|
934
1272
|
});
|
935
1273
|
}
|
936
1274
|
async handleColsChange() {
|
@@ -948,6 +1286,10 @@ const Table = class {
|
|
948
1286
|
virtualTotalItemsChangeHandler() {
|
949
1287
|
this.setBlocks();
|
950
1288
|
}
|
1289
|
+
/** @readonly - shows the currently applied filters */
|
1290
|
+
get appliedFilters() {
|
1291
|
+
return this.filters;
|
1292
|
+
}
|
951
1293
|
/** Remove any column sorts currently applied
|
952
1294
|
* @returns a promise which resolves when complete */
|
953
1295
|
async resetSorting() {
|
@@ -990,8 +1332,6 @@ const Table = class {
|
|
990
1332
|
}
|
991
1333
|
/** Updates a row model at a given index
|
992
1334
|
* @param row - the row to update.
|
993
|
-
* *Note* - this should come from the `col.cellTemplate` or `row.rowRender.template` `rowModel` property
|
994
|
-
* - rows are augmented with certain properties to aid with efficient rendering
|
995
1335
|
* @param rowIndex - the row index to insert this row
|
996
1336
|
*/
|
997
1337
|
async updateRow(row, rowIndex) {
|
@@ -1022,7 +1362,9 @@ const Table = class {
|
|
1022
1362
|
? document
|
1023
1363
|
: this._scrollParent).removeEventListener('scroll', this.scrollHandler);
|
1024
1364
|
}
|
1025
|
-
(ele === document.documentElement ? document : ele).addEventListener('scroll', this.scrollHandler
|
1365
|
+
(ele === document.documentElement ? document : ele).addEventListener('scroll', this.scrollHandler
|
1366
|
+
// {passive: true}
|
1367
|
+
);
|
1026
1368
|
this._scrollParent = ele;
|
1027
1369
|
}
|
1028
1370
|
// used to fire `nanoTblBlockRendered` on block render change
|
@@ -1076,17 +1418,20 @@ const Table = class {
|
|
1076
1418
|
return Object.assign(Object.assign({}, c), { order: null });
|
1077
1419
|
});
|
1078
1420
|
this.nanoTblAfterSort.emit({ column: column, order });
|
1421
|
+
perMark('sort', true);
|
1079
1422
|
}
|
1080
1423
|
async searchStart() {
|
1081
1424
|
this._loading = true;
|
1082
1425
|
const sortEvent = this.nanoTblBeforeSearch.emit({ term: this.searchTerm });
|
1083
1426
|
if (sortEvent.defaultPrevented)
|
1084
1427
|
return;
|
1428
|
+
perMark('search');
|
1085
1429
|
// doesn't make sense to leave user in place for a search
|
1086
1430
|
this.scrollToTop();
|
1087
1431
|
try {
|
1088
1432
|
await storeSearch(this.host, this.searchTerm);
|
1089
1433
|
this.nanoTblAfterSearch.emit({ term: this.searchTerm });
|
1434
|
+
perMark('search', true);
|
1090
1435
|
}
|
1091
1436
|
catch (e) {
|
1092
1437
|
console.warn('search failed', e);
|
@@ -1113,6 +1458,7 @@ const Table = class {
|
|
1113
1458
|
const sortEvent = this.nanoTblBeforeFilter.emit({ filters: this.filters });
|
1114
1459
|
if (sortEvent.defaultPrevented)
|
1115
1460
|
return;
|
1461
|
+
perMark('filter');
|
1116
1462
|
this.currentFilters = JSON.stringify(this.filters);
|
1117
1463
|
// doesn't make sense to leave user in place for a search
|
1118
1464
|
this.scrollToTop();
|
@@ -1121,10 +1467,11 @@ const Table = class {
|
|
1121
1467
|
const res = await this.customFilterFn(this.filters);
|
1122
1468
|
// if the response is 'true', the custom filter did it's thing
|
1123
1469
|
// handover to finish and stop loading state.
|
1124
|
-
// if response is
|
1470
|
+
// if response is falsy, carry on to do a FE filter
|
1125
1471
|
if (res === true) {
|
1126
1472
|
this.filterComplete();
|
1127
1473
|
this._loading = false;
|
1474
|
+
return;
|
1128
1475
|
}
|
1129
1476
|
}
|
1130
1477
|
catch (e) {
|
@@ -1133,8 +1480,8 @@ const Table = class {
|
|
1133
1480
|
console.warn('custom filter failed', e);
|
1134
1481
|
this.currentFilters = '';
|
1135
1482
|
this._loading = false;
|
1483
|
+
return;
|
1136
1484
|
}
|
1137
|
-
return;
|
1138
1485
|
}
|
1139
1486
|
try {
|
1140
1487
|
await storeFilter(this.host, this.filters);
|
@@ -1150,13 +1497,22 @@ const Table = class {
|
|
1150
1497
|
filterComplete() {
|
1151
1498
|
this.columns = this.columns.map((c) => {
|
1152
1499
|
const cFilter = this.filters.find((f) => f.prop === c.prop);
|
1153
|
-
if
|
1500
|
+
// if we found a filter AND
|
1501
|
+
// it isn't true / false and has a length OR
|
1502
|
+
// it is true or false
|
1503
|
+
if (cFilter &&
|
1504
|
+
((typeof cFilter.filter !== 'boolean' && cFilter.filter.length) ||
|
1505
|
+
typeof cFilter.filter === 'boolean'))
|
1154
1506
|
c.filter = cFilter.filter;
|
1155
|
-
|
1507
|
+
// if a filter value is not set OR
|
1508
|
+
// it isn't true / false and has no length
|
1509
|
+
else if ((c.filter !== null && c.filter !== undefined) ||
|
1510
|
+
(!!c.filter && typeof c.filter !== 'boolean' && !c.filter.length))
|
1156
1511
|
c.filter = undefined;
|
1157
1512
|
return c;
|
1158
1513
|
});
|
1159
1514
|
this.nanoTblAfterFilter.emit({ filters: this.filters });
|
1515
|
+
perMark('filter', true);
|
1160
1516
|
}
|
1161
1517
|
/** Scrolls to the top immediately - used whilst sorting / filtering */
|
1162
1518
|
scrollToTop(element) {
|
@@ -1192,6 +1548,7 @@ const Table = class {
|
|
1192
1548
|
var _a;
|
1193
1549
|
if (!((_a = this.blockElements) === null || _a === void 0 ? void 0 : _a.length))
|
1194
1550
|
return;
|
1551
|
+
perMark('blockDims');
|
1195
1552
|
const testForDimensions = async () => {
|
1196
1553
|
await this.setMeasureElement();
|
1197
1554
|
if (this.unitHeight)
|
@@ -1215,6 +1572,8 @@ const Table = class {
|
|
1215
1572
|
});
|
1216
1573
|
// we're all finished.
|
1217
1574
|
dimensionsReady.then(() => {
|
1575
|
+
perMark('blockDims', true);
|
1576
|
+
perMark('init', true);
|
1218
1577
|
requestAnimationFrame(() => (this.isReady = true));
|
1219
1578
|
});
|
1220
1579
|
}
|
@@ -1237,6 +1596,8 @@ const Table = class {
|
|
1237
1596
|
if (!!col) {
|
1238
1597
|
await this.sortStart(col.order, col.prop);
|
1239
1598
|
}
|
1599
|
+
if (this.tablePinnedService)
|
1600
|
+
this.tablePinnedService.assessCols();
|
1240
1601
|
}
|
1241
1602
|
/** Split up all incoming rows into 'blocks' split amongst tbody elements.
|
1242
1603
|
* These can then be hidden / shown to improve performance.
|
@@ -1247,6 +1608,7 @@ const Table = class {
|
|
1247
1608
|
this.blocks = [];
|
1248
1609
|
return;
|
1249
1610
|
}
|
1611
|
+
perMark('setBlocks');
|
1250
1612
|
// this.ignoreIO = true;
|
1251
1613
|
let i = 1;
|
1252
1614
|
const l = this.virtualTotalItems > dRows.length
|
@@ -1269,6 +1631,7 @@ const Table = class {
|
|
1269
1631
|
blocks.push({ rows, __uuid: math.cyrb53(rows.map((b) => b.__uuid).join()) });
|
1270
1632
|
}
|
1271
1633
|
this.blocks = blocks;
|
1634
|
+
perMark('setBlocks', true);
|
1272
1635
|
}
|
1273
1636
|
/**
|
1274
1637
|
* Returns a block render height.
|
@@ -1281,14 +1644,14 @@ const Table = class {
|
|
1281
1644
|
getBlockHeight(blockIndex) {
|
1282
1645
|
if (this.blockHeights.length) {
|
1283
1646
|
const cachedBlockHeight = this.blockHeights.find((bh) => bh.blockIndex === blockIndex);
|
1284
|
-
if (cachedBlockHeight)
|
1647
|
+
if (cachedBlockHeight && cachedBlockHeight.height)
|
1285
1648
|
return cachedBlockHeight.height;
|
1286
1649
|
}
|
1287
1650
|
const blockLength = this.blocks[blockIndex].rows.length;
|
1288
1651
|
if (blockLength === this.perBlock && this.measureHeight) {
|
1289
1652
|
return this.measureHeight;
|
1290
1653
|
}
|
1291
|
-
return this.unitHeight ? this.unitHeight * blockLength :
|
1654
|
+
return this.unitHeight ? this.unitHeight * blockLength : 100;
|
1292
1655
|
}
|
1293
1656
|
/** cache the height for all active blocks for later renders */
|
1294
1657
|
setBlockHeight() {
|
@@ -1337,10 +1700,13 @@ const Table = class {
|
|
1337
1700
|
}
|
1338
1701
|
// Component lifecycle
|
1339
1702
|
async componentWillLoad() {
|
1703
|
+
perMark('init');
|
1340
1704
|
// setup stores
|
1341
1705
|
this.store = await generateStore(this.host, this.columns, this.scrollParent, this.isReady);
|
1342
1706
|
await this.handleRowsChange();
|
1343
|
-
this.store.general.onChange('isActive',
|
1707
|
+
this.store.general.onChange('isActive', () => {
|
1708
|
+
this.scrollHandler();
|
1709
|
+
});
|
1344
1710
|
this.store.data.onChange('rows', () => this.setBlocks());
|
1345
1711
|
// setup dom and attach listeners
|
1346
1712
|
this.processSlots();
|
@@ -1354,6 +1720,9 @@ const Table = class {
|
|
1354
1720
|
}
|
1355
1721
|
componentDidLoad() {
|
1356
1722
|
this.setInitialBlockDimension();
|
1723
|
+
if (!this.tablePinnedService) {
|
1724
|
+
this.tablePinnedService = new TablePinService(this.tableEle, this.scrollParent);
|
1725
|
+
}
|
1357
1726
|
}
|
1358
1727
|
componentShouldUpdate(_newVal, _oldVal, stateName) {
|
1359
1728
|
// stop double rendering - we use the store for rendering internally
|
@@ -1363,9 +1732,11 @@ const Table = class {
|
|
1363
1732
|
return false;
|
1364
1733
|
}
|
1365
1734
|
componentWillRender() {
|
1735
|
+
perMark('render');
|
1366
1736
|
}
|
1367
1737
|
componentDidRender() {
|
1368
|
-
this.setMeasureElement();
|
1738
|
+
this.setMeasureElement().then(() => this.setBlockHeight());
|
1739
|
+
perMark('render', true);
|
1369
1740
|
}
|
1370
1741
|
disconnectedCallback() {
|
1371
1742
|
if (!this.activeWatcherIo)
|
@@ -1378,28 +1749,31 @@ const Table = class {
|
|
1378
1749
|
}
|
1379
1750
|
render() {
|
1380
1751
|
this.blockElements = [];
|
1381
|
-
return (index.h(index.Host, null, index.h("div", { class: `${CSSNAMESPACE}__top-anchor`, ref: (a) => (this.topAnchorEle = a) }, "\u00A0"), index.h("nano-resize-observe", { states: "576w sm, 768w md", class: "sm md", onNanoResizeStateChange: this.handleResizeChange
|
1752
|
+
return (index.h(index.Host, null, index.h("div", { class: `${CSSNAMESPACE}__top-anchor`, ref: (a) => (this.topAnchorEle = a) }, "\u00A0"), index.h("nano-resize-observe", { states: "576w sm, 768w md", class: "sm md", onNanoResizeStateChange: this.handleResizeChange, onNanoResize: () => {
|
1753
|
+
if (this.tablePinnedService)
|
1754
|
+
this.tablePinnedService.onResize();
|
1755
|
+
} }), index.h("div", { class: `${CSSNAMESPACE}__wrap sm md`, ref: (div) => (this.tableWrapperEle = div), "aria-labelledby": 'nano-table-caption-' + this.renderId, tabindex: this.type === 'grid' ? '0' : undefined }, index.h("nano-progress-bar", { indeterminate: true, class: {
|
1382
1756
|
[`${CSSNAMESPACE}__progress-bar`]: true,
|
1383
1757
|
[`${CSSNAMESPACE}__progress-bar--show`]: this._loading,
|
1384
|
-
} }), index.h("table", { role: this.type === 'grid' ? 'grid' : undefined, "aria-rowcount": this.store.data.state.rows.length, "aria-colcount": this.store.config.state.columns.length, class: `${CSSNAMESPACE}`, ref: (tbl) => (this.tableEle = tbl) }, index.h("caption", { class: {
|
1758
|
+
} }), index.h("table", { role: this.type === 'grid' ? 'grid' : undefined, "aria-rowcount": this.store.data.state.rows.length, "aria-colcount": this.store.config.state.columns.length, class: `${CSSNAMESPACE}`, ref: (tbl) => (this.tableEle = tbl), id: 'nano-table-' + this.renderId }, index.h("caption", { class: {
|
1385
1759
|
[`${CSSNAMESPACE}__caption`]: true,
|
1386
1760
|
[`${CSSNAMESPACE}__caption--hide`]: !this.showCaption,
|
1387
|
-
}, id: 'table-caption-' + this.renderId }, index.h("slot", { name: "caption" }, this.caption)), index.h("thead", null, index.h(TableHeadFootRow, { rowRenderer: this.headRender
|
1388
|
-
index.h(TableColHead, { column: colModel, headRenderer: this.headRender, onColumnSortClick: this.sortStart,
|
1761
|
+
}, id: 'nano-table-caption-' + this.renderId }, index.h("slot", { name: "caption" }, this.caption)), index.h("thead", null, index.h(TableHeadFootRow, { rowRenderer: this.headRender }, this.store.config.state.columns.map((colModel) => [
|
1762
|
+
index.h(TableColHead, { column: colModel, headRenderer: this.headRender, onColumnSortClick: this.sortStart, defaults: {
|
1389
1763
|
sortable: this.defaultSort,
|
1390
1764
|
} }),
|
1391
|
-
]))), this._loading && !this.blocks.length && (index.h("tbody", { class: `${CSSNAMESPACE}__active` }, [...Array(10).keys()].map((rowIndex) => (index.h("tr", null, this.store.config.state.columns.map((_colModel, colIndex) => (index.h(TableCell
|
1765
|
+
]))), this._loading && !this.blocks.length && (index.h("tbody", { class: `${CSSNAMESPACE}__active ${CSSNAMESPACE}__loading` }, [...Array(10).keys()].map((rowIndex) => (index.h("tr", null, this.store.config.state.columns.map((_colModel, colIndex) => (index.h(TableCell, { rowIndex: rowIndex, colIndex: colIndex, nestedContent: () => index.h("nano-skeleton", null) })))))))), index.h("tr", { hidden: !!this._loading || !!this.blocks.length }, index.h("th", { class: `${CSSNAMESPACE}__th`, colSpan: this.store.config.state.columns.length }, index.h("div", { class: "nano-tbl__cell-content nano-tbl__cell-content--no-result" }, index.h("slot", { name: "no-results" }, "No results found")))), this.blocks.map((block, blockIndex) => (index.h("tbody", { key: block.__uuid, id: `tbody-${this.renderId}-${blockIndex}`, ref: (tb) => {
|
1392
1766
|
this.blockElements.push(tb);
|
1393
1767
|
}, class: {
|
1394
1768
|
[`${CSSNAMESPACE}__inactive`]: !this.activeBlocks.includes(blockIndex),
|
1395
1769
|
[`${CSSNAMESPACE}__active`]: this.activeBlocks.includes(blockIndex),
|
1396
1770
|
} }, this.activeBlocks.includes(blockIndex) ? (block.rows.map((row, i) => {
|
1397
1771
|
const rowIndex = blockIndex > 0 ? blockIndex * this.perBlock + i : i;
|
1398
|
-
return (index.h(TableRow, { rowRenderer: this.rowRender, rowModel: row, rowIndex: rowIndex }, this.store.config.state.columns.map((_colModel, colIndex) => (index.h(TableCell
|
1399
|
-
})) : (index.h("tr",
|
1772
|
+
return (index.h(TableRow, { rowRenderer: this.rowRender, rowModel: row, rowIndex: rowIndex }, this.store.config.state.columns.map((_colModel, colIndex) => (index.h(TableCell, { rowIndex: rowIndex, colIndex: colIndex })))));
|
1773
|
+
})) : (index.h("tr", { class: `${CSSNAMESPACE}__tr--placeholder` }, index.h("td", { colSpan: this.store.config.state.columns.length, style: {
|
1400
1774
|
height: this.getBlockHeight(blockIndex) + 'px',
|
1401
|
-
} })))))), this.showFooter && (index.h("tfoot", null, index.h(TableHeadFootRow, { rowRenderer: this.footRender
|
1402
|
-
index.h(TableColHead, { column: colModel, headRenderer: this.footRender,
|
1775
|
+
} })))))), this.showFooter && (index.h("tfoot", null, index.h(TableHeadFootRow, { rowRenderer: this.footRender }, this.store.config.state.columns.map((colModel) => [
|
1776
|
+
index.h(TableColHead, { column: colModel, headRenderer: this.footRender, onColumnSortClick: this.sortStart, defaults: {
|
1403
1777
|
sortable: this.defaultSort,
|
1404
1778
|
} }),
|
1405
1779
|
]))))), !!this.blocks.length && (index.h("nano-spinner", { type: "circle", class: {
|
@@ -1420,4 +1794,4 @@ Table.style = tableCss;
|
|
1420
1794
|
exports.Table = Table;
|
1421
1795
|
exports.createWorker = createWorker;
|
1422
1796
|
|
1423
|
-
//# sourceMappingURL=nano-table-
|
1797
|
+
//# sourceMappingURL=nano-table-04993bb4.js.map
|