@startlibs/form 1.0.12 → 1.1.0

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 (92) hide show
  1. package/lib/AutoComplete.mjs +550 -0
  2. package/lib/AutoComplete.mjs.map +1 -0
  3. package/lib/Checkbox.mjs +76 -0
  4. package/lib/Checkbox.mjs.map +1 -0
  5. package/lib/Combobox.mjs +544 -0
  6. package/lib/Combobox.mjs.map +1 -0
  7. package/lib/ComboboxWithCustom.mjs +77 -0
  8. package/lib/ComboboxWithCustom.mjs.map +1 -0
  9. package/lib/DatePicker.mjs +625 -0
  10. package/lib/DatePicker.mjs.map +1 -0
  11. package/lib/EditableBox.mjs +496 -0
  12. package/lib/EditableBox.mjs.map +1 -0
  13. package/lib/Errors.mjs +176 -0
  14. package/lib/Errors.mjs.map +1 -0
  15. package/lib/ExpandableBox.mjs +209 -0
  16. package/lib/ExpandableBox.mjs.map +1 -0
  17. package/lib/Field.mjs +65 -0
  18. package/lib/Field.mjs.map +1 -0
  19. package/lib/FieldBox.mjs +80 -0
  20. package/lib/FieldBox.mjs.map +1 -0
  21. package/lib/Form.mjs +322 -0
  22. package/lib/Form.mjs.map +1 -0
  23. package/lib/FormValue.mjs +111 -0
  24. package/lib/FormValue.mjs.map +1 -0
  25. package/lib/InputboxGroup.mjs +104 -0
  26. package/lib/InputboxGroup.mjs.map +1 -0
  27. package/lib/Radiobox.mjs +67 -0
  28. package/lib/Radiobox.mjs.map +1 -0
  29. package/lib/RichText.mjs +634 -0
  30. package/lib/RichText.mjs.map +1 -0
  31. package/lib/TextInput.mjs +359 -0
  32. package/lib/TextInput.mjs.map +1 -0
  33. package/lib/alt/checkbox/SimpleCheckbox.mjs +82 -0
  34. package/lib/alt/checkbox/SimpleCheckbox.mjs.map +1 -0
  35. package/lib/alt/checkbox/ToggleCheckbox.mjs +68 -0
  36. package/lib/alt/checkbox/ToggleCheckbox.mjs.map +1 -0
  37. package/lib/alt/radiobox/CleanTabRadiobox.mjs +44 -0
  38. package/lib/alt/radiobox/CleanTabRadiobox.mjs.map +1 -0
  39. package/lib/alt/radiobox/IconRadioBox.mjs +52 -0
  40. package/lib/alt/radiobox/IconRadioBox.mjs.map +1 -0
  41. package/lib/alt/radiobox/SimpleRadiobox.mjs +61 -0
  42. package/lib/alt/radiobox/SimpleRadiobox.mjs.map +1 -0
  43. package/lib/alt/radiobox/TabRadiobox.mjs +54 -0
  44. package/lib/alt/radiobox/TabRadiobox.mjs.map +1 -0
  45. package/lib/enhanceInput.mjs +131 -0
  46. package/lib/enhanceInput.mjs.map +1 -0
  47. package/lib/index.cjs +5345 -0
  48. package/lib/index.cjs.map +1 -0
  49. package/lib/index.mjs +28 -0
  50. package/lib/index.mjs.map +1 -0
  51. package/lib/useConfirmDialog.mjs +117 -0
  52. package/lib/useConfirmDialog.mjs.map +1 -0
  53. package/lib/useDraftConfirmation.mjs +56 -0
  54. package/lib/useDraftConfirmation.mjs.map +1 -0
  55. package/lib/validation.mjs +91 -0
  56. package/lib/validation.mjs.map +1 -0
  57. package/lib/withFormImageInput.mjs +281 -0
  58. package/lib/withFormImageInput.mjs.map +1 -0
  59. package/package.json +44 -25
  60. package/src/AutoComplete.jsx +642 -0
  61. package/src/Checkbox.jsx +45 -0
  62. package/src/Combobox.jsx +606 -0
  63. package/src/ComboboxWithCustom.jsx +68 -0
  64. package/src/DatePicker.jsx +733 -0
  65. package/src/EditableBox.jsx +502 -0
  66. package/src/Errors.jsx +174 -0
  67. package/src/ExpandableBox.jsx +207 -0
  68. package/src/Field.jsx +76 -0
  69. package/src/FieldBox.jsx +136 -0
  70. package/src/Form.jsx +291 -0
  71. package/src/FormValue.jsx +67 -0
  72. package/src/IconRadioBoxOldHubt.jsx +93 -0
  73. package/src/InputboxGroup.jsx +121 -0
  74. package/src/Radiobox.jsx +33 -0
  75. package/src/RichText.jsx +812 -0
  76. package/src/TextInput.jsx +519 -0
  77. package/src/alt/checkbox/SimpleCheckbox.jsx +162 -0
  78. package/src/alt/checkbox/ToggleCheckbox.jsx +143 -0
  79. package/src/alt/radiobox/CleanTabRadiobox.jsx +46 -0
  80. package/src/alt/radiobox/IconRadioBox.jsx +93 -0
  81. package/src/alt/radiobox/SimpleRadiobox.jsx +153 -0
  82. package/src/alt/radiobox/TabRadiobox.jsx +73 -0
  83. package/src/enhanceInput.jsx +107 -0
  84. package/src/index.js +27 -0
  85. package/src/useConfirmDialog.jsx +105 -0
  86. package/src/useDraftConfirmation.jsx +60 -0
  87. package/src/validation.js +92 -0
  88. package/src/withFormImageInput.jsx +297 -0
  89. package/.babelrc +0 -28
  90. package/lib/index.js +0 -6258
  91. package/rollup.config.js +0 -43
  92. package/yarn-error.log +0 -1607
