@teselagen/ui 0.8.6 → 0.8.8

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 (31) hide show
  1. package/DataTable/EditabelCell.d.ts +10 -0
  2. package/DataTable/defaultProps.d.ts +43 -0
  3. package/DataTable/utils/computePresets.d.ts +1 -0
  4. package/DataTable/utils/getRowCopyText.d.ts +3 -1
  5. package/DataTable/utils/handleCopyRows.d.ts +5 -1
  6. package/DataTable/utils/index.d.ts +1 -0
  7. package/DataTable/utils/rowClick.d.ts +1 -1
  8. package/FormComponents/Uploader.d.ts +3 -1
  9. package/FormComponents/tryToMatchSchemas.d.ts +1 -1
  10. package/MenuBar/index.d.ts +3 -1
  11. package/ResizableDraggableDialog/index.d.ts +3 -1
  12. package/TagSelect/index.d.ts +1 -1
  13. package/index.cjs.js +31604 -34714
  14. package/index.es.js +30599 -33709
  15. package/package.json +1 -1
  16. package/src/DataTable/EditabelCell.js +55 -0
  17. package/src/DataTable/defaultProps.js +45 -0
  18. package/src/DataTable/utils/computePresets.js +42 -0
  19. package/src/ExcelCell.js +38 -0
  20. package/src/FormComponents/Uploader.js +5 -1
  21. package/src/autoTooltip.js +1 -0
  22. package/utils/hotkeyUtils.d.ts +3 -1
  23. package/DataTable/utils/filterLocalEntitiesToHasura.d.ts +0 -5
  24. package/DataTable/utils/initializeHasuraWhereAndFilter.d.ts +0 -2
  25. package/DataTable/utils/tableQueryParamsToHasuraClauses.d.ts +0 -26
  26. package/src/DataTable/utils/filterLocalEntitiesToHasura.js +0 -236
  27. package/src/DataTable/utils/filterLocalEntitiesToHasura.test.js +0 -587
  28. package/src/DataTable/utils/initializeHasuraWhereAndFilter.js +0 -26
  29. package/src/DataTable/utils/tableQueryParamsToHasuraClauses.js +0 -260
  30. package/src/DataTable/utils/tableQueryParamsToHasuraClauses.test.js +0 -206
  31. /package/{ui.css → style.css} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teselagen/ui",
3
- "version": "0.8.6",
3
+ "version": "0.8.8",
4
4
  "main": "./src/index.js",
5
5
  "type": "module",
