schummar-table 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/es/index.js CHANGED
@@ -29,15 +29,43 @@ var __objRest = (source, exclude) => {
29
29
  }
30
30
  return target;
31
31
  };
32
- import { useState, useEffect, useMemo, useRef, createContext, useCallback, memo, useContext, cloneElement, useLayoutEffect, Fragment as Fragment$1 } from "react";
32
+ import { createContext, useContext, useMemo, useState, useEffect, useRef, useCallback, memo, useLayoutEffect, cloneElement, Fragment as Fragment$1 } from "react";
33
33
  import { Store, StoreScope } from "schummar-state/react";
34
- import { d as defaultClasses, a as darkGray, l as lightGray, P as Popover, m as mergeThemes, g as globalTableTheme, T as TableThemeContext, b as PopoverContext, c as gray } from "./tableTheme.js";
34
+ import { d as defaultClasses, a as darkGray, l as lightGray, P as Popover, T as TableThemeContext, m as mergeThemes, g as globalTableTheme, b as PopoverContext, c as gray } from "./tableTheme.js";
35
35
  export { T as TableThemeContext, f as TableThemeProvider, e as configureTableTheme, m as mergeThemes } from "./tableTheme.js";
36
36
  import { jsx, jsxs, Fragment } from "@emotion/react/jsx-runtime";
37
37
  import { useDayzed } from "dayzed";
38
38
  import { castDraft } from "immer";
39
39
  import { css, ClassNames } from "@emotion/react";
40
40
  import "react-dom";
41
+ const TableMemoContext = createContext(/* @__PURE__ */ new Map());
42
+ function TableMemoContextProvider({
43
+ children
44
+ }) {
45
+ return jsx(TableMemoContext.Provider, {
46
+ value: useMemo(() => /* @__PURE__ */ new Map(), []),
47
+ children
48
+ });
49
+ }
50
+ function useTableMemo() {
51
+ const memoCache = useContext(TableMemoContext);
52
+ return (key, fn) => {
53
+ let deps;
54
+ if (Array.isArray(fn)) {
55
+ deps = fn.slice(1);
56
+ fn = fn[0];
57
+ } else {
58
+ deps = [fn.toString()];
59
+ }
60
+ let cachedValue = memoCache.get(key);
61
+ const hit = cachedValue && cachedValue[1].length === deps.length && cachedValue[1].every((x, i) => x === deps[i]);
62
+ if (!cachedValue || !hit) {
63
+ cachedValue = [fn, deps];
64
+ memoCache.set(key, cachedValue);
65
+ }
66
+ return cachedValue[0];
67
+ };
68
+ }
41
69
  class Queue {
42
70
  constructor() {
43
71
  this.q = new Array();
@@ -293,8 +321,10 @@ function calcItems(state) {
293
321
  const column = activeColumns.find((column2) => column2.id === sort2.columnId);
294
322
  if (!column)
295
323
  return [];
296
- const sortBy = column.sortBy instanceof Array ? column.sortBy : [column.sortBy];
297
- return sortBy.map((sortBy2) => ({ selector: (item) => sortBy2(column.value(item), item), direction: sort2.direction }));
324
+ return column.sortBy.map((sortBy) => ({
325
+ selector: (item) => sortBy(column.value(item), item),
326
+ direction: sort2.direction
327
+ }));
298
328
  }).filter(Boolean);
299
329
  sorted = orderBy(tableItems, selectors.map((x) => x.selector), selectors.map((x) => x.direction));
300
330
  }
@@ -366,20 +396,20 @@ function calcItems(state) {
366
396
  }
367
397
  const noopParentId = () => void 0;
