@teselagen/ui 0.7.34 → 0.7.36
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/isBeingCalledExcessively.js +2 -0
- package/package.json +1 -1
- package/style.css +26 -10
- package/DataTable/utils/filterLocalEntitiesToHasura.d.ts +0 -5
- package/DataTable/utils/initializeHasuraWhereAndFilter.d.ts +0 -2
- package/DataTable/utils/tableQueryParamsToHasuraClauses.d.ts +0 -26
- package/src/AdvancedOptions.js +0 -33
- package/src/AdvancedOptions.spec.js +0 -26
- package/src/AssignDefaultsModeContext.js +0 -22
- package/src/AsyncValidateFieldSpinner/index.js +0 -12
- package/src/BlueprintError/index.js +0 -14
- package/src/BounceLoader/index.js +0 -16
- package/src/BounceLoader/style.css +0 -45
- package/src/CollapsibleCard/index.js +0 -68
- package/src/CollapsibleCard/style.css +0 -23
- package/src/DNALoader/index.js +0 -20
- package/src/DNALoader/style.css +0 -251
- package/src/DataTable/CellDragHandle.js +0 -132
- package/src/DataTable/ColumnFilterMenu.js +0 -62
- package/src/DataTable/Columns.js +0 -979
- package/src/DataTable/DisabledLoadingComponent.js +0 -15
- package/src/DataTable/DisplayOptions.js +0 -199
- package/src/DataTable/DropdownCell.js +0 -61
- package/src/DataTable/EditableCell.js +0 -44
- package/src/DataTable/FilterAndSortMenu.js +0 -388
- package/src/DataTable/PagingTool.js +0 -225
- package/src/DataTable/RenderCell.js +0 -191
- package/src/DataTable/SearchBar.js +0 -69
- package/src/DataTable/SortableColumns.js +0 -100
- package/src/DataTable/TableFormTrackerContext.js +0 -10
- package/src/DataTable/ThComponent.js +0 -44
- package/src/DataTable/dataTableEnhancer.js +0 -41
- package/src/DataTable/defaultFormatters.js +0 -32
- package/src/DataTable/defaultValidators.js +0 -40
- package/src/DataTable/editCellHelper.js +0 -44
- package/src/DataTable/getCellVal.js +0 -20
- package/src/DataTable/getVals.js +0 -8
- package/src/DataTable/index.js +0 -3209
- package/src/DataTable/isTruthy.js +0 -12
- package/src/DataTable/isValueEmpty.js +0 -3
- package/src/DataTable/style.css +0 -608
- package/src/DataTable/utils/convertSchema.js +0 -69
- package/src/DataTable/utils/filterLocalEntitiesToHasura.js +0 -236
- package/src/DataTable/utils/filterLocalEntitiesToHasura.test.js +0 -587
- package/src/DataTable/utils/formatPasteData.js +0 -16
- package/src/DataTable/utils/getAllRows.js +0 -11
- package/src/DataTable/utils/getCellCopyText.js +0 -7
- package/src/DataTable/utils/getCellInfo.js +0 -36
- package/src/DataTable/utils/getFieldPathToField.js +0 -7
- package/src/DataTable/utils/getIdOrCodeOrIndex.js +0 -9
- package/src/DataTable/utils/getLastSelectedEntity.js +0 -11
- package/src/DataTable/utils/getNewEntToSelect.js +0 -25
- package/src/DataTable/utils/getRowCopyText.js +0 -28
- package/src/DataTable/utils/getTableConfigFromStorage.js +0 -5
- package/src/DataTable/utils/handleCopyColumn.js +0 -21
- package/src/DataTable/utils/handleCopyHelper.js +0 -15
- package/src/DataTable/utils/handleCopyRows.js +0 -23
- package/src/DataTable/utils/handleCopyTable.js +0 -16
- package/src/DataTable/utils/index.js +0 -55
- package/src/DataTable/utils/initializeHasuraWhereAndFilter.js +0 -26
- package/src/DataTable/utils/isBottomRightCornerOfRectangle.js +0 -20
- package/src/DataTable/utils/isEntityClean.js +0 -15
- package/src/DataTable/utils/primarySelectedValue.js +0 -1
- package/src/DataTable/utils/queryParams.js +0 -350
- package/src/DataTable/utils/removeCleanRows.js +0 -22
- package/src/DataTable/utils/rowClick.js +0 -181
- package/src/DataTable/utils/selection.js +0 -8
- package/src/DataTable/utils/tableQueryParamsToHasuraClauses.js +0 -253
- package/src/DataTable/utils/tableQueryParamsToHasuraClauses.test.js +0 -206
- package/src/DataTable/utils/useTableEntities.js +0 -38
- package/src/DataTable/utils/utils.js +0 -37
- package/src/DataTable/utils/withSelectedEntities.js +0 -65
- package/src/DataTable/utils/withTableParams.js +0 -288
- package/src/DataTable/validateTableWideErrors.js +0 -160
- package/src/DataTable/viewColumn.js +0 -97
- package/src/DialogFooter/index.js +0 -86
- package/src/DialogFooter/style.css +0 -9
- package/src/DropdownButton.js +0 -36
- package/src/FillWindow.css +0 -6
- package/src/FillWindow.js +0 -69
- package/src/FormComponents/FormSeparator.js +0 -9
- package/src/FormComponents/LoadingDots.js +0 -14
- package/src/FormComponents/Uploader.js +0 -1278
- package/src/FormComponents/getNewName.js +0 -31
- package/src/FormComponents/index.js +0 -1266
- package/src/FormComponents/itemUpload.js +0 -84
- package/src/FormComponents/sortify.js +0 -73
- package/src/FormComponents/style.css +0 -275
- package/src/FormComponents/tryToMatchSchemas.js +0 -264
- package/src/FormComponents/utils.js +0 -6
- package/src/HotkeysDialog/index.js +0 -79
- package/src/HotkeysDialog/style.css +0 -54
- package/src/InfoHelper/index.js +0 -78
- package/src/InfoHelper/style.css +0 -7
- package/src/IntentText/index.js +0 -18
- package/src/Loading/index.js +0 -70
- package/src/Loading/style.css +0 -4
- package/src/MatchHeaders.js +0 -234
- package/src/MenuBar/index.js +0 -423
- package/src/MenuBar/style.css +0 -45
- package/src/PromptUnsavedChanges/index.js +0 -38
- package/src/ResizableDraggableDialog/index.js +0 -141
- package/src/ResizableDraggableDialog/style.css +0 -42
- package/src/ScrollToTop/index.js +0 -72
- package/src/SimpleStepViz.js +0 -22
- package/src/Tag.js +0 -112
- package/src/TagSelect/index.js +0 -69
- package/src/TagSelect/style.css +0 -13
- package/src/TgHtmlSelect/index.js +0 -20
- package/src/TgSelect/index.js +0 -537
- package/src/TgSelect/style.css +0 -61
- package/src/TgSuggest/index.js +0 -124
- package/src/Timeline/TimelineEvent.js +0 -31
- package/src/Timeline/index.js +0 -15
- package/src/Timeline/style.css +0 -29
- package/src/UploadCsvWizard.css +0 -4
- package/src/UploadCsvWizard.js +0 -719
- package/src/autoTooltip.js +0 -201
- package/src/constants.js +0 -1
- package/src/customIcons.js +0 -361
- package/src/enhancers/withDialog/index.js +0 -196
- package/src/enhancers/withDialog/tg_modalState.js +0 -47
- package/src/enhancers/withField.js +0 -20
- package/src/enhancers/withFields.js +0 -11
- package/src/enhancers/withLocalStorage.js +0 -11
- package/src/index.js +0 -88
- package/src/rerenderOnWindowResize.js +0 -26
- package/src/showAppSpinner.js +0 -12
- package/src/showConfirmationDialog/index.js +0 -148
- package/src/showDialogOnDocBody.js +0 -33
- package/src/style.css +0 -265
- package/src/throwFormError.js +0 -16
- package/src/toastr.js +0 -148
- package/src/typeToCommonType.js +0 -6
- package/src/useDialog.js +0 -63
- package/src/utils/adHoc.js +0 -10
- package/src/utils/basicHandleActionsWithFullState.js +0 -14
- package/src/utils/browserUtils.js +0 -3
- package/src/utils/combineReducersWithFullState.js +0 -14
- package/src/utils/commandControls.js +0 -82
- package/src/utils/commandUtils.js +0 -112
- package/src/utils/determineBlackOrWhiteTextColor.js +0 -4
- package/src/utils/getDayjsFormatter.js +0 -35
- package/src/utils/getTextFromEl.js +0 -28
- package/src/utils/handlerHelpers.js +0 -24
- package/src/utils/hooks/index.js +0 -1
- package/src/utils/hooks/useDeepEqualMemo.js +0 -15
- package/src/utils/hooks/useStableReference.js +0 -9
- package/src/utils/hotkeyUtils.js +0 -131
- package/src/utils/isBeingCalledExcessively.js +0 -24
- package/src/utils/menuUtils.js +0 -433
- package/src/utils/popoverOverflowModifiers.js +0 -11
- package/src/utils/pureNoFunc.js +0 -31
- package/src/utils/renderOnDoc.js +0 -32
- package/src/utils/showProgressToast.js +0 -22
- package/src/utils/tagUtils.js +0 -45
- package/src/utils/tgFormValues.js +0 -35
- package/src/utils/useTraceUpdate.js +0 -19
- package/src/utils/withSelectTableRecords.js +0 -43
- package/src/utils/withStore.js +0 -10
- package/src/wrapDialog.js +0 -116
package/src/TgSelect/index.js
DELETED
|
@@ -1,537 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-empty-function */
|
|
2
|
-
import { MultiSelect, getCreateNewItem } from "@blueprintjs/select";
|
|
3
|
-
import { Keys, Button, MenuItem, Tag } from "@blueprintjs/core";
|
|
4
|
-
import React, { useEffect, useState } from "react";
|
|
5
|
-
import { filter, isEqual } from "lodash-es";
|
|
6
|
-
import classNames from "classnames";
|
|
7
|
-
import "./style.css";
|
|
8
|
-
import { withProps } from "recompose";
|
|
9
|
-
import fuzzysearch from "fuzzysearch";
|
|
10
|
-
import getTextFromEl from "../utils/getTextFromEl";
|
|
11
|
-
import { getTagColorStyle, getTagProps } from "../utils/tagUtils";
|
|
12
|
-
import popoverOverflowModifiers from "../utils/popoverOverflowModifiers";
|
|
13
|
-
import { compose } from "redux";
|
|
14
|
-
|
|
15
|
-
class TgSelect extends React.Component {
|
|
16
|
-
constructor(props) {
|
|
17
|
-
super(props);
|
|
18
|
-
const { autoOpen = false } = this.props;
|
|
19
|
-
|
|
20
|
-
this.state = {
|
|
21
|
-
isOpen: autoOpen,
|
|
22
|
-
activeItem: null,
|
|
23
|
-
query: ""
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
setOpenState = isOpen => {
|
|
27
|
-
const { handleOpenChange } = this.props;
|
|
28
|
-
if (handleOpenChange) {
|
|
29
|
-
handleOpenChange(isOpen);
|
|
30
|
-
}
|
|
31
|
-
this.setState({ isOpen });
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
static defaultProps = {
|
|
35
|
-
onChange: () => {},
|
|
36
|
-
options: [],
|
|
37
|
-
unfilteredOptions: [],
|
|
38
|
-
value: undefined
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
itemRenderer = (i, { index, handleClick, modifiers }) => {
|
|
42
|
-
const optionRenderer = this.getOptionRenderer();
|
|
43
|
-
const onClick = i.onClick || handleClick;
|
|
44
|
-
return (
|
|
45
|
-
<div //we specifically don't use a BP MenuItem component here because the menu item is too slow when 100s are loaded and will cause the component to lag
|
|
46
|
-
onClick={modifiers.disabled ? undefined : onClick}
|
|
47
|
-
key={index}
|
|
48
|
-
className={classNames(
|
|
49
|
-
"tg-select-option bp3-menu-item bp3-fill bp3-text-overflow-ellipsis",
|
|
50
|
-
{
|
|
51
|
-
"bp3-active": modifiers.active,
|
|
52
|
-
"bp3-disabled": modifiers.disabled
|
|
53
|
-
}
|
|
54
|
-
)}
|
|
55
|
-
>
|
|
56
|
-
{optionRenderer ? optionRenderer(i, this.props) : i.label}
|
|
57
|
-
</div>
|
|
58
|
-
);
|
|
59
|
-
};
|
|
60
|
-
tagRenderer = i => {
|
|
61
|
-
if (!i || (!this.props.multi && this.state.query)) {
|
|
62
|
-
return null;
|
|
63
|
-
}
|
|
64
|
-
// return i
|
|
65
|
-
return i.label;
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
handleItemSelect = (item, e) => {
|
|
69
|
-
e.stopPropagation();
|
|
70
|
-
const { onChange, value, multi, closeOnSelect, isTagSelect } = this.props;
|
|
71
|
-
this.setState({ activeItem: null });
|
|
72
|
-
if (multi) {
|
|
73
|
-
let valArray = getValueArray(value);
|
|
74
|
-
|
|
75
|
-
if (closeOnSelect || item.closeOnSelect) {
|
|
76
|
-
this.setOpenState(false);
|
|
77
|
-
this.input && this.input.blur();
|
|
78
|
-
}
|
|
79
|
-
if (
|
|
80
|
-
isTagSelect &&
|
|
81
|
-
item.value &&
|
|
82
|
-
item.value.includes &&
|
|
83
|
-
item.value.includes(":")
|
|
84
|
-
) {
|
|
85
|
-
const topLevelId = item.value.split(":")[0];
|
|
86
|
-
valArray = valArray.filter(val => {
|
|
87
|
-
if (val?.value && val.value.includes && val.value.includes(":")) {
|
|
88
|
-
const valId = val.value.split(":")[0];
|
|
89
|
-
if (valId === topLevelId) {
|
|
90
|
-
return false;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
return true;
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
return onChange([...valArray, item], e);
|
|
97
|
-
} else {
|
|
98
|
-
this.setOpenState(false);
|
|
99
|
-
this.input && this.input.blur();
|
|
100
|
-
return onChange(item, e);
|
|
101
|
-
}
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
handleTagRemove = (e, tagProps) => {
|
|
105
|
-
const { onChange, value } = this.props;
|
|
106
|
-
const filteredVals = filter(
|
|
107
|
-
value,
|
|
108
|
-
(obj, i) => !isEqual(i, tagProps["data-tag-index"])
|
|
109
|
-
);
|
|
110
|
-
e.stopPropagation();
|
|
111
|
-
onChange(filteredVals);
|
|
112
|
-
this.setOpenState(false);
|
|
113
|
-
this.input.focus();
|
|
114
|
-
};
|
|
115
|
-
handleTagInputRemove = (val, index) => {
|
|
116
|
-
const { onChange, value } = this.props;
|
|
117
|
-
const filteredVals = filter(value, (obj, i) => !isEqual(i, index));
|
|
118
|
-
// e.stopPropagation();
|
|
119
|
-
return onChange(filteredVals);
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
handleClear = e => {
|
|
123
|
-
const { multi, value } = this.props;
|
|
124
|
-
|
|
125
|
-
e.stopPropagation();
|
|
126
|
-
e.preventDefault();
|
|
127
|
-
let newValue = null;
|
|
128
|
-
if (multi) {
|
|
129
|
-
newValue = filter(value, obj => obj?.disabled) || [];
|
|
130
|
-
} else if (value && value.disabled) {
|
|
131
|
-
newValue = value;
|
|
132
|
-
}
|
|
133
|
-
const { onChange } = this.props;
|
|
134
|
-
this.setState({ query: "" });
|
|
135
|
-
onChange(newValue);
|
|
136
|
-
this.setOpenState(false);
|
|
137
|
-
this.input.focus();
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
itemListPredicate = (queryString, item) => {
|
|
141
|
-
// this will hide an option if it returns false
|
|
142
|
-
// each item is an individual option item
|
|
143
|
-
const { isSimpleSearch } = this.props;
|
|
144
|
-
|
|
145
|
-
return itemListPredicate(queryString, item, isSimpleSearch);
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
onQueryChange = query => {
|
|
149
|
-
const { onInputChange = () => {} } = this.props;
|
|
150
|
-
this.setState({
|
|
151
|
-
query
|
|
152
|
-
});
|
|
153
|
-
onInputChange(query);
|
|
154
|
-
};
|
|
155
|
-
handleActiveItemChange = (item, isCreateNewItem) => {
|
|
156
|
-
this.setState({
|
|
157
|
-
activeItem:
|
|
158
|
-
item ||
|
|
159
|
-
//if there's no item and we're in creatable mode, auto-select the create-new option
|
|
160
|
-
(isCreateNewItem || this.props.creatable ? getCreateNewItem() : null)
|
|
161
|
-
});
|
|
162
|
-
};
|
|
163
|
-
onInteraction = () => {
|
|
164
|
-
if (this.input != null && this.input !== document.activeElement) {
|
|
165
|
-
// the input is no longer focused so we can close the popover
|
|
166
|
-
this.setOpenState(false);
|
|
167
|
-
this.setState({
|
|
168
|
-
query: ""
|
|
169
|
-
});
|
|
170
|
-
} else if (!this.props.openOnKeyDown) {
|
|
171
|
-
// open the popover when focusing the tag input
|
|
172
|
-
this.setOpenState(true);
|
|
173
|
-
}
|
|
174
|
-
};
|
|
175
|
-
|
|
176
|
-
queryHasExactOptionMatch = () => {
|
|
177
|
-
//we don't want to show the creatable if the thing being created already exactly matches the label
|
|
178
|
-
return (
|
|
179
|
-
[
|
|
180
|
-
...(this.props.options || []),
|
|
181
|
-
...(Array.isArray(this.props.value)
|
|
182
|
-
? this.props.value
|
|
183
|
-
: [this.props.value])
|
|
184
|
-
].filter(o => {
|
|
185
|
-
const { label, value } = o || {};
|
|
186
|
-
const lowerQuery = (this.state.query || "").toLowerCase();
|
|
187
|
-
const lowerLabelOrVal =
|
|
188
|
-
label && label.toLowerCase
|
|
189
|
-
? label.toLowerCase()
|
|
190
|
-
: value && value.toLowerCase && value.toLowerCase();
|
|
191
|
-
const textFromEl = getTextFromEl(label);
|
|
192
|
-
|
|
193
|
-
return lowerQuery === lowerLabelOrVal || lowerQuery === textFromEl;
|
|
194
|
-
}).length > 0
|
|
195
|
-
);
|
|
196
|
-
};
|
|
197
|
-
|
|
198
|
-
getTagProps = label => {
|
|
199
|
-
const { multi, value = [], disabled: _disabled } = this.props;
|
|
200
|
-
const val = Array.isArray(value) ? value : [value];
|
|
201
|
-
const matchingVal = val.find(op => op?.label === label);
|
|
202
|
-
const disabled = _disabled || (matchingVal && matchingVal.disabled);
|
|
203
|
-
const className = matchingVal && matchingVal.className;
|
|
204
|
-
|
|
205
|
-
return {
|
|
206
|
-
...getTagColorStyle(multi && matchingVal && matchingVal.color),
|
|
207
|
-
intent: disabled ? "" : "primary",
|
|
208
|
-
minimal: true,
|
|
209
|
-
className: classNames(className, "tg-select-value", {
|
|
210
|
-
disabled
|
|
211
|
-
}),
|
|
212
|
-
onRemove: multi && !disabled ? this.handleTagRemove : null
|
|
213
|
-
};
|
|
214
|
-
};
|
|
215
|
-
|
|
216
|
-
getOptionRenderer = () => {
|
|
217
|
-
const { isTagSelect, optionRenderer, multi } = this.props;
|
|
218
|
-
|
|
219
|
-
if (isTagSelect && multi) {
|
|
220
|
-
return tagOptionRender;
|
|
221
|
-
}
|
|
222
|
-
return optionRenderer;
|
|
223
|
-
};
|
|
224
|
-
renderCreateNewOption = (query, active, handleClick) => {
|
|
225
|
-
if (this.props.renderCreateNewOption) {
|
|
226
|
-
return this.props.renderCreateNewOption(query, active, handleClick);
|
|
227
|
-
}
|
|
228
|
-
return (
|
|
229
|
-
<MenuItem
|
|
230
|
-
icon="add"
|
|
231
|
-
text={`Create "${query}"`}
|
|
232
|
-
active={active}
|
|
233
|
-
onClick={(...args) => {
|
|
234
|
-
const shouldStopEarly = this.props.onCreateNewOption?.(query);
|
|
235
|
-
if (shouldStopEarly) {
|
|
236
|
-
this.setOpenState(false);
|
|
237
|
-
} else {
|
|
238
|
-
handleClick(...args);
|
|
239
|
-
}
|
|
240
|
-
}}
|
|
241
|
-
shouldDismissPopover={false}
|
|
242
|
-
/>
|
|
243
|
-
);
|
|
244
|
-
};
|
|
245
|
-
|
|
246
|
-
render() {
|
|
247
|
-
let {
|
|
248
|
-
multi,
|
|
249
|
-
asTag,
|
|
250
|
-
options,
|
|
251
|
-
unfilteredOptions,
|
|
252
|
-
value,
|
|
253
|
-
creatable,
|
|
254
|
-
optionRenderer, //pull this one out here so it doesn't get passsed along
|
|
255
|
-
tagInputProps,
|
|
256
|
-
autoFocus,
|
|
257
|
-
autoOpen,
|
|
258
|
-
mustHaveQueryToOpen,
|
|
259
|
-
noResultsText,
|
|
260
|
-
noResults: _noResults,
|
|
261
|
-
inputProps,
|
|
262
|
-
backgroundColor,
|
|
263
|
-
doNotFillWidth,
|
|
264
|
-
noToggle,
|
|
265
|
-
small,
|
|
266
|
-
placeholder,
|
|
267
|
-
isLoading,
|
|
268
|
-
disallowClear,
|
|
269
|
-
onBlur,
|
|
270
|
-
disabled,
|
|
271
|
-
popoverProps,
|
|
272
|
-
additionalRightEl,
|
|
273
|
-
resetOnSelect = true,
|
|
274
|
-
...rest
|
|
275
|
-
} = this.props;
|
|
276
|
-
if (asTag) {
|
|
277
|
-
small = true;
|
|
278
|
-
placeholder = " ";
|
|
279
|
-
backgroundColor = "red";
|
|
280
|
-
disallowClear = true;
|
|
281
|
-
doNotFillWidth = true;
|
|
282
|
-
noToggle = true;
|
|
283
|
-
}
|
|
284
|
-
let noResults = _noResults;
|
|
285
|
-
|
|
286
|
-
// Null is also a valid value for a React Component, noResultsDefault should only be appplied when noResults is undefined
|
|
287
|
-
if (noResults === undefined) noResults = noResultsDefault;
|
|
288
|
-
const hasQuery = this.state.query?.length > 0;
|
|
289
|
-
const hasValue = Array.isArray(value)
|
|
290
|
-
? value.length > 0
|
|
291
|
-
: !!value || value === 0;
|
|
292
|
-
|
|
293
|
-
const rightElement = isLoading ? (
|
|
294
|
-
<Button loading minimal />
|
|
295
|
-
) : (
|
|
296
|
-
<span>
|
|
297
|
-
{additionalRightEl}
|
|
298
|
-
{hasValue && !disallowClear && !disabled && (
|
|
299
|
-
<Button
|
|
300
|
-
className="tg-select-clear-all"
|
|
301
|
-
icon="cross"
|
|
302
|
-
minimal
|
|
303
|
-
onClick={this.handleClear}
|
|
304
|
-
/>
|
|
305
|
-
)}
|
|
306
|
-
{noResults !== null && !noToggle && (
|
|
307
|
-
<Button
|
|
308
|
-
onClick={e => {
|
|
309
|
-
if (this.state.isOpen) {
|
|
310
|
-
e.stopPropagation();
|
|
311
|
-
|
|
312
|
-
this.setOpenState(false);
|
|
313
|
-
}
|
|
314
|
-
}}
|
|
315
|
-
disabled={disabled}
|
|
316
|
-
className="tg-select-toggle"
|
|
317
|
-
minimal
|
|
318
|
-
icon={this.state.isOpen ? "caret-up" : "caret-down"}
|
|
319
|
-
/>
|
|
320
|
-
)}
|
|
321
|
-
</span>
|
|
322
|
-
);
|
|
323
|
-
|
|
324
|
-
const maybeCreateNewItemFromQuery = creatable ? createNewOption : undefined;
|
|
325
|
-
const maybeCreateNewItemRenderer =
|
|
326
|
-
creatable && !this.queryHasExactOptionMatch()
|
|
327
|
-
? this.renderCreateNewOption
|
|
328
|
-
: null;
|
|
329
|
-
const selectedItems = getValueArray(value).map(value => {
|
|
330
|
-
if (value && value.label) return value; //if the value has a label, just use that
|
|
331
|
-
//if not, look for an existing option to use that value
|
|
332
|
-
// unfilteredOptions will have every option included selected ones
|
|
333
|
-
return unfilteredOptions.find(
|
|
334
|
-
opt => opt && opt.value === ((value && value.value) || value)
|
|
335
|
-
);
|
|
336
|
-
});
|
|
337
|
-
const toRet = (
|
|
338
|
-
<MultiSelect
|
|
339
|
-
onActiveItemChange={this.handleActiveItemChange}
|
|
340
|
-
closeOnSelect={!multi}
|
|
341
|
-
resetOnSelect={resetOnSelect}
|
|
342
|
-
items={options || []}
|
|
343
|
-
activeItem={
|
|
344
|
-
this.state.activeItem ||
|
|
345
|
-
(options && options.filter(opt => !selectedItems.includes(opt))[0]) ||
|
|
346
|
-
null //it's important we pass null here instead of undefined if no active item is found
|
|
347
|
-
}
|
|
348
|
-
itemDisabled={itemDisabled}
|
|
349
|
-
query={this.state.query}
|
|
350
|
-
popoverProps={{
|
|
351
|
-
captureDismiss: true,
|
|
352
|
-
minimal: true,
|
|
353
|
-
className: classNames("tg-select", "tg-stop-dialog-form-enter", {
|
|
354
|
-
"tg-single-select": !multi,
|
|
355
|
-
"tg-select-as-tag": asTag,
|
|
356
|
-
"do-not-fill-width": doNotFillWidth,
|
|
357
|
-
"tg-small": small
|
|
358
|
-
}),
|
|
359
|
-
wrapperTagName: "div",
|
|
360
|
-
canEscapeKeyClose: true,
|
|
361
|
-
onInteraction: this.onInteraction,
|
|
362
|
-
isOpen: mustHaveQueryToOpen
|
|
363
|
-
? hasQuery && this.state.isOpen
|
|
364
|
-
: this.state.isOpen,
|
|
365
|
-
modifiers: popoverOverflowModifiers,
|
|
366
|
-
...popoverProps
|
|
367
|
-
}}
|
|
368
|
-
onItemSelect={this.handleItemSelect}
|
|
369
|
-
createNewItemFromQuery={maybeCreateNewItemFromQuery}
|
|
370
|
-
createNewItemRenderer={maybeCreateNewItemRenderer}
|
|
371
|
-
noResults={noResultsText || noResults}
|
|
372
|
-
onQueryChange={this.onQueryChange}
|
|
373
|
-
itemRenderer={this.itemRenderer}
|
|
374
|
-
itemListPredicate={this.itemListPredicate}
|
|
375
|
-
{...{
|
|
376
|
-
selectedItems,
|
|
377
|
-
tagRenderer: this.tagRenderer,
|
|
378
|
-
tagInputProps: {
|
|
379
|
-
inputRef: n => {
|
|
380
|
-
if (n) this.input = n;
|
|
381
|
-
},
|
|
382
|
-
placeholder:
|
|
383
|
-
placeholder || (creatable ? "Select/Create..." : "Select..."),
|
|
384
|
-
tagProps: this.getTagProps,
|
|
385
|
-
onRemove: multi ? this.handleTagInputRemove : null,
|
|
386
|
-
rightElement: rightElement,
|
|
387
|
-
disabled: disabled, // tg: adding isLoading will cause the input to be blurred when using generic select asReactSelect (don't do it),
|
|
388
|
-
...tagInputProps, //spread additional tag input props here
|
|
389
|
-
intent: this.props.intent,
|
|
390
|
-
onKeyDown: e => {
|
|
391
|
-
const { which } = e;
|
|
392
|
-
e.persist();
|
|
393
|
-
if (which === Keys.ENTER) {
|
|
394
|
-
e.preventDefault();
|
|
395
|
-
// e.stopPropagation();
|
|
396
|
-
}
|
|
397
|
-
if (which === Keys.ESCAPE || which === Keys.TAB) {
|
|
398
|
-
// By default the escape key will not trigger a blur on the
|
|
399
|
-
// input element. It must be done explicitly.
|
|
400
|
-
if (this.input != null) {
|
|
401
|
-
this.input.blur();
|
|
402
|
-
}
|
|
403
|
-
this.setOpenState(false);
|
|
404
|
-
e.preventDefault();
|
|
405
|
-
e.stopPropagation(); //this prevents dialog's it is in from closing
|
|
406
|
-
} else if (
|
|
407
|
-
!(
|
|
408
|
-
which === Keys.BACKSPACE ||
|
|
409
|
-
which === Keys.ARROW_LEFT ||
|
|
410
|
-
which === Keys.ARROW_RIGHT
|
|
411
|
-
)
|
|
412
|
-
) {
|
|
413
|
-
this.setOpenState(true);
|
|
414
|
-
}
|
|
415
|
-
},
|
|
416
|
-
inputProps: {
|
|
417
|
-
autoFocus: autoFocus || autoOpen,
|
|
418
|
-
onBlur,
|
|
419
|
-
...(tagInputProps && tagInputProps.inputProps)
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
}}
|
|
423
|
-
{...rest}
|
|
424
|
-
/>
|
|
425
|
-
);
|
|
426
|
-
return toRet;
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
const withAsyncOptions = Component => props => {
|
|
431
|
-
const { loadOptions, options, ...rest } = props;
|
|
432
|
-
const [asyncOptions, setAsyncOptions] = useState([]);
|
|
433
|
-
const [isLoading, setLoading] = useState(false);
|
|
434
|
-
useEffect(() => {
|
|
435
|
-
if (loadOptions) {
|
|
436
|
-
setLoading(true);
|
|
437
|
-
loadOptions().then(options => {
|
|
438
|
-
setAsyncOptions(options);
|
|
439
|
-
setLoading(false);
|
|
440
|
-
});
|
|
441
|
-
}
|
|
442
|
-
}, [loadOptions]);
|
|
443
|
-
|
|
444
|
-
return (
|
|
445
|
-
<Component
|
|
446
|
-
{...rest}
|
|
447
|
-
isLoading={isLoading || rest.isLoading}
|
|
448
|
-
options={loadOptions ? asyncOptions : options}
|
|
449
|
-
/>
|
|
450
|
-
);
|
|
451
|
-
};
|
|
452
|
-
|
|
453
|
-
export default compose(
|
|
454
|
-
withAsyncOptions,
|
|
455
|
-
withProps(props => {
|
|
456
|
-
const { multi, value, options = [] } = props;
|
|
457
|
-
let optionsToRet = options;
|
|
458
|
-
// based on incoming value hide those selected options from the option list
|
|
459
|
-
if (multi && value) {
|
|
460
|
-
const valArray = getValueArray(value);
|
|
461
|
-
optionsToRet = options.filter(op => {
|
|
462
|
-
const isOptionSelected = valArray.some(val => {
|
|
463
|
-
if (!val) return false;
|
|
464
|
-
const matching = isEqual(val.value, op.value);
|
|
465
|
-
return matching;
|
|
466
|
-
});
|
|
467
|
-
return !isOptionSelected;
|
|
468
|
-
});
|
|
469
|
-
}
|
|
470
|
-
return {
|
|
471
|
-
// unfilteredOptions is needed for finding selected items
|
|
472
|
-
unfilteredOptions: options,
|
|
473
|
-
options: optionsToRet
|
|
474
|
-
};
|
|
475
|
-
})
|
|
476
|
-
)(TgSelect);
|
|
477
|
-
|
|
478
|
-
const itemDisabled = i => i.disabled;
|
|
479
|
-
const noResultsDefault = <div>No Results...</div>;
|
|
480
|
-
|
|
481
|
-
export function createNewOption(newValString) {
|
|
482
|
-
if (!newValString) return;
|
|
483
|
-
return {
|
|
484
|
-
userCreated: true,
|
|
485
|
-
label: newValString,
|
|
486
|
-
value: newValString
|
|
487
|
-
};
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
function getValueArray(value) {
|
|
491
|
-
return value || value === 0 ? (Array.isArray(value) ? value : [value]) : [];
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
//we export this here for use in createGenericSelect
|
|
495
|
-
export const itemListPredicate = (_queryString = "", items, isSimpleSearch) => {
|
|
496
|
-
const queryString = _queryString.toLowerCase();
|
|
497
|
-
const toSearchArr = (items || []).map(item => {
|
|
498
|
-
return {
|
|
499
|
-
item,
|
|
500
|
-
text: item.toLowerCase
|
|
501
|
-
? item.toLowerCase()
|
|
502
|
-
: item.label
|
|
503
|
-
? item.label.toLowerCase
|
|
504
|
-
? item.label.toLowerCase()
|
|
505
|
-
: getTextFromEl(item.label).toLowerCase()
|
|
506
|
-
: (item.value &&
|
|
507
|
-
item.value.toLowerCase &&
|
|
508
|
-
item.value.toLowerCase()) ||
|
|
509
|
-
""
|
|
510
|
-
};
|
|
511
|
-
});
|
|
512
|
-
let toRet = toSearchArr.filter(({ text }) =>
|
|
513
|
-
(isSimpleSearch ? simplesearch : fuzzysearch)(queryString, text)
|
|
514
|
-
);
|
|
515
|
-
toRet = toRet.sort(({ text }, { text: text2 }) => {
|
|
516
|
-
return getSort(text, queryString) - getSort(text2, queryString);
|
|
517
|
-
});
|
|
518
|
-
|
|
519
|
-
toRet = toRet.map(({ item }) => item);
|
|
520
|
-
return toRet;
|
|
521
|
-
};
|
|
522
|
-
|
|
523
|
-
export function simplesearch(needle, haystack) {
|
|
524
|
-
return (haystack || "").indexOf(needle) !== -1;
|
|
525
|
-
}
|
|
526
|
-
function tagOptionRender(vals) {
|
|
527
|
-
if (vals.noTagStyle) return vals.label;
|
|
528
|
-
return <Tag {...getTagProps(vals)}></Tag>;
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
function getSort(text, queryString) {
|
|
532
|
-
let ret;
|
|
533
|
-
if (text === queryString) ret = -1;
|
|
534
|
-
else if (text.includes(queryString)) ret = text.indexOf(queryString);
|
|
535
|
-
else ret = text.length;
|
|
536
|
-
return ret;
|
|
537
|
-
}
|
package/src/TgSelect/style.css
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
.tg-select {
|
|
2
|
-
width: 100%;
|
|
3
|
-
min-width: 170px;
|
|
4
|
-
}
|
|
5
|
-
.tg-select.tg-select-as-tag {
|
|
6
|
-
/* background-color: red; */
|
|
7
|
-
border-radius: 4px;
|
|
8
|
-
width: fit-content;
|
|
9
|
-
color: white;
|
|
10
|
-
border: 2px solid white;
|
|
11
|
-
}
|
|
12
|
-
.tg-select.tg-select-as-tag .bp3-tag.bp3-minimal.bp3-intent-primary {
|
|
13
|
-
color: white !important;
|
|
14
|
-
}
|
|
15
|
-
.tg-select.do-not-fill-width {
|
|
16
|
-
width: auto;
|
|
17
|
-
min-width: 50px;
|
|
18
|
-
}
|
|
19
|
-
.tg-select.tg-small .bp3-input {
|
|
20
|
-
min-height: 25px;
|
|
21
|
-
height: 25px;
|
|
22
|
-
}
|
|
23
|
-
.tg-select.tg-small input {
|
|
24
|
-
line-height: 10.5px;
|
|
25
|
-
}
|
|
26
|
-
.tg-select.tg-small .bp3-tag-input .bp3-input-ghost {
|
|
27
|
-
line-height: 10.5px;
|
|
28
|
-
}
|
|
29
|
-
.tg-select.tg-small .bp3-tag-input .bp3-tag-input-values {
|
|
30
|
-
margin-top: 2px;
|
|
31
|
-
}
|
|
32
|
-
.tg-select input {
|
|
33
|
-
font-size: 14px;
|
|
34
|
-
}
|
|
35
|
-
.tg-select-option {
|
|
36
|
-
width: fit-content;
|
|
37
|
-
min-width: 100%;
|
|
38
|
-
}
|
|
39
|
-
/* Fix cutoff placeholder */
|
|
40
|
-
.tg-select .bp3-input-ghost[placeholder] {
|
|
41
|
-
width: 80%;
|
|
42
|
-
text-overflow: ellipsis;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
.tg-single-select input {
|
|
46
|
-
position: absolute;
|
|
47
|
-
top: 5px;
|
|
48
|
-
}
|
|
49
|
-
.tg-single-select .bp3-tag {
|
|
50
|
-
background-color: initial !important;
|
|
51
|
-
font-size: 14px;
|
|
52
|
-
}
|
|
53
|
-
.tg-single-select .bp3-popover-open .bp3-tag {
|
|
54
|
-
opacity: 0.6;
|
|
55
|
-
}
|
|
56
|
-
.bp3-multi-select-popover .bp3-menu,
|
|
57
|
-
.bp3-select-popover .bp3-menu {
|
|
58
|
-
max-width: 400px;
|
|
59
|
-
max-height: 300px;
|
|
60
|
-
overflow: auto;
|
|
61
|
-
}
|
package/src/TgSuggest/index.js
DELETED
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
import { Suggest } from "@blueprintjs/select";
|
|
2
|
-
import { Keys } from "@blueprintjs/core";
|
|
3
|
-
import React, { useCallback, useMemo, useRef } from "react";
|
|
4
|
-
import classNames from "classnames";
|
|
5
|
-
import { itemListPredicate } from "../TgSelect";
|
|
6
|
-
|
|
7
|
-
const itemRenderer = (i = "", { index, handleClick, modifiers }) => (
|
|
8
|
-
<div //we specifically don't use a BP MenuItem component here because the menu item is too slow when 100s are loaded and will cause the component to lag
|
|
9
|
-
onClick={handleClick}
|
|
10
|
-
key={index}
|
|
11
|
-
className={classNames(
|
|
12
|
-
"tg-select-option bp3-menu-item bp3-fill bp3-text-overflow-ellipsis",
|
|
13
|
-
{
|
|
14
|
-
"bp3-active": modifiers.active
|
|
15
|
-
}
|
|
16
|
-
)}
|
|
17
|
-
>
|
|
18
|
-
{i}
|
|
19
|
-
</div>
|
|
20
|
-
);
|
|
21
|
-
|
|
22
|
-
const TgSuggest = ({
|
|
23
|
-
disabled,
|
|
24
|
-
inputProps: _inputProps,
|
|
25
|
-
intent,
|
|
26
|
-
isLoading,
|
|
27
|
-
isSimpleSearch,
|
|
28
|
-
multi,
|
|
29
|
-
noResultsText,
|
|
30
|
-
notCreateable,
|
|
31
|
-
onBlur,
|
|
32
|
-
onChange,
|
|
33
|
-
optionRenderer, //pull this one out here so it doesn't get passsed along
|
|
34
|
-
options,
|
|
35
|
-
placeholder,
|
|
36
|
-
popoverProps: _popoverProps,
|
|
37
|
-
value,
|
|
38
|
-
...rest
|
|
39
|
-
}) => {
|
|
40
|
-
const inputRef = useRef(null);
|
|
41
|
-
|
|
42
|
-
const handleItemSelect = useCallback(
|
|
43
|
-
item => {
|
|
44
|
-
inputRef.current && inputRef.current.blur();
|
|
45
|
-
return onChange?.(item);
|
|
46
|
-
},
|
|
47
|
-
[onChange]
|
|
48
|
-
);
|
|
49
|
-
|
|
50
|
-
const _itemListPredicate = useCallback(
|
|
51
|
-
(queryString, item) => {
|
|
52
|
-
return itemListPredicate(queryString, item, isSimpleSearch);
|
|
53
|
-
},
|
|
54
|
-
[isSimpleSearch]
|
|
55
|
-
);
|
|
56
|
-
|
|
57
|
-
const popoverProps = useMemo(
|
|
58
|
-
() => ({
|
|
59
|
-
minimal: true,
|
|
60
|
-
className: classNames("tg-select", {
|
|
61
|
-
"tg-single-select": !multi
|
|
62
|
-
}),
|
|
63
|
-
wrapperTagName: "div",
|
|
64
|
-
usePortal: false,
|
|
65
|
-
canEscapeKeyClose: true,
|
|
66
|
-
..._popoverProps
|
|
67
|
-
}),
|
|
68
|
-
[multi, _popoverProps]
|
|
69
|
-
);
|
|
70
|
-
|
|
71
|
-
const onKeyDown = useCallback(e => {
|
|
72
|
-
const { which } = e;
|
|
73
|
-
if (which === Keys.ENTER) {
|
|
74
|
-
e.preventDefault();
|
|
75
|
-
e.stopPropagation(); //this prevents the dialog it is in from closing
|
|
76
|
-
}
|
|
77
|
-
if (which === Keys.ESCAPE || which === Keys.TAB) {
|
|
78
|
-
// By default the escape key will not trigger a blur on the
|
|
79
|
-
// input element. It must be done explicitly.
|
|
80
|
-
if (inputRef.current != null) {
|
|
81
|
-
inputRef.current.blur();
|
|
82
|
-
}
|
|
83
|
-
e.preventDefault();
|
|
84
|
-
e.stopPropagation(); //this prevents dialog's it is in from closing
|
|
85
|
-
}
|
|
86
|
-
}, []);
|
|
87
|
-
|
|
88
|
-
const inputProps = useMemo(
|
|
89
|
-
() => ({
|
|
90
|
-
inputRef: n => {
|
|
91
|
-
if (n) inputRef.current = n;
|
|
92
|
-
},
|
|
93
|
-
placeholder: placeholder || "Type here...",
|
|
94
|
-
disabled: disabled, // tg: adding isLoading will cause the input to be blurred when using generic select asReactSelect (don't do it),
|
|
95
|
-
intent: intent,
|
|
96
|
-
..._inputProps
|
|
97
|
-
}),
|
|
98
|
-
[disabled, _inputProps, intent, placeholder]
|
|
99
|
-
);
|
|
100
|
-
|
|
101
|
-
return (
|
|
102
|
-
<Suggest
|
|
103
|
-
closeOnSelect
|
|
104
|
-
items={options}
|
|
105
|
-
query={value}
|
|
106
|
-
popoverProps={popoverProps}
|
|
107
|
-
onKeyDown={onKeyDown}
|
|
108
|
-
onItemSelect={handleItemSelect}
|
|
109
|
-
noResults={null}
|
|
110
|
-
resetOnSelect={false}
|
|
111
|
-
onQueryChange={onChange}
|
|
112
|
-
itemRenderer={itemRenderer}
|
|
113
|
-
itemListPredicate={_itemListPredicate}
|
|
114
|
-
selectedItem={value}
|
|
115
|
-
inputValueRenderer={item => item}
|
|
116
|
-
inputProps={inputProps}
|
|
117
|
-
isSimpleSearch={isSimpleSearch}
|
|
118
|
-
onChange={onChange}
|
|
119
|
-
{...rest}
|
|
120
|
-
/>
|
|
121
|
-
);
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
export default TgSuggest;
|