ish-ui 1.0.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.
Files changed (126) hide show
  1. package/.eslintrc.json +39 -0
  2. package/.gitattributes +3 -0
  3. package/.github/workflows/release-package.yml +33 -0
  4. package/.prettierrc +5 -0
  5. package/README.md +80 -0
  6. package/assets/fonts/inter/Inter-Italic.var.woff2 +0 -0
  7. package/assets/fonts/inter/Inter-Roman.var.woff2 +0 -0
  8. package/assets/fonts/inter/LICENSE.txt +92 -0
  9. package/assets/fonts/inter/index.d.ts +10 -0
  10. package/assets/fonts/inter/inter.scss +17 -0
  11. package/package.json +108 -0
  12. package/src/actions/FieldProcessing.ts +21 -0
  13. package/src/actions/index.ts +10 -0
  14. package/src/appBar/AppBarHelpMenu.tsx +139 -0
  15. package/src/appBar/index.ts +9 -0
  16. package/src/buttons/AddButton.tsx +30 -0
  17. package/src/buttons/TimetableButton.tsx +19 -0
  18. package/src/buttons/index.ts +10 -0
  19. package/src/colorPicker/ColorPicker.tsx +223 -0
  20. package/src/colorPicker/index.ts +9 -0
  21. package/src/dialog/BrowserWarning.tsx +24 -0
  22. package/src/dialog/confirm/ConfirmBase.tsx +59 -0
  23. package/src/dialog/index.ts +11 -0
  24. package/src/dialog/message/Message.tsx +140 -0
  25. package/src/documents/DocumentIconsChooser.tsx +69 -0
  26. package/src/documents/index.ts +10 -0
  27. package/src/documents/utils/index.tsx +71 -0
  28. package/src/dynamicSizeList/DynamicSizeList.tsx +208 -0
  29. package/src/dynamicSizeList/index.ts +9 -0
  30. package/src/fieldMessage/ErrorMessage.tsx +28 -0
  31. package/src/fieldMessage/WarningMessage.tsx +28 -0
  32. package/src/fieldMessage/index.ts +11 -0
  33. package/src/fieldMessage/styles.ts +21 -0
  34. package/src/fileUploader/FileUploaderDialog.tsx +158 -0
  35. package/src/fileUploader/index.ts +9 -0
  36. package/src/formFields/CheckboxField.tsx +90 -0
  37. package/src/formFields/CodeEditorField.tsx +103 -0
  38. package/src/formFields/ColoredCheckBox.tsx +74 -0
  39. package/src/formFields/DateTimeField.tsx +61 -0
  40. package/src/formFields/EditInPlaceDateTimeField.tsx +285 -0
  41. package/src/formFields/EditInPlaceDurationField.tsx +79 -0
  42. package/src/formFields/EditInPlaceField.tsx +131 -0
  43. package/src/formFields/EditInPlaceFieldBase.tsx +241 -0
  44. package/src/formFields/EditInPlaceFileField.tsx +67 -0
  45. package/src/formFields/EditInPlaceMoneyField.tsx +64 -0
  46. package/src/formFields/EditInPlacePhoneField.tsx +97 -0
  47. package/src/formFields/EditInPlaceSearchSelect.tsx +562 -0
  48. package/src/formFields/FieldAdornments.tsx +70 -0
  49. package/src/formFields/FilePreview.tsx +149 -0
  50. package/src/formFields/FormRadioButtons.tsx +62 -0
  51. package/src/formFields/SelectCustomComponents.tsx +228 -0
  52. package/src/formFields/Switch.tsx +146 -0
  53. package/src/formFields/TextField.tsx +60 -0
  54. package/src/formFields/UneditableBase.tsx +101 -0
  55. package/src/formFields/index.ts +27 -0
  56. package/src/index.ts +26 -0
  57. package/src/layout/InfoPill.tsx +36 -0
  58. package/src/layout/index.ts +10 -0
  59. package/src/layout/resizable/ResizableWrapper.tsx +87 -0
  60. package/src/markdownEditor/HtmlEditor.tsx +44 -0
  61. package/src/markdownEditor/WysiwygEditor.tsx +137 -0
  62. package/src/markdownEditor/index.ts +12 -0
  63. package/src/markdownEditor/style.ts +188 -0
  64. package/src/markdownEditor/utils/index.ts +48 -0
  65. package/src/model/AppBar.ts +20 -0
  66. package/src/model/CommomObjects.ts +8 -0
  67. package/src/model/CommonFunctions.ts +20 -0
  68. package/src/model/Confirm.ts +27 -0
  69. package/src/model/Fields.ts +254 -0
  70. package/src/model/NestedEntity.ts +14 -0
  71. package/src/model/Theme.ts +42 -0
  72. package/src/model/index.ts +16 -0
  73. package/src/styles/GlobalStylesProvider.tsx +520 -0
  74. package/src/styles/StylesProviderCustom.tsx +8 -0
  75. package/src/styles/animateStyles.ts +94 -0
  76. package/src/styles/bootstrap.ts +503 -0
  77. package/src/styles/hooks.ts +44 -0
  78. package/src/styles/index.ts +18 -0
  79. package/src/styles/makeStyles.ts +21 -0
  80. package/src/styles/mixins/common.ts +40 -0
  81. package/src/styles/mixins/keyframes.ts +16 -0
  82. package/src/styles/mixins/prefixer.ts +21 -0
  83. package/src/tagsInput/AddTagMenu.tsx +74 -0
  84. package/src/tagsInput/AddTagMenuItem.tsx +50 -0
  85. package/src/tagsInput/TagInputList.tsx +428 -0
  86. package/src/tagsInput/index.ts +4 -0
  87. package/src/themes/appTheme.ts +324 -0
  88. package/src/themes/index.ts +10 -0
  89. package/src/themes/ishTheme.ts +401 -0
  90. package/src/timetable/datePeriodFilter/DayPeriodIcons.tsx +95 -0
  91. package/src/timetable/datePeriodFilter/index.ts +10 -0
  92. package/src/timetable/index.ts +11 -0
  93. package/src/timetable/miniCalendar/CalendarDay.tsx +109 -0
  94. package/src/timetable/miniCalendar/CalendarHeader.tsx +37 -0
  95. package/src/timetable/miniCalendar/CalendarWeekPanel.tsx +35 -0
  96. package/src/timetable/miniCalendar/WeekDay.tsx +49 -0
  97. package/src/timetable/miniCalendar/index.ts +13 -0
  98. package/src/utils/DOM/Links.ts +17 -0
  99. package/src/utils/DOM/getCaretCoordinates.ts +122 -0
  100. package/src/utils/DOM/getOS.ts +32 -0
  101. package/src/utils/DOM/index.ts +34 -0
  102. package/src/utils/dates/datesNormalizing.ts +4 -0
  103. package/src/utils/dates/format.ts +52 -0
  104. package/src/utils/dates/formatRelative.ts +22 -0
  105. package/src/utils/dates/formatString.ts +233 -0
  106. package/src/utils/dates/formatTimezone.ts +37 -0
  107. package/src/utils/dates/index.ts +15 -0
  108. package/src/utils/dates/timetable.ts +46 -0
  109. package/src/utils/events/index.ts +8 -0
  110. package/src/utils/fields/index.ts +23 -0
  111. package/src/utils/formatting/PhoneMasks.ts +320 -0
  112. package/src/utils/formatting/index.tsx +20 -0
  113. package/src/utils/hooks/index.ts +19 -0
  114. package/src/utils/index.ts +15 -0
  115. package/src/utils/numbers/decimalCalculation.ts +26 -0
  116. package/src/utils/numbers/index.ts +11 -0
  117. package/src/utils/numbers/numbersNormalizing.ts +52 -0
  118. package/src/utils/stubs/index.tsx +12 -0
  119. package/src/utils/tags/index.ts +53 -0
  120. package/tools/webpack/webpack.aliases.js +13 -0
  121. package/tools/webpack/webpack.config.dev.js +29 -0
  122. package/tools/webpack/webpack.config.prod.js +36 -0
  123. package/tools/webpack/webpack.helpers.js +26 -0
  124. package/tools/webpack/webpack.plugins.js +15 -0
  125. package/tools/webpack/webpack.rules.js +51 -0
  126. package/tsconfig.json +24 -0