6
6
  "exports": {
@@ -0,0 +1,55 @@
1
+ import React, { useEffect, useRef, useState } from "react";
2
+
3
+ export const EditableCell = ({
4
+ cancelEdit,
5
+ dataTest,
6
+ finishEdit,
7
+ initialValue,
8
+ isEditableCellInitialValue,
9
+ isNumeric,
10
+ shouldSelectAll,
11
+ stopSelectAll
12
+ }) => {
13
+ const [value, setValue] = useState(initialValue);
14
+ const inputRef = useRef(null);
15
+
16
+ useEffect(() => {
17
+ if (inputRef.current) {
18
+ inputRef.current.focus();
19
+ if (isEditableCellInitialValue && !isNumeric) {
20
+ inputRef.current.selectionStart = inputRef.current.value.length;
21
+ inputRef.current.selectionEnd = inputRef.current.value.length;
22
+ } else if (shouldSelectAll) {
23
+ inputRef.current.select();
24
+ stopSelectAll();
25
+ }
26
+ }
27
+ }, [isEditableCellInitialValue, isNumeric, shouldSelectAll, stopSelectAll]);
28
+
29
+ return (
30
+ <input
31
+ style={{
32
+ border: 0,
33
+ width: "95%",
34
+ fontSize: 12,
35
+ background: "none"
36
+ }}
37
+ ref={inputRef}
38
+ {...dataTest}
39
+ autoFocus
40
+ onKeyDown={e => {
41
+ if (e.key === "Enter") {
42
+ finishEdit(value);
43
+ e.stopPropagation();
44
+ } else if (e.key === "Escape") {
45
+ e.stopPropagation();
46
+ cancelEdit();
47
+ }
48
+ }}
49
+ onBlur={() => finishEdit(value)}
50
+ onChange={e => setValue(e.target.value)}
51
+ type={isNumeric ? "number" : undefined}
52
+ value={value}
53
+ />
54
+ );
55
+ };
@@ -0,0 +1,45 @@
1
+ import { noop } from "lodash-es";
2
+
3
+ // eslint-disable-next-line import/no-anonymous-default-export
4
+ export default {
5
+ //NOTE: DO NOT SET DEFAULTS HERE FOR PROPS THAT GET COMPUTED AS PART OF PRESET GROUPS IN computePresets
6
+ addFilters: noop,
7
+ className: "",
8
+ clearFilters: noop,
9
+ contextMenu: noop,
10
+ disabled: false,
11
+ entities: [],
12
+ extraClasses: "",
13
+ filters: [],
14
+ isCopyable: true,
15
+ isEntityDisabled: noop,
16
+ isLoading: false,
17
+ isSimple: false,
18
+ isSingleSelect: false,
19
+ maxHeight: 600,
20
+ noHeader: false,
21
+ noSelect: false,
22
+ noUserSelect: false,
23
+ onDeselect: noop,
24
+ onMultiRowSelect: noop,
25
+ onRowClick: noop,
26
+ onRowSelect: noop,
27
+ onSingleRowSelect: noop,
28
+ page: 1,
29
+ pageSize: 10,
30
+ reduxFormExpandedEntityIdMap: {},
31
+ reduxFormSearchInput: "",
32
+ reduxFormSelectedEntityIdMap: {},
33
+ removeSingleFilter: noop,
34
+ resized: [],
35
+ resizePersist: noop,
36
+ setFilter: noop,
37
+ setOrder: noop,
38
+ setPage: noop,
39
+ setPageSize: noop,
40
+ setSearchTerm: noop,
41
+ showCount: false,
42
+ style: {},
43
+ withCheckboxes: false,
44
+ withSort: true
45
+ };
@@ -0,0 +1,42 @@
1
+ import { omitBy, isNil } from "lodash-es";
2
+ //we use this to make adding preset prop groups simpler
3
+ export default function computePresets(props = {}) {
4
+ const { isSimple } = props;
5
+ let toReturn = omitBy(props, isNil);
6
+ toReturn.pageSize = toReturn.controlled_pageSize || toReturn.pageSize;
7
+ if (isSimple) {
8
+ //isSimplePreset
9
+ toReturn = {
10
+ noHeader: true,
11
+ noFooter: !props.withPaging,
12
+ noPadding: true,
13
+ noFullscreenButton: true,
14
+ hidePageSizeWhenPossible: !props.withPaging,
15
+ isInfinite: !props.withPaging,
16
+ hideSelectedCount: true,
17
+ withTitle: false,
18
+ withSearch: false,
19
+ compact: true,
20
+ withPaging: false,
21
+ withFilter: false,
22
+ ...toReturn
23
+ };
24
+ } else {
25
+ toReturn = {
26
+ // the usual defaults:
27
+ noFooter: false,
28
+ noPadding: false,
29
+ compact: true,
30
+ noFullscreenButton: false,
31
+ hidePageSizeWhenPossible: false,
32
+ isInfinite: false,
33
+ hideSelectedCount: false,
34
+ withTitle: true,
35
+ withSearch: true,
36
+ withPaging: true,
37
+ withFilter: true,
38
+ ...toReturn
39
+ };
40
+ }
41
+ return toReturn || {};
42
+ }
@@ -0,0 +1,38 @@
1
+ /* eslint react/jsx-no-bind: 0 */
2
+ import { Popover } from "@blueprintjs/core";
3
+ import React, { useState } from "react";
4
+
5
+ export default function ExcelCell() {
6
+ const [v, setV] = useState("");
7
+ const [isPopoverOpen, setIsPopoverOpen] = useState(false);
8
+ return (
9
+ <Popover
10
+ onClose={() => {
11
+ setIsPopoverOpen(false);
12
+ }}
13
+ isOpen={isPopoverOpen}
14
+ content={<div>Sum</div>}
15
+ >
16
+ <div
17
+ style={{
18
+ border: "1px solid #ccc",
19
+ padding: 5,
20
+ width: 100,
21
+ height: 30
22
+ }}
23
+ contentEditable
24
+ onInput={e => {
25
+ const text = e.currentTarget.textContent;
26
+
27
+ if (text === "=") {
28
+ // open a popover
29
+ setIsPopoverOpen(true);
30
+ }
31
+ setV(text);
32
+ }}
33
+ >
34
+ {v}
35
+ </div>
36
+ </Popover>
37
+ );
38
+ }
@@ -788,7 +788,11 @@ const Uploader = ({
788
788
  .join(", ")
789
789
  : undefined
790
790
  }
791
- onDrop={async (_acceptedFiles, rejectedFiles) => {
791
+ onDrop={async (_acceptedFiles, rejectedFiles, e) => {
792
+ const parentDropzone = e.target.closest(".tg-dropzone");
793
+ if (parentDropzone) {
794
+ parentDropzone.blur();
795
+ }
792
796
  let acceptedFiles = [];
793
797
  for (const file of _acceptedFiles) {
794
798
  if ((validateAgainstSchema || autoUnzip) && isZipFile(file)) {
@@ -18,6 +18,7 @@ document.addEventListener("mouseup", () => {
18
18
  });
19
19
 
20
20
  let tippys = [];
21
+
21
22
  let recentlyHidden = false;
22
23
  let clearMe;
23
24
  (function () {
@@ -1,4 +1,6 @@
1
1
  export function comboToLabel(def: any, useSymbols?: boolean): any;
2
2
  export function hotkeysById(hotkeys: any, mode?: string): (id: any) => any;
3
3
  export function getHotkeyProps(def: any, id: any): any;
4
- export function withHotkeys(hotkeys: any, handlers: any): ({ children }?: {}) => import("react/jsx-runtime").JSX.Element;
4
+ export function withHotkeys(hotkeys: any, handlers: any): ({ children }?: {
5
+ children: any;
6
+ }) => import("react/jsx-runtime").JSX.Element;
@@ -1,5 +0,0 @@
1
- export function filterLocalEntitiesToHasura(records: any, { where, order_by, limit, offset, isInfinite }?: {}): {
2
- entities: any[];
3
- entitiesAcrossPages: any[];
4
- entityCount: number;
5
- };
@@ -1,2 +0,0 @@
1
- export function initializeHasuraWhereAndFilter(additionalFilter: any, where: {} | undefined, currentParams: any): void;
2
- export function addCustomColumnFilters(where: any, fields: any, currentParams: any): void;
@@ -1,26 +0,0 @@
1
- export function tableQueryParamsToHasuraClauses({ page, pageSize, searchTerm, filters, order, schema, additionalFilter }: {
2
- page: any;
3
- pageSize: any;
4
- searchTerm: any;
5
- filters: any;
6
- order: any;
7
- schema: any;
8
- additionalFilter: any;
9
- }): {
10
- where: {};
11
- order_by: {};
12
- limit: any;
13
- offset: number;
14
- };
15
- /**
16
- * Takes a schema and returns an object with the fields mapped by their camelCased display name.
17
- * If the displayName is not set or is a jsx element, the path is used instead.
18
- * The same conversion must be done when using the result of this method
19
- */
20
- export function getFieldsMappedByCCDisplayName(schema: any): any;
21
- /**
22
- *
23
- * @param {object} field
24
- * @returns the camelCase display name of the field, to be used for filters, sorting, etc
25
- */
26
- export function getCCDisplayName(field: object): string;
@@ -1,236 +0,0 @@
1
- import {
2
- isEmpty,
3
- every,
4
- some,
5
- isEqual,
6
- isString,
7
- isNull,
8
- isArray,
9
- includes,
10
- isObject,
11
- has,
12
- orderBy
13
- } from "lodash-es";
14
-
15
- export function filterLocalEntitiesToHasura(
16
- records,
17
- { where, order_by, limit, offset, isInfinite } = {}
18
- ) {
19
- let filteredRecords = [...records];
20
-
21
- // Apply where clause if it exists
22
- if (where) {
23
- filteredRecords = applyWhereClause(filteredRecords, where);
24
- }
25
-
26
- // Apply order_by if it exists
27
- if (order_by) {
28
- filteredRecords = applyOrderBy(filteredRecords, order_by);
29
- }
30
-
31
- // Store the complete filtered and ordered records for pagination info
32
- const allFilteredRecords = [...filteredRecords];
33
-
34
- // Apply limit and offset
35
- if (!isInfinite && offset !== undefined) {
36
- filteredRecords = filteredRecords.slice(offset);
37
- }
38
-
39
- if (!isInfinite && limit !== undefined) {
40
- filteredRecords = filteredRecords.slice(0, limit);
41
- }
42
-
43
- // For consistency, always return an object with entities, entitiesAcrossPages, and entityCount
44
- return {
45
- entities: filteredRecords,
46
- entitiesAcrossPages: allFilteredRecords,
47
- entityCount: allFilteredRecords.length
48
- };
49
- }
50
-
51
- function applyWhereClause(records, where) {
52
- function applyFilter(record, filter) {
53
- if (isEmpty(filter)) {
54
- return true; // No filter, all records pass
55
- }
56
-
57
- for (const key in filter) {
58
- if (key === "_and") {
59
- if (isEmpty(filter[key])) {
60
- continue;
61
- }
62
- if (!every(filter[key], subFilter => applyFilter(record, subFilter))) {
63
- return false;
64
- }
65
- } else if (key === "_or") {
66
- if (isEmpty(filter[key])) {
67
- continue;
68
- }
69
- if (!some(filter[key], subFilter => applyFilter(record, subFilter))) {
70
- return false;
71
- }
72
- } else if (key === "_not") {
73
- if (applyFilter(record, filter[key])) {
74
- return false;
75
- }
76
- } else {
77
- const value = record[key];
78
- const conditions = filter[key];
79
-
80
- // Handle nested object properties
81
- if (
82
- isObject(value) &&
83
- isObject(conditions) &&
84
- !hasOperator(conditions)
85
- ) {
86
- return applyFilter(value, conditions);
87
- }
88
-
89
- for (const operator in conditions) {
90
- const conditionValue = conditions[operator];
91
-
92
- // Handle range conditions (_gt/_lt or _gte/_lte combinations)
93
- if (operator === "_gt" && conditions._lt) {
94
- if (!(value > conditionValue && value < conditions._lt))
95
- return false;
96
- continue;
97
- }
98
- if (operator === "_gte" && conditions._lte) {
99
- if (!(value >= conditionValue && value <= conditions._lte))
100
- return false;
101
- continue;
102
- }
103
-
104
- switch (operator) {
105
- case "_eq":
106
- if (!isEqual(value, conditionValue)) return false;
107
- break;
108
- case "_neq":
109
- if (isEqual(value, conditionValue)) return false;
110
- break;
111
- case "_gt":
112
- if (!(value > conditionValue)) return false;
113
- break;
114
- case "_gte":
115
- if (!(value >= conditionValue)) return false;
116
- break;
117
- case "_lt":
118
- if (!(value < conditionValue)) return false;
119
- break;
120
- case "_lte":
121
- if (!(value <= conditionValue)) return false;
122
- break;
123
- case "_like":
124
- if (
125
- !isString(value) ||
126
- !new RegExp(conditionValue.replace(/%/g, ".*")).test(value)
127
- )
128
- return false;
129
- break;
130
- case "_ilike":
131
- if (
132
- !isString(value) ||
133
- !new RegExp(conditionValue.replace(/%/g, ".*"), "i").test(value)
134
- )
135
- return false;
136
- break;
137
- case "_nlike":
138
- if (
139
- !isString(value) ||
140
- new RegExp(conditionValue.replace(/%/g, ".*")).test(value)
141
- )
142
- return false;
143
- break;
144
- case "_nilike":
145
- if (
146
- !isString(value) ||
147
- new RegExp(conditionValue.replace(/%/g, ".*"), "i").test(value)
148
- )
149
- return false;
150
- break;
151
- case "_starts_with":
152
- if (!isString(value) || !value.startsWith(conditionValue))
153
- return false;
154
- break;
155
- case "_ends_with":
156
- if (!isString(value) || !value.endsWith(conditionValue))
157
- return false;
158
- break;
159
- case "_is_null":
160
- if (
161
- (conditionValue && !isNull(value)) ||
162
- (!conditionValue && isNull(value))
163
- )
164
- return false;
165
- break;
166
- case "_contains":
167
- if (
168
- !isArray(value) ||
169
- !every(conditionValue, item => includes(value, item))
170
- )
171
- return false;
172
- break;
173
- case "_contained_in":
174
- if (
175
- !isArray(value) ||
176
- !every(value, item => includes(conditionValue, item))
177
- )
178
- return false;
179
- break;
180
- case "_has_key":
181
- if (!isObject(value) || !has(value, conditionValue)) return false;
182
- break;
183
- case "_has_keys_any":
184
- if (
185
- !isObject(value) ||
186
- !some(conditionValue, item => has(value, item))
187
- )
188
- return false;
189
- break;
190
- case "_has_keys_all":
191
- if (
192
- !isObject(value) ||
193
- !every(conditionValue, item => has(value, item))
194
- )
195
- return false;
196
- break;
197
- case "_similar":
198
- if (
199
- !isString(value) ||
200
- !new RegExp(conditionValue.replace(/%/g, ".*")).test(value)
201
- )
202
- return false;
203
- break;
204
- default:
205
- if (operator.startsWith("_")) {
206
- console.warn(`Unsupported operator: ${operator}`);
207
- return false;
208
- } else {
209
- console.warn(`Unsupported operator: ${operator}`);
210
- return false;
211
- }
212
- }
213
- }
214
- }
215
- }
216
-
217
- return true;
218
- }
219
-
220
- // Helper to check if an object contains any Hasura operators
221
- function hasOperator(obj) {
222
- return Object.keys(obj).some(key => key.startsWith("_"));
223
- }
224
-
225
- return records.filter(record => applyFilter(record, where));
226
- }
227
-
228
- function applyOrderBy(records, order_by) {
229
- const keys = Object.keys(order_by);
230
- if (keys.length > 0) {
231
- const field = keys[0];
232
- const direction = order_by[field] === "asc" ? "asc" : "desc";
233
- return orderBy(records, [field], [direction]);
234
- }
235
- return records;
236
- }