368
398
  function calcProps(props) {
369
- const columnCache = useRef(/* @__PURE__ */ new Map());
399
+ const cache = useTableMemo();
370
400
  return useMemo(() => {
371
- var _c, _d, _e, _f, _g, _h;
401
+ var _e, _f, _g, _h, _i, _j;
372
402
  let id;
373
- if (props.id instanceof Function) {
374
- id = props.id;
403
+ if (props.id instanceof Function || Array.isArray(props.id)) {
404
+ id = cache("id", props.id);
375
405
  } else {
376
- id = (item) => item[props.id];
406
+ id = cache("id", [(item) => item[props.id], props.id]);
377
407
  }
378
408
  let parentId;
379
- if (props.parentId instanceof Function) {
380
- parentId = props.parentId;
381
- } else if (typeof props.parentId === "string") {
382
- parentId = (item) => item[props.parentId];
409
+ if (props.parentId instanceof Function || Array.isArray(props.parentId)) {
410
+ parentId = cache("parentId", props.parentId);
411
+ } else if (props.parentId !== void 0) {
412
+ parentId = cache("parentId", [(item) => item[props.parentId], props.parentId]);
383
413
  } else {
384
414
  parentId = noopParentId;
385
415
  }
@@ -389,42 +419,37 @@ function calcProps(props) {
389
419
  } else {
390
420
  inputColumns = props.columns.map((column) => __spreadProps(__spreadValues({}, column), { dependecies: void 0 }));
391
421
  }
392
- const newColumnCache = /* @__PURE__ */ new Map();
393
- const columns = inputColumns.map(function(_a, index) {
394
- var _b = _a, {
422
+ const defCol = props.defaultColumnProps;
423
+ const mapColumn = ({
424
+ id: _id,
425
+ header = ((_a) => (_a = defCol == null ? void 0 : defCol.header) != null ? _a : null)(),
426
+ value,
427
+ renderCell = ((_b) => (_b = defCol == null ? void 0 : defCol.renderCell) != null ? _b : asString)(),
428
+ exportCell = ((_c) => (_c = defCol == null ? void 0 : defCol.exportCell) != null ? _c : asString)(),
429
+ sortBy = ((_d) => (_d = defCol == null ? void 0 : defCol.sortBy) != null ? _d : [(v) => typeof v === "number" || v instanceof Date ? v : String(v)])(),
430
+ cannotHide = defCol == null ? void 0 : defCol.cannotHide,
431
+ classes = defCol == null ? void 0 : defCol.classes,
432
+ filter = defCol == null ? void 0 : defCol.filter,
433
+ width = defCol == null ? void 0 : defCol.width
434
+ }, index) => {
435
+ const id2 = _id != null ? _id : index;
436
+ const cacheKey = typeof id2 === "string" ? `s${id2}` : `n${id2}`;
437
+ return {
395
438
  id: id2,
396
- header = null,
397
- renderCell = asString,
398
- exportCell = asString,
399
- sortBy = (v) => typeof v === "number" || v instanceof Date ? v : String(v),
400
- dependencies = []
401
- } = _b, props2 = __objRest(_b, [
402
- "id",
403
- "header",
404
- "renderCell",
405
- "exportCell",
406
- "sortBy",
407
- "dependencies"
408
- ]);
409
- var _a2;
410
- const [depsInCache, columnInCache] = (_a2 = columnCache.current.get(id2 != null ? id2 : index)) != null ? _a2 : [];
411
- let column;
412
- if (depsInCache && columnInCache && depsInCache.length === dependencies.length && depsInCache.every((x, i) => dependencies[i] === x)) {
413
- column = columnInCache;
414
- } else {
415
- column = __spreadValues({
416
- id: id2 != null ? id2 : index,
417
- header,
418
- renderCell,
419
- exportCell,
420
- sortBy,
421
- dependencies
422
- }, props2);
423
- }
424
- newColumnCache.set(id2 != null ? id2 : index, [dependencies, column]);
425
- return column;
426
- });
427
- columnCache.current = newColumnCache;
439
+ header,
440
+ value: cache(`columns.${cacheKey}.value`, value),
441
+ renderCell: cache(`columns.${cacheKey}.renderCell`, renderCell),
442
+ exportCell,
443
+ sortBy: sortBy.map((fn, i) => cache(`columns.${cacheKey}.sortBy.${i}`, fn)),
444
+ cannotHide,
445
+ classes,
446
+ filter,
447
+ width
448
+ };
449
+ };
450
+ const columns = inputColumns.map(mapColumn);
451
+ const wrapCell = props.wrapCell && cache("wrapCell", props.wrapCell);
452
+ const rowAction = props.rowAction instanceof Function || Array.isArray(props.rowAction) ? cache("rowAction", props.rowAction) : props.rowAction;
428
453
  let copy;
429
454
  if (props.enableExport === true || props.enableExport instanceof Object && props.enableExport.copy === true) {
430
455
  copy = { separator: " " };
@@ -442,13 +467,15 @@ function calcProps(props) {
442
467
  id,
443
468
  parentId,
444
469
  columns,
445
- enableSelection: (_c = props.enableSelection) != null ? _c : true,
446
- selectSyncChildren: (_d = props.selectSyncChildren) != null ? _d : true,
447
- stickyHeader: (_e = props.stickyHeader) != null ? _e : true,
470
+ wrapCell,
471
+ rowAction,
472
+ enableSelection: (_e = props.enableSelection) != null ? _e : true,
473
+ selectSyncChildren: (_f = props.selectSyncChildren) != null ? _f : true,
474
+ stickyHeader: (_g = props.stickyHeader) != null ? _g : true,
448
475
  enableExport,
449
- enableColumnSelection: (_f = props.enableColumnSelection) != null ? _f : true,
450
- enableColumnResize: (_g = props.enableColumnResize) != null ? _g : true,
451
- enableColumnReorder: (_h = props.enableColumnReorder) != null ? _h : true
476
+ enableColumnSelection: (_h = props.enableColumnSelection) != null ? _h : true,
477
+ enableColumnResize: (_i = props.enableColumnResize) != null ? _i : true,
478
+ enableColumnReorder: (_j = props.enableColumnReorder) != null ? _j : true
452
479
  });
453
480
  }, [props]);
454
481
  }
@@ -578,16 +605,15 @@ function useTableState(_props) {
578
605
  return state;
579
606
  }
580
607
  function useCssVariables() {
581
- const theme = useTheme();
582
- return {
583
- "--spacing": theme.spacing,
584
- "--primaryMain": theme.colors.primary.main,
585
- "--primaryLight": theme.colors.primary.light,
586
- "--primaryContrastText": theme.colors.primary.contrastText,
587
- "--secondaryMain": theme.colors.secondary.main,
588
- "--secondaryLight": theme.colors.secondary.light,
589
- "--secondaryContrastText": theme.colors.secondary.contrastText
590
- };
608
+ return useTheme(({ spacing, colors }) => ({
609
+ "--spacing": spacing,
610
+ "--primaryMain": colors.primary.main,
611
+ "--primaryLight": colors.primary.light,
612
+ "--primaryContrastText": colors.primary.contrastText,
613
+ "--secondaryMain": colors.secondary.main,
614
+ "--secondaryLight": colors.secondary.light,
615
+ "--secondaryContrastText": colors.secondary.contrastText
616
+ }));
591
617
  }
592
618
  const ColumnHeaderContext = new StoreScope({
593
619
  items: /* @__PURE__ */ new Map()
@@ -753,17 +779,11 @@ function FormControlLabel({
753
779
  });
754
780
  }
755
781
  function ColumnSelection() {
756
- const {
757
- components: {
758
- IconButton: IconButton2,
759
- Popover: Popover2,
760
- Checkbox: Checkbox2
761
- },
762
- icons: {
763
- Settings: Settings2
764
- },
765
- text
766
- } = useTheme();
782
+ const IconButton2 = useTheme((t) => t.components.IconButton);
783
+ const Popover2 = useTheme((t) => t.components.Popover);
784
+ const Checkbox2 = useTheme((t) => t.components.Checkbox);
785
+ const Settings2 = useTheme((t) => t.icons.Settings);
786
+ const selectColumns = useTheme((t) => t.text.selectColumns);
767
787
  const cssVariables = useCssVariables();
768
788
  const table = useTableContext();
769
789
  const columns = table.useState("props.columns");
@@ -806,7 +826,7 @@ function ColumnSelection() {
806
826
  css: {
807
827
  marginBottom: "var(--spacing)"
808
828
  },
809
- children: text.selectColumns
829
+ children: selectColumns
810
830
  }), columns.map((column) => jsx(FormControlLabel, {
811
831
  control: jsx(Checkbox2, {
812
832
  checked: !hiddenColumns.has(column.id),
@@ -833,18 +853,14 @@ function csvExport(data, { sepPrefix, separator = ",", quote = '"', eol = "\n" }
833
853
  }
834
854
  function Export$1() {
835
855
  const table = useTableContext();
836
- const {
837
- components: {
838
- Button: Button2,
839
- IconButton: IconButton2,
840
- Popover: Popover2
841
- },
842
- icons: {
843
- Export: Export2,
844
- Clipboard: Clipboard2
845
- },
846
- text
847
- } = useTheme();
856
+ const Button2 = useTheme((t) => t.components.Button);
857
+ const IconButton2 = useTheme((t) => t.components.IconButton);
858
+ const Popover2 = useTheme((t) => t.components.Popover);
859
+ const Export2 = useTheme((t) => t.icons.Export);
860
+ const Clipboard2 = useTheme((t) => t.icons.Clipboard);
861
+ const exportTitle = useTheme((t) => t.text.exportTitle);
862
+ const exportCopy = useTheme((t) => t.text.exportCopy);
863
+ const exportDownload = useTheme((t) => t.text.exportDownload);
848
864
  const cssVariables = useCssVariables();
849
865
  const [anchor, setAnchor] = useState(null);
850
866
  const generate = (options) => {
@@ -893,15 +909,15 @@ function Export$1() {
893
909
  css: {
894
910
  marginBottom: "var(--spacing)"
895
911
  },
896
- children: text.exportTitle
912
+ children: exportTitle
897
913
  }), jsx(Button2, {
898
914
  startIcon: jsx(Clipboard2, {}),
899
915
  onClick: copy,
900
- children: text.exportCopy
916
+ children: exportCopy
901
917
  }), jsx(Button2, {
902
918
  startIcon: jsx(Export2, {}),
903
919
  onClick: download,
904
- children: text.exportDownload
920
+ children: exportDownload
905
921
  })]
906
922
  })
907
923
  })]
@@ -911,16 +927,10 @@ const FilterControlContext = createContext(() => void 0);
911
927
  function FilterControl() {
912
928
  const table = useTableContext();
913
929
  const columnId = useColumnContext();
914
- const {
915
- components: {
916
- IconButton: IconButton2,
917
- Popover: Popover2
918
- },
919
- icons: {
920
- FilterList: FilterList2,
921
- ArrowDropDown: ArrowDropDown2
922
- }
923
- } = useTheme();
930
+ const IconButton2 = useTheme((t) => t.components.IconButton);
931
+ const Popover2 = useTheme((t) => t.components.Popover);
932
+ const FilterList2 = useTheme((t) => t.icons.FilterList);
933
+ const ArrowDropDown2 = useTheme((t) => t.icons.ArrowDropDown);
924
934
  const cssVariables = useCssVariables();
925
935
  const [anchor, setAnchor] = useState(null);
926
936
  const isActive = table.useState((state) => {
@@ -1042,49 +1052,56 @@ function ResizeHandleView(_a) {
1042
1052
  }
1043
1053
  }, props));
1044
1054
  }
1055
+ const defaultWrapCell = (content) => {
1056
+ if (typeof content === "string") {
1057
+ return jsx("span", {
1058
+ css: defaultClasses.text,
1059
+ title: content,
1060
+ children: content
1061
+ });
1062
+ }
1063
+ return content;
1064
+ };
1045
1065
  const Cell = memo(function Cell2({
1046
1066
  itemId,
1047
1067
  rowIndex
1048
1068
  }) {
1049
- var _a, _b;
1069
+ var _a;
1050
1070
  const table = useTableContext();
1051
1071
  const columnId = useColumnContext();
1052
- const {
1053
- classes
1054
- } = useTheme();
1055
- const column = table.useState((state) => state.activeColumns.find((column2) => column2.id === columnId));
1072
+ const column = table.useState((state) => {
1073
+ const col = state.activeColumns.find((column2) => column2.id === columnId);
1074
+ return col && {
1075
+ value: col.value,
1076
+ renderCell: col.renderCell
1077
+ };
1078
+ });
1079
+ const wrapCell = (_a = table.useState((state) => state.props.wrapCell)) != null ? _a : defaultWrapCell;
1056
1080
  const item = table.useState((state) => state.activeItemsById.get(itemId));
1057
1081
  const columnStyleOverride = table.useState((state) => state.columnStyleOverride.get(columnId), {
1058
1082
  throttle: 16
1059
1083
  });
1084
+ useLayoutEffect(() => {
1085
+ var _a2, _b;
1086
+ return (_b = (_a2 = table.getState().props).debugRender) == null ? void 0 : _b.call(_a2, "render cell", itemId, columnId);
1087
+ });
1088
+ const className2 = useTheme((t) => cx(...calcClassNames(t.classes, item, rowIndex)));
1060
1089
  if (!column || !item)
1061
1090
  return null;
1062
- (_b = (_a = table.getState().props).debugRender) == null ? void 0 : _b.call(_a, "render cell", itemId, columnId);
1063
- const classNames = [...calcClassNames(classes, item, rowIndex), ...calcClassNames(column == null ? void 0 : column.classes, item, rowIndex)];
1064
1091
  const content = column.renderCell(column.value(item), item);
1065
1092
  return jsx("div", {
1066
- className: cx(...classNames),
1067
- css: [defaultClasses.cell, classNames, columnStyleOverride],
1068
- children: typeof content === "string" ? jsx("span", {
1069
- css: defaultClasses.text,
1070
- title: content,
1071
- children: content
1072
- }) : content
1093
+ className: className2,
1094
+ css: [defaultClasses.cell, columnStyleOverride],
1095
+ children: wrapCell(content, column.value(item), item, rowIndex)
1073
1096
  });
1074
1097
  });
1075
1098
  function ExpandControl({
1076
1099
  itemId,
1077
1100
  hasDeferredChildren
1078
1101
  }) {
1079
- const {
1080
- components: {
1081
- IconButton: IconButton2,
1082
- Spinner: Spinner2
1083
- },
1084
- icons: {
1085
- ChevronRight: ChevronRight2
1086
- }
1087
- } = useTheme();
1102
+ const IconButton2 = useTheme((t) => t.components.IconButton);
1103
+ const Spinner2 = useTheme((t) => t.components.Spinner);
1104
+ const ChevronRight2 = useTheme((t) => t.icons.ChevronRight);
1088
1105
  const table = useTableContext();
1089
1106
  const isExpanded = table.useState((state) => state.expanded.has(itemId));
1090
1107
  const hasChildren = table.useState((state) => {
@@ -1143,11 +1160,7 @@ function SelectComponent({
1143
1160
  itemId
1144
1161
  }) {
1145
1162
  const table = useTableContext();
1146
- const {
1147
- components: {
1148
- Checkbox: Checkbox2
1149
- }
1150
- } = useTheme();
1163
+ const Checkbox2 = useTheme((t) => t.components.Checkbox);
1151
1164
  const isSelected = table.useState((state) => {
1152
1165
  const itemIds = itemId ? [itemId] : Array.from(state.activeItemsById.keys());
1153
1166
  return state.activeItemsById.size > 0 && itemIds.every((itemId2) => state.selection.has(itemId2));
@@ -1215,9 +1228,9 @@ const Row = memo(function Row2({
1215
1228
  itemId,
1216
1229
  rowIndex
1217
1230
  }) {
1218
- var _a, _b;
1219
1231
  const table = useTableContext();
1220
1232
  const divRef = useRef(null);
1233
+ const classes = useTheme((t) => t.classes);
1221
1234
  const {
1222
1235
  className: className2,
1223
1236
  indent,
@@ -1227,17 +1240,16 @@ const Row = memo(function Row2({
1227
1240
  enableSelection,
1228
1241
  rowAction
1229
1242
  } = table.useState((state) => {
1230
- var _a2, _b2;
1243
+ var _a, _b;
1231
1244
  const item = state.activeItemsById.get(itemId);
1232
- const index = !item ? -1 : state.activeItems.indexOf(item);
1233
1245
  return {
1234
- className: cx(...calcClassNames(state.props.classes, item, index)),
1246
+ className: cx(...calcClassNames(classes, item, rowIndex)),
1235
1247
  indent: item ? getAncestors(state.activeItemsById, item).size : 0,
1236
1248
  hasChildren: !!(item == null ? void 0 : item.children.length),
1237
- hasDeferredChildren: item && ((_b2 = (_a2 = state.props).hasDeferredChildren) == null ? void 0 : _b2.call(_a2, item)),
1249
+ hasDeferredChildren: item && ((_b = (_a = state.props).hasDeferredChildren) == null ? void 0 : _b.call(_a, item)),
1238
1250
  columnIds: state.activeColumns.map((column) => column.id),
1239
1251
  enableSelection: state.props.enableSelection,
1240
- rowAction: state.props.rowAction instanceof Function ? item ? state.props.rowAction(item, index) : null : state.props.rowAction
1252
+ rowAction: state.props.rowAction instanceof Function ? item ? state.props.rowAction(item, rowIndex) : null : state.props.rowAction
1241
1253
  };
1242
1254
  });
1243
1255
  useEffect(() => {
@@ -1254,7 +1266,10 @@ const Row = memo(function Row2({
1254
1266
  o.observe(div);
1255
1267
  return () => o.disconnect();
1256
1268
  }, [divRef.current]);
1257
- (_b = (_a = table.getState().props).debugRender) == null ? void 0 : _b.call(_a, "render row", itemId);
1269
+ useLayoutEffect(() => {
1270
+ var _a, _b;
1271
+ return (_b = (_a = table.getState().props).debugRender) == null ? void 0 : _b.call(_a, "render row", itemId);
1272
+ });
1258
1273
  return jsxs(Fragment, {
1259
1274
  children: [jsx("div", {
1260
1275
  className: className2,
@@ -1290,14 +1305,8 @@ function SortComponent({
1290
1305
  }) {
1291
1306
  const table = useTableContext();
1292
1307
  const columnId = useColumnContext();
1293
- const {
1294
- components: {
1295
- Badge: Badge2
1296
- },
1297
- icons: {
1298
- ArrowUpward: ArrowUpward2
1299
- }
1300
- } = useTheme();
1308
+ const Badge2 = useTheme((t) => t.components.Badge);
1309
+ const ArrowUpward2 = useTheme((t) => t.icons.ArrowUpward);
1301
1310
  const {
1302
1311
  direction,
1303
1312
  index
@@ -1391,6 +1400,11 @@ function throttle(fn, ms) {
1391
1400
  if (lastArgs) {
1392
1401
  run();
1393
1402
  }
1403
+ },
1404
+ cancel() {
1405
+ if (timeout) {
1406
+ clearTimeout(timeout);
1407
+ }
1394
1408
  }
1395
1409
  });
1396
1410
  }
@@ -1417,7 +1431,7 @@ function Virtualized(_c) {
1417
1431
  "header",
1418
1432
  "children"
1419
1433
  ]);
1420
- var _a, _b, _c2, _d2;
1434
+ var _a, _b;
1421
1435
  const table = useTableContext();
1422
1436
  const virtual = table.useState("props.virtual");
1423
1437
  const probeRef = useRef(null);
@@ -1491,7 +1505,11 @@ function Virtualized(_c) {
1491
1505
  window.removeEventListener("resize", incCounter, true);
1492
1506
  };
1493
1507
  }, [probeRef.current, incCounter]);
1494
- (_d2 = (_c2 = table.getState().props).debugRender) == null ? void 0 : _d2.call(_c2, `Virtualalized render ${from} to ${to}`);
1508
+ useEffect(() => incCounter.cancel, [incCounter]);
1509
+ useLayoutEffect(() => {
1510
+ var _a2, _b2;
1511
+ return (_b2 = (_a2 = table.getState().props).debugRender) == null ? void 0 : _b2.call(_a2, `Virtualalized render ${from} to ${to}`);
1512
+ });
1495
1513
  return jsxs("div", __spreadProps(__spreadValues({}, props), {
1496
1514
  children: [header, virtual && jsx("div", {
1497
1515
  style: {
@@ -1522,18 +1540,20 @@ function useColumnContext() {
1522
1540
  return value;
1523
1541
  }
1524
1542
  function Table(props) {
1525
- var _a, _b;
1526
1543
  const table = useTableState(props);
1527
- (_b = (_a = table.getState().props).debugRender) == null ? void 0 : _b.call(_a, "render table");
1544
+ useLayoutEffect(() => {
1545
+ var _a, _b;
1546
+ return (_b = (_a = table.getState().props).debugRender) == null ? void 0 : _b.call(_a, "render table");
1547
+ });
1528
1548
  return jsx(TableContext.Provider, {
1529
1549
  value: table,
1530
- children: jsx(TableLoadingState, {})
1550
+ children: jsx(TableMemoContextProvider, {
1551
+ children: jsx(TableLoadingState, {})
1552
+ })
1531
1553
  });
1532
1554
  }
1533
1555
  function TableLoadingState() {
1534
- const {
1535
- text
1536
- } = useTheme();
1556
+ const loadingText = useTheme((t) => t.text.loading);
1537
1557
  const isHydrated = useTableStateStorage();
1538
1558
  const [showLoading, setShowLoading] = useState(false);
1539
1559
  useEffect(() => {
@@ -1542,7 +1562,7 @@ function TableLoadingState() {
1542
1562
  });
1543
1563
  return jsxs(Fragment, {
1544
1564
  children: [!isHydrated && showLoading && jsx("div", {
1545
- children: text.loading
1565
+ children: loadingText
1546
1566
  }), jsx(TableInner, {
1547
1567
  hidden: !isHydrated
1548
1568
  })]
@@ -1551,7 +1571,6 @@ function TableLoadingState() {
1551
1571
  const TableInner = memo(function TableInner2({
1552
1572
  hidden
1553
1573
  }) {
1554
- var _a, _b;
1555
1574
  const table = useTableContext();
1556
1575
  const fullWidth = table.useState("props.fullWidth");
1557
1576
  const activeColumns = table.useState((state) => state.activeColumns.map((column) => ({
@@ -1566,14 +1585,16 @@ const TableInner = memo(function TableInner2({
1566
1585
  const columnStyleOverride = table.useState("columnStyleOverride", {
1567
1586
  throttle: 16
1568
1587
  });
1569
- const defaultWidth = table.useState("props.defaultWidth");
1570
1588
  const classes = table.useState("props.classes");
1571
1589
  const stickyHeader = table.useState("props.stickyHeader");
1572
1590
  const enableSelection = table.useState("props.enableSelection");
1573
1591
  const enableColumnSelection = table.useState("props.enableColumnSelection");
1574
1592
  const enableExport = table.useState((state) => !!state.props.enableExport.copy || !!state.props.enableExport.download);
1575
1593
  const cssVariables = useCssVariables();
1576
- (_b = (_a = table.getState().props).debugRender) == null ? void 0 : _b.call(_a, "render table inner");
1594
+ useLayoutEffect(() => {
1595
+ var _a, _b;
1596
+ return (_b = (_a = table.getState().props).debugRender) == null ? void 0 : _b.call(_a, "render table inner");
1597
+ });
1577
1598
  return jsx(Virtualized, {
1578
1599
  className: classes == null ? void 0 : classes.table,
1579
1600
  css: [cssVariables, defaultClasses.table, {
@@ -1581,8 +1602,8 @@ const TableInner = memo(function TableInner2({
1581
1602
  fullWidth === "right" || fullWidth === true ? "auto" : "0",
1582
1603
  "max-content",
1583
1604
  ...activeColumns.map((column) => {
1584
- var _a2, _b2, _c;
1585
- return (_c = (_b2 = (_a2 = columnWidths.get(column.id)) != null ? _a2 : column.width) != null ? _b2 : defaultWidth) != null ? _c : "max-content";
1605
+ var _a, _b;
1606
+ return (_b = (_a = columnWidths.get(column.id)) != null ? _a : column.width) != null ? _b : "max-content";
1586
1607
  }),
1587
1608
  fullWidth === "left" || fullWidth === true ? "auto" : "0"
1588
1609
  ].join(" ")
@@ -1599,11 +1620,11 @@ const TableInner = memo(function TableInner2({
1599
1620
  children: [enableSelection && jsx(SelectComponent, {}), enableColumnSelection && jsx(ColumnSelection, {}), enableExport && jsx(Export$1, {}), jsx(ResizeHandleView, {})]
1600
1621
  }), jsx(ColumnHeaderContext.Provider, {
1601
1622
  children: activeColumns.map((column) => {
1602
- var _a2;
1623
+ var _a;
1603
1624
  return jsx(ColumnContext.Provider, {
1604
1625
  value: column.id,
1605
1626
  children: jsxs(ColumnHeader, {
1606
- className: cx(classes == null ? void 0 : classes.headerCell, (_a2 = column.classes) == null ? void 0 : _a2.headerCell),
1627
+ className: cx(classes == null ? void 0 : classes.headerCell, (_a = column.classes) == null ? void 0 : _a.headerCell),
1607
1628
  css: [defaultClasses.headerCell, columnStyleOverride.get(column.id), stickyHeader && defaultClasses.sticky, stickyHeader instanceof Object && stickyHeader],
1608
1629
  children: [jsx(SortComponent, {
1609
1630
  children: column.header
@@ -2061,26 +2082,45 @@ const defaultTableTheme = {
2061
2082
  spacing: "5px"
2062
2083
  };
2063
2084
  const emptyStore = new Store(void 0);
2064
- function useTheme() {
2085
+ function useTheme(selector) {
2065
2086
  var _a, _b;
2066
- const table = useContext(TableContext);
2067
- const localTheme = (_b = (_a = table == null ? void 0 : table.useState((state) => ({
2068
- text: state.props.text,
2069
- classes: state.props.classes,
2070
- components: state.props.components,
2071
- icons: state.props.icons,
2072
- colors: state.props.colors,
2073
- spacing: state.props.spacing
2074
- }))) != null ? _a : emptyStore.useState()) != null ? _b : {};
2075
2087
  const contextTableTheme = useContext(TableThemeContext);
2076
- return mergeThemes(defaultTableTheme, globalTableTheme, contextTableTheme, localTheme);
2088
+ const table = useContext(TableContext);
2089
+ const columnId = useContext(ColumnContext);
2090
+ const memo2 = useTableMemo();
2091
+ const process = (t) => {
2092
+ var _a2;
2093
+ const cell = (_a2 = t.classes) == null ? void 0 : _a2.cell;
2094
+ const selected = t.text.selected;
2095
+ return __spreadProps(__spreadValues({}, t), {
2096
+ classes: __spreadProps(__spreadValues({}, t.classes), {
2097
+ cell: cell instanceof Function || Array.isArray(cell) ? memo2("theme.classes.cell", cell) : cell
2098
+ }),
2099
+ text: __spreadProps(__spreadValues({}, t.text), {
2100
+ selected: selected instanceof Function || Array.isArray(selected) ? memo2("theme.text.selected", selected) : selected
2101
+ })
2102
+ });
2103
+ };
2104
+ const theme = (_b = (_a = table == null ? void 0 : table.useState((state) => {
2105
+ const localTheme = {
2106
+ text: state.props.text,
2107
+ classes: state.props.classes,
2108
+ components: state.props.components,
2109
+ icons: state.props.icons,
2110
+ colors: state.props.colors,
2111
+ spacing: state.props.spacing
2112
+ };
2113
+ const column = state.activeColumns.find((column2) => column2.id === columnId);
2114
+ const columnsTheme = {
2115
+ classes: column == null ? void 0 : column.classes
2116
+ };
2117
+ const theme2 = mergeThemes(defaultTableTheme, globalTableTheme, contextTableTheme, localTheme, columnsTheme);
2118
+ return selector(process(theme2));
2119
+ })) != null ? _a : emptyStore.useState()) != null ? _b : selector(process(mergeThemes(defaultTableTheme, globalTableTheme, contextTableTheme)));
2120
+ return theme;
2077
2121
  }
2078
2122
  function AutoFocusTextField(props) {
2079
- const {
2080
- components: {
2081
- TextField: TextField2
2082
- }
2083
- } = useTheme();
2123
+ const TextField2 = useTheme((t) => t.components.TextField);
2084
2124
  const ref = useRef(null);
2085
2125
  const {
2086
2126
  visible
@@ -2240,16 +2280,12 @@ function DatePicker({
2240
2280
  locale,
2241
2281
  firstDayOfWeek = 0
2242
2282
  }) {
2243
- const {
2244
- components: {
2245
- Button: Button2,
2246
- IconButton: IconButton2
2247
- },
2248
- icons: {
2249
- ChevronRight: ChevronRight2
2250
- },
2251
- text
2252
- } = useTheme();
2283
+ const Button2 = useTheme((t) => t.components.Button);
2284
+ const IconButton2 = useTheme((t) => t.components.IconButton);
2285
+ const ChevronRight2 = useTheme((t) => t.icons.ChevronRight);
2286
+ const textToday = useTheme((t) => t.text.today);
2287
+ const textThisWeek = useTheme((t) => t.text.thisWeek);
2288
+ const textReset = useTheme((t) => t.text.reset);
2253
2289
  const [baseDate] = useState(new Date());
2254
2290
  const [dateInView, setDateInView] = useState(baseDate);
2255
2291
  const [dirty, setDirty] = useState();
@@ -2463,21 +2499,21 @@ function DatePicker({
2463
2499
  setDirty(void 0);
2464
2500
  onChange(today());
2465
2501
  },
2466
- children: text.today
2502
+ children: textToday
2467
2503
  }), jsx(Button2, {
2468
2504
  variant: "text",
2469
2505
  onClick: () => {
2470
2506
  setDirty(void 0);
2471
2507
  onChange(thisWeek(firstDayOfWeek));
2472
2508
  },
2473
- children: text.thisWeek
2509
+ children: textThisWeek
2474
2510
  }), jsx(Button2, {
2475
2511
  variant: "text",
2476
2512
  onClick: () => {
2477
2513
  setDirty(void 0);
2478
2514
  onChange(null);
2479
2515
  },
2480
- children: text.reset
2516
+ children: textReset
2481
2517
  })]
2482
2518
  })]
2483
2519
  });
@@ -2564,34 +2600,18 @@ function SelectFilter(_m) {
2564
2600
  "render",
2565
2601
  "singleSelect"
2566
2602
  ]);
2567
- const {
2568
- components: {
2569
- IconButton: IconButton2,
2570
- Checkbox: Checkbox2
2571
- },
2572
- icons: {
2573
- Search: Search2,
2574
- Clear: Clear2
2575
- },
2576
- text
2577
- } = useTheme();
2603
+ const IconButton2 = useTheme((t) => t.components.IconButton);
2604
+ const Checkbox2 = useTheme((t) => t.components.Checkbox);
2605
+ const Search2 = useTheme((t) => t.icons.Search);
2606
+ const Clear2 = useTheme((t) => t.icons.Clear);
2607
+ const selected = useTheme((t) => t.text.selected);
2608
+ const noResults = useTheme((t) => t.text.noResults);
2578
2609
  const table = useTableContext();
2579
2610
  const columnId = useColumnContext();
2580
- const options = table.useState((state) => {
2581
- var _a;
2582
- if (providedOptions)
2583
- return uniq(providedOptions);
2584
- const column = state.activeColumns.find((column2) => column2.id === columnId);
2585
- if (!column)
2586
- return [];
2587
- const filterBy = (_a = props.filterBy) != null ? _a : (x) => x;
2588
- return uniq(flatMap(state.items, (item) => castArray(filterBy(column.value(item), item))));
2589
- });
2590
- const [query, setQuery] = useState("");
2591
- const filtered = options.filter((option) => !query || stringValue(option).toLowerCase().includes(query.toLowerCase()));
2592
2611
  const {
2593
2612
  value = /* @__PURE__ */ new Set(),
2594
- onChange
2613
+ onChange,
2614
+ filterBy
2595
2615
  } = useFilter(__spreadProps(__spreadValues({}, props), {
2596
2616
  id: "selectFilter",
2597
2617
  isActive(filterValue) {
@@ -2601,6 +2621,16 @@ function SelectFilter(_m) {
2601
2621
  return filterValue.has(value2);
2602
2622
  }
2603
2623
  }));
2624
+ const options = table.useState((state) => {
2625
+ if (providedOptions)
2626
+ return uniq(providedOptions);
2627
+ const column = state.activeColumns.find((column2) => column2.id === columnId);
2628
+ if (!column)
2629
+ return [];
2630
+ return uniq(flatMap(state.items, (item) => castArray(filterBy(column.value(item), item))));
2631
+ });
2632
+ const [query, setQuery] = useState("");
2633
+ const filtered = options.filter((option) => !query || stringValue(option).toLowerCase().includes(query.toLowerCase()));
2604
2634
  return jsxs("div", {
2605
2635
  css: {
2606
2636
  padding: "calc(var(--spacing) * 2)",
@@ -2630,7 +2660,7 @@ function SelectFilter(_m) {
2630
2660
  onChange: () => onChange(/* @__PURE__ */ new Set())
2631
2661
  }),
2632
2662
  label: jsxs(Fragment, {
2633
- children: ["<", text.selected(value.size), ">"]
2663
+ children: ["<", selected(value.size), ">"]
2634
2664
  })
2635
2665
  }), filtered.map((option, index) => jsx(FormControlLabel, {
2636
2666
  control: jsx(Checkbox2, {
@@ -2643,7 +2673,7 @@ function SelectFilter(_m) {
2643
2673
  css: {
2644
2674
  textAlign: "center"
2645
2675
  },
2646
- children: text.noResults
2676
+ children: noResults
2647
2677
  })]
2648
2678
  });
2649
2679
  }
@@ -2674,6 +2704,8 @@ function debounce(fn, ms) {
2674
2704
  function useFilter(impl) {
2675
2705
  const table = useTableContext();
2676
2706
  const columnId = useColumnContext();
2707
+ const cache = useTableMemo();
2708
+ const filterBy = impl.filterBy && cache("", impl.filterBy);
2677
2709
  useEffect(() => {
2678
2710
  table.update((state) => {
2679
2711
  if (impl.defaultValue !== void 0) {
@@ -2683,7 +2715,7 @@ function useFilter(impl) {
2683
2715
  }, []);
2684
2716
  useEffect(() => {
2685
2717
  table.update((state) => {
2686
- state.filters.set(columnId, castDraft(impl));
2718
+ state.filters.set(columnId, castDraft(__spreadProps(__spreadValues({}, impl), { filterBy })));
2687
2719
  if (impl.value !== void 0) {
2688
2720
  state.filterValues.set(columnId, impl.value);
2689
2721
  }
@@ -2718,7 +2750,8 @@ function useFilter(impl) {
2718
2750
  return {
2719
2751
  value: dirtyValue != null ? dirtyValue : value,
2720
2752
  onChange,
2721
- close: useContext(FilterControlContext)
2753
+ close: useContext(FilterControlContext),
2754
+ filterBy: filterBy != null ? filterBy : (x) => x
2722
2755
  };
2723
2756
  }
2724
2757
  const textMatch = (text, query) => {
@@ -2748,15 +2781,9 @@ function TextFilter(_o) {
2748
2781
  "compare",
2749
2782
  "filterBy"
2750
2783
  ]);
2751
- const {
2752
- components: {
2753
- IconButton: IconButton2
2754
- },
2755
- icons: {
2756
- Search: Search2,
2757
- Clear: Clear2
2758
- }
2759
- } = useTheme();
2784
+ const IconButton2 = useTheme((t) => t.components.IconButton);
2785
+ const Search2 = useTheme((t) => t.icons.Search);
2786
+ const Clear2 = useTheme((t) => t.icons.Clear);
2760
2787
  const {
2761
2788
  value = "",
2762
2789
  onChange