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