schummar-table 0.2.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/dist/cjs/components/cell.d.ts +3 -2
  2. package/dist/cjs/components/cell.js +16 -13
  3. package/dist/cjs/components/columnSelection.js +1 -1
  4. package/dist/cjs/components/expandComponent.js +1 -1
  5. package/dist/cjs/components/export.js +1 -1
  6. package/dist/cjs/components/row.d.ts +3 -2
  7. package/dist/cjs/components/row.js +8 -5
  8. package/dist/cjs/components/textFilterComponent.d.ts +0 -1
  9. package/dist/cjs/components/textFilterComponent.js +0 -1
  10. package/dist/cjs/components/useCommonClasses.d.ts +1 -1
  11. package/dist/cjs/components/useCommonClasses.js +10 -6
  12. package/dist/cjs/components/virtualized.d.ts +1 -1
  13. package/dist/cjs/components/virtualized.js +5 -5
  14. package/dist/cjs/index.d.ts +2 -1
  15. package/dist/cjs/internalState/calcProps.js +23 -6
  16. package/dist/cjs/internalState/tableStateStorage.d.ts +11 -0
  17. package/dist/cjs/internalState/tableStateStorage.js +74 -0
  18. package/dist/cjs/misc/queue.d.ts +6 -0
  19. package/dist/cjs/misc/queue.js +42 -0
  20. package/dist/cjs/table.d.ts +3 -0
  21. package/dist/cjs/table.js +13 -2
  22. package/dist/cjs/types.d.ts +23 -6
  23. package/dist/esm/components/cell.d.ts +3 -2
  24. package/dist/esm/components/cell.js +16 -13
  25. package/dist/esm/components/columnSelection.js +1 -1
  26. package/dist/esm/components/expandComponent.js +1 -1
  27. package/dist/esm/components/export.js +2 -2
  28. package/dist/esm/components/row.d.ts +3 -2
  29. package/dist/esm/components/row.js +8 -5
  30. package/dist/esm/components/textFilterComponent.d.ts +0 -1
  31. package/dist/esm/components/textFilterComponent.js +0 -1
  32. package/dist/esm/components/useCommonClasses.d.ts +1 -1
  33. package/dist/esm/components/useCommonClasses.js +10 -6
  34. package/dist/esm/components/virtualized.d.ts +1 -1
  35. package/dist/esm/components/virtualized.js +5 -5
  36. package/dist/esm/index.d.ts +2 -1
  37. package/dist/esm/internalState/calcProps.js +24 -7
  38. package/dist/esm/internalState/tableStateStorage.d.ts +11 -0
  39. package/dist/esm/internalState/tableStateStorage.js +70 -0
  40. package/dist/esm/misc/queue.d.ts +6 -0
  41. package/dist/esm/misc/queue.js +38 -0
  42. package/dist/esm/table.d.ts +3 -0
  43. package/dist/esm/table.js +11 -1
  44. package/dist/esm/types.d.ts +23 -6
  45. package/package.json +11 -10
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
2
  import { Id } from '..';
3
- export declare const Cell: React.MemoExoticComponent<(<T>({ itemId }: {
3
+ export declare const Cell: React.MemoExoticComponent<(<T>({ itemId, rowIndex }: {
4
4
  itemId: Id;
5
- }) => JSX.Element)>;
5
+ rowIndex: number;
6
+ }) => JSX.Element | null)>;
@@ -7,22 +7,25 @@ const __1 = require("..");
7
7
  const helpers_1 = require("../misc/helpers");
8
8
  const row_1 = require("./row");
9
9
  const useCommonClasses_1 = require("./useCommonClasses");
10
- exports.Cell = (0, react_1.memo)(function Cell({ itemId }) {
10
+ exports.Cell = (0, react_1.memo)(function Cell({ itemId, rowIndex }) {
11
11
  var _a, _b;
12
12
  const commonClasses = (0, useCommonClasses_1.useCommonClasses)();
13
13
  const state = (0, __1.useTableContext)();
14
14
  const columnId = (0, __1.useColumnContext)();
15
- const content = state.useState((state) => {
16
- var _a;
17
- const item = state.activeItemsById.get(itemId);
18
- const column = state.activeColumns.find((column) => column.id === columnId);
19
- if (!item || !column)
20
- return null;
21
- const index = item ? state.activeItems.indexOf(item) : -1;
22
- const className = (0, helpers_1.c)((0, row_1.calcClassName)(state.props.classes, index), (0, row_1.calcClassName)(column === null || column === void 0 ? void 0 : column.classes, index));
23
- const wrapCell = (_a = state.props.wrapCell) !== null && _a !== void 0 ? _a : ((cell) => (0, jsx_runtime_1.jsx)("div", Object.assign({ className: (0, helpers_1.c)(commonClasses.cell, className) }, { children: cell }), void 0));
24
- return wrapCell(column.renderCell(column.value(item), item), item);
25
- }, [itemId, columnId, commonClasses]);
15
+ const column = state.useState((state) => state.activeColumns.find((column) => column.id === columnId), [columnId]);
16
+ const item = state.useState((state) => state.activeItemsById.get(itemId), [itemId]);
17
+ const classes = state.useState('props.classes');
18
+ let wrapCell = state.useState('props.wrapCell');
19
+ if (!column || !item)
20
+ return null;
26
21
  (_b = (_a = state.getState().props).debug) === null || _b === void 0 ? void 0 : _b.call(_a, 'render cell', itemId, columnId);
27
- return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: content }, void 0);
22
+ const className = (0, helpers_1.c)((0, row_1.calcClassName)(classes, item, rowIndex), (0, row_1.calcClassName)(column === null || column === void 0 ? void 0 : column.classes, item, rowIndex));
23
+ const content = column.renderCell(column.value(item), item);
24
+ if (!wrapCell && typeof content === 'string') {
25
+ wrapCell = (content) => ((0, jsx_runtime_1.jsx)("div", Object.assign({ className: (0, helpers_1.c)(commonClasses.cell, className) }, { children: (0, jsx_runtime_1.jsx)("span", Object.assign({ className: (0, helpers_1.c)(commonClasses.text) }, { children: content }), void 0) }), void 0));
26
+ }
27
+ else if (!wrapCell) {
28
+ wrapCell = (content) => (0, jsx_runtime_1.jsx)("div", Object.assign({ className: (0, helpers_1.c)(commonClasses.cell, className) }, { children: content }), void 0);
29
+ }
30
+ return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: wrapCell(content, item) }, void 0);
28
31
  });