@@ -0,0 +1,550 @@
1
+ import _defineProperty from '@babel/runtime/helpers/defineProperty';
2
+ import _extends from '@babel/runtime/helpers/extends';
3
+ import _objectWithoutProperties from '@babel/runtime/helpers/objectWithoutProperties';
4
+ import _taggedTemplateLiteral from '@babel/runtime/helpers/taggedTemplateLiteral';
5
+ import _isString from 'lodash/fp/isString';
6
+ import _filter from 'lodash/fp/filter';
7
+ import _concat from 'lodash/fp/concat';
8
+ import _set from 'lodash/fp/set';
9
+ import _flow from 'lodash/fp/flow';
10
+ import _without from 'lodash/fp/without';
11
+ import _isEqual from 'lodash/fp/isEqual';
12
+ import _last from 'lodash/fp/last';
13
+ import React, { useRef, useState, useEffect } from 'react';
14
+ import ContentEditable from 'react-contenteditable';
15
+ import { useToggle, useEnsureRef, useRefState } from '@startlibs/core';
16
+ import { Icon, ContextMenu, Loading, Li } from '@startlibs/components';
17
+ import { Errors, useProvideErrors } from './Errors.mjs';
18
+ import { Field } from './Field.mjs';
19
+ import { useInput } from './enhanceInput.mjs';
20
+ import { getColor, media, customTheme, callIfFunction, constrainEvent, _s, stopPropagation } from '@startlibs/utils';
21
+ import styled, { css } from 'styled-components';
22
+ import { darken } from 'polished';
23
+
24
+ const _excluded = ["CompletedBox", "isEditable", "getLabel", "cancelEditable", "value", "remove", "index"],
25
+ _excluded2 = ["value", "confirmKeys", "index", "EditableInput", "confirmIfNewKeys", "confirmIfNew", "confirm", "remove"];
26
+ var _templateObject, _templateObject2, _templateObject3, _templateObject4;
27
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
28
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
29
+ const ua = navigator.userAgent.toLowerCase();
30
+ const isSafari = ua.indexOf('safari') >= 0 && ua.indexOf('chrome') < 0;
31
+ const InputLoading = /*#__PURE__*/styled(Loading).withConfig({
32
+ displayName: "AutoComplete__InputLoading",
33
+ componentId: "sc-g0526o-0"
34
+ })(["bottom:8px;right:0.6rem;left:auto;top:50%;transform:translate(-50%);"]);
35
+ const AutoCompleteInput = /*#__PURE__*/styled.div.withConfig({
36
+ displayName: "AutoComplete__AutoCompleteInput",
37
+ componentId: "sc-g0526o-1"
38
+ })(["width:100%;font-size:14px;border:1px solid ", ";border-radius:8px;color:", ";cursor:text;background:white;position:relative;outline:0;outline:none;min-height:3rem;line-height:28px;padding:0.25rem 0.7rem;display:flex;align-items:center;flex-wrap:wrap;", " ", " ", " ", " ", ""], getColor('gray210'), getColor('gray60'), props => props.focused && "\n border-color: ".concat(getColor('gray180'), ";\n box-shadow: 0px 0px 0px 2px rgba(0,0,0,0.075);\n "), props => props.hasErrors && css(["border-color:", " !important;"], getColor('alert')), media.mobile(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n padding: 0.25rem 1rem;\n min-height: 42px;\n "]))), props => props.withDropdown && css(["padding-right:3rem;", ""], media.mobile(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["\n padding-right: 4rem;\n "])))), customTheme('TextInput'));
39
+ const AutoCompletePlaceholder = /*#__PURE__*/styled.span.withConfig({
40
+ displayName: "AutoComplete__AutoCompletePlaceholder",
41
+ componentId: "sc-g0526o-2"
42
+ })(["position:absolute;top:50%;transform:translateY(-50%);pointer-events:none;color:rgba(0,0,0,0.3);left:0.7rem;right:0.7rem;", ""], media.mobile(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral(["\n left: 1rem;\n right: 1rem;\n "]))));
43
+ const AutoCompleteTextboxDiv = /*#__PURE__*/styled(ContentEditable).withConfig({
44
+ displayName: "AutoComplete__AutoCompleteTextboxDiv",
45
+ componentId: "sc-g0526o-3"
46
+ })(["display:inline-block;outline:0;outline:none;padding:0 1px;line-height:130%;"]);
47
+ const AddedBox = /*#__PURE__*/styled.span.withConfig({
48
+ displayName: "AutoComplete__AddedBox",
49
+ componentId: "sc-g0526o-4"
50
+ })(["background-color:rgb(230,230,230);padding:5px 2rem 5px 0.75rem;border-radius:12px;font-size:13px;position:relative;margin-left:-3px;margin-right:9px;white-space:nowrap;cursor:default;line-height:normal;max-width:90%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;", ""], isSafari ? "\n vertical-align: 2px;\n " : "\n vertical-align: -7px;\n ");
51
+ const RemoveIcon = /*#__PURE__*/styled(Icon).withConfig({
52
+ displayName: "AutoComplete__RemoveIcon",
53
+ componentId: "sc-g0526o-5"
54
+ })(["width:20px;height:20px;border-radius:50%;display:inline-block;position:absolute;top:50%;line-height:20px;transform:translateY(-50%);right:2px;font-size:14px;text-align:center;cursor:pointer;color:", ";:hover{background-color:", ";color:", ";}"], getColor('gray120'), getColor('gray210'), props => darken(0.05, getColor('alert')(props)));
55
+ const AutoCompleteMenu = /*#__PURE__*/styled(ContextMenu).withConfig({
56
+ displayName: "AutoComplete__AutoCompleteMenu",
57
+ componentId: "sc-g0526o-6"
58
+ })(["box-shadow:0 2px 3px 1px rgba(0,0,0,0.2),0 0px 0px 1px rgba(0,0,0,0.05);max-height:22rem;overflow:auto;", "{> *{padding:11px;}}"], ContextMenu.ListItem);
59
+ const AutoCompleteError = /*#__PURE__*/styled(Errors).withConfig({
60
+ displayName: "AutoComplete__AutoCompleteError",
61
+ componentId: "sc-g0526o-7"
62
+ })(["", "{background:transparent;border:none;color:", ";padding:0;margin-top:0.5rem;font-weight:600;", "{display:none;}}"], Errors.Item, getColor('alert'), Errors.CloseIcon);
63
+ const DropdownIconContainer = /*#__PURE__*/styled(Icon).withConfig({
64
+ displayName: "AutoComplete__DropdownIconContainer",
65
+ componentId: "sc-g0526o-8"
66
+ })(["position:absolute;right:0;bottom:0;width:3rem;height:3rem;bottom:-1px;", " ", "{position:absolute;width:2rem;height:2rem;line-height:2rem;top:50%;left:50%;transform:translate(-50%,-50%);background:rgba(0,0,0,0.1);border-radius:50%;text-align:center;cursor:pointer;color:", ";:hover,:active{background:rgba(0,0,0,0.15);}}"], media.mobile(_templateObject4 || (_templateObject4 = _taggedTemplateLiteral(["\n height: 42px;\n "]))), Icon, getColor('gray90'));
67
+ const focusBeforeLast = e => {
68
+ if (e.target && e.target !== e.currentTarget) return;
69
+ const el = [].slice.call(e.currentTarget.querySelectorAll('div[contenteditable]')).slice(-1)[0];
70
+ if (!el) return;
71
+ el.focus();
72
+ if (!el.firstChild) {
73
+ const node = document.createTextNode('');
74
+ el.appendChild(node);
75
+ }
76
+ setSelectionRange(el.firstChild, el.textContent.length + 1);
77
+ };
78
+ const setSelectionRange = function (input, selectionStart) {
79
+ let range = document.createRange();
80
+ let sel = window.getSelection();
81
+ range.setStart(input, Math.max(selectionStart - 1, 0));
82
+ sel.removeAllRanges();
83
+ sel.addRange(range);
84
+ };
85
+ const AutoComplete = /*#__PURE__*/React.forwardRef((_ref, outerRef) => {
86
+ let {
87
+ path,
88
+ AutoCompleteLi = Li,
89
+ CompletedBox = _ref2 => {
90
+ let {
91
+ label,
92
+ remove,
93
+ value
94
+ } = _ref2;
95
+ return /*#__PURE__*/React.createElement(AddedBox, {
96
+ title: label
97
+ }, label, /*#__PURE__*/React.createElement(RemoveIcon, {
98
+ icon: "x",
99
+ onMouseUp: constrainEvent(remove)
100
+ }));
101
+ },
102
+ EditableInput = props => /*#__PURE__*/React.createElement(AutoCompleteTextboxDiv, props),
103
+ getLabel = v => v,
104
+ minQueryLength = 3,
105
+ ignoreCase = true,
106
+ autoSelect,
107
+ autoSelectEquals,
108
+ fetchLimit = 6,
109
+ deleteOnBackspace = true,
110
+ fetchSuggestions: rawFetchSuggestions,
111
+ validation = value => ({
112
+ success: value.trim()
113
+ }),
114
+ transform,
115
+ withDropdown,
116
+ autoFocus,
117
+ clickOpensWhenEmpty,
118
+ tabIndex = 1,
119
+ confirmIfNewKeys = [],
120
+ confirmKeys = ['Enter', ','],
121
+ confirmIfValueKeys = ['Tab'],
122
+ placeholder,
123
+ className,
124
+ getListItem = getLabel,
125
+ onAddValue,
126
+ getUniqueKey,
127
+ translatable = true,
128
+ withoutField,
129
+ fieldClassName,
130
+ bellowDescText,
131
+ mandatory,
132
+ descText,
133
+ helpText,
134
+ label,
135
+ value,
136
+ setValue,
137
+ raw
138
+ } = _ref;
139
+ const autoCompleteBox = useToggle();
140
+ const hoverIndex = useToggle();
141
+ const isLoading = useToggle();
142
+ const cancelEditable = useRef();
143
+ const [formValue, _setFormValue, {
144
+ hasErrors
145
+ }] = useInput({
146
+ path,
147
+ transform,
148
+ value,
149
+ setValue
150
+ }, raw);
151
+ const formValueRef = useRef(formValue);
152
+ formValueRef.current = formValue;
153
+ const [localFormValue, setLocalFormValue] = useState(_last(formValue) === "" ? formValue : formValue.concat(""));
154
+ const setFormValue = updater => {
155
+ _setFormValue(updater);
156
+ setLocalFormValue(updater);
157
+ formValueRef.current = typeof updater === 'function' ? updater(formValueRef.current) : updater;
158
+ };
159
+ const lastIsEditable = _isEqual(localFormValue, formValue);
160
+ const [ErrorProvider, errorUtils] = useProvideErrors();
161
+ const hooksRef = useEnsureRef(outerRef);
162
+ const ref = useRef();
163
+ const queries = useRefState([]);
164
+ const suggestionsFetchCache = useRefState({});
165
+ const suggestionsLabelMapCache = useRefState({});
166
+ const lastSuggestionQuery = useRefState('');
167
+ const [autoCompleteList, setAutoCompleteList] = useState([]);
168
+ const getValue = () => formValueRef.current || [];
169
+ const shouldFocusInput = useToggle();
170
+ const recentlyAdded = useRefState(false);
171
+ useEffect(() => {
172
+ if (autoFocus) {
173
+ focusInput();
174
+ }
175
+ }, []);
176
+ const focusInput = () => shouldFocusInput.openWith(i => i + 1);
177
+ useEffect(() => {
178
+ if (shouldFocusInput.isOpen) focusBeforeLast({
179
+ currentTarget: ref.current,
180
+ target: ref.current
181
+ });
182
+ }, [shouldFocusInput.isOpen]);
183
+ const editableIsEmpty = () => !lastIsEditable || lastIsEditable && !formValue[formValue.length - 1];
184
+ const ignoreCaseIfNeeded = s => ignoreCase ? (s || '').toLowerCase() : s;
185
+ const refreshSuggestions = function () {
186
+ let value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
187
+ let justFetch = arguments.length > 1 ? arguments[1] : undefined;
188
+ let dropdownFetch = arguments.length > 2 ? arguments[2] : undefined;
189
+ if ((value.length >= minQueryLength || dropdownFetch) && rawFetchSuggestions) {
190
+ queries.set([value]);
191
+ const removeEditable = list => lastIsEditable ? list.slice(0, -1) : list;
192
+ return isLoading.wait(Promise.resolve(fetchSuggestions(ignoreCaseIfNeeded(value))).then(list => {
193
+ const noRepeatedList = list.filter(v => !removeEditable(getValue()).find(_ => getLabel(v) === getLabel(_)));
194
+ if (justFetch) {
195
+ return noRepeatedList;
196
+ }
197
+ const index = queries.get().indexOf(value);
198
+ if (index >= 0) {
199
+ queries.set(q => q.slice(index + 1));
200
+ if (!autoSelect && !(autoSelectEquals && noRepeatedList.slice(0, 1).find(v => ignoreCaseIfNeeded(getLabel(v)) === ignoreCaseIfNeeded(value)))) {
201
+ hoverIndex.openWith(-1);
202
+ } else {
203
+ hoverIndex.openWith(0);
204
+ }
205
+ autoCompleteBox.open();
206
+ setAutoCompleteList(noRepeatedList);
207
+ }
208
+ }));
209
+ } else {
210
+ hoverIndex.openWith(-1);
211
+ setAutoCompleteList([]);
212
+ return Promise.resolve([]);
213
+ }
214
+ };
215
+ const fetchSuggestions = s => {
216
+ const prevQuery = lastSuggestionQuery.get();
217
+ lastSuggestionQuery.set(s);
218
+ if (suggestionsFetchCache.get()[s]) {
219
+ return suggestionsFetchCache.get()[s];
220
+ } else {
221
+ const lastFetch = suggestionsFetchCache.get()[ignoreCaseIfNeeded(prevQuery)];
222
+ if (s.indexOf(ignoreCaseIfNeeded(prevQuery)) >= 0 && lastFetch && lastFetch.length < fetchLimit) {
223
+ return suggestionsFetchCache.get()[s] = lastFetch.map(getLabel).filter(_ => ignoreCaseIfNeeded(_).indexOf(ignoreCaseIfNeeded(s)) >= 0).map(_ => suggestionsLabelMapCache.get()()[ignoreCaseIfNeeded(_)]);
224
+ } else {
225
+ const fetch = Promise.resolve(rawFetchSuggestions(s));
226
+ fetch.then(list => {
227
+ suggestionsFetchCache[ignoreCaseIfNeeded(s)] = list;
228
+ list.forEach(suggestion => suggestionsLabelMapCache.get()[ignoreCaseIfNeeded(getLabel(suggestion))] = suggestionsLabelMapCache.get()[ignoreCaseIfNeeded(getLabel(suggestion))] || suggestion);
229
+ });
230
+ return fetch;
231
+ }
232
+ }
233
+ };
234
+ useEffect(() => {
235
+ if (!lastIsEditable) {
236
+ if (recentlyAdded.get() !== cancelEditable.current) {
237
+ setFormValue(_without([cancelEditable.current], formValue).concat(""));
238
+ } else {
239
+ setLocalFormValue(_last(formValue) === "" ? formValue : formValue.concat(""));
240
+ }
241
+ cancelEditable.current = null;
242
+ }
243
+ }, [lastIsEditable]);
244
+ useEffect(() => {
245
+ refreshSuggestions(lastIsEditable ? getValue().slice(-1)[0] : '');
246
+ if (recentlyAdded.get()) {
247
+ recentlyAdded.set(false);
248
+ callIfFunction(onAddValue, formValue, setFormValue);
249
+ }
250
+ }, [formValue]);
251
+ const confirmIfNew = (index, newValue) => {
252
+ refreshSuggestions(newValue, true).then(list => {
253
+ if (!list.length) {
254
+ confirm(index, newValue);
255
+ } else {
256
+ onChange(index, newValue);
257
+ }
258
+ });
259
+ };
260
+ const confirm = (index, newValue) => {
261
+ if (autoCompleteList.length && hoverIndex.isOpen >= 0) {
262
+ addValue(autoCompleteList[hoverIndex.isOpen]);
263
+ } else {
264
+ confirmValue(index, newValue);
265
+ }
266
+ };
267
+ const confirmValue = (index, newValue, fromBlur) => {
268
+ if (!newValue) {
269
+ return;
270
+ }
271
+ const suggestedValue = suggestionsLabelMapCache[ignoreCaseIfNeeded(newValue || '').trim()];
272
+ if (suggestedValue) {
273
+ addValue(suggestedValue, fromBlur);
274
+ return;
275
+ }
276
+ const {
277
+ success,
278
+ errors
279
+ } = validation(newValue);
280
+ if (errors) {
281
+ errorUtils.setErrors({
282
+ errors
283
+ });
284
+ } else {
285
+ addValue(success, fromBlur);
286
+ }
287
+ };
288
+ const onChange = (index, value) => {
289
+ errorUtils.clearErrors();
290
+ setFormValue(_s.set([index], value));
291
+ };
292
+ const addValue = (value, fromBlur) => {
293
+ const index = Math.max(lastIsEditable ? getValue().length - 1 : getValue().length, 0);
294
+ recentlyAdded.set((formValue === null || formValue === void 0 ? void 0 : formValue[index]) || "");
295
+ setFormValue(_flow(_set([index], value), _concat(_concat.placeholder, "")));
296
+ if (!fromBlur) {
297
+ focusInput();
298
+ }
299
+ };
300
+ const remove = index => {
301
+ setFormValue(_flow(_s.unset(index), _filter(_ => _ !== undefined)));
302
+ focusInput();
303
+ };
304
+ const onBlur = e => {
305
+ autoCompleteBox.close();
306
+ const v = getValue().slice(-1)[0];
307
+ if (lastIsEditable) {
308
+ const {
309
+ errors
310
+ } = validation(v);
311
+ const firstIsEqual = autoCompleteList.slice(0, 1).find(item => ignoreCaseIfNeeded(getLabel(item)) === ignoreCaseIfNeeded(v));
312
+ if (v && autoSelect && (autoCompleteList.length === 1 || firstIsEqual) && errors) {
313
+ addValue(autoCompleteList[0], true);
314
+ } else if (autoSelectEquals && firstIsEqual) {
315
+ addValue(autoCompleteList[0], true);
316
+ } else {
317
+ confirmValue(getValue().length - 1, v, true);
318
+ }
319
+ } else if (autoCompleteList.length) {
320
+ setAutoCompleteList([]);
321
+ }
322
+ };
323
+ React.useImperativeHandle(hooksRef, () => ({
324
+ addValue,
325
+ confirm,
326
+ remove
327
+ }), [formValue]);
328
+ const validValue = formValue || [''];
329
+ const uniqueKeyLabel = {};
330
+ const _getUniqueKey = value => {
331
+ if (getUniqueKey) {
332
+ return getUniqueKey(value);
333
+ }
334
+ const label = getLabel(value);
335
+ const uid = uniqueKeyLabel[label] = (uniqueKeyLabel[label] || 0) + 1;
336
+ return label + uid;
337
+ };
338
+ const tryOpenSuggestions = e => {
339
+ if (autoCompleteBox.get()) {
340
+ stopPropagation(onBlur)(e);
341
+ } else {
342
+ errorUtils.clearErrors();
343
+ refreshSuggestions(lastIsEditable ? getValue().slice(-1)[0] : '', false, true);
344
+ focusInput();
345
+ }
346
+ };
347
+ const input = /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(AutoCompleteInput, {
348
+ onKeyDown: e => e.key === ' ' && e.stopPropagation(),
349
+ className: className,
350
+ ref: ref,
351
+ onFocus: () => {
352
+ if (autoCompleteList.length) autoCompleteBox.open();else if (withDropdown && editableIsEmpty()) refreshSuggestions(undefined, undefined, true);
353
+ },
354
+ hasErrors: errorUtils.errors.length > 0 || hasErrors,
355
+ onBlur: onBlur,
356
+ onClick: e => {
357
+ focusBeforeLast(e);
358
+ if (editableIsEmpty() && !isLoading.isOpen) {
359
+ refreshSuggestions(undefined, undefined, true);
360
+ }
361
+ },
362
+ focused: autoCompleteBox.isOpen,
363
+ withDropdown: withDropdown
364
+ }, /*#__PURE__*/React.createElement("span", null, '\u200b'), validValue.map((v, i) => /*#__PURE__*/React.createElement(ValueItem, {
365
+ value: v,
366
+ index: i,
367
+ cancelEditable: v => {
368
+ cancelEditable.current = v;
369
+ },
370
+ isEditable: lastIsEditable && validValue.length === i + 1,
371
+ confirmKeys: confirmKeys,
372
+ confirmIfValueKeys: confirmIfValueKeys,
373
+ deleteOnBackspace: deleteOnBackspace,
374
+ EditableInput: EditableInput,
375
+ key: lastIsEditable && validValue.length === i + 1 ? '$$editable$$' : _getUniqueKey(v),
376
+ onChange: onChange,
377
+ remove: remove,
378
+ confirm: confirm,
379
+ getLabel: getLabel,
380
+ tabIndex: tabIndex,
381
+ confirmIfNew: confirmIfNew,
382
+ confirmIfNewKeys: confirmIfNewKeys,
383
+ CompletedBox: CompletedBox
384
+ })), /*#__PURE__*/React.createElement("span", null, '\u200b'), (!formValue || !formValue.join('')) && placeholder && /*#__PURE__*/React.createElement(AutoCompletePlaceholder, {
385
+ onClick: e => ref.current.click()
386
+ }, placeholder), withDropdown && !isLoading.isOpen && /*#__PURE__*/React.createElement(DropdownIconContainer, {
387
+ onClick: tryOpenSuggestions
388
+ }, /*#__PURE__*/React.createElement(Icon, {
389
+ icon: "arrow-down"
390
+ }))), autoCompleteBox.isOpen !== false && !errorUtils.errors.length && autoCompleteList.length > 0 && /*#__PURE__*/React.createElement(AutoCompleteMenu, {
391
+ hoverIndex: hoverIndex.isOpen,
392
+ autoHover: autoSelect,
393
+ onClick: constrainEvent(),
394
+ onHover: hoverIndex.openWith,
395
+ my: "top left",
396
+ at: "bottom left",
397
+ fill: true
398
+ }, autoCompleteList.map(value => /*#__PURE__*/React.createElement(AutoCompleteLi, {
399
+ className: !translatable ? 'notranslate' : null,
400
+ key: _getUniqueKey(value),
401
+ label: getListItem(value),
402
+ onMouseDown: e => e.preventDefault(),
403
+ onClick: () => addValue(value)
404
+ }))), /*#__PURE__*/React.createElement(ErrorProvider, {
405
+ value: errorUtils
406
+ }, /*#__PURE__*/React.createElement(AutoCompleteError, null)));
407
+ return withoutField ? input : /*#__PURE__*/React.createElement(Field, {
408
+ bellowDescText: bellowDescText,
409
+ className: fieldClassName,
410
+ value: formValue,
411
+ mandatory: mandatory,
412
+ descText: descText,
413
+ helpText: helpText,
414
+ label: label,
415
+ labelClick: focusInput
416
+ }, isLoading.isOpen && /*#__PURE__*/React.createElement(InputLoading, {
417
+ absolute: true,
418
+ size: 24
419
+ }), input);
420
+ });
421
+ AutoComplete.AddedBox = AddedBox;
422
+ AutoComplete.RemoveIcon = RemoveIcon;
423
+ AutoComplete.AutoCompleteTextboxDiv = AutoCompleteTextboxDiv;
424
+ const cleanText = text => {
425
+ const clean = text.replace('\u200b', '').replace(/\n/g, ' ').replace(/\s+/g, ' ');
426
+ return clean.trim() ? clean : '';
427
+ };
428
+ const ValueItem = _ref3 => {
429
+ let {
430
+ CompletedBox,
431
+ isEditable,
432
+ getLabel,
433
+ cancelEditable,
434
+ value,
435
+ remove,
436
+ index
437
+ } = _ref3,
438
+ props = _objectWithoutProperties(_ref3, _excluded);
439
+ const isEditing = useToggle(isEditable);
440
+ const valueRef = useRef(value);
441
+ valueRef.current = value;
442
+ useEffect(() => () => {
443
+ if (isEditing.isOpen) {
444
+ cancelEditable(valueRef.current);
445
+ }
446
+ }, []);
447
+ return isEditing.isOpen ? /*#__PURE__*/React.createElement(AutoCompleteTextbox, _extends({}, props, {
448
+ value: value,
449
+ index: index,
450
+ remove: remove
451
+ })) : /*#__PURE__*/React.createElement(CompletedBox, {
452
+ label: getLabel(value),
453
+ value: value,
454
+ remove: () => remove(index)
455
+ });
456
+ };
457
+ class AutoCompleteTextbox extends React.Component {
458
+ constructor() {
459
+ super(...arguments);
460
+ this.state = {
461
+ value: this.props.value
462
+ };
463
+ this.deletePrev = () => this.props.index > 0 && this.props.remove(this.props.index - 1);
464
+ this.onKeyDown = e => {
465
+ const range = window.getSelection().getRangeAt(0);
466
+ if (this.props.confirmIfNewKeys.indexOf(e.key) >= 0) {
467
+ e.preventDefault();
468
+ const text = range.startContainer.textContent;
469
+ this.props.confirmIfNew(this.props.index, cleanText((text.slice(0, range.startOffset) + '\uFFFD' + text.slice(range.startOffset)).replace('\uFFFD', e.key)));
470
+ } else if (e.key === 'ArrowLeft' || e.key === 'ArrowRight') {
471
+ e.stopPropagation();
472
+ } else if (this.props.confirmKeys.indexOf(e.key) >= 0 || this.props.confirmIfValueKeys.indexOf(e.key) >= 0) {
473
+ if (this.props.confirmKeys.indexOf(e.key) >= 0) {
474
+ e.preventDefault();
475
+ }
476
+ if (this.props.value) {
477
+ e.preventDefault();
478
+ e.stopPropagation();
479
+ this.props.confirm(this.props.index, this.props.value);
480
+ }
481
+ } else if (e.key === 'Backspace' && this.props.deleteOnBackspace) {
482
+ if (e.target.textContent !== '\u200b' || !range.collapsed) {
483
+ if (range.startContainer.previousSibling) {
484
+ if (range.startContainer.previousSibling.textContent.length) {
485
+ return;
486
+ }
487
+ } else if (range.startOffset > 0) {
488
+ return;
489
+ }
490
+ }
491
+ e.preventDefault();
492
+ this.deletePrev();
493
+ }
494
+ };
495
+ this.onChange = evt => {
496
+ this.props.onChange(this.props.index, cleanText(evt.currentTarget.isContentEditable ? evt.currentTarget.innerText : evt.target.value));
497
+ };
498
+ this.onPaste = ev => {
499
+ ev.preventDefault();
500
+ const text = ev.clipboardData.getData('text');
501
+ document.execCommand('insertText', false, text);
502
+ };
503
+ }
504
+ shouldComponentUpdate(nextProps) {
505
+ const event = new CustomEvent('portalReposition');
506
+ setTimeout(() => window.dispatchEvent(event), 1);
507
+ if (this.el.innerHTML === '<br>' || !this.el.innerHTML) {
508
+ this.props.onChange(this.props.index, '');
509
+ }
510
+ return nextProps.value !== cleanText(this.el.innerText) || !!Object.keys(nextProps).find(k => nextProps[k] !== this.props[k]);
511
+ }
512
+ componentDidUpdate(oldProps) {
513
+ if (this.props.value.slice(-1) === ' ' && /\S/.test(this.el.textContent.slice(-1))) {
514
+ // does not have blank space as last
515
+ this.el.innerHTML = this.props.value.replace(/\s/, '&nbsp;');
516
+ }
517
+ if (this.props.value !== oldProps.value && document.activeElement === this.el) {
518
+ setSelectionRange(this.el.firstChild || this.el, this.el.textContent.length + 1);
519
+ }
520
+ }
521
+ render() {
522
+ const _this$props = this.props,
523
+ {
524
+ value,
525
+ confirmKeys,
526
+ index,
527
+ EditableInput,
528
+ confirmIfNewKeys,
529
+ confirmIfNew,
530
+ confirm,
531
+ remove
532
+ } = _this$props,
533
+ rest = _objectWithoutProperties(_this$props, _excluded2);
534
+ const valueOrBlank = /*android fix, not needed? value || */_isString(value) && value ? value : '\u200b';
535
+ const props = _objectSpread(_objectSpread({
536
+ innerRef: ref => this.el = ref,
537
+ onKeyDown: this.onKeyDown,
538
+ onPaste: this.onPaste,
539
+ value: value,
540
+ index: index,
541
+ html: valueOrBlank.replace(/\s$/, '&nbsp;')
542
+ }, rest), {}, {
543
+ onChange: this.onChange
544
+ });
545
+ return typeof EditableInput === 'function' ? EditableInput(props) : /*#__PURE__*/React.createElement(EditableInput, props);
546
+ }
547
+ }
548
+
549
+ export { AutoComplete, AutoCompleteTextbox };
550
+ //# sourceMappingURL=AutoComplete.mjs.map