@luomus/laji-form 15.1.27 → 15.1.28
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/dist/laji-form.js +1 -1
- package/lib/components/LajiForm.d.ts +4 -1
- package/lib/components/fields/EnumRangeArrayField.d.ts +7 -16
- package/lib/components/fields/EnumRangeArrayField.js +28 -98
- package/lib/components/widgets/CheckboxWidget.js +0 -6
- package/lib/components/widgets/SelectWidget.d.ts +10 -2
- package/lib/components/widgets/SelectWidget.js +97 -24
- package/lib/utils.d.ts +1 -0
- package/lib/utils.js +9 -1
- package/package.json +1 -1
|
@@ -84,7 +84,10 @@ export interface FormContext {
|
|
|
84
84
|
googleApiKey: string;
|
|
85
85
|
notifier: Notifier;
|
|
86
86
|
apiClient: ApiClient;
|
|
87
|
-
Label: React.
|
|
87
|
+
Label: React.ComponentType<{
|
|
88
|
+
label?: string;
|
|
89
|
+
id: string;
|
|
90
|
+
}>;
|
|
88
91
|
formDataTransformers?: any[];
|
|
89
92
|
_parentLajiFormId?: number;
|
|
90
93
|
mediaMetadata?: MediaMetadata;
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import * as PropTypes from "prop-types";
|
|
3
|
+
import { FieldProps, JSONSchemaArray, JSONSchemaString } from "../../types";
|
|
4
|
+
declare function EnumRangeArrayField(props: FieldProps<JSONSchemaArray<JSONSchemaString>>): JSX.Element | null;
|
|
5
|
+
declare namespace EnumRangeArrayField {
|
|
6
|
+
var propTypes: {
|
|
3
7
|
uiSchema: PropTypes.Requireable<PropTypes.InferProps<{
|
|
4
8
|
"ui:options": PropTypes.Requireable<PropTypes.InferProps<{
|
|
5
9
|
range: PropTypes.Requireable<string>;
|
|
@@ -10,18 +14,5 @@ export default class EnumRangeArrayField extends React.Component<any, any, any>
|
|
|
10
14
|
}>>;
|
|
11
15
|
formData: PropTypes.Requireable<any[]>;
|
|
12
16
|
};
|
|
13
|
-
static getName(): string;
|
|
14
|
-
constructor(props: any);
|
|
15
|
-
setRef: (elem: any) => void;
|
|
16
|
-
autosuggestRef: any;
|
|
17
|
-
onInputChange: ({ target: { value } }: {
|
|
18
|
-
target: {
|
|
19
|
-
value: any;
|
|
20
|
-
};
|
|
21
|
-
}, reason: any, callback: any) => any;
|
|
22
|
-
onSuggestionSelected: (suggestion: any) => void;
|
|
23
|
-
onUnsuggestedSelected: (value: any) => void;
|
|
24
|
-
onChange: (formData: any, reason: any) => void;
|
|
25
17
|
}
|
|
26
|
-
|
|
27
|
-
import * as PropTypes from "prop-types";
|
|
18
|
+
export default EnumRangeArrayField;
|
|
@@ -1,89 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
7
10
|
};
|
|
8
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
12
|
const React = require("react");
|
|
10
13
|
const PropTypes = require("prop-types");
|
|
11
|
-
const react_dom_1 = require("react-dom");
|
|
12
|
-
const BaseComponent_1 = require("../BaseComponent");
|
|
13
14
|
const utils_1 = require("../../utils");
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
this.onSuggestionSelected = (suggestion) => {
|
|
35
|
-
this.setState({ value: "" }, () => {
|
|
36
|
-
this.onChange([...(this.props.formData || []), suggestion.value], "suggestion selected");
|
|
37
|
-
});
|
|
38
|
-
};
|
|
39
|
-
this.onUnsuggestedSelected = (value) => {
|
|
40
|
-
this.setState({ value: "" }, () => {
|
|
41
|
-
this.onChange([...(this.props.formData || []), value], "unsuggested selected");
|
|
42
|
-
});
|
|
43
|
-
};
|
|
44
|
-
this.onChange = (formData, reason) => {
|
|
45
|
-
function onlyUnique(value, index, self) {
|
|
46
|
-
return self.indexOf(value) === index;
|
|
47
|
-
}
|
|
48
|
-
formData = formData.filter(onlyUnique);
|
|
49
|
-
if (reason !== "remove" && reason !== "suggestion selected" && reason !== "unsuggested selected") {
|
|
50
|
-
this.setState({ value: "" });
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
this.setState({ value: "" }, () => {
|
|
54
|
-
this.props.onChange(formData);
|
|
55
|
-
});
|
|
56
|
-
};
|
|
57
|
-
this.state = { value: "" };
|
|
58
|
-
}
|
|
59
|
-
static getName() { return "EnumRangeArrayField"; }
|
|
60
|
-
render() {
|
|
61
|
-
const { range } = utils_1.getUiOptions(this.props.uiSchema);
|
|
62
|
-
const autosuggestOptions = {
|
|
63
|
-
autosuggestField: range,
|
|
64
|
-
onSuggestionSelected: this.onSuggestionSelected,
|
|
65
|
-
onConfirmUnsuggested: this.onConfirmUnsuggested,
|
|
66
|
-
id: this.props.idSchema.$id,
|
|
67
|
-
value: this.state.value,
|
|
68
|
-
controlledValue: true,
|
|
69
|
-
minFetchLength: 0,
|
|
70
|
-
wrapperClassName: "laji-form-enum-range",
|
|
71
|
-
inputProps: {
|
|
72
|
-
value: this.state.value,
|
|
73
|
-
that: this,
|
|
74
|
-
InputComponent: EnumRangeInputInjection,
|
|
75
|
-
onChange: this.onInputChange,
|
|
76
|
-
tags: this.props.formData,
|
|
77
|
-
id: this.props.idSchema.$id
|
|
78
|
-
},
|
|
79
|
-
allowNonsuggestedValue: false
|
|
80
|
-
};
|
|
81
|
-
const { Label } = this.props.formContext;
|
|
82
|
-
return (React.createElement(React.Fragment, null,
|
|
83
|
-
React.createElement(Label, { label: this.props.schema.title, id: this.props.idSchema.$id }),
|
|
84
|
-
React.createElement(AutosuggestWidget_1.Autosuggest, Object.assign({}, this.props, { onChange: undefined }, autosuggestOptions, { ref: this.setRef }))));
|
|
85
|
-
}
|
|
86
|
-
};
|
|
15
|
+
const react_1 = require("react");
|
|
16
|
+
const SelectWidget_1 = require("../widgets/SelectWidget");
|
|
17
|
+
const options = {};
|
|
18
|
+
const schema = { type: "array", items: { type: "string" } };
|
|
19
|
+
function EnumRangeArrayField(props) {
|
|
20
|
+
const { onChange: propsOnChange } = props;
|
|
21
|
+
const { range } = utils_1.getUiOptions(props.uiSchema);
|
|
22
|
+
const onChange = react_1.useCallback((value) => {
|
|
23
|
+
propsOnChange(value);
|
|
24
|
+
}, [propsOnChange]);
|
|
25
|
+
const getEnumOptionsAsync = react_1.useCallback(() => __awaiter(this, void 0, void 0, function* () {
|
|
26
|
+
const enums = yield props.formContext.apiClient.fetchCached(`/metadata/ranges/${range}`);
|
|
27
|
+
return enums.map(({ value }) => ({ value, label: value }));
|
|
28
|
+
}), [props.formContext.apiClient, range]);
|
|
29
|
+
const { Label } = props.formContext;
|
|
30
|
+
return React.createElement(React.Fragment, null,
|
|
31
|
+
React.createElement(Label, { label: props.schema.title, id: props.idSchema.$id }),
|
|
32
|
+
React.createElement(SelectWidget_1.default, { getEnumOptionsAsync: getEnumOptionsAsync, schema: schema, onChange: onChange, value: props.formData, options: options }));
|
|
33
|
+
}
|
|
34
|
+
exports.default = EnumRangeArrayField;
|
|
87
35
|
EnumRangeArrayField.propTypes = {
|
|
88
36
|
uiSchema: PropTypes.shape({
|
|
89
37
|
"ui:options": PropTypes.shape({
|
|
@@ -95,21 +43,3 @@ EnumRangeArrayField.propTypes = {
|
|
|
95
43
|
}).isRequired,
|
|
96
44
|
formData: PropTypes.array
|
|
97
45
|
};
|
|
98
|
-
EnumRangeArrayField = __decorate([
|
|
99
|
-
BaseComponent_1.default
|
|
100
|
-
], EnumRangeArrayField);
|
|
101
|
-
exports.default = EnumRangeArrayField;
|
|
102
|
-
class EnumRangeInputInjection extends React.Component {
|
|
103
|
-
constructor() {
|
|
104
|
-
super(...arguments);
|
|
105
|
-
this.onInputChange = e => {
|
|
106
|
-
this.props.onChange(e);
|
|
107
|
-
};
|
|
108
|
-
this.onChange = (tags, reason) => {
|
|
109
|
-
this.props.that.onChange(tags, reason);
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
render() {
|
|
113
|
-
return React.createElement(TagArrayField_1.TagInputComponent, Object.assign({}, this.props, { formContext: this.props.that.props.formContext, onChange: this.onChange, onInputChange: this.onInputChange }));
|
|
114
|
-
}
|
|
115
|
-
}
|
|
@@ -46,12 +46,6 @@ class CheckboxWidget extends React.Component {
|
|
|
46
46
|
this.onGroupKeyDown = this.props.formContext.utils.keyboardClick((e) => {
|
|
47
47
|
this.getToggleMode(this.props) && this.toggle(e);
|
|
48
48
|
}, [" "]);
|
|
49
|
-
// onTrueKeyDown = this.props.formContext.utils.keyboardClick(() => {
|
|
50
|
-
// if (this.props.disabled || this.props.readonly) {
|
|
51
|
-
// return;
|
|
52
|
-
// }
|
|
53
|
-
// this.onChange(true);
|
|
54
|
-
// }, [" "]);
|
|
55
49
|
this.onTrueKeyDown = (e) => {
|
|
56
50
|
const { key } = e;
|
|
57
51
|
if (key === " ") {
|
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
+
import { EnumOptionsType as _EnumOptionsType } from "@rjsf/utils";
|
|
2
3
|
import { JSONSchemaArray, JSONSchemaEnum, JSONSchemaEnumOneOf, WidgetProps } from "../../types";
|
|
4
|
+
declare type EnumOptionsType<T = string | undefined> = Omit<_EnumOptionsType, "value"> & {
|
|
5
|
+
value: T;
|
|
6
|
+
};
|
|
7
|
+
declare type SelectWidgetCustomProps = {
|
|
8
|
+
includeEmpty?: boolean;
|
|
9
|
+
getEnumOptionsAsync?: () => Promise<EnumOptionsType<string>[]>;
|
|
10
|
+
};
|
|
3
11
|
declare type SingleSelectWidgetProps = Omit<WidgetProps<JSONSchemaEnum>, "value" | "onChange"> & {
|
|
4
12
|
value?: string;
|
|
5
13
|
onChange: (value?: string) => void;
|
|
6
|
-
};
|
|
14
|
+
} & SelectWidgetCustomProps;
|
|
7
15
|
declare type MultiSelectWidgetProps = Omit<WidgetProps<JSONSchemaArray<JSONSchemaEnumOneOf>>, "value" | "onChange"> & {
|
|
8
16
|
value?: string[];
|
|
9
17
|
onChange: (value?: string[]) => void;
|
|
10
|
-
};
|
|
18
|
+
} & SelectWidgetCustomProps;
|
|
11
19
|
declare type SelectWidgetProps = SingleSelectWidgetProps | MultiSelectWidgetProps;
|
|
12
20
|
export default function SelectWidget(props: SelectWidgetProps): JSX.Element | null;
|
|
13
21
|
export {};
|
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
2
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
12
|
const React = require("react");
|
|
4
13
|
// import * as PropTypes from "prop-types";
|
|
@@ -6,8 +15,9 @@ const ReactContext_1 = require("../../ReactContext");
|
|
|
6
15
|
const utils_1 = require("../../utils");
|
|
7
16
|
const react_1 = require("react");
|
|
8
17
|
const react_dom_1 = require("react-dom");
|
|
18
|
+
const Spinner = require("react-spinner");
|
|
9
19
|
const useRangeIncrementor = (length, defaultIdx) => {
|
|
10
|
-
const [idx, _setIdx] =
|
|
20
|
+
const [idx, _setIdx] = react_1.useState(defaultIdx);
|
|
11
21
|
const setIdx = react_1.useCallback((idx) => {
|
|
12
22
|
let nextIdx = idx;
|
|
13
23
|
if (idx === undefined || idx < 0 || length === 0) {
|
|
@@ -40,7 +50,6 @@ function getEnumOptions(enumOptions, uiSchema, includeEmpty = true) {
|
|
|
40
50
|
}
|
|
41
51
|
}
|
|
42
52
|
function SelectWidget(props) {
|
|
43
|
-
// export default function SelectWidget(props: SelectWidgetProps): Widget<JSONSchemaEnum | JSONSchemaArray<JSONSchemaEnumOneOf>> {
|
|
44
53
|
return props.schema.type === "array" ? React.createElement(SearchableMultiDrowndown, Object.assign({}, props)) : React.createElement(SearchableDrowndown, Object.assign({}, props));
|
|
45
54
|
}
|
|
46
55
|
exports.default = SelectWidget;
|
|
@@ -53,12 +62,12 @@ function SearchableDrowndown(props) {
|
|
|
53
62
|
const enumOptions = React.useMemo(() =>
|
|
54
63
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
55
64
|
getEnumOptions(options.enumOptions, uiSchema, includeEmpty), [options.enumOptions, uiSchema, includeEmpty]);
|
|
56
|
-
const [inputValue, setInputValue] =
|
|
65
|
+
const [inputValue, setInputValue] = react_1.useState(value
|
|
57
66
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
58
67
|
? enumOptions.find(item => item.value === value).label
|
|
59
68
|
: "");
|
|
60
|
-
const [inputTouched, setInputTouched] =
|
|
61
|
-
const [filterTerm, setFilterTerm] =
|
|
69
|
+
const [inputTouched, setInputTouched] = react_1.useState(false);
|
|
70
|
+
const [filterTerm, setFilterTerm] = react_1.useState("");
|
|
62
71
|
const onInputChange = react_1.useCallback((e) => {
|
|
63
72
|
const { value } = e.target;
|
|
64
73
|
setInputValue(value);
|
|
@@ -74,9 +83,7 @@ function SearchableDrowndown(props) {
|
|
|
74
83
|
}, [filterTerm, enumOptions]);
|
|
75
84
|
const [isOpen, show, hide] = utils_1.useBooleanSetter(false);
|
|
76
85
|
const { FormControl } = theme;
|
|
77
|
-
const [activeIdx, activeIdxUp, activeIdxDown, setActiveIdx] = useRangeIncrementor((displayedEnums || []).length,
|
|
78
|
-
? displayedEnums.findIndex(item => item.value === value)
|
|
79
|
-
: 0);
|
|
86
|
+
const [activeIdx, activeIdxUp, activeIdxDown, setActiveIdx] = useRangeIncrementor((displayedEnums || []).length, getDefaultActiveIdx(displayedEnums, value));
|
|
80
87
|
const onItemSelected = react_1.useCallback((item) => {
|
|
81
88
|
onChange(item.value);
|
|
82
89
|
setInputValue(item.label);
|
|
@@ -113,8 +120,13 @@ function SearchableDrowndown(props) {
|
|
|
113
120
|
activeIdx !== undefined && displayedEnums && onItemSelected(displayedEnums[activeIdx]);
|
|
114
121
|
e.preventDefault();
|
|
115
122
|
break;
|
|
123
|
+
case "Escape":
|
|
124
|
+
setInputValue("");
|
|
125
|
+
setActiveIdx(getDefaultActiveIdx(displayedEnums, value));
|
|
126
|
+
e.preventDefault();
|
|
127
|
+
break;
|
|
116
128
|
}
|
|
117
|
-
}, [activeIdx, activeIdxDown, activeIdxUp, displayedEnums, onItemSelected]);
|
|
129
|
+
}, [activeIdx, activeIdxDown, activeIdxUp, displayedEnums, onItemSelected, setActiveIdx, value]);
|
|
118
130
|
const onFocus = react_1.useCallback(() => {
|
|
119
131
|
var _a;
|
|
120
132
|
show();
|
|
@@ -129,12 +141,21 @@ function SearchableDrowndown(props) {
|
|
|
129
141
|
}))));
|
|
130
142
|
}
|
|
131
143
|
function SearchableMultiDrowndown(props) {
|
|
132
|
-
const { id, disabled, readonly, value, uiSchema, options, onChange, } = props;
|
|
133
|
-
const enumOptions = React.useMemo(() =>
|
|
134
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
135
|
-
getEnumOptions(options.enumOptions
|
|
136
|
-
|
|
137
|
-
const [
|
|
144
|
+
const { id, disabled, readonly, value, uiSchema, options, onChange, getEnumOptionsAsync } = props;
|
|
145
|
+
// const enumOptions = React.useMemo(() =>
|
|
146
|
+
// // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
147
|
+
// getEnumOptions(options.enumOptions!, uiSchema, false),
|
|
148
|
+
// [options.enumOptions, uiSchema]);
|
|
149
|
+
const [enumOptions, setEnumOptions] = react_1.useState(getEnumOptionsAsync
|
|
150
|
+
? undefined
|
|
151
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
152
|
+
: getEnumOptions(options.enumOptions, uiSchema, false));
|
|
153
|
+
const [inputValue, setInputValue] = react_1.useState("");
|
|
154
|
+
const [filterTerm, setFilterTerm] = react_1.useState("");
|
|
155
|
+
const [loading, setLoading] = react_1.useState(undefined);
|
|
156
|
+
const [isOpen, show, hide] = utils_1.useBooleanSetter(false);
|
|
157
|
+
const containerRef = React.useRef(null);
|
|
158
|
+
const inputRef = React.useRef(null);
|
|
138
159
|
const onInputChange = react_1.useCallback((e) => {
|
|
139
160
|
const { value } = e.target;
|
|
140
161
|
setInputValue(value);
|
|
@@ -143,6 +164,9 @@ function SearchableMultiDrowndown(props) {
|
|
|
143
164
|
setFilterTerm(inputValue);
|
|
144
165
|
}, [inputValue]);
|
|
145
166
|
const displayedEnums = React.useMemo(() => {
|
|
167
|
+
if (!enumOptions) {
|
|
168
|
+
return [];
|
|
169
|
+
}
|
|
146
170
|
const notAlreadySelected = (value === null || value === void 0 ? void 0 : value.length)
|
|
147
171
|
? enumOptions.filter(({ value: enumValue }) => !value.includes(enumValue))
|
|
148
172
|
: enumOptions;
|
|
@@ -151,9 +175,6 @@ function SearchableMultiDrowndown(props) {
|
|
|
151
175
|
|| label.toLowerCase().match(filterTerm.toLowerCase()))
|
|
152
176
|
: notAlreadySelected;
|
|
153
177
|
}, [filterTerm, enumOptions, value]);
|
|
154
|
-
const [isOpen, show, hide] = utils_1.useBooleanSetter(false);
|
|
155
|
-
const containerRef = React.useRef(null);
|
|
156
|
-
const inputRef = React.useRef(null);
|
|
157
178
|
const [activeIdx, activeIdxUp, activeIdxDown, setActiveIdx] = useRangeIncrementor((displayedEnums || []).length, undefined);
|
|
158
179
|
const onItemSelected = react_1.useCallback((item) => {
|
|
159
180
|
var _a;
|
|
@@ -167,6 +188,48 @@ function SearchableMultiDrowndown(props) {
|
|
|
167
188
|
setInputValue("");
|
|
168
189
|
setActiveIdx(undefined);
|
|
169
190
|
}, [onChange, setActiveIdx, value]);
|
|
191
|
+
const [isFocused, setFocused, setBlurred] = utils_1.useBooleanSetter(false);
|
|
192
|
+
const loadEnums = react_1.useCallback(() => {
|
|
193
|
+
const asyncOp = () => __awaiter(this, void 0, void 0, function* () {
|
|
194
|
+
try {
|
|
195
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
196
|
+
const enums = yield getEnumOptionsAsync();
|
|
197
|
+
setEnumOptions(enums);
|
|
198
|
+
}
|
|
199
|
+
finally {
|
|
200
|
+
setLoading(false);
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
setLoading(true);
|
|
204
|
+
void asyncOp();
|
|
205
|
+
}, [getEnumOptionsAsync]);
|
|
206
|
+
const prevEnumOptions = utils_1.usePrevious(enumOptions);
|
|
207
|
+
// If the enums are async loaded, this effect takes care of opening the
|
|
208
|
+
// dropdown once the enums are loaded, if the input if still focused.
|
|
209
|
+
react_1.useEffect(() => {
|
|
210
|
+
if (!getEnumOptionsAsync) {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
if (isFocused && !(prevEnumOptions === null || prevEnumOptions === void 0 ? void 0 : prevEnumOptions.length) && (enumOptions === null || enumOptions === void 0 ? void 0 : enumOptions.length)) {
|
|
214
|
+
show();
|
|
215
|
+
}
|
|
216
|
+
}, [prevEnumOptions, enumOptions, isFocused, show, getEnumOptionsAsync]);
|
|
217
|
+
// If there is a pre-existing value (or a value is updated from parent after component is rendered) and we are async,
|
|
218
|
+
// load the enums.
|
|
219
|
+
react_1.useEffect(() => {
|
|
220
|
+
if ((value === null || value === void 0 ? void 0 : value.length) && getEnumOptionsAsync && !enumOptions && !loading) {
|
|
221
|
+
loadEnums();
|
|
222
|
+
}
|
|
223
|
+
}, [enumOptions, getEnumOptionsAsync, loadEnums, loading, value === null || value === void 0 ? void 0 : value.length]);
|
|
224
|
+
const onFocus = react_1.useCallback(() => {
|
|
225
|
+
setFocused();
|
|
226
|
+
if (!(enumOptions === null || enumOptions === void 0 ? void 0 : enumOptions.length) && getEnumOptionsAsync) {
|
|
227
|
+
void loadEnums();
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
show();
|
|
231
|
+
}
|
|
232
|
+
}, [enumOptions === null || enumOptions === void 0 ? void 0 : enumOptions.length, getEnumOptionsAsync, loadEnums, setFocused, show]);
|
|
170
233
|
const onBlur = react_1.useCallback((e) => {
|
|
171
234
|
// Fixes the problem when user tries to click an enum item, `setOpen(false)`
|
|
172
235
|
// hides the enum list, so the elem list item is hidden before the click, thus never
|
|
@@ -174,6 +237,7 @@ function SearchableMultiDrowndown(props) {
|
|
|
174
237
|
if (e.relatedTarget && utils_1.isDescendant(containerRef.current, e.relatedTarget)) {
|
|
175
238
|
return;
|
|
176
239
|
}
|
|
240
|
+
setBlurred();
|
|
177
241
|
hide();
|
|
178
242
|
if (activeIdx !== undefined && displayedEnums[activeIdx]) {
|
|
179
243
|
onItemSelectedByBlur(displayedEnums[activeIdx]);
|
|
@@ -181,7 +245,7 @@ function SearchableMultiDrowndown(props) {
|
|
|
181
245
|
else {
|
|
182
246
|
setInputValue("");
|
|
183
247
|
}
|
|
184
|
-
}, [activeIdx, displayedEnums, hide, onItemSelectedByBlur]);
|
|
248
|
+
}, [activeIdx, displayedEnums, hide, onItemSelectedByBlur, setBlurred]);
|
|
185
249
|
const onKeyDown = react_1.useCallback((e) => {
|
|
186
250
|
switch (e.key) {
|
|
187
251
|
case "ArrowDown":
|
|
@@ -196,6 +260,11 @@ function SearchableMultiDrowndown(props) {
|
|
|
196
260
|
activeIdx !== undefined && displayedEnums && onItemSelected(displayedEnums[activeIdx]);
|
|
197
261
|
e.preventDefault();
|
|
198
262
|
break;
|
|
263
|
+
case "Escape":
|
|
264
|
+
setInputValue("");
|
|
265
|
+
setActiveIdx(undefined);
|
|
266
|
+
e.preventDefault();
|
|
267
|
+
break;
|
|
199
268
|
case "Backspace":
|
|
200
269
|
if (inputValue === "" && (value === null || value === void 0 ? void 0 : value.length)) {
|
|
201
270
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
@@ -204,7 +273,7 @@ function SearchableMultiDrowndown(props) {
|
|
|
204
273
|
}
|
|
205
274
|
break;
|
|
206
275
|
}
|
|
207
|
-
}, [activeIdx, activeIdxDown, activeIdxUp, displayedEnums, inputValue, onChange, onItemSelected, value]);
|
|
276
|
+
}, [activeIdx, activeIdxDown, activeIdxUp, displayedEnums, inputValue, onChange, onItemSelected, setActiveIdx, value]);
|
|
208
277
|
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
209
278
|
const onDelete = react_1.useCallback((enu) => {
|
|
210
279
|
const filtered = value.filter(v => v !== enu.value);
|
|
@@ -222,10 +291,11 @@ function SearchableMultiDrowndown(props) {
|
|
|
222
291
|
const wrapperClassNames = utils_1.classNames("laji-form-multiselect-input-wrapper", isOpen && "laji-form-multiselect-input-wrapper-focus", (readonly || disabled) && "laji-form-multiselect-input-wrapper-readonly");
|
|
223
292
|
return (React.createElement("div", { onBlur: onBlur, onKeyDown: onKeyDown, ref: containerRef, className: "laji-form-multiselect", style: { position: "relative" } },
|
|
224
293
|
React.createElement("div", { className: wrapperClassNames, tabIndex: -1, onFocus: redirectFocusToInput },
|
|
225
|
-
React.createElement("ul", { style: { listStyle: "none", display: "inline-block" } },
|
|
226
|
-
.map(
|
|
227
|
-
React.createElement("input", { disabled: disabled || readonly, id: id, onFocus:
|
|
228
|
-
|
|
294
|
+
React.createElement("ul", { style: { listStyle: "none", display: "inline-block" } }, value && enumOptions && value.map(v => enumOptions.find(({ value: _value }) => v === _value) || ({ value: v, label: v }))
|
|
295
|
+
.map(enu => React.createElement(SelectedMultiValue, { key: enu.value, onDelete: onDelete, readonly: readonly || disabled }, enu))),
|
|
296
|
+
React.createElement("input", { disabled: disabled || readonly, id: id, onFocus: onFocus, value: inputValue, onChange: onInputChange, autoComplete: "off", ref: inputRef }),
|
|
297
|
+
loading && React.createElement(Spinner, null)),
|
|
298
|
+
React.createElement(Caret, { onFocus: onFocus }),
|
|
229
299
|
React.createElement("div", { className: `laji-form-dropdown laji-form-dropdown-${isOpen ? "open" : "closed"}`, style: { position: "absolute", zIndex: 99999 }, tabIndex: -1 }, displayedEnums.map((oneOf, idx) => {
|
|
230
300
|
var _a;
|
|
231
301
|
return (React.createElement(ListItem, { key: (_a = oneOf.value) !== null && _a !== void 0 ? _a : "", onSelected: onItemSelected, active: idx === activeIdx }, oneOf));
|
|
@@ -245,3 +315,6 @@ function ListItem({ onSelected, active, children }) {
|
|
|
245
315
|
}, [children, onSelected]);
|
|
246
316
|
return (React.createElement("div", { onClick: onClick, className: utils_1.classNames("laji-form-dropdown-item", active && "active"), tabIndex: -1 }, children.label));
|
|
247
317
|
}
|
|
318
|
+
const getDefaultActiveIdx = (displayedEnums, value) => value !== undefined && value !== ""
|
|
319
|
+
? displayedEnums.findIndex(item => item.value === value)
|
|
320
|
+
: 0;
|
package/lib/utils.d.ts
CHANGED
|
@@ -170,4 +170,5 @@ export declare function translate(translations: ByLang, key: string, params?: {
|
|
|
170
170
|
* @returns [stateValue, setTrue, setFalse]
|
|
171
171
|
*/
|
|
172
172
|
export declare function useBooleanSetter(value: boolean): [boolean, () => void, () => void];
|
|
173
|
+
export declare function usePrevious<T>(value: T): T | undefined;
|
|
173
174
|
export {};
|
package/lib/utils.js
CHANGED
|
@@ -12,7 +12,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
12
12
|
};
|
|
13
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
14
|
exports.bsSizeToPixels = exports.canAdd = exports.stringifyKeyCombo = exports.decapitalizeFirstLetter = exports.capitalizeFirstLetter = exports.getKeyHandlerTargetId = exports.isDescendant = exports.getBootstrapCols = exports.getNestedUiFieldsList = exports.updateTailUiSchema = exports.getNestedTailUiSchema = exports.keyboardClick = exports.formDataEquals = exports.formDataIsEmpty = exports.filterItemIdsDeeply = exports.filterItemId = exports.filterLajiFormId = exports.syncScroll = exports._syncScroll = exports.shouldSyncScroll = exports.focusAndScroll = exports.focusById = exports.getSchemaElementById = exports.findNearestParentSchemaElemId = exports.focusNextInput = exports.getNextInput = exports.getNextInputInInputs = exports.ReactUtils = exports.findNearestParentTabbableElem = exports.findNearestParentSchemaElem = exports.canFocusNextInput = exports.isTabbableInput = exports.getTabbableFields = exports.isSelect = exports.isMultiSelect = exports.getReactComponentName = exports.parseJSONPointer = exports.isEmptyString = exports.isNullOrUndefined = exports.getInnerUiSchema = exports.getUiOptions = exports.immutableDelete = exports.getUpdateObjectFromJSONPointer = exports.getUpdateObjectFromJSONPath = exports.propertyHasData = exports.hasData = exports.getDefaultFormState = exports.isDefaultData = exports.isHidden = exports.isObject = void 0;
|
|
15
|
-
exports.useBooleanSetter = exports.translate = exports.classNames = exports.getTitle = exports.toJSONPointer = exports.getReversedFormDataIndex = exports.getFormDataIndex = exports.getIdxWithoutOffset = exports.getIdxWithOffset = exports.constructTranslations = exports.filteredErrors = exports.highlightElem = exports.findPointerForLajiFormId = exports.removeLajiFormIds = exports.getAllLajiFormIdsDeeply = exports.addLajiFormIds = exports.getFieldUUID = exports.getUUID = exports.assignUUID = exports.updateFormDataWithJSONPointer = exports.uiSchemaJSONPointer = exports.schemaJSONPointer = exports.idSchemaIdToJSONPointer = exports.JSONPointerToId = exports.checkJSONPointer = exports.parseUiSchemaFromFormDataPointer = exports.parseSchemaFromFormDataPointer = exports.triggerParentComponent = exports.bringRemoteFormData = exports.checkArrayRules = exports.checkRules = exports.formatErrorMessage = exports.formatValue = exports.dictionarify = exports.injectButtons = exports.updateSafelyWithJSONPointer = exports.updateSafelyWithJSONPath = exports.filter = exports.scrollIntoViewIfNeeded = exports.getScrollPositionForScrollIntoViewIfNeeded = exports.getWindowScrolled = exports.applyFunction = exports.pixelsToBsSize = void 0;
|
|
15
|
+
exports.usePrevious = exports.useBooleanSetter = exports.translate = exports.classNames = exports.getTitle = exports.toJSONPointer = exports.getReversedFormDataIndex = exports.getFormDataIndex = exports.getIdxWithoutOffset = exports.getIdxWithOffset = exports.constructTranslations = exports.filteredErrors = exports.highlightElem = exports.findPointerForLajiFormId = exports.removeLajiFormIds = exports.getAllLajiFormIdsDeeply = exports.addLajiFormIds = exports.getFieldUUID = exports.getUUID = exports.assignUUID = exports.updateFormDataWithJSONPointer = exports.uiSchemaJSONPointer = exports.schemaJSONPointer = exports.idSchemaIdToJSONPointer = exports.JSONPointerToId = exports.checkJSONPointer = exports.parseUiSchemaFromFormDataPointer = exports.parseSchemaFromFormDataPointer = exports.triggerParentComponent = exports.bringRemoteFormData = exports.checkArrayRules = exports.checkRules = exports.formatErrorMessage = exports.formatValue = exports.dictionarify = exports.injectButtons = exports.updateSafelyWithJSONPointer = exports.updateSafelyWithJSONPath = exports.filter = exports.scrollIntoViewIfNeeded = exports.getScrollPositionForScrollIntoViewIfNeeded = exports.getWindowScrolled = exports.applyFunction = exports.pixelsToBsSize = void 0;
|
|
16
16
|
const React = require("react");
|
|
17
17
|
const react_dom_1 = require("react-dom");
|
|
18
18
|
const utils_1 = require("@rjsf/utils");
|
|
@@ -1195,3 +1195,11 @@ function useBooleanSetter(value) {
|
|
|
1195
1195
|
return [open, setTrue, setFalse];
|
|
1196
1196
|
}
|
|
1197
1197
|
exports.useBooleanSetter = useBooleanSetter;
|
|
1198
|
+
function usePrevious(value) {
|
|
1199
|
+
const ref = React.useRef();
|
|
1200
|
+
React.useEffect(() => {
|
|
1201
|
+
ref.current = value;
|
|
1202
|
+
});
|
|
1203
|
+
return ref.current;
|
|
1204
|
+
}
|
|
1205
|
+
exports.usePrevious = usePrevious;
|