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