@@ -0,0 +1,74 @@
1
+ import React from 'react';
2
+ import clsx from 'clsx';
3
+ import withStyles from '@mui/styles/withStyles';
4
+ import KeyboardArrowLeft from '@mui/icons-material/KeyboardArrowLeft';
5
+ import MenuItem from '@mui/material/MenuItem';
6
+ import List from '@mui/material/List';
7
+ import AddTagMenuItem from './AddTagMenuItem';
8
+ import { MenuTag, TagLike } from '@src/model';
9
+
10
+ const styles = theme => ({
11
+ listItem: {
12
+ padding: theme.spacing(0, 0.5, 0, 2)
13
+ },
14
+ proceedIcon: {
15
+ marginTop: '2px'
16
+ },
17
+ backContainer: {
18
+ marginLeft: '-6px'
19
+ },
20
+ tagColorDotSmall: {
21
+ width: theme.spacing(2),
22
+ height: theme.spacing(2),
23
+ background: 'red',
24
+ borderRadius: '100%'
25
+ }
26
+ });
27
+
28
+ interface Props<T> {
29
+ classes?: any;
30
+ tags: MenuTag<T>[];
31
+ handleAdd: (tag: MenuTag<T>) => void;
32
+ activeTag: MenuTag<T>;
33
+ setActiveTag: (arg: (MenuTag<T> | ((prevState: MenuTag<T>) => MenuTag<T>))) => void;
34
+ }
35
+
36
+ function AddTagMenu<T extends TagLike>(
37
+ {
38
+ classes,
39
+ tags,
40
+ handleAdd,
41
+ activeTag,
42
+ setActiveTag
43
+ }: Props<T>
44
+ ) {
45
+ const handleBack = () => {
46
+ setActiveTag(prev => prev.parent);
47
+ };
48
+
49
+ return (
50
+ <List
51
+ className={classes.rootMenu}
52
+ >
53
+ {activeTag && (
54
+ <MenuItem onClick={handleBack} className={classes.listItem}>
55
+ <span className={clsx('d-flex textSecondaryColor', classes.backContainer)}>
56
+ <KeyboardArrowLeft color="inherit" />
57
+ Back
58
+ </span>
59
+ </MenuItem>
60
+ )}
61
+ {(activeTag ? activeTag.children : tags).map(t => (
62
+ <AddTagMenuItem
63
+ key={t.tagBody.id}
64
+ tag={t}
65
+ classes={classes}
66
+ setActiveTag={setActiveTag}
67
+ handleAdd={handleAdd}
68
+ />
69
+ ))}
70
+ </List>
71
+ );
72
+ }
73
+
74
+ export default withStyles(styles)(AddTagMenu);
@@ -0,0 +1,50 @@
1
+ /*
2
+ * Copyright ish group pty ltd 2023.
3
+ *
4
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License version 3 as published by the Free Software Foundation.
5
+ *
6
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
7
+ */
8
+
9
+ import React from 'react';
10
+ import clsx from 'clsx';
11
+ import KeyboardArrowRight from '@mui/icons-material/KeyboardArrowRight';
12
+ import Checkbox from '@mui/material/Checkbox';
13
+ import MenuItem from '@mui/material/MenuItem';
14
+ import { MenuTag, TagLike } from '@src/model';
15
+
16
+ interface Props<T> {
17
+ classes: any;
18
+ setActiveTag: (tag: MenuTag<T>) => void;
19
+ handleAdd: (tag: MenuTag<T>) => void;
20
+ tag: MenuTag<T>;
21
+ }
22
+
23
+ function AddTagMenuItem<T extends TagLike>({ setActiveTag, tag, classes, handleAdd }: Props<T>) {
24
+ const openSubmenu = () => {
25
+ setActiveTag(tag);
26
+ };
27
+
28
+ const toggleChecked = () => {
29
+ handleAdd(tag);
30
+ };
31
+
32
+ const hasChildren = Boolean(tag.children.length);
33
+
34
+ return (
35
+ <MenuItem
36
+ classes={{ root: classes.listItem }}
37
+ onClick={hasChildren ? openSubmenu : toggleChecked}
38
+ >
39
+ <div className={clsx(classes.tagColorDotSmall, 'mr-1')} style={{ background: '#' + tag.tagBody.color }} />
40
+ <span className="mr-2 flex-fill">{tag.tagBody.name}</span>
41
+ {hasChildren ? (
42
+ <KeyboardArrowRight className={clsx('d-flex textSecondaryColor', classes.proceedIcon)} />
43
+ ) : (
44
+ <Checkbox classes={{ root: 'smallIconButton' }} checked={tag.active} />
45
+ )}
46
+ </MenuItem>
47
+ );
48
+ }
49
+
50
+ export default AddTagMenuItem;
@@ -0,0 +1,428 @@
1
+ /*
2
+ * Copyright ish group pty ltd 2023.
3
+ *
4
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License version 3 as published by the Free Software Foundation.
5
+ *
6
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
7
+ */
8
+
9
+ import React, {
10
+ useCallback, useEffect, useMemo, useRef, useState
11
+ } from 'react';
12
+ import {
13
+ InputAdornment, MenuItem, Select
14
+ } from '@mui/material';
15
+ import ClickAwayListener from '@mui/material/ClickAwayListener';
16
+ import createStyles from '@mui/styles/createStyles';
17
+ import withStyles from '@mui/styles/withStyles';
18
+ import Autocomplete from '@mui/material/Autocomplete';
19
+ import clsx from 'clsx';
20
+ import { Edit } from '@mui/icons-material';
21
+ import { selectStyles } from '@src/formFields';
22
+ import AddTagMenu from './AddTagMenu';
23
+ import EditInPlaceFieldBase from '../formFields/EditInPlaceFieldBase';
24
+ import { FieldInputProps, FieldMetaProps, MenuTag, TagLike, TagsFieldProps } from '@src/model';
25
+ import { getAllMenuTags, getHighlightedPartLabel, getMenuTags } from '../utils';
26
+ import { stubComponent } from '@src/utils/stubs';
27
+ import getCaretCoordinates from '@src/utils/DOM/getCaretCoordinates';
28
+
29
+ const styles = theme =>
30
+ createStyles({
31
+ inputEndAdornment: {
32
+ visibility: 'hidden',
33
+ display: 'flex',
34
+ color: theme.palette.primary.main,
35
+ alignItems: 'flex-end',
36
+ alignSelf: 'flex-end',
37
+ marginBottom: '4px',
38
+ opacity: 0.5
39
+ },
40
+ tagColorDotSmall: {
41
+ width: theme.spacing(2),
42
+ minWidth: theme.spacing(2),
43
+ height: theme.spacing(2),
44
+ minHeight: theme.spacing(2),
45
+ background: 'red',
46
+ borderRadius: '100%'
47
+ },
48
+ listbox: {
49
+ whiteSpace: 'break-spaces'
50
+ },
51
+ invalid: {}
52
+ });
53
+
54
+ const endTagRegex = /#\s*[^\w\d]*$/;
55
+
56
+ const getCurrentInputString = (input, formTagIds: number[] = [], allMenuTags: MenuTag<TagLike>[] = []) => {
57
+ let substr = input;
58
+
59
+ formTagIds?.forEach(id => {
60
+ const tag = allMenuTags.find(t => t.tagBody.id === id);
61
+ if (tag) {
62
+ substr = substr.replace('#' + tag.tagBody.name, '').trim();
63
+ }
64
+ });
65
+
66
+ if (substr) {
67
+ return substr.trim().replace(/#/g, '');
68
+ }
69
+
70
+ return substr;
71
+ };
72
+
73
+ const getFullTag = (tagId: number, tags: TagLike[]) => {
74
+ let i = 0;
75
+ let result;
76
+
77
+ while (i < tags.length) {
78
+ if (tagId === tags[i].id) {
79
+ return tags[i];
80
+ }
81
+
82
+ if (result) break;
83
+
84
+ if (tags[i].childTags.length) {
85
+ result = getFullTag(tagId, tags[i].childTags);
86
+ if (result) return result;
87
+ }
88
+
89
+ ++i;
90
+ }
91
+ };
92
+
93
+ const getInputString = (tagIds: number[], allTags: TagLike[]) => (tagIds?.length && allTags?.length
94
+ ? tagIds.reduce((acc, id) => {
95
+ const tag = getFullTag(id, allTags);
96
+ return (tag ? `${acc}#${tag.name} ` : acc);
97
+ }, '')
98
+ : '');
99
+
100
+ function TagInputList<T extends TagLike, IP extends FieldInputProps, MP extends FieldMetaProps>({
101
+ input,
102
+ tags,
103
+ classes,
104
+ placeholder,
105
+ labelAdornment,
106
+ meta,
107
+ label = 'Tags',
108
+ disabled,
109
+ className,
110
+ warning,
111
+ fieldClasses = {}
112
+ }: TagsFieldProps<T, IP, MP>) {
113
+ const [menuIsOpen, setMenuIsOpen] = useState(false);
114
+ const [activeTag, setActiveTag] = useState<MenuTag<TagLike>>(null);
115
+ const [isEditing, setIsEditing] = useState(false);
116
+ const [inputValue, setInputValue] = useState('');
117
+ const [currentInputString, setCurrentInputString] = useState('');
118
+
119
+ const InputValueForRender = useMemo(() => {
120
+ if (!inputValue || !tags || !tags.length) return '';
121
+
122
+ const arrayOfTags = input?.value?.length
123
+ && input.value.map(id => getFullTag(id, tags)).filter(t => t);
124
+
125
+ if (!arrayOfTags?.length) return '';
126
+
127
+ return arrayOfTags.map((tag: T, index) => (
128
+ <span key={tag.id} className={clsx('centeredFlex', index !== arrayOfTags.length - 1 ? 'pr-1' : '')}>
129
+ <div key={tag.id} className={clsx(classes.tagColorDotSmall, 'mr-0-5')} style={{ background: '#' + tag.color }} />
130
+ <span className="text-nowrap">
131
+ {`#${tag.name} `}
132
+ </span>
133
+ </span>
134
+ ));
135
+ }, [tags, input.value, inputValue]);
136
+
137
+ const inputNode = useRef<any>();
138
+ const tagMenuNode = useRef<any>();
139
+
140
+ const menuTags = useMemo(
141
+ () => (tags && input.value ? getMenuTags(tags.filter(t => t.childrenCount > 0), input.value.map(id => getFullTag(id, tags)).filter(t => t)) : []),
142
+ [tags, input.value]
143
+ );
144
+
145
+ const allMenuTags = useMemo(
146
+ () => getAllMenuTags(menuTags),
147
+ [menuTags]
148
+ );
149
+
150
+ const synchronizeTags = () => {
151
+ const inputString = getInputString(input.value, tags);
152
+
153
+ if (inputString.trim() === inputValue.replace(endTagRegex, '').trim()) {
154
+ return;
155
+ }
156
+
157
+ const updated = [];
158
+ const current = inputValue.split('#').filter(i => i).map(i => i.trim());
159
+
160
+ allMenuTags.forEach(t => {
161
+ if (!t.children.length) {
162
+ const index = current.findIndex(c => c === t.tagBody.name);
163
+ if (index !== -1) {
164
+ const addedTagsMatch = input.value.find(id => getFullTag(id, tags)?.name === t.tagBody.name);
165
+ if (addedTagsMatch && addedTagsMatch !== t.tagBody.id) {
166
+ return;
167
+ }
168
+ updated.push(t.tagBody.id);
169
+ current.splice(index, 1);
170
+ }
171
+ }
172
+ });
173
+
174
+ input.onChange(updated);
175
+ setInputValue(getInputString(updated, tags));
176
+ };
177
+
178
+ const onTagAdd = (tag: MenuTag<T>) => {
179
+ const updated = [...input.value];
180
+
181
+ const index = updated.findIndex(id => id === tag.tagBody.id);
182
+
183
+ if (index !== -1) {
184
+ updated.splice(index, 1);
185
+ } else {
186
+ updated.push(tag.tagBody.id);
187
+ }
188
+
189
+ input.onChange(updated);
190
+
191
+ setTimeout(() => {
192
+ inputNode?.current?.focus();
193
+ }, 100);
194
+ };
195
+
196
+ const filterOptions = item => !item.children.length && !input.value.some(id => id === item.tagBody.id) && item.tagBody.name
197
+ .toLowerCase()
198
+ .trim()
199
+ .startsWith(currentInputString.toLowerCase().trim());
200
+
201
+ const filterOptionsInner = options => options.filter(filterOptions);
202
+
203
+ const filteredOptions = allMenuTags.filter(filterOptions);
204
+
205
+ const getOptionText = (option, optionProps, label) => (
206
+ <div {...optionProps}>
207
+ {`${option.path ? option.path + ' /' : ''}`}
208
+ {' '}
209
+ {label}
210
+ </div>
211
+ );
212
+
213
+ const getOptionLabel = op => op.path;
214
+
215
+ const renderOption = (optionProps, option) => {
216
+ const label = option?.tagBody?.name;
217
+ const highlightedLabel = getHighlightedPartLabel(label, currentInputString);
218
+ return getOptionText(option, optionProps, highlightedLabel);
219
+ };
220
+
221
+ const handleInputChange = e => {
222
+ setInputValue(e.target.value);
223
+ };
224
+
225
+ const edit = () => {
226
+ setIsEditing(true);
227
+ setTimeout(() => {
228
+ inputNode?.current?.focus();
229
+ }, 50);
230
+ };
231
+
232
+ const exit = () => {
233
+ setMenuIsOpen(false);
234
+ setIsEditing(false);
235
+ setActiveTag(null);
236
+
237
+ if (endTagRegex.test(inputValue)) {
238
+ setTimeout(() => {
239
+ setInputValue(inputValue.replace(endTagRegex, '').trim());
240
+ }, 100);
241
+ }
242
+ };
243
+
244
+ const onFocus = () => {
245
+ setMenuIsOpen(true);
246
+ if (!endTagRegex.test(inputValue)) {
247
+ setInputValue(inputValue + ' #');
248
+ }
249
+ };
250
+
251
+ const onBlur = () => {
252
+ if (currentInputString) {
253
+ exit();
254
+ synchronizeTags();
255
+ }
256
+ };
257
+
258
+ const onTagListBlur = () => {
259
+ setTimeout(() => {
260
+ if (document.activeElement !== inputNode.current) {
261
+ exit();
262
+ synchronizeTags();
263
+ }
264
+ }, 60);
265
+ };
266
+
267
+ const handleChange = (e, value, action) => {
268
+ if (action === 'selectOption') {
269
+ onTagAdd(value);
270
+ }
271
+ };
272
+
273
+ useEffect(() => {
274
+ let inputString = getInputString(input.value, tags);
275
+
276
+ if (document.activeElement === inputNode.current && !endTagRegex.test(inputString)) {
277
+ inputString += ' #';
278
+ }
279
+
280
+ setInputValue(inputString);
281
+ }, [input.value, tags]);
282
+
283
+ useEffect(() => {
284
+ setCurrentInputString(getCurrentInputString(inputValue, input.value || [], allMenuTags));
285
+ }, [inputValue, input.value, allMenuTags]);
286
+
287
+ useEffect(() => {
288
+ if (meta.invalid && !isEditing) {
289
+ setIsEditing(true);
290
+ }
291
+ }, [meta.invalid]);
292
+
293
+ useEffect(() => {
294
+ if (activeTag) {
295
+ const activeUpdated = allMenuTags.find(t => t.tagBody.id === activeTag.tagBody.id);
296
+ if (activeUpdated) {
297
+ setActiveTag(activeUpdated);
298
+ }
299
+ }
300
+ }, [allMenuTags]);
301
+
302
+ const popperAdapter = useCallback(params => {
303
+ if (currentInputString || !inputNode.current) {
304
+ return <div {...params} />;
305
+ }
306
+
307
+ const coords = getCaretCoordinates(inputNode.current, inputValue.length);
308
+ const position = tagMenuNode.current
309
+ && coords.left > inputNode.current.clientWidth - tagMenuNode.current.clientWidth
310
+ ? { right: 0 }
311
+ : { left: coords.left };
312
+
313
+ return (
314
+ <div id="popper" style={{ ...position, position: 'absolute', zIndex: 2 }}>
315
+ <ClickAwayListener onClickAway={onTagListBlur}>
316
+ {params.children}
317
+ </ClickAwayListener>
318
+ </div>
319
+ );
320
+ }, [allMenuTags, inputValue, currentInputString, inputNode.current, tagMenuNode.current, input.value]);
321
+
322
+ const listboxAdapter = useCallback(params => (
323
+ <div className={params.className} ref={tagMenuNode}>
324
+ <AddTagMenu
325
+ tags={menuTags}
326
+ handleAdd={onTagAdd}
327
+ activeTag={activeTag}
328
+ setActiveTag={setActiveTag}
329
+ />
330
+ </div>
331
+ ), [menuTags, activeTag, setActiveTag, onTagAdd]);
332
+
333
+ return (
334
+ <div className={className} id={input.name}>
335
+ <div
336
+ className={clsx('relative', {
337
+ 'pointer-events-none': disabled
338
+ })}
339
+ >
340
+ <Autocomplete
341
+ value={null}
342
+ open={menuIsOpen}
343
+ options={filteredOptions}
344
+ onChange={handleChange}
345
+ renderOption={renderOption}
346
+ filterOptions={filterOptionsInner}
347
+ getOptionLabel={getOptionLabel}
348
+ PopperComponent={currentInputString ? undefined : popperAdapter}
349
+ ListboxComponent={currentInputString ? undefined : listboxAdapter}
350
+ classes={{
351
+ root: classes.root,
352
+ hasPopupIcon: classes.hasPopup,
353
+ hasClearIcon: classes.hasClear,
354
+ listbox: clsx(classes.listbox, fieldClasses.listbox),
355
+ inputRoot: classes.inputWrapper,
356
+ noOptions: 'd-none'
357
+ }}
358
+ renderInput={({
359
+ InputLabelProps, InputProps, inputProps, ...params
360
+ }) => (
361
+ <EditInPlaceFieldBase
362
+ {...params}
363
+ name={input.name}
364
+ value={input.value}
365
+ error={meta.error}
366
+ invalid={meta?.invalid}
367
+ label={label}
368
+ warning={warning}
369
+ disabled={disabled}
370
+ fieldClasses={fieldClasses}
371
+ shrink={Boolean(label || input.value)}
372
+ labelAdornment={labelAdornment}
373
+ placeholder={placeholder || 'No value'}
374
+ editIcon={<Edit fontSize="inherit" />}
375
+ InputProps={{
376
+ ...InputProps,
377
+ onChange: handleInputChange,
378
+ onFocus,
379
+ onBlur,
380
+ inputProps: {
381
+ ...inputProps,
382
+ ref: ref => {
383
+ (inputProps as any).ref.current = ref;
384
+ inputNode.current = ref;
385
+ },
386
+ value: inputValue
387
+ },
388
+ }}
389
+ CustomInput={!isEditing
390
+ ? <Select
391
+ inputRef={ref => {
392
+ (inputProps as any).ref.current = ref?.node;
393
+ }}
394
+ onFocus={edit}
395
+ value="stub"
396
+ className={classes.inputWrapper}
397
+ classes={{ select: 'd-flex flex-wrap cursor-text' }}
398
+ endAdornment={
399
+ <InputAdornment
400
+ position="end"
401
+ className={classes.inputEndAdornment}>
402
+ <Edit />
403
+ </InputAdornment>
404
+ }
405
+ IconComponent={stubComponent}
406
+ >
407
+ <MenuItem value="stub">
408
+ {InputValueForRender || <span className="placeholderContent">No value</span>}
409
+ </MenuItem>
410
+ </Select>
411
+ : null}
412
+ />)
413
+ }
414
+ popupIcon={stubComponent()}
415
+ disableListWrap
416
+ openOnFocus
417
+ />
418
+ </div>
419
+ </div>
420
+ );
421
+ }
422
+
423
+ export default withStyles(theme => ({
424
+ ...selectStyles(theme),
425
+ ...styles(theme)
426
+ }))(
427
+ TagInputList
428
+ ) as any;
@@ -0,0 +1,4 @@
1
+
2
+ export * from './AddTagMenuItem';
3
+ export * from './AddTagMenu';
4
+ export * from './TagInputList';