@teselagen/ui 0.8.6-beta.23 → 0.8.6-beta.25

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 (66) hide show
  1. package/DataTable/EditabelCell.d.ts +7 -0
  2. package/DataTable/defaultProps.d.ts +43 -0
  3. package/DataTable/utils/computePresets.d.ts +1 -0
  4. package/DataTable/utils/convertSchema.d.ts +22 -2
  5. package/DataTable/utils/formatPasteData.d.ts +11 -5
  6. package/DataTable/utils/getAllRows.d.ts +4 -1
  7. package/DataTable/utils/getCellCopyText.d.ts +1 -1
  8. package/DataTable/utils/getCellInfo.d.ts +20 -15
  9. package/DataTable/utils/getFieldPathToField.d.ts +5 -1
  10. package/DataTable/utils/getIdOrCodeOrIndex.d.ts +2 -1
  11. package/DataTable/utils/getLastSelectedEntity.d.ts +7 -1
  12. package/DataTable/utils/getNewEntToSelect.d.ts +7 -6
  13. package/DataTable/utils/getRowCopyText.d.ts +1 -1
  14. package/DataTable/utils/handleCopyColumn.d.ts +1 -1
  15. package/DataTable/utils/handleCopyTable.d.ts +1 -1
  16. package/DataTable/utils/initializeHasuraWhereAndFilter.d.ts +22 -1
  17. package/DataTable/utils/isBottomRightCornerOfRectangle.d.ts +10 -8
  18. package/DataTable/utils/isEntityClean.d.ts +3 -1
  19. package/DataTable/utils/primarySelectedValue.d.ts +1 -1
  20. package/DataTable/utils/removeCleanRows.d.ts +11 -3
  21. package/DataTable/utils/selection.d.ts +3 -1
  22. package/DataTable/utils/types/Entity.d.ts +5 -0
  23. package/DataTable/utils/types/Field.d.ts +4 -0
  24. package/DataTable/utils/types/OrderBy.d.ts +11 -0
  25. package/DataTable/utils/types/Schema.d.ts +4 -0
  26. package/DataTable/utils/useDeepEqualMemo.d.ts +1 -0
  27. package/DataTable/utils/useTableEntities.d.ts +17 -4
  28. package/DataTable/utils/useTableParams.d.ts +49 -0
  29. package/DataTable/utils/utils.d.ts +16 -5
  30. package/index.cjs.js +147 -121
  31. package/index.es.js +147 -121
  32. package/package.json +2 -2
  33. package/src/DataTable/Columns.jsx +945 -0
  34. package/src/DataTable/EditabelCell.js +44 -0
  35. package/src/DataTable/EditabelCell.jsx +44 -0
  36. package/src/DataTable/RenderCell.jsx +191 -0
  37. package/src/DataTable/defaultProps.js +45 -0
  38. package/src/DataTable/index.js +96 -68
  39. package/src/DataTable/utils/computePresets.js +42 -0
  40. package/src/DataTable/utils/convertSchema.ts +79 -0
  41. package/src/DataTable/utils/formatPasteData.ts +34 -0
  42. package/src/DataTable/utils/getAllRows.js +2 -6
  43. package/src/DataTable/utils/getAllRows.ts +11 -0
  44. package/src/DataTable/utils/getCellCopyText.ts +7 -0
  45. package/src/DataTable/utils/getCellInfo.ts +46 -0
  46. package/src/DataTable/utils/getFieldPathToField.ts +10 -0
  47. package/src/DataTable/utils/getIdOrCodeOrIndex.ts +14 -0
  48. package/src/DataTable/utils/getLastSelectedEntity.ts +15 -0
  49. package/src/DataTable/utils/getNewEntToSelect.ts +32 -0
  50. package/src/DataTable/utils/handleCopyColumn.js +2 -2
  51. package/src/DataTable/utils/handleCopyTable.js +2 -2
  52. package/src/DataTable/utils/initializeHasuraWhereAndFilter.ts +35 -0
  53. package/src/DataTable/utils/isBottomRightCornerOfRectangle.ts +27 -0
  54. package/src/DataTable/utils/isEntityClean.ts +15 -0
  55. package/src/DataTable/utils/primarySelectedValue.ts +1 -0
  56. package/src/DataTable/utils/removeCleanRows.ts +25 -0
  57. package/src/DataTable/utils/selection.ts +11 -0
  58. package/src/DataTable/utils/types/Entity.ts +7 -0
  59. package/src/DataTable/utils/types/Field.ts +4 -0
  60. package/src/DataTable/utils/types/OrderBy.ts +15 -0
  61. package/src/DataTable/utils/types/Schema.ts +5 -0
  62. package/src/DataTable/utils/useDeepEqualMemo.js +10 -0
  63. package/src/DataTable/utils/useTableEntities.ts +60 -0
  64. package/src/DataTable/utils/useTableParams.js +361 -0
  65. package/src/DataTable/utils/utils.ts +39 -0
  66. package/style.css +10537 -0
