@nanoporetech-digital/components 5.1.3 → 5.2.1
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 +26 -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 +1 -1
- package/dist/cjs/nano-components.cjs.js +1 -1
- package/dist/cjs/nano-datalist_3.cjs.entry.js +1 -1
- package/dist/cjs/nano-dialog.cjs.entry.js +2 -2
- package/dist/cjs/nano-global-nav-user-profile_3.cjs.entry.js +2 -2
- 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 +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 +16 -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-5a7a4d53.js → nano-table-10a40ab3.js} +557 -185
- package/dist/cjs/nano-table-10a40ab3.js.map +1 -0
- package/dist/cjs/nano-table.cjs.entry.js +2 -2
- package/dist/cjs/{table.worker-77e56070.js → table.worker-f04588c1.js} +4 -4
- package/dist/cjs/table.worker-f04588c1.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/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 +0 -1
- package/dist/collection/components/sortable/sortable.js +3 -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 +101 -47
- 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/nano-sortable.js +15 -7
- package/dist/components/nano-sortable.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 +530 -187
- 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 +1 -1
- package/dist/esm/nano-components.js +1 -1
- package/dist/esm/nano-datalist_3.entry.js +1 -1
- package/dist/esm/nano-dialog.entry.js +2 -2
- package/dist/esm/nano-global-nav-user-profile_3.entry.js +2 -2
- 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 +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 +16 -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-026a0d30.js → nano-table-2bbcaa8d.js} +558 -186
- package/dist/esm/nano-table-2bbcaa8d.js.map +1 -0
- package/dist/esm/nano-table.entry.js +2 -2
- package/dist/esm/{table.worker-c17a27ed.js → table.worker-7324ad73.js} +4 -4
- package/dist/esm/table.worker-7324ad73.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-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-39aec880.entry.js +5 -0
- package/dist/nano-components/{p-3b4b7f40.entry.js → p-3eb6d833.entry.js} +2 -2
- package/dist/nano-components/{p-a1c0afb6.entry.js → p-4884b65a.entry.js} +2 -2
- package/dist/nano-components/p-52ae36ec.js +5 -0
- package/dist/nano-components/{p-34501eae.entry.js → p-565793a2.entry.js} +2 -2
- 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-9b533dc3.js +5 -0
- package/dist/nano-components/p-9b533dc3.js.map +1 -0
- 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-9c4efe14.entry.js → p-bf18e298.entry.js} +2 -2
- 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-1a9d9956.entry.js → p-d74e2642.entry.js} +2 -2
- package/dist/nano-components/{p-bd51e29f.js → p-f258383d.js} +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 -8
- 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 +580 -194
- package/package.json +2 -2
- package/dist/cjs/nano-table-5a7a4d53.js.map +0 -1
- package/dist/cjs/table.worker-77e56070.js.map +0 -1
- package/dist/cjs/throttle-f55496c8.js.map +0 -1
- package/dist/esm/nano-table-026a0d30.js.map +0 -1
- package/dist/esm/table.worker-c17a27ed.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-2e63676f.js +0 -5
- package/dist/nano-components/p-30cc21c2.entry.js +0 -5
- package/dist/nano-components/p-59eb9caa.js +0 -5
- package/dist/nano-components/p-59eb9caa.js.map +0 -1
- package/dist/nano-components/p-7759d185.entry.js +0 -5
- package/dist/nano-components/p-7759d185.entry.js.map +0 -1
- package/dist/nano-components/p-7d6065c6.entry.js.map +0 -1
- package/dist/nano-components/p-9746b0a5.js +0 -5
- package/dist/nano-components/p-9746b0a5.js.map +0 -1
- package/dist/nano-components/p-9c4efe14.entry.js.map +0 -1
- /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-2e63676f.js.map → p-39aec880.entry.js.map} +0 -0
- /package/dist/nano-components/{p-3b4b7f40.entry.js.map → p-3eb6d833.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-30cc21c2.entry.js.map → p-52ae36ec.js.map} +0 -0
- /package/dist/nano-components/{p-34501eae.entry.js.map → p-565793a2.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-1a9d9956.entry.js.map → p-d74e2642.entry.js.map} +0 -0
package/dist/components/table.js
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
/*!
|
2
2
|
* Web Components for Nanopore digital Web Apps
|
3
3
|
*/
|
4
|
-
import { consoleError, h, Fragment, getElement, getRenderingRef,
|
4
|
+
import { consoleError, h, Fragment, getElement, getRenderingRef, writeTask, readTask, proxyCustomElement, HTMLElement, createEvent, Host } from '@stencil/core/internal/client';
|
5
5
|
import { a as cyrb53 } from './math.js';
|
6
6
|
import { d as debounce } from './throttle.js';
|
7
7
|
import { c as createStore } from './index2.js';
|
@@ -367,92 +367,6 @@ function colheadFootRender(col) {
|
|
367
367
|
const tpl = col === null || col === void 0 ? void 0 : col.columnTemplate;
|
368
368
|
return tpl ? (tpl(h, col)) : (h(Fragment, null, col.title));
|
369
369
|
}
|
370
|
-
const stickyHIOs = new WeakMap();
|
371
|
-
const stickyVIOs = new WeakMap();
|
372
|
-
/**
|
373
|
-
* Adds element to Intersection Observer. Fires when element changes on the x axis
|
374
|
-
* @param el - an element to observe
|
375
|
-
* @param pos - the edge to watch (start or end)
|
376
|
-
* @param cb - callback when an intersection state changes.
|
377
|
-
*/
|
378
|
-
function addHObserver(el, pos, cb) {
|
379
|
-
if (stickyHIOs.get(el))
|
380
|
-
return;
|
381
|
-
const store = fetchStores();
|
382
|
-
const root = store.general.state.scrollParent;
|
383
|
-
const observer = new IntersectionObserver(([e]) => {
|
384
|
-
const rootBounds = e.rootBounds || document.scrollingElement.getBoundingClientRect();
|
385
|
-
const positions = {};
|
386
|
-
if (pos === 'start') {
|
387
|
-
positions.start =
|
388
|
-
e.boundingClientRect.x - (rootBounds.x + root.scrollLeft) < 0 &&
|
389
|
-
!e.isIntersecting;
|
390
|
-
}
|
391
|
-
if (pos === 'end') {
|
392
|
-
// TODO - sort these out for RtL
|
393
|
-
positions.end =
|
394
|
-
e.boundingClientRect.right > e.boundingClientRect.width &&
|
395
|
-
!e.isIntersecting;
|
396
|
-
}
|
397
|
-
if (!!cb)
|
398
|
-
cb(positions);
|
399
|
-
}, {
|
400
|
-
threshold: [1],
|
401
|
-
rootMargin: '1px 0px 100px 0px',
|
402
|
-
root: root === document.scrollingElement ? null : root,
|
403
|
-
});
|
404
|
-
stickyHIOs.set(el, observer);
|
405
|
-
if (store.general.state.isReady) {
|
406
|
-
observer.observe(el);
|
407
|
-
}
|
408
|
-
else {
|
409
|
-
store.general.state.host.addEventListener('nanoTblReady', () => {
|
410
|
-
observer.observe(el);
|
411
|
-
}, { once: true });
|
412
|
-
}
|
413
|
-
}
|
414
|
-
/**
|
415
|
-
* Adds element to Intersection Observer. Fires when element changes on the y axis
|
416
|
-
* @param el - an element to observe
|
417
|
-
* @param pos - the edge to watch (start or end)
|
418
|
-
* @param cb - callback when an intersection state changes.
|
419
|
-
*/
|
420
|
-
function addVObserver(el, pos, cb) {
|
421
|
-
if (stickyVIOs.get(el))
|
422
|
-
return;
|
423
|
-
const store = fetchStores();
|
424
|
-
const root = store.general.state.scrollParent;
|
425
|
-
const observer = new IntersectionObserver(([e]) => {
|
426
|
-
const rootBounds = e.rootBounds || document.scrollingElement.getBoundingClientRect();
|
427
|
-
const positions = {};
|
428
|
-
if (pos === 'top') {
|
429
|
-
positions.top =
|
430
|
-
e.boundingClientRect.y - (rootBounds.y + root.scrollTop) < 0 &&
|
431
|
-
!e.isIntersecting;
|
432
|
-
}
|
433
|
-
if (pos === 'bottom') {
|
434
|
-
const boundingClientRect = e.target.getBoundingClientRect();
|
435
|
-
positions.bottom =
|
436
|
-
boundingClientRect.height + boundingClientRect.y >
|
437
|
-
rootBounds.height && !e.isIntersecting;
|
438
|
-
}
|
439
|
-
if (!!cb)
|
440
|
-
cb(positions);
|
441
|
-
}, {
|
442
|
-
threshold: [1],
|
443
|
-
rootMargin: '0px 100px 0px 100px',
|
444
|
-
root: root === document.scrollingElement ? null : root,
|
445
|
-
});
|
446
|
-
stickyVIOs.set(el, observer);
|
447
|
-
if (store.general.state.isReady) {
|
448
|
-
observer.observe(el);
|
449
|
-
}
|
450
|
-
else {
|
451
|
-
store.general.state.host.addEventListener('nanoTblReady', () => {
|
452
|
-
observer.observe(el);
|
453
|
-
}, { once: true });
|
454
|
-
}
|
455
|
-
}
|
456
370
|
function headerPinClasses(type, vPinned, toString = false) {
|
457
371
|
const classes = {
|
458
372
|
[`${CSSNAMESPACE}__${type}`]: true,
|
@@ -522,7 +436,7 @@ function isInViewport(el, percentVisible = 100) {
|
|
522
436
|
percentVisible);
|
523
437
|
}
|
524
438
|
|
525
|
-
const TableColHead = ({ column,
|
439
|
+
const TableColHead = ({ column, onColumnSortClick, defaults, }) => {
|
526
440
|
// Sort handling
|
527
441
|
function handleColumnSortClick(e) {
|
528
442
|
let order;
|
@@ -547,7 +461,7 @@ const TableColHead = ({ column, headRenderer, onColumnSortClick, onColumnPinned,
|
|
547
461
|
extraProps = column.columnProperties(column) || extraProps;
|
548
462
|
}
|
549
463
|
const baseProps = {
|
550
|
-
class: Object.assign(Object.assign({}, headerPinClasses('th',
|
464
|
+
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 }),
|
551
465
|
};
|
552
466
|
let props = extraProps ? mergeProperties(baseProps, extraProps) : baseProps;
|
553
467
|
const content = colheadFootRender(column);
|
@@ -564,12 +478,7 @@ const TableColHead = ({ column, headRenderer, onColumnSortClick, onColumnPinned,
|
|
564
478
|
: 'none';
|
565
479
|
props = Object.assign(Object.assign({}, props), { 'aria-sort': sort });
|
566
480
|
}
|
567
|
-
return (h("th", Object.assign({}, props, {
|
568
|
-
if (['end', 'start'].includes(column.pinned))
|
569
|
-
addHObserver(th, column.pinned, onColumnPinned);
|
570
|
-
if (['top', 'bottom'].includes(headRenderer.pinned))
|
571
|
-
addVObserver(th, headRenderer.pinned, onColumnPinned);
|
572
|
-
}, key: column.prop }), isSortable() ? (h("button", { class: {
|
481
|
+
return (h("th", Object.assign({}, props, { key: column.prop }), isSortable() ? (h("button", { class: {
|
573
482
|
[`${CSSNAMESPACE}__order-btn`]: true,
|
574
483
|
[`${CSSNAMESPACE}__cell-content`]: true,
|
575
484
|
}, onClick: handleColumnSortClick },
|
@@ -597,6 +506,7 @@ function cellRender(rowIndex, colIndex) {
|
|
597
506
|
const columns = store.config.state.columns;
|
598
507
|
const tpl = (_a = columns[colIndex]) === null || _a === void 0 ? void 0 : _a.cellTemplate;
|
599
508
|
const model = colDataModel(rowIndex, colIndex);
|
509
|
+
const tableInstance = getRenderingRef();
|
600
510
|
if (!!model.cellModel && columns[colIndex].type === 'date') {
|
601
511
|
const d = new Date(model.cellModel);
|
602
512
|
if (d instanceof Date && !isNaN(d)) {
|
@@ -605,7 +515,28 @@ function cellRender(rowIndex, colIndex) {
|
|
605
515
|
: d;
|
606
516
|
}
|
607
517
|
}
|
608
|
-
|
518
|
+
// Wrap the h pragma, then we can know if we're using Stencil's
|
519
|
+
// jsx renderer or a different one
|
520
|
+
let hCalled = false;
|
521
|
+
const hWrap = (...args) => {
|
522
|
+
hCalled = true;
|
523
|
+
return h(...args);
|
524
|
+
};
|
525
|
+
let tplResult = tpl ? tpl(hWrap, model) : undefined;
|
526
|
+
if (tplResult &&
|
527
|
+
tableInstance.customRenderer &&
|
528
|
+
tplResult['$attrs$'] === undefined &&
|
529
|
+
!(tplResult instanceof Element) &&
|
530
|
+
typeof tplResult !== 'string' &&
|
531
|
+
!hCalled) {
|
532
|
+
// template result is jsx *not* from Stencil.
|
533
|
+
// Render it now and output it later.
|
534
|
+
const templateEle = document.createElement('template');
|
535
|
+
// @ts-expect-error
|
536
|
+
tableInstance.customRenderer(tplResult, templateEle.content);
|
537
|
+
tplResult = templateEle;
|
538
|
+
}
|
539
|
+
return tplResult ? (tplResult) : model.cellModel !== undefined && model.cellModel !== null ? (h(Fragment, null, (_b = model.cellModel) === null || _b === void 0 ? void 0 : _b.toString())) : ('');
|
609
540
|
}
|
610
541
|
const baseCellClasses = (colIndex, toString = false) => {
|
611
542
|
const store = fetchStores();
|
@@ -621,11 +552,12 @@ const baseCellClasses = (colIndex, toString = false) => {
|
|
621
552
|
return classListToStr(classes);
|
622
553
|
return classes;
|
623
554
|
};
|
624
|
-
const TableCell
|
555
|
+
const TableCell = ({ rowIndex, colIndex, nestedContent, }) => {
|
625
556
|
const Content = () => nestedContent
|
626
557
|
? nestedContent()
|
627
558
|
: cellRender(rowIndex, colIndex) || (h("span", { class: "placeholder" }, "\u00A0"));
|
628
559
|
let CellType = 'td';
|
560
|
+
const tableInstance = getRenderingRef();
|
629
561
|
const store = fetchStores();
|
630
562
|
const column = store.config.state.columns[colIndex];
|
631
563
|
let props = mergeCellProperties(rowIndex, colIndex, {
|
@@ -637,14 +569,23 @@ const TableCell$1 = ({ rowIndex, colIndex, nestedContent, }) => {
|
|
637
569
|
? Object.assign(Object.assign({}, props), { scope: 'rowgroup' }) : Object.assign(Object.assign({}, props), { scope: 'row' });
|
638
570
|
CellType = 'th';
|
639
571
|
}
|
640
|
-
const ContentWrap = (props) =>
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
572
|
+
const ContentWrap = (props) => {
|
573
|
+
const content = Content();
|
574
|
+
return (h("div", Object.assign({ ref: (d) => {
|
575
|
+
if (d && content instanceof Element) {
|
576
|
+
d.replaceChildren();
|
577
|
+
d.append(content['content'] || content);
|
578
|
+
}
|
579
|
+
} }, props, { class: {
|
580
|
+
[`${CSSNAMESPACE}__cell-content`]: true,
|
581
|
+
[`${CSSNAMESPACE}__cell-content--wrap`]: !!column.wrap,
|
582
|
+
}, innerHTML: typeof content === 'string' && content.includes('<')
|
583
|
+
? content
|
584
|
+
: undefined }), (typeof content !== 'string' || !content.includes('<')) &&
|
585
|
+
!(content instanceof Element) &&
|
586
|
+
content));
|
587
|
+
};
|
588
|
+
return (h(CellType, Object.assign({ role: tableInstance.type === 'grid' ? 'gridcell' : undefined }, props), column.autoTooltip && !column.wrap ? (h("nano-resize-observe", { notifyContentFit: "x", onNanoResizeContentFitChange: (e) => (e.target.firstElementChild.disabled =
|
648
589
|
e.detail.x) },
|
649
590
|
h("nano-tooltip", { disabled: true, placement: "top", onNanoShow: (e) => (e.target.closest(CellType).style.zIndex = '100'), onNanoHide: (e) => (e.target.closest(CellType).style.zIndex = '') },
|
650
591
|
h(ContentWrap, null),
|
@@ -652,14 +593,18 @@ const TableCell$1 = ({ rowIndex, colIndex, nestedContent, }) => {
|
|
652
593
|
h(Content, null))))) : (h(ContentWrap, null))));
|
653
594
|
};
|
654
595
|
|
655
|
-
const
|
656
|
-
const cell = (h("div", { class: {
|
596
|
+
const tableCellContent = (props, children, ctx) => {
|
597
|
+
const cell = (h("div", Object.assign({}, props.wrapperProps, { class: {
|
657
598
|
[`${CSSNAMESPACE}__cell-content`]: true,
|
658
|
-
[`${CSSNAMESPACE}__cell-content--wrap`]: wrap,
|
659
|
-
} }, children));
|
660
|
-
return header ? h("th", { scope:
|
599
|
+
[`${CSSNAMESPACE}__cell-content--wrap`]: props.wrap,
|
600
|
+
} }), children));
|
601
|
+
return props.header ? (h("th", Object.assign({ scope: ctx }, props.cellProps), cell)) : (h("td", Object.assign({}, props.cellProps), cell));
|
661
602
|
};
|
662
|
-
const TableRow = ({ rowRenderer, rowIndex, rowModel
|
603
|
+
const TableRow = ({ rowRenderer, rowIndex, rowModel }, children, utils) => {
|
604
|
+
// helper, generates <td> or <th>
|
605
|
+
const TableCell = ({ header, wrap, cellProps, wrapperProps }, children) => {
|
606
|
+
return tableCellContent({ header, wrap, cellProps, wrapperProps }, children, 'row');
|
607
|
+
};
|
663
608
|
let extraProps = {};
|
664
609
|
if (!rowModel) {
|
665
610
|
const model = rowDataModel(rowIndex);
|
@@ -669,13 +614,28 @@ const TableRow = ({ rowRenderer, rowIndex, rowModel, onColumnPinned }, children,
|
|
669
614
|
extraProps =
|
670
615
|
rowRenderer.rowProperties({ rowModel, rowIndex }) || extraProps;
|
671
616
|
}
|
672
|
-
let
|
617
|
+
let rowPinned;
|
673
618
|
if ((rowRenderer === null || rowRenderer === void 0 ? void 0 : rowRenderer.pinned) && typeof rowRenderer.pinned === 'function') {
|
674
|
-
|
619
|
+
rowPinned = rowRenderer.pinned({ rowModel, rowIndex });
|
675
620
|
}
|
676
|
-
const
|
677
|
-
const props = extraProps ? mergeProperties(baseProps, extraProps) : baseProps;
|
621
|
+
const props = mergeProperties({ class: headerPinClasses('tr', rowPinned, true) }, extraProps);
|
678
622
|
const tpl = rowRenderer === null || rowRenderer === void 0 ? void 0 : rowRenderer.template;
|
623
|
+
/**
|
624
|
+
* Applies appropriate classes to td / th VNodes;
|
625
|
+
* which can be supplied by user defined templates
|
626
|
+
* @param children virtual / jsx node array
|
627
|
+
* @returns virtual / jsx node array
|
628
|
+
*/
|
629
|
+
const applyCellClasses = (children) => {
|
630
|
+
return utils.map(children, (cNode, i) => {
|
631
|
+
if (['td', 'th'].includes(cNode.vtag.toString())) {
|
632
|
+
cNode.vattrs = mergeProperties({
|
633
|
+
class: baseCellClasses(i, true),
|
634
|
+
}, cNode.vattrs);
|
635
|
+
}
|
636
|
+
return cNode;
|
637
|
+
});
|
638
|
+
};
|
679
639
|
if (tpl) {
|
680
640
|
let toRender = tpl(h, {
|
681
641
|
renderedRow: (h("tr", Object.assign({}, props, { key: rowModel.__uuid }), children)),
|
@@ -687,24 +647,9 @@ const TableRow = ({ rowRenderer, rowIndex, rowModel, onColumnPinned }, children,
|
|
687
647
|
if (node.vtag === 'tr') {
|
688
648
|
if (!node.vkey)
|
689
649
|
node.vkey = `${rowModel.__uuid}_${i}`;
|
690
|
-
node.vattrs = mergeProperties({ class: headerPinClasses('tr',
|
650
|
+
node.vattrs = mergeProperties({ class: headerPinClasses('tr', rowPinned, true) }, node.vattrs);
|
691
651
|
if (!!node.vchildren) {
|
692
|
-
node.vchildren =
|
693
|
-
if (['td', 'th'].includes(cNode.vtag.toString())) {
|
694
|
-
cNode.vattrs = mergeProperties({
|
695
|
-
class: headerPinClasses(cNode.vtag.toString(), pinned, true) + baseCellClasses(i, true),
|
696
|
-
ref: (th) => {
|
697
|
-
if ((!!th && pinned === 'top') || pinned === 'bottom')
|
698
|
-
addVObserver(th, pinned, onColumnPinned);
|
699
|
-
if (!!th && th.classList.contains('nano-tbl__pin--end'))
|
700
|
-
addHObserver(th, 'end', onColumnPinned);
|
701
|
-
if (!!th && th.classList.contains('nano-tbl__pin--start'))
|
702
|
-
addHObserver(th, 'start', onColumnPinned);
|
703
|
-
},
|
704
|
-
}, cNode.vattrs);
|
705
|
-
}
|
706
|
-
return cNode;
|
707
|
-
});
|
652
|
+
node.vchildren = applyCellClasses(node.vchildren);
|
708
653
|
}
|
709
654
|
}
|
710
655
|
return node;
|
@@ -712,28 +657,25 @@ const TableRow = ({ rowRenderer, rowIndex, rowModel, onColumnPinned }, children,
|
|
712
657
|
}
|
713
658
|
return toRender;
|
714
659
|
}
|
715
|
-
return (h("tr", Object.assign({}, props, { key: rowModel.__uuid }), children));
|
660
|
+
return (h("tr", Object.assign({}, props, { key: rowModel.__uuid }), applyCellClasses(children)));
|
716
661
|
};
|
717
|
-
const TableHeadFootRow = ({ rowRenderer
|
662
|
+
const TableHeadFootRow = ({ rowRenderer }, // onRowPinned, onColPinned
|
663
|
+
children, utils) => {
|
718
664
|
let extraProps = {};
|
719
665
|
if (rowRenderer.rowProperties) {
|
720
666
|
extraProps = rowRenderer.rowProperties() || {};
|
721
667
|
}
|
722
|
-
const
|
723
|
-
|
724
|
-
[`${CSSNAMESPACE}__cell-content`]: true,
|
725
|
-
[`${CSSNAMESPACE}__cell-content--wrap`]: wrap,
|
726
|
-
} }, children));
|
727
|
-
return header !== false ? h("th", { scope: "col" }, cell) : h("td", null, cell);
|
668
|
+
const TableHeadFootCell = ({ header, wrap, cellProps, wrapperProps }, children) => {
|
669
|
+
return tableCellContent({ header, wrap, cellProps, wrapperProps }, children, 'col');
|
728
670
|
};
|
729
671
|
const pinned = rowRenderer.pinned || null;
|
730
|
-
const baseProps = { class: headerPinClasses('tr',
|
672
|
+
const baseProps = { class: headerPinClasses('tr', pinned) };
|
731
673
|
const props = extraProps ? mergeProperties(baseProps, extraProps) : baseProps;
|
732
674
|
const tpl = rowRenderer === null || rowRenderer === void 0 ? void 0 : rowRenderer.template;
|
733
675
|
if (tpl) {
|
734
676
|
let toRender = tpl(h, {
|
735
677
|
renderedRow: h("tr", Object.assign({}, props), children),
|
736
|
-
},
|
678
|
+
}, TableHeadFootCell);
|
737
679
|
if (Array.isArray(toRender)) {
|
738
680
|
toRender = utils.map(toRender, (node) => {
|
739
681
|
if (node.vtag === 'tr') {
|
@@ -743,14 +685,6 @@ const TableHeadFootRow = ({ rowRenderer, onColumnPinned }, children, utils) => {
|
|
743
685
|
if (['td', 'th'].includes(cNode.vtag.toString())) {
|
744
686
|
cNode.vattrs = mergeProperties({
|
745
687
|
class: headerPinClasses(cNode.vtag.toString(), pinned, true),
|
746
|
-
ref: (th) => {
|
747
|
-
if ((!!th && pinned === 'top') || pinned === 'bottom')
|
748
|
-
addVObserver(th, pinned, onColumnPinned);
|
749
|
-
if (!!th && th.classList.contains('nano-tbl__pin--end'))
|
750
|
-
addHObserver(th, 'end', onColumnPinned);
|
751
|
-
if (!!th && th.classList.contains('nano-tbl__pin--start'))
|
752
|
-
addHObserver(th, 'start', onColumnPinned);
|
753
|
-
},
|
754
688
|
}, cNode.vattrs);
|
755
689
|
}
|
756
690
|
return cNode;
|
@@ -765,11 +699,388 @@ const TableHeadFootRow = ({ rowRenderer, onColumnPinned }, children, utils) => {
|
|
765
699
|
return h("tr", Object.assign({}, props), children);
|
766
700
|
};
|
767
701
|
|
768
|
-
|
702
|
+
function addStyleSheet(id, css) {
|
703
|
+
const styleSheet = document.getElementById(id) ||
|
704
|
+
document.createElement('style');
|
705
|
+
styleSheet.id = id;
|
706
|
+
styleSheet.innerHTML = css;
|
707
|
+
if (!styleSheet.isConnected)
|
708
|
+
document.head.append(styleSheet);
|
709
|
+
}
|
710
|
+
/**
|
711
|
+
* Manages the complex business of table 'pinning'; sticking columns and rows to the scrolling parent element.
|
712
|
+
*
|
713
|
+
* *knowing* when an element is pinned is tricky.
|
714
|
+
* Managing the display of multiple, side-by-side pinned elements is trickier still.
|
715
|
+
*
|
716
|
+
* Pinning table columns are very different from pinning table rows:
|
717
|
+
* - Rows are actual elements we can select, measure and apply styles to.
|
718
|
+
* - Columns are disparate collections of elements that are much harder to select, measure and apply styles to.
|
719
|
+
*
|
720
|
+
* With this in mind, how columns and rows are pinned is different:
|
721
|
+
* Rows can have changes applied directly, Columns have changes applied via dynamic stylesheets.
|
722
|
+
*
|
723
|
+
* The service is slightly opinionated on how it pins rows and columns (with some room for override):
|
724
|
+
* - Pinned columns are stuck consecutively, without overlapping.
|
725
|
+
* e.g. If column 'name' and 'surname' are both `pin: 'start'`; 'surname' will display **next** to name.
|
726
|
+
* Both columns are important for context
|
727
|
+
*
|
728
|
+
* - Pinned rows are set to overlap *when* they have the same ancestor,
|
729
|
+
* and stuck consecutively when they have a different ancestor.
|
730
|
+
* e.g. `tbody > tr.pin ~ tr.pin` the second row will **overlap** the first; it's unlikely both rows will be important for context.
|
731
|
+
* `thead > tr.pin`, `tbody > tr.pin`. Both rows are required for context so will require next to each other.
|
732
|
+
*
|
733
|
+
* Devs can override this behaviour by setting `--pin-start`, `--pin-end`, `--pin-top`, `--pin-bottom` custom vars.
|
734
|
+
*/
|
735
|
+
class TablePinService {
|
736
|
+
constructor(table, scrollElement) {
|
737
|
+
// Private state
|
738
|
+
this.cachedColMeta = new WeakMap();
|
739
|
+
this._pinnedStart = [];
|
740
|
+
this._pinnedEnd = [];
|
741
|
+
this._cssColDimensionCacheKey = '';
|
742
|
+
this.cacheX = 0;
|
743
|
+
this.cacheY = 0;
|
744
|
+
this.tableEle = table;
|
745
|
+
this.tableId = this.tableEle.id;
|
746
|
+
this.scrollElement = scrollElement;
|
747
|
+
// Secret sauce - `getElementsByClassName` is a live collection.
|
748
|
+
// An HTMLCollection will keep itself up-to-date as elements come and go
|
749
|
+
// So we can keep assessing on scroll
|
750
|
+
this.startColumns = table
|
751
|
+
.querySelector('thead')
|
752
|
+
.getElementsByClassName(`${CSSNAMESPACE}__pin--start`);
|
753
|
+
this.endColumns = table
|
754
|
+
.querySelector('thead')
|
755
|
+
.getElementsByClassName(`${CSSNAMESPACE}__pin--end`);
|
756
|
+
this.topRows = table.getElementsByClassName(`${CSSNAMESPACE}__pin--top`);
|
757
|
+
this.bottomRows = table.getElementsByClassName(`${CSSNAMESPACE}__pin--bottom`);
|
758
|
+
this.onResize();
|
759
|
+
}
|
760
|
+
// Pinned cols & change detection
|
761
|
+
get pinnedStart() {
|
762
|
+
return this._pinnedStart;
|
763
|
+
}
|
764
|
+
set pinnedStart(cols) {
|
765
|
+
this._pinnedStart = cols;
|
766
|
+
this.handlePinnedStartChange();
|
767
|
+
}
|
768
|
+
/**
|
769
|
+
* Called when columns are either pinned or unpinned.
|
770
|
+
* Attaches a tiny stylesheet to target the 'last' start column.
|
771
|
+
* (e.g. We only want to apply drop shadow on last pinned start column - not all pinned columns)
|
772
|
+
*/
|
773
|
+
handlePinnedStartChange() {
|
774
|
+
writeTask(() => {
|
775
|
+
if (this.pinnedStart.length) {
|
776
|
+
this.tableEle.classList.add(`${CSSNAMESPACE}__pinned--start`);
|
777
|
+
const lastActiveCol = this.cachedColMeta.get(this.pinnedStart[this.pinnedStart.length - 1]);
|
778
|
+
addStyleSheet(`${this.tableId}-col-start-active-style`,
|
779
|
+
/* css */ `
|
780
|
+
#${this.tableId} tr > :nth-child(${lastActiveCol.idx + 1}) {
|
781
|
+
--pin-start-active: 1;
|
782
|
+
}
|
783
|
+
`);
|
784
|
+
}
|
785
|
+
else {
|
786
|
+
this.tableEle.classList.remove(`${CSSNAMESPACE}__pinned--start`);
|
787
|
+
addStyleSheet(`${this.tableId}-col-start-active-style`, ``);
|
788
|
+
}
|
789
|
+
});
|
790
|
+
}
|
791
|
+
get pinnedEnd() {
|
792
|
+
return this._pinnedEnd;
|
793
|
+
}
|
794
|
+
set pinnedEnd(cols) {
|
795
|
+
this._pinnedEnd = cols;
|
796
|
+
this.handlePinnedEndChange();
|
797
|
+
}
|
798
|
+
/**
|
799
|
+
* Called when columns are either pinned or unpinned.
|
800
|
+
* Attaches a tiny stylesheet to target the 'first' end column.
|
801
|
+
* (e.g. We only want to apply drop shadow on first pinned end column - not all pinned columns)
|
802
|
+
*/
|
803
|
+
handlePinnedEndChange() {
|
804
|
+
writeTask(() => {
|
805
|
+
if (this.pinnedEnd.length) {
|
806
|
+
this.tableEle.classList.add(`${CSSNAMESPACE}__pinned--end`);
|
807
|
+
const firstActiveCol = this.cachedColMeta.get(this.pinnedEnd[0]);
|
808
|
+
addStyleSheet(`${this.tableId}-col-end-active-style`,
|
809
|
+
/* css */ `
|
810
|
+
#${this.tableId} tr > :nth-child(${firstActiveCol.idx + 1}) { --pin-end-active: 1; }
|
811
|
+
`);
|
812
|
+
}
|
813
|
+
else {
|
814
|
+
this.tableEle.classList.remove(`${CSSNAMESPACE}__pinned--end`);
|
815
|
+
addStyleSheet(`${this.tableId}-col-end-active-style`, ``);
|
816
|
+
}
|
817
|
+
});
|
818
|
+
}
|
819
|
+
get cssColDimensionCacheKey() {
|
820
|
+
return this._cssColDimensionCacheKey;
|
821
|
+
}
|
822
|
+
set cssColDimensionCacheKey(key) {
|
823
|
+
if (key === this._cssColDimensionCacheKey)
|
824
|
+
return;
|
825
|
+
this._cssColDimensionCacheKey = key;
|
826
|
+
this.createPinnedColDimensionStyles();
|
827
|
+
}
|
828
|
+
/**
|
829
|
+
* To only generate column dimension styles when necessary we
|
830
|
+
* maintain a cache key string via serialised column meta.
|
831
|
+
* Only when this key changes do we generate a new stylesheet
|
832
|
+
*/
|
833
|
+
generateCssCacheKey() {
|
834
|
+
let key = '';
|
835
|
+
for (const col of this.startColumns) {
|
836
|
+
const colMeta = this.cachedColMeta.get(col);
|
837
|
+
key += `${colMeta.idx}-start-${colMeta.width}`;
|
838
|
+
}
|
839
|
+
for (const col of this.endColumns) {
|
840
|
+
const colMeta = this.cachedColMeta.get(col);
|
841
|
+
key += `${colMeta.idx}-start-${colMeta.width}`;
|
842
|
+
}
|
843
|
+
this.cssColDimensionCacheKey = key;
|
844
|
+
}
|
845
|
+
/**
|
846
|
+
* Generates pinned column width offset styles
|
847
|
+
* so pinned columns can appear stuck together,
|
848
|
+
* then attaches a stylesheet.
|
849
|
+
*/
|
850
|
+
createPinnedColDimensionStyles() {
|
851
|
+
let widthS = 0;
|
852
|
+
let widthE = 0;
|
853
|
+
const startCols = Array.from(this.startColumns);
|
854
|
+
const endCols = Array.from(this.endColumns).reverse();
|
855
|
+
const css = /* css */ `
|
856
|
+
${startCols
|
857
|
+
.map((col) => {
|
858
|
+
const colMeta = this.cachedColMeta.get(col);
|
859
|
+
widthS += colMeta.width || 0;
|
860
|
+
return /* css */ `
|
861
|
+
#${this.tableId} tr > :nth-child(${colMeta.idx + 1}) ~ td,
|
862
|
+
#${this.tableId} tr > :nth-child(${colMeta.idx + 1}) ~ th {
|
863
|
+
--pin-start: ${widthS - 1}px;
|
864
|
+
}
|
865
|
+
`;
|
866
|
+
})
|
867
|
+
.join('')}
|
868
|
+
${endCols
|
869
|
+
.map((col) => {
|
870
|
+
const colMeta = this.cachedColMeta.get(col);
|
871
|
+
widthE += colMeta.width;
|
872
|
+
return /* css */ `
|
873
|
+
#${this.tableId} tr > td:has(~ :nth-child(${colMeta.idx + 1})),
|
874
|
+
#${this.tableId} tr > th:has(~ :nth-child(${colMeta.idx + 1})) {
|
875
|
+
--pin-end: ${widthE - 1}px;
|
876
|
+
}
|
877
|
+
`;
|
878
|
+
})
|
879
|
+
.join('')}
|
880
|
+
`;
|
881
|
+
addStyleSheet(`${this.tableId}-dimension-style`, css);
|
882
|
+
}
|
883
|
+
getParentOffsets() {
|
884
|
+
const { x, y } = this.scrollElement.getBoundingClientRect();
|
885
|
+
let offsetX = x;
|
886
|
+
let offsetY = y;
|
887
|
+
if (this.scrollElement === document.documentElement) {
|
888
|
+
offsetX = this.scrollElement.offsetLeft;
|
889
|
+
offsetY = this.scrollElement.offsetTop;
|
890
|
+
}
|
891
|
+
return { offsetX, offsetY };
|
892
|
+
}
|
893
|
+
/**
|
894
|
+
* Loops through all 'top' & 'bottom' rows (on scroll or resize)
|
895
|
+
* Manages their visual state by applying classes on stuck / unstuck
|
896
|
+
* And their pinned offset / distance
|
897
|
+
*/
|
898
|
+
assessRows() {
|
899
|
+
if (!this.topRows.length && !this.bottomRows.length)
|
900
|
+
return;
|
901
|
+
// top rows
|
902
|
+
if (this.topRows.length) {
|
903
|
+
readTask(async () => {
|
904
|
+
let heightAggregate = 0;
|
905
|
+
let cacheParent;
|
906
|
+
const { offsetY } = this.getParentOffsets();
|
907
|
+
for (const topRow of this.topRows) {
|
908
|
+
const { y, height } = topRow.getBoundingClientRect();
|
909
|
+
const currParent = topRow.parentElement;
|
910
|
+
// we'll use the applied `--pin-top` css var to decide row offset.
|
911
|
+
// This allows devs to override this behaviour through selector specificity
|
912
|
+
const pinTop = getComputedStyle(topRow).getPropertyValue('--pin-top');
|
913
|
+
const offset = pinTop !== '' ? parseFloat(pinTop) : heightAggregate;
|
914
|
+
// we need to wait for the row to finish sticking
|
915
|
+
// and generating it's offset (`--pin-top`) so we can see, on
|
916
|
+
// subsequent rows *if* the offset was applied
|
917
|
+
await new Promise((resolve) => writeTask(() => {
|
918
|
+
if (y - offsetY <= offset) {
|
919
|
+
topRow.classList.add(`${CSSNAMESPACE}__pinned`, `${CSSNAMESPACE}__pinned--top`);
|
920
|
+
}
|
921
|
+
else {
|
922
|
+
topRow.classList.remove(`${CSSNAMESPACE}__pinned`, `${CSSNAMESPACE}__pinned--top`);
|
923
|
+
}
|
924
|
+
// by default, we only want to stick one row from each parental block (thead, tbody, tfoot)
|
925
|
+
// so only aggregate height / offset when cacheParent is different from current parent.
|
926
|
+
// Devs can override this behaviour by manually setting `--pin-bottom` on the table row
|
927
|
+
if (cacheParent !== currParent) {
|
928
|
+
currParent.style.setProperty('--pin-top', `${heightAggregate}px`);
|
929
|
+
heightAggregate += height;
|
930
|
+
cacheParent = currParent;
|
931
|
+
}
|
932
|
+
resolve();
|
933
|
+
}));
|
934
|
+
}
|
935
|
+
});
|
936
|
+
}
|
937
|
+
// bottom rows
|
938
|
+
if (this.bottomRows.length) {
|
939
|
+
const bottomRows = Array.from(this.bottomRows).reverse();
|
940
|
+
readTask(async () => {
|
941
|
+
let cacheParent;
|
942
|
+
let heightAggregate = 0;
|
943
|
+
const { offsetY } = this.getParentOffsets();
|
944
|
+
for (const bottomRow of bottomRows) {
|
945
|
+
if (!bottomRow.isConnected)
|
946
|
+
continue;
|
947
|
+
const { y, height } = bottomRow.getBoundingClientRect();
|
948
|
+
const currParent = bottomRow.parentElement;
|
949
|
+
// we'll use the applied `--pin-bottom` css var to decide row offset.
|
950
|
+
// This allows devs to override this behaviour through selector specificity
|
951
|
+
const pinBottom = getComputedStyle(bottomRow).getPropertyValue('--pin-bottom');
|
952
|
+
const offset = pinBottom !== '' ? parseFloat(pinBottom) : heightAggregate;
|
953
|
+
// we need to wait for the row to finish sticking
|
954
|
+
// and generating it's offset (`--pin-bottom`) to we can see, on
|
955
|
+
// subsequent rows *if* the offset was applied
|
956
|
+
await new Promise((resolve) => writeTask(() => {
|
957
|
+
if (this.tableDims.height + offsetY - (y + height) <= offset) {
|
958
|
+
bottomRow.classList.add(`${CSSNAMESPACE}__pinned`, `${CSSNAMESPACE}__pinned--bottom`);
|
959
|
+
}
|
960
|
+
else {
|
961
|
+
bottomRow.classList.remove(`${CSSNAMESPACE}__pinned`, `${CSSNAMESPACE}__pinned--bottom`);
|
962
|
+
}
|
963
|
+
// by default, we only want to stick one row from each parental block (thead, tbody, tfoot)
|
964
|
+
// so only aggregate height / offset when cacheParent is different from current parent.
|
965
|
+
// Devs can override this behaviour by manually setting `--pin-bottom` on the table row
|
966
|
+
if (cacheParent !== currParent) {
|
967
|
+
currParent.style.setProperty('--pin-bottom', `${heightAggregate}px`);
|
968
|
+
heightAggregate += height;
|
969
|
+
cacheParent = currParent;
|
970
|
+
}
|
971
|
+
resolve();
|
972
|
+
}));
|
973
|
+
}
|
974
|
+
});
|
975
|
+
}
|
976
|
+
}
|
977
|
+
/**
|
978
|
+
* Loops through all 'start' & 'end' columns (on scroll or resize)
|
979
|
+
* Caches meta about each column (e.g. size, position-index)
|
980
|
+
* and decides which columns are pinned
|
981
|
+
*/
|
982
|
+
async assessCols() {
|
983
|
+
if (!this.startColumns.length && !this.endColumns.length)
|
984
|
+
return;
|
985
|
+
let boundBox;
|
986
|
+
let currPinned;
|
987
|
+
let parentEles;
|
988
|
+
const done = new Promise((resolve) => {
|
989
|
+
// start cols
|
990
|
+
if (this.startColumns.length) {
|
991
|
+
readTask(() => {
|
992
|
+
const { offsetX } = this.getParentOffsets();
|
993
|
+
// cumulatively add widths of columns together
|
994
|
+
// 'cos columns stick together
|
995
|
+
let widthAggregate = offsetX;
|
996
|
+
parentEles = Array.from(this.startColumns[0].parentElement.children);
|
997
|
+
for (const startCol of this.startColumns) {
|
998
|
+
boundBox = startCol.getBoundingClientRect();
|
999
|
+
// cache meta for later
|
1000
|
+
this.cachedColMeta.set(startCol, {
|
1001
|
+
width: boundBox.width,
|
1002
|
+
idx: parentEles.indexOf(startCol),
|
1003
|
+
});
|
1004
|
+
currPinned = this.pinnedStart.find((c) => c === startCol);
|
1005
|
+
if (boundBox.x < widthAggregate) {
|
1006
|
+
// this column is pinned
|
1007
|
+
if (!currPinned)
|
1008
|
+
this.pinnedStart = [
|
1009
|
+
...this.pinnedStart,
|
1010
|
+
startCol,
|
1011
|
+
];
|
1012
|
+
}
|
1013
|
+
else if (currPinned) {
|
1014
|
+
// this column is unpinned
|
1015
|
+
this.pinnedStart = this.pinnedStart.filter((c) => c !== startCol);
|
1016
|
+
}
|
1017
|
+
widthAggregate += boundBox.width;
|
1018
|
+
}
|
1019
|
+
if (!this.endColumns.length)
|
1020
|
+
resolve();
|
1021
|
+
});
|
1022
|
+
}
|
1023
|
+
// end cols
|
1024
|
+
if (this.endColumns.length) {
|
1025
|
+
readTask(() => {
|
1026
|
+
const endCols = Array.from(this.endColumns).reverse();
|
1027
|
+
parentEles = Array.from(this.endColumns[0].parentElement.children);
|
1028
|
+
const { offsetX } = this.getParentOffsets();
|
1029
|
+
// cumulatively add widths of columns together
|
1030
|
+
// 'cos columns stick together
|
1031
|
+
let widthAggregate = 0;
|
1032
|
+
for (const endCol of endCols) {
|
1033
|
+
boundBox = endCol.getBoundingClientRect();
|
1034
|
+
// cache meta for later
|
1035
|
+
this.cachedColMeta.set(endCol, {
|
1036
|
+
width: boundBox.width,
|
1037
|
+
idx: parentEles.indexOf(endCol),
|
1038
|
+
});
|
1039
|
+
currPinned = this.pinnedEnd.find((c) => c === endCol);
|
1040
|
+
if (this.tableDims.width + offsetX - boundBox.right <=
|
1041
|
+
widthAggregate) {
|
1042
|
+
// this column is pinned
|
1043
|
+
if (!currPinned)
|
1044
|
+
this.pinnedEnd = [endCol, ...this.pinnedEnd];
|
1045
|
+
}
|
1046
|
+
else if (currPinned) {
|
1047
|
+
// this column is unpinned
|
1048
|
+
this.pinnedEnd = this.pinnedEnd.filter((c) => c !== endCol);
|
1049
|
+
}
|
1050
|
+
widthAggregate += boundBox.width;
|
1051
|
+
}
|
1052
|
+
resolve();
|
1053
|
+
});
|
1054
|
+
}
|
1055
|
+
});
|
1056
|
+
await done;
|
1057
|
+
// potentially generate a new css stylesheet if anything changed
|
1058
|
+
this.generateCssCacheKey();
|
1059
|
+
}
|
1060
|
+
onScroll(pos) {
|
1061
|
+
if (this.cacheX !== pos.x) {
|
1062
|
+
this.cacheX = pos.x;
|
1063
|
+
this.assessCols();
|
1064
|
+
}
|
1065
|
+
if (this.cacheY !== pos.y) {
|
1066
|
+
this.cacheY = pos.y;
|
1067
|
+
this.assessRows();
|
1068
|
+
}
|
1069
|
+
}
|
1070
|
+
onResize() {
|
1071
|
+
const width = this.scrollElement.clientWidth;
|
1072
|
+
const height = this.scrollElement.clientHeight;
|
1073
|
+
this.tableDims = { width, height };
|
1074
|
+
this.assessCols();
|
1075
|
+
this.assessRows();
|
1076
|
+
}
|
1077
|
+
}
|
1078
|
+
|
1079
|
+
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)}";
|
769
1080
|
|
770
1081
|
const measurePerf = false;
|
771
1082
|
function perMark(name, end = false) {
|
772
|
-
if (!
|
1083
|
+
if (!performance || !measurePerf)
|
773
1084
|
return;
|
774
1085
|
if (end) {
|
775
1086
|
performance === null || performance === void 0 ? void 0 : performance.mark('end' + name);
|
@@ -799,7 +1110,6 @@ const Table = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
|
|
799
1110
|
this.filters = [];
|
800
1111
|
this.currentFilters = '[]';
|
801
1112
|
this.currentSort = '';
|
802
|
-
this.cacheScrollPosition = 0;
|
803
1113
|
this.measureHeight = 0;
|
804
1114
|
this.blockHeights = [];
|
805
1115
|
this.unitHeight = 0;
|
@@ -862,25 +1172,40 @@ const Table = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
|
|
862
1172
|
* stop loop - it's on the current active block.
|
863
1173
|
*/
|
864
1174
|
this.scrollHandler = () => {
|
1175
|
+
var _a;
|
1176
|
+
let scrollPos = 0;
|
1177
|
+
perMark('scrollHandler');
|
865
1178
|
// don't listen if this table isn't in the viewport
|
866
|
-
if (!this.store.general.state.isActive || !this.rows)
|
1179
|
+
if (!((_a = this.store) === null || _a === void 0 ? void 0 : _a.general.state.isActive) || !this.rows)
|
867
1180
|
return;
|
868
1181
|
if (this.primaryBlockIndex === undefined)
|
869
1182
|
this.primaryBlockIndex = 0;
|
870
1183
|
readTask(() => {
|
871
|
-
|
1184
|
+
scrollPos =
|
1185
|
+
typeof this.scrollParent.scrollTop !== 'undefined'
|
1186
|
+
? this.scrollParent.scrollTop
|
1187
|
+
: window.scrollY;
|
1188
|
+
scrollPos += this.host.offsetTop;
|
1189
|
+
if (this.tablePinnedService) {
|
1190
|
+
this.tablePinnedService.onScroll({
|
1191
|
+
x: typeof this.scrollParent.scrollLeft !== 'undefined'
|
1192
|
+
? this.scrollParent.scrollLeft
|
1193
|
+
: window.scrollX,
|
1194
|
+
y: scrollPos,
|
1195
|
+
});
|
1196
|
+
}
|
872
1197
|
let cumulativeHeight = this.host.offsetTop;
|
873
1198
|
let blockIndex = 0;
|
874
1199
|
const blockLen = this.blocks.length;
|
875
|
-
while (blockIndex < blockLen &&
|
876
|
-
this.cacheScrollPosition >= cumulativeHeight) {
|
1200
|
+
while (blockIndex < blockLen && scrollPos >= cumulativeHeight) {
|
877
1201
|
cumulativeHeight += this.getBlockHeight(blockIndex);
|
878
|
-
if (
|
1202
|
+
if (scrollPos < cumulativeHeight) {
|
879
1203
|
const potentialBlocks = [
|
880
1204
|
blockIndex,
|
881
1205
|
blockIndex + 1,
|
882
|
-
Math.max(0, blockIndex - 1),
|
1206
|
+
// Math.max(0, blockIndex - 1),
|
883
1207
|
];
|
1208
|
+
console.log(potentialBlocks);
|
884
1209
|
if (potentialBlocks.toString() !== this.activeBlocks.toString()) {
|
885
1210
|
this.activeBlocks = potentialBlocks;
|
886
1211
|
}
|
@@ -888,11 +1213,7 @@ const Table = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
|
|
888
1213
|
}
|
889
1214
|
blockIndex++;
|
890
1215
|
}
|
891
|
-
|
892
|
-
};
|
893
|
-
this.handleColumnPinned = (positions) => {
|
894
|
-
Object.entries(positions).forEach(([key, applied]) => {
|
895
|
-
this.tableEle.classList.toggle(`${CSSNAMESPACE}__pinned--${key}`, applied);
|
1216
|
+
perMark('scrollHandler', true);
|
896
1217
|
});
|
897
1218
|
};
|
898
1219
|
this.handleResizeChange = (e) => {
|
@@ -903,12 +1224,12 @@ const Table = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
|
|
903
1224
|
classes = [...e.target.className.split(' '), ...classes];
|
904
1225
|
this.tableWrapperEle.classList.add(...classes.filter((cl) => !!cl));
|
905
1226
|
};
|
906
|
-
this.
|
1227
|
+
this.customRenderer = undefined;
|
907
1228
|
this.type = 'table';
|
908
1229
|
this.caption = undefined;
|
909
1230
|
this.showCaption = false;
|
910
1231
|
this.loading = undefined;
|
911
|
-
this.internalLoading =
|
1232
|
+
this.internalLoading = true;
|
912
1233
|
this.placeholderSize = 5;
|
913
1234
|
this.rows = undefined;
|
914
1235
|
this.columns = [];
|
@@ -916,14 +1237,14 @@ const Table = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
|
|
916
1237
|
this.rowRender = undefined;
|
917
1238
|
this.footRender = { pinned: 'bottom' };
|
918
1239
|
this.showFooter = false;
|
919
|
-
this.perBlock =
|
1240
|
+
this.perBlock = 50;
|
920
1241
|
this.searchTerm = undefined;
|
921
1242
|
this.customFilterFn = undefined;
|
922
1243
|
this.customSortFn = undefined;
|
923
1244
|
this.defaultSort = true;
|
924
1245
|
this.virtualTotalItems = 0;
|
925
1246
|
this.blocks = [];
|
926
|
-
this.activeBlocks = [0, 1
|
1247
|
+
this.activeBlocks = [0, 1];
|
927
1248
|
this.debounceSetLoading = debounce(this.debounceSetLoading.bind(this), 50);
|
928
1249
|
}
|
929
1250
|
get _loading() {
|
@@ -952,6 +1273,8 @@ const Table = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
|
|
952
1273
|
if (!this.isReady)
|
953
1274
|
requestAnimationFrame(() => this.setInitialBlockDimension());
|
954
1275
|
this._loading = false;
|
1276
|
+
if (this.tablePinnedService)
|
1277
|
+
this.tablePinnedService.assessRows();
|
955
1278
|
});
|
956
1279
|
}
|
957
1280
|
async handleColsChange() {
|
@@ -969,6 +1292,10 @@ const Table = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
|
|
969
1292
|
virtualTotalItemsChangeHandler() {
|
970
1293
|
this.setBlocks();
|
971
1294
|
}
|
1295
|
+
/** @readonly - shows the currently applied filters */
|
1296
|
+
get appliedFilters() {
|
1297
|
+
return this.filters;
|
1298
|
+
}
|
972
1299
|
/** Remove any column sorts currently applied
|
973
1300
|
* @returns a promise which resolves when complete */
|
974
1301
|
async resetSorting() {
|
@@ -1011,8 +1338,6 @@ const Table = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
|
|
1011
1338
|
}
|
1012
1339
|
/** Updates a row model at a given index
|
1013
1340
|
* @param row - the row to update.
|
1014
|
-
* *Note* - this should come from the `col.cellTemplate` or `row.rowRender.template` `rowModel` property
|
1015
|
-
* - rows are augmented with certain properties to aid with efficient rendering
|
1016
1341
|
* @param rowIndex - the row index to insert this row
|
1017
1342
|
*/
|
1018
1343
|
async updateRow(row, rowIndex) {
|
@@ -1043,7 +1368,9 @@ const Table = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
|
|
1043
1368
|
? document
|
1044
1369
|
: this._scrollParent).removeEventListener('scroll', this.scrollHandler);
|
1045
1370
|
}
|
1046
|
-
(ele === document.documentElement ? document : ele).addEventListener('scroll', this.scrollHandler
|
1371
|
+
(ele === document.documentElement ? document : ele).addEventListener('scroll', this.scrollHandler
|
1372
|
+
// {passive: true}
|
1373
|
+
);
|
1047
1374
|
this._scrollParent = ele;
|
1048
1375
|
}
|
1049
1376
|
// used to fire `nanoTblBlockRendered` on block render change
|
@@ -1146,10 +1473,11 @@ const Table = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
|
|
1146
1473
|
const res = await this.customFilterFn(this.filters);
|
1147
1474
|
// if the response is 'true', the custom filter did it's thing
|
1148
1475
|
// handover to finish and stop loading state.
|
1149
|
-
// if response is
|
1476
|
+
// if response is falsy, carry on to do a FE filter
|
1150
1477
|
if (res === true) {
|
1151
1478
|
this.filterComplete();
|
1152
1479
|
this._loading = false;
|
1480
|
+
return;
|
1153
1481
|
}
|
1154
1482
|
}
|
1155
1483
|
catch (e) {
|
@@ -1158,8 +1486,8 @@ const Table = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
|
|
1158
1486
|
console.warn('custom filter failed', e);
|
1159
1487
|
this.currentFilters = '';
|
1160
1488
|
this._loading = false;
|
1489
|
+
return;
|
1161
1490
|
}
|
1162
|
-
return;
|
1163
1491
|
}
|
1164
1492
|
try {
|
1165
1493
|
await storeFilter(this.host, this.filters);
|
@@ -1175,9 +1503,17 @@ const Table = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
|
|
1175
1503
|
filterComplete() {
|
1176
1504
|
this.columns = this.columns.map((c) => {
|
1177
1505
|
const cFilter = this.filters.find((f) => f.prop === c.prop);
|
1178
|
-
if
|
1506
|
+
// if we found a filter AND
|
1507
|
+
// it isn't true / false and has a length OR
|
1508
|
+
// it is true or false
|
1509
|
+
if (cFilter &&
|
1510
|
+
((typeof cFilter.filter !== 'boolean' && cFilter.filter.length) ||
|
1511
|
+
typeof cFilter.filter === 'boolean'))
|
1179
1512
|
c.filter = cFilter.filter;
|
1180
|
-
|
1513
|
+
// if a filter value is not set OR
|
1514
|
+
// it isn't true / false and has no length
|
1515
|
+
else if ((c.filter !== null && c.filter !== undefined) ||
|
1516
|
+
(!!c.filter && typeof c.filter !== 'boolean' && !c.filter.length))
|
1181
1517
|
c.filter = undefined;
|
1182
1518
|
return c;
|
1183
1519
|
});
|
@@ -1266,6 +1602,8 @@ const Table = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
|
|
1266
1602
|
if (!!col) {
|
1267
1603
|
await this.sortStart(col.order, col.prop);
|
1268
1604
|
}
|
1605
|
+
if (this.tablePinnedService)
|
1606
|
+
this.tablePinnedService.assessCols();
|
1269
1607
|
}
|
1270
1608
|
/** Split up all incoming rows into 'blocks' split amongst tbody elements.
|
1271
1609
|
* These can then be hidden / shown to improve performance.
|
@@ -1388,6 +1726,9 @@ const Table = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
|
|
1388
1726
|
}
|
1389
1727
|
componentDidLoad() {
|
1390
1728
|
this.setInitialBlockDimension();
|
1729
|
+
if (!this.tablePinnedService) {
|
1730
|
+
this.tablePinnedService = new TablePinService(this.tableEle, this.scrollParent);
|
1731
|
+
}
|
1391
1732
|
}
|
1392
1733
|
componentShouldUpdate(_newVal, _oldVal, stateName) {
|
1393
1734
|
// stop double rendering - we use the store for rendering internally
|
@@ -1395,8 +1736,6 @@ const Table = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
|
|
1395
1736
|
// but we don't want it to cause renders
|
1396
1737
|
if (['rows', 'columns'].includes(stateName))
|
1397
1738
|
return false;
|
1398
|
-
if (Build.isDev && !Build.isTesting && measurePerf)
|
1399
|
-
console.log(stateName, _newVal, _oldVal);
|
1400
1739
|
}
|
1401
1740
|
componentWillRender() {
|
1402
1741
|
perMark('render');
|
@@ -1416,28 +1755,31 @@ const Table = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
|
|
1416
1755
|
}
|
1417
1756
|
render() {
|
1418
1757
|
this.blockElements = [];
|
1419
|
-
return (h(Host, null, h("div", { class: `${CSSNAMESPACE}__top-anchor`, ref: (a) => (this.topAnchorEle = a) }, "\u00A0"), h("nano-resize-observe", { states: "576w sm, 768w md", class: "sm md", onNanoResizeStateChange: this.handleResizeChange
|
1758
|
+
return (h(Host, null, h("div", { class: `${CSSNAMESPACE}__top-anchor`, ref: (a) => (this.topAnchorEle = a) }, "\u00A0"), h("nano-resize-observe", { states: "576w sm, 768w md", class: "sm md", onNanoResizeStateChange: this.handleResizeChange, onNanoResize: () => {
|
1759
|
+
if (this.tablePinnedService)
|
1760
|
+
this.tablePinnedService.onResize();
|
1761
|
+
} }), 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 }, h("nano-progress-bar", { indeterminate: true, class: {
|
1420
1762
|
[`${CSSNAMESPACE}__progress-bar`]: true,
|
1421
1763
|
[`${CSSNAMESPACE}__progress-bar--show`]: this._loading,
|
1422
|
-
} }), 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) }, h("caption", { class: {
|
1764
|
+
} }), 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 }, h("caption", { class: {
|
1423
1765
|
[`${CSSNAMESPACE}__caption`]: true,
|
1424
1766
|
[`${CSSNAMESPACE}__caption--hide`]: !this.showCaption,
|
1425
|
-
}, id: 'table-caption-' + this.renderId }, h("slot", { name: "caption" }, this.caption)), h("thead", null, h(TableHeadFootRow, { rowRenderer: this.headRender
|
1426
|
-
h(TableColHead, { column: colModel, headRenderer: this.headRender, onColumnSortClick: this.sortStart,
|
1767
|
+
}, id: 'nano-table-caption-' + this.renderId }, h("slot", { name: "caption" }, this.caption)), h("thead", null, h(TableHeadFootRow, { rowRenderer: this.headRender }, this.store.config.state.columns.map((colModel) => [
|
1768
|
+
h(TableColHead, { column: colModel, headRenderer: this.headRender, onColumnSortClick: this.sortStart, defaults: {
|
1427
1769
|
sortable: this.defaultSort,
|
1428
1770
|
} }),
|
1429
|
-
]))), 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
|
1771
|
+
]))), this._loading && !this.blocks.length && (h("tbody", { class: `${CSSNAMESPACE}__active ${CSSNAMESPACE}__loading` }, [...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) })))))))), h("tr", { hidden: !!this._loading || !!this.blocks.length }, 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) => {
|
1430
1772
|
this.blockElements.push(tb);
|
1431
1773
|
}, class: {
|
1432
1774
|
[`${CSSNAMESPACE}__inactive`]: !this.activeBlocks.includes(blockIndex),
|
1433
1775
|
[`${CSSNAMESPACE}__active`]: this.activeBlocks.includes(blockIndex),
|
1434
1776
|
} }, this.activeBlocks.includes(blockIndex) ? (block.rows.map((row, i) => {
|
1435
1777
|
const rowIndex = blockIndex > 0 ? blockIndex * this.perBlock + i : i;
|
1436
|
-
return (h(TableRow, { rowRenderer: this.rowRender, rowModel: row, rowIndex: rowIndex }, this.store.config.state.columns.map((_colModel, colIndex) => (h(TableCell
|
1437
|
-
})) : (h("tr",
|
1778
|
+
return (h(TableRow, { rowRenderer: this.rowRender, rowModel: row, rowIndex: rowIndex }, this.store.config.state.columns.map((_colModel, colIndex) => (h(TableCell, { rowIndex: rowIndex, colIndex: colIndex })))));
|
1779
|
+
})) : (h("tr", { class: `${CSSNAMESPACE}__tr--placeholder` }, h("td", { colSpan: this.store.config.state.columns.length, style: {
|
1438
1780
|
height: this.getBlockHeight(blockIndex) + 'px',
|
1439
|
-
} })))))), this.showFooter && (h("tfoot", null, h(TableHeadFootRow, { rowRenderer: this.footRender
|
1440
|
-
h(TableColHead, { column: colModel, headRenderer: this.footRender,
|
1781
|
+
} })))))), this.showFooter && (h("tfoot", null, h(TableHeadFootRow, { rowRenderer: this.footRender }, this.store.config.state.columns.map((colModel) => [
|
1782
|
+
h(TableColHead, { column: colModel, headRenderer: this.footRender, onColumnSortClick: this.sortStart, defaults: {
|
1441
1783
|
sortable: this.defaultSort,
|
1442
1784
|
} }),
|
1443
1785
|
]))))), !!this.blocks.length && (h("nano-spinner", { type: "circle", class: {
|
@@ -1454,7 +1796,7 @@ const Table = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
|
|
1454
1796
|
}; }
|
1455
1797
|
static get style() { return tableCss; }
|
1456
1798
|
}, [4, "nano-table", {
|
1457
|
-
"
|
1799
|
+
"customRenderer": [16],
|
1458
1800
|
"type": [1],
|
1459
1801
|
"caption": [1],
|
1460
1802
|
"showCaption": [4, "show-caption"],
|
@@ -1473,6 +1815,7 @@ const Table = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
|
|
1473
1815
|
"customSortFn": [16],
|
1474
1816
|
"defaultSort": [4, "default-sort"],
|
1475
1817
|
"virtualTotalItems": [2, "virtual-total-items"],
|
1818
|
+
"appliedFilters": [2064],
|
1476
1819
|
"internalLoading": [32],
|
1477
1820
|
"blocks": [32],
|
1478
1821
|
"activeBlocks": [32],
|