@@ -32,6 +32,6 @@ function ColumnSelection() {
32
32
  }
33
33
  onHiddenColumnsChange === null || onHiddenColumnsChange === void 0 ? void 0 : onHiddenColumnsChange(newValue);
34
34
  };
35
- return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(core_1.IconButton, Object.assign({ color: "inherit", onClick: (e) => setAnchor(e.currentTarget) }, { children: (0, jsx_runtime_1.jsx)(icons_1.Settings, {}, void 0) }), void 0), (0, jsx_runtime_1.jsx)(core_1.Popover, Object.assign({ open: !!anchor, onClose: () => setAnchor(null), anchorEl: anchor, anchorOrigin: { vertical: 'bottom', horizontal: 'center' }, transformOrigin: { vertical: 'top', horizontal: 'center' } }, { children: (0, jsx_runtime_1.jsx)("div", Object.assign({ className: classes.list }, { children: columns.map((column) => ((0, jsx_runtime_1.jsx)(core_1.FormControlLabel, { control: (0, jsx_runtime_1.jsx)(core_1.Checkbox, { checked: !hiddenColumns.has(column.id), onChange: () => toggle(column), disabled: column.cannotHide }, void 0), label: column.header }, column.id))) }), void 0) }), void 0)] }, void 0));
35
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(core_1.IconButton, Object.assign({ color: "inherit", size: "small", onClick: (e) => setAnchor(e.currentTarget) }, { children: (0, jsx_runtime_1.jsx)(icons_1.Settings, {}, void 0) }), void 0), (0, jsx_runtime_1.jsx)(core_1.Popover, Object.assign({ open: !!anchor, onClose: () => setAnchor(null), anchorEl: anchor, anchorOrigin: { vertical: 'bottom', horizontal: 'center' }, transformOrigin: { vertical: 'top', horizontal: 'left' } }, { children: (0, jsx_runtime_1.jsx)("div", Object.assign({ className: classes.list }, { children: columns.map((column) => ((0, jsx_runtime_1.jsx)(core_1.FormControlLabel, { control: (0, jsx_runtime_1.jsx)(core_1.Checkbox, { checked: !hiddenColumns.has(column.id), onChange: () => toggle(column), disabled: column.cannotHide }, void 0), label: column.header }, column.id))) }), void 0) }), void 0)] }, void 0));
36
36
  }
37
37
  exports.ColumnSelection = ColumnSelection;
@@ -30,7 +30,7 @@ function ExpandComponent({ itemId }) {
30
30
  });
31
31
  }
32
32
  }
33
- return ((0, jsx_runtime_1.jsx)(core_1.IconButton, Object.assign({ onClick: toggle }, { children: (0, jsx_runtime_1.jsx)(icons_1.ChevronRight, { style: {
33
+ return ((0, jsx_runtime_1.jsx)(core_1.IconButton, Object.assign({ size: "small", onClick: toggle }, { children: (0, jsx_runtime_1.jsx)(icons_1.ChevronRight, { style: {
34
34
  transition: 'all 500ms',
35
35
  transform: isExpanded ? 'rotate3d(0, 0, 1, 90deg)' : 'none',
36
36
  } }, void 0) }), void 0));
@@ -43,6 +43,6 @@ function Export() {
43
43
  a.click();
44
44
  document.body.removeChild(a);
45
45
  };
46
- return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(core_1.IconButton, Object.assign({ color: "inherit", onClick: (e) => setAnchor(e.currentTarget) }, { children: (0, jsx_runtime_1.jsx)(icons_1.GetApp, {}, void 0) }), void 0), (0, jsx_runtime_1.jsx)(core_1.Popover, Object.assign({ open: !!anchor, onClose: () => setAnchor(null), anchorEl: anchor, anchorOrigin: { vertical: 'bottom', horizontal: 'center' }, transformOrigin: { vertical: 'top', horizontal: 'center' } }, { children: (0, jsx_runtime_1.jsxs)("div", Object.assign({ className: classes.dialog }, { children: [(0, jsx_runtime_1.jsx)(core_1.Typography, Object.assign({ variant: "caption" }, { children: textTitle !== null && textTitle !== void 0 ? textTitle : 'Export' }), void 0), (0, jsx_runtime_1.jsx)(core_1.Button, Object.assign({ startIcon: (0, jsx_runtime_1.jsx)(icons_1.AssignmentReturn, {}, void 0), fullWidth: true, onClick: copy }, { children: textCopy !== null && textCopy !== void 0 ? textCopy : 'In die Zwischenablage' }), void 0), (0, jsx_runtime_1.jsx)(core_1.Button, Object.assign({ startIcon: (0, jsx_runtime_1.jsx)(icons_1.CloudDownload, {}, void 0), fullWidth: true, onClick: download }, { children: textDownload !== null && textDownload !== void 0 ? textDownload : 'Herunterladen' }), void 0)] }), void 0) }), void 0)] }, void 0));
46
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(core_1.IconButton, Object.assign({ color: "inherit", size: "small", onClick: (e) => setAnchor(e.currentTarget) }, { children: (0, jsx_runtime_1.jsx)(icons_1.CloudDownload, {}, void 0) }), void 0), (0, jsx_runtime_1.jsx)(core_1.Popover, Object.assign({ open: !!anchor, onClose: () => setAnchor(null), anchorEl: anchor, anchorOrigin: { vertical: 'bottom', horizontal: 'center' }, transformOrigin: { vertical: 'top', horizontal: 'left' } }, { children: (0, jsx_runtime_1.jsxs)("div", Object.assign({ className: classes.dialog }, { children: [(0, jsx_runtime_1.jsx)(core_1.Typography, Object.assign({ variant: "caption" }, { children: textTitle !== null && textTitle !== void 0 ? textTitle : 'Export' }), void 0), (0, jsx_runtime_1.jsx)(core_1.Button, Object.assign({ startIcon: (0, jsx_runtime_1.jsx)(icons_1.AssignmentReturn, {}, void 0), fullWidth: true, onClick: copy }, { children: textCopy !== null && textCopy !== void 0 ? textCopy : 'In die Zwischenablage' }), void 0), (0, jsx_runtime_1.jsx)(core_1.Button, Object.assign({ startIcon: (0, jsx_runtime_1.jsx)(icons_1.CloudDownload, {}, void 0), fullWidth: true, onClick: download }, { children: textDownload !== null && textDownload !== void 0 ? textDownload : 'Herunterladen' }), void 0)] }), void 0) }), void 0)] }, void 0));
47
47
  }