@@ -0,0 +1,34 @@
1
+ import { getFieldPathToField } from "./getFieldPathToField";
2
+ import type { Schema } from "./types/Schema";
3
+
4
+ type GenericSelectValue = {
5
+ __strVal: string;
6
+ __genSelCol: string;
7
+ };
8
+
9
+ export const formatPasteData = ({
10
+ schema,
11
+ newVal,
12
+ path
13
+ }: {
14
+ schema: Schema;
15
+ newVal: GenericSelectValue | string | number | boolean | null | undefined;
16
+ path: string;
17
+ }) => {
18
+ const pathToField = getFieldPathToField(schema);
19
+ const column = pathToField[path];
20
+ if (column.type === "genericSelect") {
21
+ const value = newVal as GenericSelectValue;
22
+ if (value.__genSelCol === path) {
23
+ newVal = value.__strVal;
24
+ } else {
25
+ newVal = undefined;
26
+ }
27
+ } else {
28
+ newVal =
29
+ typeof newVal === "object" && newVal !== null && "__strVal" in newVal
30
+ ? newVal.__strVal
31
+ : newVal;
32
+ }
33
+ return newVal;
34
+ };
@@ -1,9 +1,5 @@
1
- export const getAllRows = e => {
2
- const el = e.target.querySelector(".data-table-container")
3
- ? e.target.querySelector(".data-table-container")
4
- : e.target.closest(".data-table-container");
5
-
6
- const allRowEls = el.querySelectorAll(".rt-tr");
1
+ export const getAllRows = tableRef => {
2
+ const allRowEls = tableRef.current?.tableRef?.querySelectorAll(".rt-tr");
7
3
  if (!allRowEls || !allRowEls.length) {
8
4
  return;
9
5
  }
@@ -0,0 +1,11 @@
1
+ import type { RefObject } from "react";
2
+
3
+ export const getAllRows = (
4
+ tableRef: RefObject<{ tableRef: HTMLDivElement }>
5
+ ) => {
6
+ const allRowEls = tableRef.current?.tableRef?.querySelectorAll(".rt-tr");
7
+ if (!allRowEls || !allRowEls.length) {
8
+ return;
9
+ }
10
+ return allRowEls;
11
+ };
@@ -0,0 +1,7 @@
1
+ export const getCellCopyText = (cellWrapper: HTMLElement | null) => {
2
+ const text = cellWrapper?.getAttribute("data-copy-text");
3
+ const jsonText = cellWrapper?.getAttribute("data-copy-json");
4
+
5
+ const textContent = text || cellWrapper?.textContent || "";
6
+ return [textContent, jsonText];
7
+ };
@@ -0,0 +1,46 @@
1
+ import { getIdOrCodeOrIndex } from "./getIdOrCodeOrIndex";
2
+ import { Entity } from "./types/Entity";
3
+
4
+ export const getCellInfo = <T extends Entity>({
5
+ columnIndex,
6
+ columnPath,
7
+ rowId,
8
+ schema,
9
+ entities,
10
+ rowIndex,
11
+ isEntityDisabled,
12
+ entity
13
+ }: {
14
+ columnIndex: number;
15
+ columnPath: string;
16
+ rowId: string | number;
17
+ schema: { fields: { path: string }[] };
18
+ entities: T[];
19
+ rowIndex: number;
20
+ isEntityDisabled: (entity: T) => boolean;
21
+ entity: T;
22
+ }) => {
23
+ const leftpath = schema.fields[columnIndex - 1]?.path;
24
+ const rightpath = schema.fields[columnIndex + 1]?.path;
25
+ const cellIdToLeft = leftpath && `${rowId}:${leftpath}`;
26
+ const cellIdToRight = rightpath && `${rowId}:${rightpath}`;
27
+ const rowAboveId =
28
+ entities[rowIndex - 1] &&
29
+ getIdOrCodeOrIndex(entities[rowIndex - 1], rowIndex - 1);
30
+ const rowBelowId =
31
+ entities[rowIndex + 1] &&
32
+ getIdOrCodeOrIndex(entities[rowIndex + 1], rowIndex + 1);
33
+ const cellIdAbove = rowAboveId && `${rowAboveId}:${columnPath}`;
34
+ const cellIdBelow = rowBelowId && `${rowBelowId}:${columnPath}`;
35
+
36
+ const cellId = `${rowId}:${columnPath}`;
37
+ const rowDisabled = isEntityDisabled(entity);
38
+ return {
39
+ cellId,
40
+ cellIdAbove,
41
+ cellIdToRight,
42
+ cellIdBelow,
43
+ cellIdToLeft,
44
+ rowDisabled
45
+ };
46
+ };
@@ -0,0 +1,10 @@
1
+ import { Field } from "./types/Field";
2
+ import { Schema } from "./types/Schema";
3
+
4
+ export const getFieldPathToField = (schema: Schema) => {
5
+ const fieldPathToField: { [path: string]: Field } = {};
6
+ schema.fields.forEach(f => {
7
+ fieldPathToField[f.path] = f;
8
+ });
9
+ return fieldPathToField;
10
+ };
@@ -0,0 +1,14 @@
1
+ import type { Entity } from "./types/Entity";
2
+
3
+ export const getIdOrCodeOrIndex = (record: Entity, rowIndex?: number) => {
4
+ if ("id" in record && (record.id || record.id === 0)) {
5
+ return record.id;
6
+ } else if ("code" in record && record.code) {
7
+ return record.code;
8
+ } else {
9
+ if (rowIndex === undefined || rowIndex === null) {
10
+ throw new Error("id, code, or rowIndex must be provided");
11
+ }
12
+ return rowIndex;
13
+ }
14
+ };
@@ -0,0 +1,15 @@
1
+ import { Entity } from "./types/Entity";
2
+
3
+ export const getLastSelectedEntity = (idMap: {
4
+ [id: string]: { time: number; entity: Entity };
5
+ }) => {
6
+ let lastSelectedEnt;
7
+ let latestTime: number | null = null;
8
+ Object.values(idMap).forEach(({ time, entity }) => {
9
+ if (!latestTime || time > latestTime) {
10
+ lastSelectedEnt = entity;
11
+ latestTime = time;
12
+ }
13
+ });
14
+ return lastSelectedEnt;
15
+ };
@@ -0,0 +1,32 @@
1
+ import { Entity } from "./types/Entity";
2
+
3
+ export const getNewEntToSelect = ({
4
+ type,
5
+ lastSelectedIndex,
6
+ entities,
7
+ isEntityDisabled
8
+ }: {
9
+ type: "up" | "down";
10
+ lastSelectedIndex: number;
11
+ entities: Entity[];
12
+ isEntityDisabled?: (entity: Entity) => boolean;
13
+ }): Entity | undefined => {
14
+ let newIndexToSelect;
15
+ if (type === "up") {
16
+ newIndexToSelect = lastSelectedIndex - 1;
17
+ } else {
18
+ newIndexToSelect = lastSelectedIndex + 1;
19
+ }
20
+ const newEntToSelect = entities[newIndexToSelect];
21
+ if (!newEntToSelect) return;
22
+ if (isEntityDisabled && isEntityDisabled(newEntToSelect)) {
23
+ return getNewEntToSelect({
24
+ type,
25
+ lastSelectedIndex: newIndexToSelect,
26
+ entities,
27
+ isEntityDisabled
28
+ }) as Entity;
29
+ } else {
30
+ return newEntToSelect;
31
+ }
32
+ };
@@ -2,9 +2,9 @@ import { getAllRows } from "./getAllRows";
2
2
  import { getIdOrCodeOrIndex } from "./getIdOrCodeOrIndex";
3
3
  import { handleCopyRows } from "./handleCopyRows";
4
4
 
5
- export const handleCopyColumn = (e, cellWrapper, selectedRecords) => {
5
+ export const handleCopyColumn = (tableRef, cellWrapper, selectedRecords) => {
6
6
  const specificColumn = cellWrapper.getAttribute("data-test");
7
- let rowElsToCopy = getAllRows(e);
7
+ let rowElsToCopy = getAllRows(tableRef);
8
8
  if (!rowElsToCopy) return;
9
9
  if (selectedRecords) {
10
10
  const ids = selectedRecords.map(e => getIdOrCodeOrIndex(e)?.toString());
@@ -1,9 +1,9 @@
1
1
  import { getAllRows } from "./getAllRows";
2
2
  import { handleCopyRows } from "./handleCopyRows";
3
3
 
4
- export const handleCopyTable = (e, opts) => {
4
+ export const handleCopyTable = (tableRef, opts) => {
5
5
  try {
6
- const allRowEls = getAllRows(e);
6
+ const allRowEls = getAllRows(tableRef);
7
7
  if (!allRowEls) return;
8
8
  handleCopyRows(allRowEls, {
9
9
  ...opts,
@@ -0,0 +1,35 @@
1
+ type Filter = {
2
+ [key: string]:
3
+ | { _eq: string | number | boolean }
4
+ | { _in: (string | number | boolean)[] }
5
+ | { _gt: number }
6
+ | { _lt: number }
7
+ | { _gte: number }
8
+ | { _lte: number };
9
+ };
10
+ type Where = { _and?: Filter[]; _or?: Filter[] };
11
+ type CurrentParams = object;
12
+
13
+ export function initializeHasuraWhereAndFilter(
14
+ additionalFilter:
15
+ | ((where: Where, currentParams: CurrentParams) => Filter | void)
16
+ | Filter
17
+ | undefined
18
+ | null,
19
+ where: Where = {},
20
+ currentParams: CurrentParams
21
+ ) {
22
+ where._and = where._and || [];
23
+ where._or = where._or || [];
24
+ if (typeof additionalFilter === "function") {
25
+ const newWhere = additionalFilter(where, currentParams);
26
+ if (newWhere) {
27
+ Object.assign(where, newWhere);
28
+ }
29
+ } else if (
30
+ typeof additionalFilter === "object" &&
31
+ additionalFilter !== null
32
+ ) {
33
+ where._and.push(additionalFilter);
34
+ }
35
+ }
@@ -0,0 +1,27 @@
1
+ export const isBottomRightCornerOfRectangle = ({
2
+ cellId,
3
+ selectionGrid,
4
+ lastRowIndex,
5
+ lastCellIndex,
6
+ entityMap,
7
+ pathToIndex
8
+ }: {
9
+ cellId: string;
10
+ selectionGrid: (string | undefined)[][];
11
+ lastRowIndex: number;
12
+ lastCellIndex: number;
13
+ entityMap: Record<string, { i: number }>;
14
+ pathToIndex: Record<string, number>;
15
+ }) => {
16
+ selectionGrid.forEach(row => {
17
+ // remove undefineds from start of row
18
+ while (row[0] === undefined && row.length) row.shift();
19
+ });
20
+ const [rowId, cellPath] = cellId.split(":");
21
+ const ent = entityMap[rowId];
22
+ if (!ent) return;
23
+ const { i } = ent;
24
+ const cellIndex = pathToIndex[cellPath];
25
+ const isBottomRight = i === lastRowIndex && cellIndex === lastCellIndex;
26
+ return isBottomRight;
27
+ };
@@ -0,0 +1,15 @@
1
+ export function isEntityClean(e: { [key: string]: unknown } | null): boolean {
2
+ if (typeof e !== "object" || e === null) {
3
+ return true; // or return false depending on what you want for non-object inputs
4
+ }
5
+ let isClean = true;
6
+ for (const [key, val] of Object.entries(e)) {
7
+ if (key === "id") continue;
8
+ if (key === "_isClean") continue;
9
+ if (val) {
10
+ isClean = false;
11
+ break;
12
+ }
13
+ }
14
+ return isClean;
15
+ }
@@ -0,0 +1 @@
1
+ export const PRIMARY_SELECTED_VAL = "main_cell";
@@ -0,0 +1,25 @@
1
+ import { isEntityClean } from "./isEntityClean";
2
+ import { getIdOrCodeOrIndex } from "./getIdOrCodeOrIndex";
3
+
4
+ export const removeCleanRows = (
5
+ entities: ({ [key: string]: unknown } & { _isClean?: boolean })[],
6
+ cellValidation: Record<string, unknown>
7
+ ) => {
8
+ const toFilterOut: Record<string, boolean> = {};
9
+ const entsToUse = (entities || []).filter(e => {
10
+ if (!(e._isClean || isEntityClean(e))) return true;
11
+ else {
12
+ toFilterOut[getIdOrCodeOrIndex(e)] = true;
13
+ return false;
14
+ }
15
+ });
16
+
17
+ const validationToUse: Record<string, unknown> = {};
18
+ Object.entries(cellValidation || {}).forEach(([k, v]) => {
19
+ const [rowId] = k.split(":");
20
+ if (!toFilterOut[rowId]) {
21
+ validationToUse[k] = v;
22
+ }
23
+ });
24
+ return { entsToUse, validationToUse };
25
+ };
@@ -0,0 +1,11 @@
1
+ import { getIdOrCodeOrIndex } from "./getIdOrCodeOrIndex";
2
+
3
+ export const getSelectedRowsFromEntities = (
4
+ entities: { [key: string]: unknown }[],
5
+ idMap: Record<string, boolean>
6
+ ) => {
7
+ if (!idMap) return [];
8
+ return entities.reduce((acc: number[], entity, i) => {
9
+ return idMap[getIdOrCodeOrIndex(entity, i)] ? acc.concat([i]) : acc;
10
+ }, []);
11
+ };
@@ -0,0 +1,7 @@
1
+ export type Entity =
2
+ | {
3
+ id?: string | number;
4
+ }
5
+ | {
6
+ code?: string;
7
+ };
@@ -0,0 +1,4 @@
1
+ export type Field = {
2
+ path: string;
3
+ type: "genericSelect" | string;
4
+ };
@@ -0,0 +1,15 @@
1
+ type OrderByClause<T = { id: string }> = {
2
+ path?: string;
3
+ direction?: "asc" | "desc";
4
+ type?: string;
5
+ sortFn?:
6
+ | ((record: T) => unknown)
7
+ | string
8
+ | Array<((record: T) => unknown) | string>;
9
+ getValueToFilterOn?: (record: T) => unknown;
10
+ };
11
+
12
+ export type OrderBy =
13
+ | OrderByClause
14
+ | OrderByClause[]
15
+ | Record<string, "asc" | "desc">;
@@ -0,0 +1,5 @@
1
+ import { Field } from "./Field";
2
+
3
+ export type Schema = {
4
+ fields: Field[];
5
+ };
@@ -0,0 +1,10 @@
1
+ import { isEqual } from "lodash-es";
2
+ import { useRef } from "react";
3
+
4
+ export const useDeepEqualMemo = value => {
5
+ const ref = useRef();
6
+ if (!isEqual(value, ref.current)) {
7
+ ref.current = value;
8
+ }
9
+ return ref.current;
10
+ };
@@ -0,0 +1,60 @@
1
+ import { useCallback } from "react";
2
+ import { useDispatch, useSelector } from "react-redux";
3
+ import { change, initialize } from "redux-form";
4
+
5
+ type _Entity = { [key: string]: unknown } & { id: string };
6
+
7
+ type SelectedEntityIdMap<Entity extends _Entity> = Record<
8
+ string,
9
+ { entity: Entity; time: number; index?: number }
10
+ >;
11
+
12
+ export const useTableEntities = <Entity extends _Entity>(
13
+ tableFormName: string
14
+ ) => {
15
+ const dispatch = useDispatch();
16
+ const selectTableEntities = useCallback(
17
+ (entities: { id: string }[] = []) => {
18
+ initialize(tableFormName, {}, true, {
19
+ keepDirty: true,
20
+ updateUnregisteredFields: true,
21
+ keepValues: true
22
+ });
23
+ const selectedEntityIdMap: SelectedEntityIdMap<{ id: string }> = {};
24
+ entities.forEach(entity => {
25
+ selectedEntityIdMap[entity.id] = {
26
+ entity,
27
+ time: Date.now()
28
+ };
29
+ });
30
+ dispatch(
31
+ change(
32
+ tableFormName,
33
+ "reduxFormSelectedEntityIdMap",
34
+ selectedEntityIdMap
35
+ )
36
+ );
37
+ },
38
+ [dispatch, tableFormName]
39
+ );
40
+
41
+ const { allOrderedEntities, selectedEntities } = useSelector(
42
+ (state: {
43
+ form: Record<
44
+ string,
45
+ {
46
+ values?: {
47
+ allOrderedEntities?: Entity[];
48
+ reduxFormSelectedEntityIdMap?: SelectedEntityIdMap<Entity>;
49
+ };
50
+ }
51
+ >;
52
+ }) => ({
53
+ allOrderedEntities:
54
+ state.form?.[tableFormName]?.values?.allOrderedEntities,
55
+ selectedEntities:
56
+ state.form?.[tableFormName]?.values?.reduxFormSelectedEntityIdMap
57
+ })
58
+ );
59
+ return { selectTableEntities, allOrderedEntities, selectedEntities };
60
+ };