@teselagen/ui 0.9.7 → 0.10.2
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/DataTable/index.d.ts +3 -3
- package/index.cjs.js +21025 -21144
- package/index.es.js +21028 -21147
- package/package.json +2 -1
- package/src/DataTable/PagingTool.js +2 -2
- package/src/DataTable/RenderCell.js +8 -4
- package/src/DataTable/index.js +1210 -224
- package/src/DataTable/utils/useTableEntities.js +3 -2
- package/src/DataTable/utils/withTableParams.js +8 -7
- package/src/UploadCsvWizard.js +7 -5
- package/src/utils/hooks/useDeepEqualMemo.js +2 -2
- package/src/utils/isEqualIgnoreFunctions.js +23 -0
- package/src/utils/pureNoFunc.js +4 -20
- package/utils/isEqualIgnoreFunctions.d.ts +1 -0
- package/DataTable/EditabelCell.d.ts +0 -7
- package/DataTable/ReactTable.d.ts +0 -78
- package/DataTable/defaultProps.d.ts +0 -43
- package/DataTable/utils/computePresets.d.ts +0 -1
- package/DataTable/utils/types/Entity.d.ts +0 -9
- package/DataTable/utils/types/Field.d.ts +0 -4
- package/DataTable/utils/types/OrderBy.d.ts +0 -11
- package/DataTable/utils/types/Schema.d.ts +0 -4
- package/DataTable/utils/useDeepEqualMemo.d.ts +0 -1
- package/DataTable/utils/useHotKeysWrapper.d.ts +0 -29
- package/DataTable/utils/useTableParams.d.ts +0 -49
- package/src/DataTable/Columns.jsx +0 -945
- package/src/DataTable/EditabelCell.js +0 -44
- package/src/DataTable/EditabelCell.jsx +0 -44
- package/src/DataTable/ReactTable.js +0 -738
- package/src/DataTable/RenderCell.jsx +0 -191
- package/src/DataTable/defaultProps.js +0 -45
- package/src/DataTable/utils/computePresets.js +0 -42
- package/src/DataTable/utils/convertSchema.ts +0 -79
- package/src/DataTable/utils/formatPasteData.ts +0 -34
- package/src/DataTable/utils/getAllRows.ts +0 -11
- package/src/DataTable/utils/getCellCopyText.ts +0 -7
- package/src/DataTable/utils/getCellInfo.ts +0 -46
- package/src/DataTable/utils/getFieldPathToField.ts +0 -10
- package/src/DataTable/utils/getIdOrCodeOrIndex.ts +0 -14
- package/src/DataTable/utils/getLastSelectedEntity.ts +0 -15
- package/src/DataTable/utils/getNewEntToSelect.ts +0 -32
- package/src/DataTable/utils/initializeHasuraWhereAndFilter.ts +0 -35
- package/src/DataTable/utils/isBottomRightCornerOfRectangle.ts +0 -27
- package/src/DataTable/utils/isEntityClean.ts +0 -15
- package/src/DataTable/utils/primarySelectedValue.ts +0 -1
- package/src/DataTable/utils/removeCleanRows.ts +0 -26
- package/src/DataTable/utils/selection.ts +0 -11
- package/src/DataTable/utils/types/Entity.ts +0 -13
- package/src/DataTable/utils/types/Field.ts +0 -4
- package/src/DataTable/utils/types/OrderBy.ts +0 -15
- package/src/DataTable/utils/types/Schema.ts +0 -5
- package/src/DataTable/utils/useDeepEqualMemo.js +0 -10
- package/src/DataTable/utils/useHotKeysWrapper.js +0 -395
- package/src/DataTable/utils/useTableEntities.ts +0 -60
- package/src/DataTable/utils/useTableParams.js +0 -361
- package/src/DataTable/utils/utils.ts +0 -39
- package/src/Timeline/TimelineEvent.tsx +0 -36
- package/src/Timeline/index.tsx +0 -21
- package/src/utils/browserUtils.ts +0 -3
- package/src/utils/determineBlackOrWhiteTextColor.ts +0 -11
- package/src/utils/getTextFromEl.ts +0 -45
- package/src/utils/handlerHelpers.ts +0 -32
- package/src/utils/hooks/index.ts +0 -1
- package/src/utils/hooks/useDeepEqualMemo.ts +0 -10
- package/src/utils/hooks/useStableReference.ts +0 -9
- package/src/utils/hotkeyUtils.tsx +0 -155
- package/src/utils/isBeingCalledExcessively.ts +0 -37
- package/style.css +0 -10537
|
@@ -1,361 +0,0 @@
|
|
|
1
|
-
import { useContext, useEffect, useMemo, useState } from "react";
|
|
2
|
-
import { change } from "redux-form";
|
|
3
|
-
import { useDispatch, useSelector } from "react-redux";
|
|
4
|
-
import { isFunction, keyBy, get } from "lodash-es";
|
|
5
|
-
import TableFormTrackerContext from "../TableFormTrackerContext";
|
|
6
|
-
import { viewColumn, openColumn } from "./viewColumn";
|
|
7
|
-
import convertSchema from "./convertSchema";
|
|
8
|
-
import { getRecordsFromIdMap } from "./withSelectedEntities";
|
|
9
|
-
import {
|
|
10
|
-
makeDataTableHandlers,
|
|
11
|
-
getQueryParams,
|
|
12
|
-
setCurrentParamsOnUrl,
|
|
13
|
-
getCurrentParamsFromUrl,
|
|
14
|
-
getCCDisplayName
|
|
15
|
-
} from "./queryParams";
|
|
16
|
-
import getTableConfigFromStorage from "./getTableConfigFromStorage";
|
|
17
|
-
|
|
18
|
-
/*
|
|
19
|
-
NOTE:
|
|
20
|
-
This haven't been tested yet. It is the first version of what we should replace withTableParams
|
|
21
|
-
and also the first bit of the DataTable.
|
|
22
|
-
*/
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Note all these options can be passed at Design Time or at Runtime (like reduxForm())
|
|
26
|
-
*
|
|
27
|
-
* @export
|
|
28
|
-
*
|
|
29
|
-
* @param {compOrOpts} compOrOpts
|
|
30
|
-
* @typedef {object} compOrOpts
|
|
31
|
-
* @property {*string} formName - required unique identifier for the table
|
|
32
|
-
* @property {Object | Function} schema - The data table schema or a function returning it. The function wll be called with props as the argument.
|
|
33
|
-
* @property {boolean} urlConnected - whether the table should connect to/update the URL
|
|
34
|
-
* @property {boolean} withSelectedEntities - whether or not to pass the selected entities
|
|
35
|
-
* @property {boolean} isCodeModel - whether the model is keyed by code instead of id in the db
|
|
36
|
-
* @property {object} defaults - tableParam defaults such as pageSize, filter, etc
|
|
37
|
-
* @property {boolean} noOrderError - won't console an error if an order is not found on schema
|
|
38
|
-
*/
|
|
39
|
-
export default function useTableParams(
|
|
40
|
-
props // This should be the same as the spread above
|
|
41
|
-
) {
|
|
42
|
-
const {
|
|
43
|
-
formName,
|
|
44
|
-
isTableParamsConnected,
|
|
45
|
-
urlConnected,
|
|
46
|
-
onlyOneFilter,
|
|
47
|
-
defaults = {},
|
|
48
|
-
// WE NEED THIS HOOK TO BE WRAPPED IN A WITHROUTER OR MOVE TO REACT-ROUTER-DOM 5
|
|
49
|
-
// BEST SOLUTION IS TO ASSUME IT IS GOING TO BE RECEIVED
|
|
50
|
-
history,
|
|
51
|
-
withSelectedEntities,
|
|
52
|
-
tableParams: _tableParams,
|
|
53
|
-
schema: __schema,
|
|
54
|
-
noForm,
|
|
55
|
-
orderByFirstColumn,
|
|
56
|
-
withDisplayOptions,
|
|
57
|
-
syncDisplayOptionsToDb,
|
|
58
|
-
tableConfigurations,
|
|
59
|
-
isViewable,
|
|
60
|
-
isOpenable,
|
|
61
|
-
showEmptyColumnsByDefault,
|
|
62
|
-
isSimple,
|
|
63
|
-
entities: _origEntities = [],
|
|
64
|
-
cellRenderer,
|
|
65
|
-
additionalFilter,
|
|
66
|
-
additionalOrFilter,
|
|
67
|
-
doNotCoercePageSize,
|
|
68
|
-
isLocalCall
|
|
69
|
-
} = props;
|
|
70
|
-
const isInfinite = props.isInfinite || isSimple || !props.withPaging;
|
|
71
|
-
const additionalFilterToUse =
|
|
72
|
-
typeof additionalFilter === "function"
|
|
73
|
-
? additionalFilter.bind(this, props)
|
|
74
|
-
: () => additionalFilter;
|
|
75
|
-
|
|
76
|
-
const additionalOrFilterToUse =
|
|
77
|
-
typeof additionalOrFilter === "function"
|
|
78
|
-
? additionalOrFilter.bind(this, props)
|
|
79
|
-
: () => additionalOrFilter;
|
|
80
|
-
|
|
81
|
-
let _schema;
|
|
82
|
-
if (isFunction(__schema)) _schema = __schema(props);
|
|
83
|
-
else _schema = __schema;
|
|
84
|
-
const convertedSchema = convertSchema(_schema);
|
|
85
|
-
|
|
86
|
-
if (isLocalCall) {
|
|
87
|
-
if (!noForm && (!formName || formName === "tgDataTable")) {
|
|
88
|
-
throw new Error(
|
|
89
|
-
"Please pass a unique 'formName' prop to the locally connected <DataTable/> component with schema: ",
|
|
90
|
-
_schema
|
|
91
|
-
);
|
|
92
|
-
}
|
|
93
|
-
if (orderByFirstColumn && !defaults?.order?.length) {
|
|
94
|
-
const r = [getCCDisplayName(convertedSchema.fields[0])];
|
|
95
|
-
defaults.order = r;
|
|
96
|
-
}
|
|
97
|
-
} else {
|
|
98
|
-
//in user instantiated withTableParams() call
|
|
99
|
-
if (!formName || formName === "tgDataTable") {
|
|
100
|
-
throw new Error(
|
|
101
|
-
"Please pass a unique 'formName' prop to the withTableParams() with schema: ",
|
|
102
|
-
_schema
|
|
103
|
-
);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const [showForcedHiddenColumns, setShowForcedHidden] = useState(() => {
|
|
108
|
-
if (showEmptyColumnsByDefault) {
|
|
109
|
-
return true;
|
|
110
|
-
}
|
|
111
|
-
return false;
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
const [tableConfig, setTableConfig] = useState({ fieldOptions: [] });
|
|
115
|
-
|
|
116
|
-
useEffect(() => {
|
|
117
|
-
let newTableConfig = {};
|
|
118
|
-
if (withDisplayOptions) {
|
|
119
|
-
if (syncDisplayOptionsToDb) {
|
|
120
|
-
newTableConfig = tableConfigurations && tableConfigurations[0];
|
|
121
|
-
} else {
|
|
122
|
-
newTableConfig = getTableConfigFromStorage(formName);
|
|
123
|
-
}
|
|
124
|
-
if (!newTableConfig) {
|
|
125
|
-
newTableConfig = {
|
|
126
|
-
fieldOptions: []
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
setTableConfig(newTableConfig);
|
|
131
|
-
}, [
|
|
132
|
-
formName,
|
|
133
|
-
syncDisplayOptionsToDb,
|
|
134
|
-
tableConfigurations,
|
|
135
|
-
withDisplayOptions
|
|
136
|
-
]);
|
|
137
|
-
|
|
138
|
-
// make user set page size persist
|
|
139
|
-
const userSetPageSize =
|
|
140
|
-
tableConfig?.userSetPageSize && parseInt(tableConfig.userSetPageSize, 10);
|
|
141
|
-
if (!syncDisplayOptionsToDb && userSetPageSize) {
|
|
142
|
-
defaults.pageSize = userSetPageSize;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
const {
|
|
146
|
-
reduxFormSearchInput = "",
|
|
147
|
-
onlyShowRowsWErrors,
|
|
148
|
-
reduxFormCellValidation,
|
|
149
|
-
reduxFormEntities,
|
|
150
|
-
reduxFormSelectedCells = {},
|
|
151
|
-
reduxFormSelectedEntityIdMap = {},
|
|
152
|
-
reduxFormQueryParams = {}
|
|
153
|
-
} = useSelector(state => {
|
|
154
|
-
if (!state.form[formName]) return {};
|
|
155
|
-
return state.form[formName].values || {};
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
const entities = reduxFormEntities || _origEntities;
|
|
159
|
-
|
|
160
|
-
const { schema } = useMemo(() => {
|
|
161
|
-
const schema = convertSchema(_schema);
|
|
162
|
-
if (isViewable) {
|
|
163
|
-
schema.fields = [viewColumn, ...schema.fields];
|
|
164
|
-
}
|
|
165
|
-
if (isOpenable) {
|
|
166
|
-
schema.fields = [openColumn, ...schema.fields];
|
|
167
|
-
}
|
|
168
|
-
// this must come before handling orderings.
|
|
169
|
-
schema.fields = schema.fields.map(field => {
|
|
170
|
-
if (field.placementPath) {
|
|
171
|
-
return {
|
|
172
|
-
...field,
|
|
173
|
-
sortDisabled:
|
|
174
|
-
field.sortDisabled ||
|
|
175
|
-
(typeof field.path === "string" && field.path.includes(".")),
|
|
176
|
-
path: field.placementPath
|
|
177
|
-
};
|
|
178
|
-
} else {
|
|
179
|
-
return field;
|
|
180
|
-
}
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
if (withDisplayOptions) {
|
|
184
|
-
const fieldOptsByPath = keyBy(tableConfig.fieldOptions, "path");
|
|
185
|
-
schema.fields = schema.fields.map(field => {
|
|
186
|
-
const fieldOpt = fieldOptsByPath[field.path];
|
|
187
|
-
let noValsForField = false;
|
|
188
|
-
// only add this hidden column ability if no paging
|
|
189
|
-
if (
|
|
190
|
-
!showForcedHiddenColumns &&
|
|
191
|
-
withDisplayOptions &&
|
|
192
|
-
(isSimple || isInfinite)
|
|
193
|
-
) {
|
|
194
|
-
noValsForField = entities.every(e => {
|
|
195
|
-
const val = get(e, field.path);
|
|
196
|
-
return field.render
|
|
197
|
-
? !field.render(val, e)
|
|
198
|
-
: cellRenderer[field.path]
|
|
199
|
-
? !cellRenderer[field.path](val, e)
|
|
200
|
-
: !val;
|
|
201
|
-
});
|
|
202
|
-
}
|
|
203
|
-
if (noValsForField) {
|
|
204
|
-
return {
|
|
205
|
-
...field,
|
|
206
|
-
isHidden: true,
|
|
207
|
-
isForcedHidden: true
|
|
208
|
-
};
|
|
209
|
-
} else if (fieldOpt) {
|
|
210
|
-
return {
|
|
211
|
-
...field,
|
|
212
|
-
isHidden: fieldOpt.isHidden
|
|
213
|
-
};
|
|
214
|
-
} else {
|
|
215
|
-
return field;
|
|
216
|
-
}
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
const columnOrderings = tableConfig.columnOrderings;
|
|
220
|
-
if (columnOrderings) {
|
|
221
|
-
const fieldsWithOrders = [];
|
|
222
|
-
const fieldsWithoutOrder = [];
|
|
223
|
-
// if a new field has been added since the orderings were set then we want
|
|
224
|
-
// it to be at the end instead of the beginning
|
|
225
|
-
schema.fields.forEach(field => {
|
|
226
|
-
if (columnOrderings.indexOf(field.path) > -1) {
|
|
227
|
-
fieldsWithOrders.push(field);
|
|
228
|
-
} else {
|
|
229
|
-
fieldsWithoutOrder.push(field);
|
|
230
|
-
}
|
|
231
|
-
});
|
|
232
|
-
schema.fields = fieldsWithOrders
|
|
233
|
-
.sort(({ path: path1 }, { path: path2 }) => {
|
|
234
|
-
return (
|
|
235
|
-
columnOrderings.indexOf(path1) - columnOrderings.indexOf(path2)
|
|
236
|
-
);
|
|
237
|
-
})
|
|
238
|
-
.concat(fieldsWithoutOrder);
|
|
239
|
-
setTableConfig(prev => ({
|
|
240
|
-
...prev,
|
|
241
|
-
columnOrderings: schema.fields.map(f => f.path)
|
|
242
|
-
}));
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
return { schema };
|
|
246
|
-
}, [
|
|
247
|
-
_schema,
|
|
248
|
-
cellRenderer,
|
|
249
|
-
entities,
|
|
250
|
-
isInfinite,
|
|
251
|
-
isOpenable,
|
|
252
|
-
isSimple,
|
|
253
|
-
isViewable,
|
|
254
|
-
showForcedHiddenColumns,
|
|
255
|
-
tableConfig,
|
|
256
|
-
withDisplayOptions
|
|
257
|
-
]);
|
|
258
|
-
|
|
259
|
-
const selectedEntities = withSelectedEntities
|
|
260
|
-
? getRecordsFromIdMap(reduxFormSelectedEntityIdMap)
|
|
261
|
-
: undefined;
|
|
262
|
-
|
|
263
|
-
const currentParams = urlConnected
|
|
264
|
-
? getCurrentParamsFromUrl(history.location) //important to use history location and not ownProps.location because for some reason the location path lags one render behind!!
|
|
265
|
-
: reduxFormQueryParams;
|
|
266
|
-
|
|
267
|
-
currentParams.searchTerm = reduxFormSearchInput;
|
|
268
|
-
|
|
269
|
-
props = {
|
|
270
|
-
...props,
|
|
271
|
-
...getQueryParams({
|
|
272
|
-
doNotCoercePageSize,
|
|
273
|
-
currentParams,
|
|
274
|
-
entities: props.entities, // for local table
|
|
275
|
-
urlConnected,
|
|
276
|
-
defaults: props.defaults,
|
|
277
|
-
schema: convertedSchema,
|
|
278
|
-
isInfinite,
|
|
279
|
-
isLocalCall,
|
|
280
|
-
additionalFilter: additionalFilterToUse,
|
|
281
|
-
additionalOrFilter: additionalOrFilterToUse,
|
|
282
|
-
noOrderError: props.noOrderError,
|
|
283
|
-
isCodeModel: props.isCodeModel,
|
|
284
|
-
ownProps: props
|
|
285
|
-
})
|
|
286
|
-
};
|
|
287
|
-
|
|
288
|
-
const dispatch = useDispatch();
|
|
289
|
-
let tableParams;
|
|
290
|
-
if (!isTableParamsConnected) {
|
|
291
|
-
const updateSearch = val => {
|
|
292
|
-
setTimeout(() => {
|
|
293
|
-
dispatch(change(formName, "reduxFormSearchInput", val || ""));
|
|
294
|
-
});
|
|
295
|
-
};
|
|
296
|
-
|
|
297
|
-
let setNewParams;
|
|
298
|
-
if (urlConnected) {
|
|
299
|
-
setNewParams = newParams => {
|
|
300
|
-
setCurrentParamsOnUrl(newParams, history.replace);
|
|
301
|
-
dispatch(change(formName, "reduxFormQueryParams", newParams)); //we always will update the redux params as a workaround for withRouter not always working if inside a redux-connected container https://github.com/ReactTraining/react-router/issues/5037
|
|
302
|
-
};
|
|
303
|
-
} else {
|
|
304
|
-
setNewParams = function (newParams) {
|
|
305
|
-
dispatch(change(formName, "reduxFormQueryParams", newParams));
|
|
306
|
-
};
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
const bindThese = makeDataTableHandlers({
|
|
310
|
-
setNewParams,
|
|
311
|
-
updateSearch,
|
|
312
|
-
defaults,
|
|
313
|
-
onlyOneFilter
|
|
314
|
-
});
|
|
315
|
-
|
|
316
|
-
const boundDispatchProps = {};
|
|
317
|
-
//bind currentParams to actions
|
|
318
|
-
Object.keys(bindThese).forEach(function (key) {
|
|
319
|
-
const action = bindThese[key];
|
|
320
|
-
boundDispatchProps[key] = function (...args) {
|
|
321
|
-
action(...args, currentParams);
|
|
322
|
-
};
|
|
323
|
-
});
|
|
324
|
-
|
|
325
|
-
const changeFormValue = (...args) => dispatch(change(formName, ...args));
|
|
326
|
-
|
|
327
|
-
tableParams = {
|
|
328
|
-
changeFormValue,
|
|
329
|
-
selectedEntities,
|
|
330
|
-
..._tableParams,
|
|
331
|
-
...props,
|
|
332
|
-
...boundDispatchProps,
|
|
333
|
-
form: formName, //this will override the default redux form name
|
|
334
|
-
isTableParamsConnected: true //let the table know not to do local sorting/filtering etc.
|
|
335
|
-
};
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
const formTracker = useContext(TableFormTrackerContext);
|
|
339
|
-
useEffect(() => {
|
|
340
|
-
if (formTracker.isActive && !formTracker.formNames.includes(formName)) {
|
|
341
|
-
formTracker.pushFormName(formName);
|
|
342
|
-
}
|
|
343
|
-
}, [formTracker, formName]);
|
|
344
|
-
|
|
345
|
-
return {
|
|
346
|
-
...props,
|
|
347
|
-
selectedEntities,
|
|
348
|
-
tableParams,
|
|
349
|
-
currentParams,
|
|
350
|
-
schema,
|
|
351
|
-
entities,
|
|
352
|
-
reduxFormSearchInput,
|
|
353
|
-
onlyShowRowsWErrors,
|
|
354
|
-
reduxFormCellValidation,
|
|
355
|
-
reduxFormSelectedCells,
|
|
356
|
-
reduxFormSelectedEntityIdMap,
|
|
357
|
-
reduxFormQueryParams,
|
|
358
|
-
showForcedHiddenColumns,
|
|
359
|
-
setShowForcedHidden
|
|
360
|
-
};
|
|
361
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { getIdOrCodeOrIndex } from "./getIdOrCodeOrIndex";
|
|
2
|
-
import { Entity } from "./types/Entity";
|
|
3
|
-
import { Field } from "./types/Field";
|
|
4
|
-
|
|
5
|
-
export const getFieldPathToIndex = (schema: { fields: Field[] }) => {
|
|
6
|
-
const fieldToIndex: { [path: string]: number } = {};
|
|
7
|
-
schema.fields.forEach((f, i) => {
|
|
8
|
-
fieldToIndex[f.path] = i;
|
|
9
|
-
});
|
|
10
|
-
return fieldToIndex;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
export const defaultParsePaste = (str: string) => {
|
|
14
|
-
return str.split(/\r\n|\n|\r/).map(row => row.split("\t"));
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export const getEntityIdToEntity = (entities: Entity[]) => {
|
|
18
|
-
const entityIdToEntity: { [id: string]: { e: Entity; i: number } } = {};
|
|
19
|
-
entities.forEach((e, i) => {
|
|
20
|
-
entityIdToEntity[getIdOrCodeOrIndex(e, i)] = { e, i };
|
|
21
|
-
});
|
|
22
|
-
return entityIdToEntity;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
const endsWithNumber = (str: string) => {
|
|
26
|
-
return /[0-9]+$/.test(str);
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
export const getNumberStrAtEnd = (str: string) => {
|
|
30
|
-
if (endsWithNumber(str)) {
|
|
31
|
-
return str.match(/[0-9]+$/)?.[0];
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
return null;
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
export const stripNumberAtEnd = (str: string) => {
|
|
38
|
-
return str?.replace?.(getNumberStrAtEnd(str) || "", "");
|
|
39
|
-
};
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import dayjs from "dayjs";
|
|
3
|
-
import { Classes } from "@blueprintjs/core";
|
|
4
|
-
import classNames from "classnames";
|
|
5
|
-
import relativeTime from "dayjs/plugin/relativeTime";
|
|
6
|
-
|
|
7
|
-
dayjs.extend(relativeTime);
|
|
8
|
-
|
|
9
|
-
interface TimelineEventProps {
|
|
10
|
-
date: string | number | Date | dayjs.Dayjs;
|
|
11
|
-
children?: React.ReactNode;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
function TimelineEvent({ date, children }: TimelineEventProps) {
|
|
15
|
-
return (
|
|
16
|
-
<div className="tg-timeline-event">
|
|
17
|
-
<div
|
|
18
|
-
style={{
|
|
19
|
-
display: "flex",
|
|
20
|
-
alignItems: "center"
|
|
21
|
-
}}
|
|
22
|
-
>
|
|
23
|
-
<div className="tg-timeline-circle" />
|
|
24
|
-
{children}
|
|
25
|
-
<div
|
|
26
|
-
style={{ marginLeft: 5 }}
|
|
27
|
-
className={classNames(Classes.TEXT_SMALL, Classes.TEXT_MUTED)}
|
|
28
|
-
>
|
|
29
|
-
({dayjs(date).fromNow()})
|
|
30
|
-
</div>
|
|
31
|
-
</div>
|
|
32
|
-
</div>
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export default TimelineEvent;
|
package/src/Timeline/index.tsx
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import React, { ReactNode, FC } from "react";
|
|
2
|
-
import "./style.css";
|
|
3
|
-
|
|
4
|
-
interface TimelineProps {
|
|
5
|
-
children: ReactNode;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
const Timeline: FC<TimelineProps> = props => {
|
|
9
|
-
return (
|
|
10
|
-
<div className="tg-timeline">
|
|
11
|
-
{React.Children.count(props.children) > 1 && (
|
|
12
|
-
<div className="tg-timeline-line" />
|
|
13
|
-
)}
|
|
14
|
-
{props.children}
|
|
15
|
-
</div>
|
|
16
|
-
);
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export { default as TimelineEvent } from "./TimelineEvent";
|
|
20
|
-
|
|
21
|
-
export default Timeline;
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/* Copyright (C) 2018 TeselaGen Biotechnology, Inc. */
|
|
2
|
-
import Color from "color";
|
|
3
|
-
|
|
4
|
-
export default function determineBlackOrWhiteTextColor(c: string) {
|
|
5
|
-
try {
|
|
6
|
-
return Color(c).isLight() ? "#000000" : "#FFFFFF";
|
|
7
|
-
} catch (e) {
|
|
8
|
-
console.error("Error in color parsing:", e);
|
|
9
|
-
return "#000000"; // Fallback to black if color parsing fails
|
|
10
|
-
}
|
|
11
|
-
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
|
-
type Node = React.ReactElement<{ children?: Node[] | Node }> | string | number;
|
|
4
|
-
|
|
5
|
-
const isReactElement = (
|
|
6
|
-
el: Node
|
|
7
|
-
): el is React.ReactElement<{ children?: Node[] | Node }> => {
|
|
8
|
-
if (el) {
|
|
9
|
-
const newEl = el as React.ReactElement<{ children?: Node[] | Node }>;
|
|
10
|
-
if (newEl.props && newEl.props.children) {
|
|
11
|
-
return true;
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
return false;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export default function getTextFromEl<T extends Node>(
|
|
18
|
-
el: T,
|
|
19
|
-
options: { lowerCase?: boolean } = {}
|
|
20
|
-
): string {
|
|
21
|
-
const { lowerCase } = options;
|
|
22
|
-
if (React.isValidElement<{ children?: Node[] | Node }>(el)) {
|
|
23
|
-
return el && el.props && el.props.children
|
|
24
|
-
? (Array.isArray(el.props.children)
|
|
25
|
-
? el.props.children
|
|
26
|
-
: [el.props.children]
|
|
27
|
-
).reduce((acc: string, child) => {
|
|
28
|
-
if (isReactElement(child)) {
|
|
29
|
-
acc += getTextFromEl(child);
|
|
30
|
-
} else if (typeof child === "string") {
|
|
31
|
-
if (lowerCase) {
|
|
32
|
-
acc += child.toLowerCase();
|
|
33
|
-
} else {
|
|
34
|
-
acc += child;
|
|
35
|
-
}
|
|
36
|
-
} else if (typeof child === "number") {
|
|
37
|
-
acc += child + "";
|
|
38
|
-
}
|
|
39
|
-
return acc;
|
|
40
|
-
}, "")
|
|
41
|
-
: "";
|
|
42
|
-
} else {
|
|
43
|
-
return el as string;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
export const onEnterHelper = (
|
|
2
|
-
callback: (event: React.KeyboardEvent<Element>) => void
|
|
3
|
-
) => ({
|
|
4
|
-
onKeyDown: (event: React.KeyboardEvent<Element>) => {
|
|
5
|
-
if (event.key === "Enter") {
|
|
6
|
-
callback(event);
|
|
7
|
-
}
|
|
8
|
-
}
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
export const onBlurHelper = (
|
|
12
|
-
callback: (event: React.FocusEvent<Element>) => void
|
|
13
|
-
) => ({
|
|
14
|
-
onBlur: (event: React.FocusEvent<Element>) => {
|
|
15
|
-
callback(event);
|
|
16
|
-
}
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
export const onEnterOrBlurHelper = (
|
|
20
|
-
callback: (
|
|
21
|
-
event: React.KeyboardEvent<Element> | React.FocusEvent<Element>
|
|
22
|
-
) => void
|
|
23
|
-
) => ({
|
|
24
|
-
onKeyDown: function (event: React.KeyboardEvent<Element>) {
|
|
25
|
-
if (event.key === "Enter") {
|
|
26
|
-
callback(event);
|
|
27
|
-
}
|
|
28
|
-
},
|
|
29
|
-
onBlur: function (event: React.FocusEvent<Element>) {
|
|
30
|
-
callback(event);
|
|
31
|
-
}
|
|
32
|
-
});
|
package/src/utils/hooks/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { useDeepEqualMemo } from "./useDeepEqualMemo";
|