48
48
  exports.Export = Export;
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import { Id, InternalColumn } from '../types';
3
- export declare const calcClassName: (classes: InternalColumn<any, any>['classes'] | undefined, index: number) => string;
4
- export declare const Row: React.MemoExoticComponent<(<T>({ itemId }: {
3
+ export declare function calcClassName<T>(classes: InternalColumn<any, any>['classes'] | undefined, item: T, index: number): string;
4
+ export declare const Row: React.MemoExoticComponent<(<T>({ itemId, rowIndex }: {
5
5
  itemId: Id;
6
+ rowIndex: number;
6
7
  }) => JSX.Element | null)>;
@@ -9,24 +9,27 @@ const cell_1 = require("./cell");
9
9
  const expandComponent_1 = require("./expandComponent");
10
10
  const selectComponent_1 = require("./selectComponent");
11
11
  const useCommonClasses_1 = require("./useCommonClasses");
12
- const calcClassName = (classes, index) => (0, helpers_1.c)(classes === null || classes === void 0 ? void 0 : classes.cell, (classes === null || classes === void 0 ? void 0 : classes.evenCell) === undefined ? undefined : { [classes.evenCell]: index % 2 === 0 }, (classes === null || classes === void 0 ? void 0 : classes.oddCell) === undefined ? undefined : { [classes.oddCell]: index % 2 === 1 });
12
+ function calcClassName(classes, item, index) {
13
+ return (0, helpers_1.c)((classes === null || classes === void 0 ? void 0 : classes.cell) instanceof Function ? classes.cell(item, index) : classes === null || classes === void 0 ? void 0 : classes.cell, (classes === null || classes === void 0 ? void 0 : classes.evenCell) === undefined ? undefined : { [classes.evenCell]: index % 2 === 0 }, (classes === null || classes === void 0 ? void 0 : classes.oddCell) === undefined ? undefined : { [classes.oddCell]: index % 2 === 1 });
14
+ }
13
15
  exports.calcClassName = calcClassName;
14
- exports.Row = (0, react_1.memo)(function Row({ itemId }) {
16
+ exports.Row = (0, react_1.memo)(function Row({ itemId, rowIndex }) {
15
17
  var _a, _b;
16
18
  const commonClasses = (0, useCommonClasses_1.useCommonClasses)();
17
19
  const state = (0, table_1.useTableContext)();
18
20
  const divRef = (0, react_1.useRef)(null);
19
- const { className, indent, hasChildren, hasDeferredChildren, columnIds, enableSelection } = state.useState((state) => {
21
+ const { className, indent, hasChildren, hasDeferredChildren, columnIds, enableSelection, rowAction } = state.useState((state) => {
20
22
  var _a, _b;
21
23
  const item = state.activeItemsById.get(itemId);
22
24
  const index = !item ? -1 : state.activeItems.indexOf(item);
23
25
  return {
24
- className: (0, exports.calcClassName)(state.props.classes, index),
26
+ className: calcClassName(state.props.classes, item, index),
25
27
  indent: item ? (0, helpers_1.getAncestors)(state.activeItemsById, item).size : 0,
26
28
  hasChildren: !!(item === null || item === void 0 ? void 0 : item.children.length),
27
29
  hasDeferredChildren: item && ((_b = (_a = state.props).hasDeferredChildren) === null || _b === void 0 ? void 0 : _b.call(_a, item)),
28
30
  columnIds: state.activeColumns.map((column) => column.id),
29
31
  enableSelection: state.props.enableSelection,
32
+ rowAction: state.props.rowAction instanceof Function ? (item ? state.props.rowAction(item, index) : null) : state.props.rowAction,
30
33
  };
31
34
  }, [itemId]);
32
35
  (0, react_1.useEffect)(() => {
@@ -44,5 +47,5 @@ exports.Row = (0, react_1.memo)(function Row({ itemId }) {
44
47
  return () => o.disconnect();
45
48
  }, [divRef.current]);
46
49
  (_b = (_a = state.getState().props).debug) === null || _b === void 0 ? void 0 : _b.call(_a, 'render row', itemId);
47
- return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: (0, helpers_1.c)(commonClasses.cellFill, className), ref: divRef }, void 0), (0, jsx_runtime_1.jsxs)("div", Object.assign({ className: (0, helpers_1.c)(commonClasses.cell, commonClasses.firstCell, className) }, { children: [(0, jsx_runtime_1.jsx)("div", { style: { width: indent * 20 } }, void 0), enableSelection && (0, jsx_runtime_1.jsx)(selectComponent_1.SelectComponent, { itemId: itemId }, void 0), (hasChildren || hasDeferredChildren) && (0, jsx_runtime_1.jsx)(expandComponent_1.ExpandComponent, { itemId: itemId }, void 0)] }), void 0), columnIds.map((columnId) => ((0, jsx_runtime_1.jsx)(table_1.ColumnContext.Provider, Object.assign({ value: columnId }, { children: (0, jsx_runtime_1.jsx)(cell_1.Cell, { itemId: itemId }, void 0) }), columnId))), (0, jsx_runtime_1.jsx)("div", { className: (0, helpers_1.c)(commonClasses.cellFill, className) }, void 0)] }, void 0));
50
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: (0, helpers_1.c)(commonClasses.cellFill, className), ref: divRef }, void 0), (0, jsx_runtime_1.jsxs)("div", Object.assign({ className: (0, helpers_1.c)(commonClasses.cell, commonClasses.firstCell, className) }, { children: [(0, jsx_runtime_1.jsx)("div", { style: { width: indent * 20 } }, void 0), enableSelection && (0, jsx_runtime_1.jsx)(selectComponent_1.SelectComponent, { itemId: itemId }, void 0), (hasChildren || hasDeferredChildren) && (0, jsx_runtime_1.jsx)(expandComponent_1.ExpandComponent, { itemId: itemId }, void 0), rowAction] }), void 0), columnIds.map((columnId) => ((0, jsx_runtime_1.jsx)(table_1.ColumnContext.Provider, Object.assign({ value: columnId }, { children: (0, jsx_runtime_1.jsx)(cell_1.Cell, { itemId: itemId, rowIndex: rowIndex }, void 0) }), columnId))), (0, jsx_runtime_1.jsx)("div", { className: (0, helpers_1.c)(commonClasses.cellFill, className) }, void 0)] }, void 0));
48
51
  });
@@ -1,5 +1,4 @@
1
1
  /// <reference types="react" />
2
- import '../misc/textMatch';
3
2
  import { Filter } from './filterComponent';
4
3
  export declare class TextFilter<T> implements Filter<T> {
5
4
  readonly query: string;
@@ -6,7 +6,6 @@ const core_1 = require("@material-ui/core");
6
6
  const icons_1 = require("@material-ui/icons");
7
7
  const react_1 = require("react");
8
8
  const helpers_1 = require("../misc/helpers");
9
- require("../misc/textMatch");
10
9
  const textMatch_1 = require("../misc/textMatch");
11
10
  const table_1 = require("../table");
12
11
  class TextFilter {
@@ -1 +1 @@
1
- export declare const useCommonClasses: (props?: any) => import("@material-ui/styles").ClassNameMap<"table" | "cell" | "sticky" | "headerCell" | "cellFill" | "firstCell" | "headerFill" | "deferredPlaceholder">;
1
+ export declare const useCommonClasses: (props?: any) => import("@material-ui/styles").ClassNameMap<"table" | "text" | "cell" | "sticky" | "headerCell" | "cellFill" | "firstCell" | "headerFill" | "deferredPlaceholder">;
@@ -3,14 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useCommonClasses = void 0;
4
4
  const core_1 = require("@material-ui/core");
5
5
  const cell = (theme) => ({
6
- padding: theme.spacing(0.5, 1),
7
- display: 'grid',
8
- gridAutoFlow: 'column',
6
+ padding: theme.spacing(0.1, 1),
7
+ display: 'flex',
9
8
  alignItems: 'center',
10
9
  borderBottom: `1px solid ${theme.palette.grey[200]}`,
11
10
  whiteSpace: 'nowrap',
12
11
  overflow: 'hidden',
13
- textOverflow: 'ellipsis',
14
12
  });
15
13
  exports.useCommonClasses = (0, core_1.makeStyles)((theme) => ({
16
14
  table: {
@@ -21,7 +19,7 @@ exports.useCommonClasses = (0, core_1.makeStyles)((theme) => ({
21
19
  cellFill: {
22
20
  borderBottom: `1px solid ${theme.palette.grey[200]}`,
23
21
  },
24
- headerCell: Object.assign(Object.assign({}, cell(theme)), { borderBottom: 'none', gridTemplateColumns: 'minmax(0, 1fr) max-content', background: theme.palette.primary.main, color: theme.palette.primary.contrastText, fontWeight: 'bold', '&:not(:first-child)': {
22
+ headerCell: Object.assign(Object.assign({}, cell(theme)), { borderBottom: `2px solid ${theme.palette.grey[400]}`, gridTemplateColumns: 'minmax(0, 1fr) max-content', background: theme.palette.common.white, '&:not(:first-child)': {
25
23
  borderLeft: `1px solid ${theme.palette.background.default}`,
26
24
  } }),
27
25
  firstCell: {
@@ -33,7 +31,8 @@ exports.useCommonClasses = (0, core_1.makeStyles)((theme) => ({
33
31
  zIndex: 1,
34
32
  },
35
33
  headerFill: {
36
- background: theme.palette.primary.main,
34
+ borderBottom: `3px solid ${theme.palette.grey[200]}`,
35
+ background: theme.palette.common.white,
37
36
  },
38
37
  deferredPlaceholder: {
39
38
  padding: theme.spacing(1),
@@ -42,4 +41,9 @@ exports.useCommonClasses = (0, core_1.makeStyles)((theme) => ({
42
41
  display: 'grid',
43
42
  justifyContent: 'center',
44
43
  },
44
+ text: {
45
+ minWidth: 0,
46
+ overflow: 'hidden',
47
+ textOverflow: 'ellipsis',
48
+ },
45
49
  }));
@@ -2,5 +2,5 @@ import { HTMLProps, ReactNode } from 'react';
2
2
  import { Id } from '../types';
3
3
  export declare function Virtualized<T>({ header, children, ...props }: {
4
4
  header: ReactNode;
5
- children: (itemIds: Id[]) => ReactNode;
5
+ children: (itemIds: Id[], startIndex: number) => ReactNode;
6
6
  } & HTMLProps<HTMLDivElement>): JSX.Element;
@@ -50,7 +50,7 @@ function Virtualized(_a) {
50
50
  const virtual = state.useState('props.virtual');
51
51
  const probeRef = (0, react_1.useRef)(null);
52
52
  const [counter, setCounter] = (0, react_1.useState)(0);
53
- const { itemIds = [], from, to, before = 0, after = 0, } = state.useState((state) => {
53
+ const { itemIds = [], from = 0, to, before = 0, after = 0, } = state.useState((state) => {
54
54
  var _a;
55
55
  const itemIds = state.activeItems.map((item) => item.id);
56
56
  const root = probeRef.current && findScrollRoot(probeRef.current);
@@ -58,7 +58,7 @@ function Virtualized(_a) {
58
58
  return { itemIds };
59
59
  if (!probeRef.current || !root || !document.contains(root))
60
60
  return {};
61
- const { rowHeight, initalRowHeight } = (_a = (state.props.virtual instanceof Object ? state.props.virtual : undefined)) !== null && _a !== void 0 ? _a : {};
61
+ const { rowHeight, initalRowHeight, overscan = 200, overscanTop, overscanBottom, } = (_a = (state.props.virtual instanceof Object ? state.props.virtual : undefined)) !== null && _a !== void 0 ? _a : {};
62
62
  let totalHeight = 0;
63
63
  const rowHeights = itemIds.map((itemId, index) => {
64
64
  var _a, _b;
@@ -72,13 +72,13 @@ function Virtualized(_a) {
72
72
  const bottomOfTable = topOfTable + root.clientHeight - headerHeight;
73
73
  let from = 0, to = itemIds.length, before = 0, after = 0;
74
74
  for (const h of rowHeights) {
75
- if (before + h > topOfTable)
75
+ if (before + h > topOfTable - (overscanTop !== null && overscanTop !== void 0 ? overscanTop : overscan))
76
76
  break;
77
77
  from++;
78
78
  before += h;
79
79
  }
80
80
  for (const h of rowHeights.reverse()) {
81
- if (after + h > totalHeight - bottomOfTable)
81
+ if (after + h > totalHeight - bottomOfTable - (overscanBottom !== null && overscanBottom !== void 0 ? overscanBottom : overscan))
82
82
  break;
83
83
  to--;
84
84
  after += h;
@@ -93,6 +93,6 @@ function Virtualized(_a) {
93
93
  return onAncestorScroll(probeRef.current, incCounter);
94
94
  }, [probeRef.current, incCounter]);
95
95
  (_e = (_d = state.getState().props).debug) === null || _e === void 0 ? void 0 : _e.call(_d, `Virtualalized render ${from} to ${to}`);
96
- return ((0, jsx_runtime_1.jsxs)("div", Object.assign({}, props, { children: [header, virtual && (0, jsx_runtime_1.jsx)("div", { style: { gridColumn: '1 / -1', height: before }, ref: probeRef }, void 0), children(itemIds), virtual && (0, jsx_runtime_1.jsx)("div", { style: { gridColumn: '1 / -1', height: after } }, void 0)] }), void 0));
96
+ return ((0, jsx_runtime_1.jsxs)("div", Object.assign({}, props, { children: [header, virtual && (0, jsx_runtime_1.jsx)("div", { style: { gridColumn: '1 / -1', height: before }, ref: probeRef }, void 0), children(itemIds, from), virtual && (0, jsx_runtime_1.jsx)("div", { style: { gridColumn: '1 / -1', height: after } }, void 0)] }), void 0));
97
97
  }
98
98
  exports.Virtualized = Virtualized;
@@ -1,5 +1,6 @@
1
1
  export { DefaultFilter, DefaultFilterComponent } from './components/defaultFilterComponent';
2
+ export type { Filter } from './components/filterComponent';
2
3
  export { TextFilter, TextFilterComponent } from './components/textFilterComponent';
3
4
  export { termMatch, textMatch } from './misc/textMatch';
4
5
  export { ColumnContext, Table, TableContext, useColumnContext, useTableContext } from './table';
5
- export type { Column, Id, Rows, Sort, SortDirection, TableProps } from './types';
6
+ export type { Column, Id, InternalColumn, Rows, Sort, SortDirection, TableProps } from './types';
@@ -16,6 +16,7 @@ const react_1 = require("react");
16
16
  const helpers_1 = require("../misc/helpers");
17
17
  const noopParentId = () => undefined;
18
18
  function calcProps(props) {
19
+ const columnCache = (0, react_1.useRef)(new Map());
19
20
  return (0, react_1.useMemo)(() => {
20
21
  var _a, _b;
21
22
  let id;
@@ -40,15 +41,31 @@ function calcProps(props) {
40
41
  inputColumns = props.columns((value, column) => (Object.assign(Object.assign({}, column), { value })));
41
42
  }
42
43
  else {
43
- inputColumns = props.columns;
44
+ inputColumns = props.columns.map((column) => (Object.assign(Object.assign({}, column), { dependecies: undefined })));
44
45
  }
46
+ const newColumnCache = new Map();
45
47
  const columns = inputColumns.map(function (_a, index) {
46
- var { id, header = null, renderCell = helpers_1.asString, exportCell = helpers_1.asString, sortBy = (v) => (typeof v === 'number' || v instanceof Date ? v : String(v)) } = _a, props = __rest(_a, ["id", "header", "renderCell", "exportCell", "sortBy"]);
47
- return Object.assign({ id: id !== null && id !== void 0 ? id : index, header,
48
- renderCell,
49
- exportCell,
50
- sortBy }, props);
48
+ var _b;
49
+ var { id, header = null, renderCell = helpers_1.asString, exportCell = helpers_1.asString, sortBy = (v) => (typeof v === 'number' || v instanceof Date ? v : String(v)), dependencies = [] } = _a, props = __rest(_a, ["id", "header", "renderCell", "exportCell", "sortBy", "dependencies"]);
50
+ const [depsInCache, columnInCache] = (_b = columnCache.current.get(id !== null && id !== void 0 ? id : index)) !== null && _b !== void 0 ? _b : [];
51
+ let column;
52
+ if (depsInCache &&
53
+ columnInCache &&
54
+ depsInCache.length === dependencies.length &&
55
+ depsInCache.every((x, i) => dependencies[i] === x)) {
56
+ column = columnInCache;
57
+ }
58
+ else {
59
+ column = Object.assign({ id: id !== null && id !== void 0 ? id : index, header,
60
+ renderCell,
61
+ exportCell,
62
+ sortBy,
63
+ dependencies }, props);
64
+ }
65
+ newColumnCache.set(id !== null && id !== void 0 ? id : index, [dependencies, column]);
66
+ return column;
51
67
  });
68
+ columnCache.current = newColumnCache;
52
69
  let copy;
53
70
  if (props.enableExport === true || (props.enableExport instanceof Object && props.enableExport.copy === true)) {
54
71
  copy = { separator: '\t' };
@@ -0,0 +1,11 @@
1
+ export declare type TableStateStorage = {
2
+ getItem: (key: string) => string | null | Promise<string | null>;
3
+ setItem: (key: string, value: string) => unknown | Promise<unknown>;
4
+ removeItem: (key: string) => unknown | Promise<unknown>;
5
+ } & ({
6
+ keys: () => string[] | Promise<string[]>;
7
+ } | {
8
+ length: number | (() => number | Promise<number>);
9
+ key: (keyIndex: number) => string | null | Promise<string | null>;
10
+ });
11
+ export declare function useTableStateStorage(): void;
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.useTableStateStorage = void 0;
13
+ const react_1 = require("react");
14
+ const __1 = require("..");
15
+ const queue_1 = require("../misc/queue");
16
+ const KEYS = ['sort', 'selection', 'expanded', 'hiddenColumns'];
17
+ function useTableStateStorage() {
18
+ const state = (0, __1.useTableContext)();
19
+ // On mount: load
20
+ (0, react_1.useEffect)(() => {
21
+ const { storeState, debug } = state.getState().props;
22
+ if (!storeState)
23
+ return;
24
+ let isCanceled = false;
25
+ const q = new queue_1.Queue();
26
+ q.run(() => __awaiter(this, void 0, void 0, function* () {
27
+ try {
28
+ const { storage, id = 'table', include } = storeState;
29
+ const json = yield storage.getItem(`${id}_state`);
30
+ if (isCanceled || !json)
31
+ return;
32
+ const data = JSON.parse(json);
33
+ state.update((state) => {
34
+ for (const key of KEYS) {
35
+ if (!include || include[key]) {
36
+ const value = key === 'sort' ? data.sort : new Set(data[key]);
37
+ state[key] = value;
38
+ }
39
+ }
40
+ });
41
+ }
42
+ catch (e) {
43
+ debug === null || debug === void 0 ? void 0 : debug('Failed to load table state:', e);
44
+ }
45
+ }));
46
+ state.subscribe((state) => {
47
+ if (!state.props.storeState)
48
+ return;
49
+ const data = {};
50
+ for (const key of KEYS) {
51
+ if (!state.props.storeState.include || state.props.storeState.include[key]) {
52
+ const value = key === 'sort' ? state.sort : Array.from(state[key]);
53
+ data[key] = value;
54
+ }
55
+ }
56
+ return {
57
+ storage: state.props.storeState.storage,
58
+ id: state.props.storeState.id,
59
+ data,
60
+ };
61
+ }, (props) => {
62
+ if (!props)
63
+ return;
64
+ const { storage, id = 'table', data } = props;
65
+ q.run(() => __awaiter(this, void 0, void 0, function* () {
66
+ yield storage.setItem(`${id}_state`, JSON.stringify(data));
67
+ }));
68
+ });
69
+ return () => {
70
+ isCanceled = true;
71
+ };
72
+ }, []);
73
+ }
74
+ exports.useTableStateStorage = useTableStateStorage;
@@ -0,0 +1,6 @@
1
+ export declare class Queue {
2
+ private q;
3
+ private isRunning;
4
+ run<T>(job: () => Promise<T>): Promise<T>;
5
+ private start;
6
+ }
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.Queue = void 0;
13
+ class Queue {
14
+ constructor() {
15
+ this.q = new Array();
16
+ this.isRunning = false;
17
+ }
18
+ run(job) {
19
+ return new Promise((resolve, reject) => {
20
+ this.q.push({ job, resolve, reject });
21
+ if (!this.isRunning)
22
+ this.start();
23
+ });
24
+ }
25
+ start() {
26
+ return __awaiter(this, void 0, void 0, function* () {
27
+ this.isRunning = true;
28
+ let next;
29
+ while ((next = this.q.shift())) {
30
+ try {
31
+ const result = yield next.job();
32
+ next.resolve(result);
33
+ }
34
+ catch (e) {
35
+ next.reject(e);
36
+ }
37
+ }
38
+ this.isRunning = false;
39
+ });
40
+ }
41
+ }
42
+ exports.Queue = Queue;
@@ -5,4 +5,7 @@ export declare const TableContext: React.Context<Store<InternalTableState<any>>
5
5
  export declare const ColumnContext: React.Context<Id | null>;
6
6
  export declare function useTableContext<T>(): Store<InternalTableState<T>>;
7
7
  export declare function useColumnContext(): Id;
8
+ declare let defaultProps: Pick<TableProps<unknown>, 'text' | 'classes'>;
9
+ export declare function configureTables(props: typeof defaultProps): void;
8
10
  export declare function Table<T>(props: TableProps<T>): JSX.Element;
11
+ export {};
package/dist/cjs/table.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Table = exports.useColumnContext = exports.useTableContext = exports.ColumnContext = exports.TableContext = void 0;
3
+ exports.Table = exports.configureTables = exports.useColumnContext = exports.useTableContext = exports.ColumnContext = exports.TableContext = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const columnSelection_1 = require("./components/columnSelection");
@@ -11,6 +11,7 @@ const selectComponent_1 = require("./components/selectComponent");
11
11
  const sortComponent_1 = require("./components/sortComponent");
12
12
  const useCommonClasses_1 = require("./components/useCommonClasses");
13
13
  const virtualized_1 = require("./components/virtualized");
14
+ const tableStateStorage_1 = require("./internalState/tableStateStorage");
14
15
  const useTableState_1 = require("./internalState/useTableState");
15
16
  const helpers_1 = require("./misc/helpers");
16
17
  exports.TableContext = (0, react_1.createContext)(null);
@@ -29,8 +30,17 @@ function useColumnContext() {
29
30
  return value;
30
31
  }
31
32
  exports.useColumnContext = useColumnContext;
33
+ let defaultProps = {};
34
+ function configureTables(props) {
35
+ defaultProps = props;
36
+ }
37
+ exports.configureTables = configureTables;
38
+ function mergeProps(props) {
39
+ return Object.assign(Object.assign({}, props), { text: Object.assign(Object.assign({}, defaultProps.text), props.text), classes: Object.assign(Object.assign({}, defaultProps.classes), props.classes) });
40
+ }
32
41
  function Table(props) {
33
42
  var _a, _b;
43
+ props = mergeProps(props);
34
44
  const state = (0, useTableState_1.useTableState)(props);
35
45
  (_b = (_a = state.getState().props).debug) === null || _b === void 0 ? void 0 : _b.call(_a, 'render table');
36
46
  return ((0, jsx_runtime_1.jsx)(exports.TableContext.Provider, Object.assign({ value: state }, { children: (0, jsx_runtime_1.jsx)(TableInner, {}, void 0) }), void 0));
@@ -38,6 +48,7 @@ function Table(props) {
38
48
  exports.Table = Table;
39
49
  const TableInner = (0, react_1.memo)(function TableInner() {
40
50
  var _a, _b;
51
+ (0, tableStateStorage_1.useTableStateStorage)();
41
52
  const commonClasses = (0, useCommonClasses_1.useCommonClasses)();
42
53
  const state = useTableContext();
43
54
  const fullWidth = state.useState('props.fullWidth');
@@ -65,5 +76,5 @@ const TableInner = (0, react_1.memo)(function TableInner() {
65
76
  }, header: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: (0, helpers_1.c)(commonClasses.headerFill, { [commonClasses.sticky]: !!stickyHeader }, classes === null || classes === void 0 ? void 0 : classes.headerCell) }, void 0), (0, jsx_runtime_1.jsxs)("div", Object.assign({ className: (0, helpers_1.c)(commonClasses.headerCell, { [commonClasses.sticky]: !!stickyHeader }, classes === null || classes === void 0 ? void 0 : classes.headerCell) }, { children: [enableSelection && (0, jsx_runtime_1.jsx)(selectComponent_1.SelectComponent, {}, void 0), enableColumnSelection && (0, jsx_runtime_1.jsx)(columnSelection_1.ColumnSelection, {}, void 0), enableExport && (0, jsx_runtime_1.jsx)(export_1.Export, {}, void 0)] }), void 0), activeColumns.map((column) => {
66
77
  var _a;
67
78
  return ((0, jsx_runtime_1.jsx)(exports.ColumnContext.Provider, Object.assign({ value: column.id }, { children: (0, jsx_runtime_1.jsxs)("div", Object.assign({ className: (0, helpers_1.c)(commonClasses.headerCell, { [commonClasses.sticky]: !!stickyHeader }, classes === null || classes === void 0 ? void 0 : classes.headerCell, (_a = column.classes) === null || _a === void 0 ? void 0 : _a.headerCell) }, { children: [(0, jsx_runtime_1.jsx)(sortComponent_1.SortComponent, { children: column.header }, void 0), (0, jsx_runtime_1.jsx)(filterComponent_1.FilterComponent, {}, void 0)] }), column.id) }), column.id));
68
- }), (0, jsx_runtime_1.jsx)("div", { className: (0, helpers_1.c)(commonClasses.headerFill, { [commonClasses.sticky]: !!stickyHeader }, classes === null || classes === void 0 ? void 0 : classes.headerCell) }, void 0)] }, void 0) }, { children: (itemIds) => itemIds.map((itemId) => (0, jsx_runtime_1.jsx)(row_1.Row, { itemId: itemId }, itemId)) }), void 0));
79
+ }), (0, jsx_runtime_1.jsx)("div", { className: (0, helpers_1.c)(commonClasses.headerFill, { [commonClasses.sticky]: !!stickyHeader }, classes === null || classes === void 0 ? void 0 : classes.headerCell) }, void 0)] }, void 0) }, { children: (itemIds, startIndex) => itemIds.map((itemId, index) => (0, jsx_runtime_1.jsx)(row_1.Row, { itemId: itemId, rowIndex: startIndex + index }, itemId)) }), void 0));
69
80
  });
@@ -1,6 +1,7 @@
1
1
  import { CSSProperties, ReactNode } from 'react';
2
2
  import { Filter } from './components/filterComponent';
3
3
  import { CsvExportOptions } from './misc/csvExport';
4
+ import { TableStateStorage } from './internalState/tableStateStorage';
4
5
  export declare type Sort = {
5
6
  columnId: string | number;
6
7
  direction: SortDirection;
@@ -16,6 +17,7 @@ export declare type TableProps<T> = {
16
17
  parentId?: ((item: T) => Id | undefined) | KeyOfType<T, Id | undefined>;
17
18
  hasDeferredChildren?: (item: T) => boolean;
18
19
  columns: Column<T, any>[] | ((col: <V>(value: (item: T) => V, column: Omit<Column<T, V>, 'value'>) => Column<T, V>) => Column<T, any>[]);
20
+ rowAction?: ReactNode | ((item: T, index: number) => ReactNode);
19
21
  defaultSort?: Sort[];
20
22
  sort?: Sort[];
21
23
  onSortChange?: (sort: Sort[]) => void;
@@ -38,17 +40,20 @@ export declare type TableProps<T> = {
38
40
  rowHeight?: number;
39
41
  initalRowHeight?: number;
40
42
  throttleScroll?: number;
43
+ overscan?: number;
44
+ overscanBottom?: number;
45
+ overscanTop?: number;
41
46
  };
42
47
  text?: {
43
- deselectAll?: string;
44
- exportTitle?: string;
45
- exportCopy?: string;
46
- exportDownload?: string;
48
+ deselectAll?: ReactNode;
49
+ exportTitle?: ReactNode;
50
+ exportCopy?: ReactNode;
51
+ exportDownload?: ReactNode;
47
52
  };
48
53
  classes?: {
49
54
  table?: string;
50
55
  headerCell?: string;
51
- cell?: string;
56
+ cell?: string | ((item: T, index: number) => string | undefined);
52
57
  evenCell?: string;
53
58
  oddCell?: string;
54
59
  };
@@ -60,6 +65,16 @@ export declare type TableProps<T> = {
60
65
  copy?: boolean | CsvExportOptions;
61
66
  download?: boolean | CsvExportOptions;
62
67
  };
68
+ storeState?: {
69
+ storage: TableStateStorage;
70
+ id?: string;
71
+ include?: {
72
+ sort?: boolean;
73
+ selection?: boolean;
74
+ expanded?: boolean;
75
+ hiddenColumns?: boolean;
76
+ };
77
+ };
63
78
  };
64
79
  export declare type InternalTableProps<T> = Omit<TableProps<T>, 'id' | 'parentId' | 'columns' | 'enableSelection' | 'enableColumnSelection' | 'enableExport'> & {
65
80
  id: (item: T) => Id;
@@ -93,10 +108,12 @@ export declare type Column<T, V> = {
93
108
  justifyContent?: CSSProperties['justifyContent'];
94
109
  classes?: {
95
110
  headerCell?: string;
96
- cell?: string;
111
+ cell?: string | ((item: T, index: number) => string | undefined);
97
112
  evenCell?: string;
98
113
  oddCell?: string;
99
114
  };
115
+ /** If the column definition changes, supply parameters that it depends on. If not set, the column will not update */
116
+ dependencies?: any[];
100
117
  };
101
118
  export declare type InternalColumn<T, V> = Required<Omit<Column<T, V>, 'id'> & {
102
119
  id: Id;
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
2
  import { Id } from '..';
3
- export declare const Cell: React.MemoExoticComponent<(<T>({ itemId }: {
3
+ export declare const Cell: React.MemoExoticComponent<(<T>({ itemId, rowIndex }: {
4
4
  itemId: Id;
5
- }) => JSX.Element)>;
5
+ rowIndex: number;
6
+ }) => JSX.Element | null)>;