@luomus/laji-form 15.1.47 → 15.1.49

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.
@@ -81,7 +81,10 @@ class _SchemaField extends React.Component {
81
81
  const props = this.functionOutputProps || this.props;
82
82
  let { schema, uiSchema = {}, formContext, registry } = props, _props = __rest(props, ["schema", "uiSchema", "formContext", "registry"]); // eslint-disable-line @typescript-eslint/no-unused-vars
83
83
  const { formContext: _formContext } = registry;
84
- if (schema.uniqueItems && schema.items.enum && !utils_1.isMultiSelect(schema, uiSchema) && schema.uniqueItems) {
84
+ // rjsf displays a duplicate label if 'uniqueItems' is true in some cases. We prevent that here.
85
+ // Example of when it shows duplicate is http://localhost:8083/?id=JX.652&local=true, "Elinympäristö" on gathering
86
+ // level.
87
+ if (props.schema.type === "array" && props.uiSchema && props.uiSchema.items && props.uiSchema.items["ui:field"]) {
85
88
  schema = Object.assign(Object.assign({}, schema), { uniqueItems: false });
86
89
  }
87
90
  const options = utils_1.getUiOptions(uiSchema);
@@ -1,3 +1,5 @@
1
+ /// <reference types="react" />
2
+ import { FieldProps, JSONSchemaEnum } from "../../types";
1
3
  /**
2
4
  * Constructs selects from given tree.
3
5
  * uiSchema = {"ui:options": {
@@ -5,35 +7,4 @@
5
7
  * labels: [<string>]
6
8
  * }
7
9
  */
8
- export default class SelectTreeField extends React.Component<any, any, any> {
9
- static propTypes: {
10
- uiSchema: PropTypes.Validator<PropTypes.InferProps<{
11
- "ui:options": PropTypes.Validator<PropTypes.InferProps<{
12
- tree: PropTypes.Validator<object>;
13
- labels: PropTypes.Requireable<(string | null | undefined)[]>;
14
- uiSchema: PropTypes.Requireable<object>;
15
- }>>;
16
- }>>;
17
- schema: PropTypes.Validator<PropTypes.InferProps<{
18
- type: PropTypes.Requireable<string>;
19
- }>>;
20
- value: PropTypes.Requireable<string>;
21
- };
22
- constructor(props: any);
23
- constructor(props: any, context: any);
24
- getStateFromProps(props: any): {
25
- schema: {
26
- type: string;
27
- title: any;
28
- };
29
- formData: {};
30
- uiSchema: any;
31
- idSchema: {
32
- $id: any;
33
- };
34
- };
35
- onChange: (formData: any) => void;
36
- onKeyDown: (e: any) => void;
37
- }
38
- import * as React from "react";
39
- import * as PropTypes from "prop-types";
10
+ export default function SelectTreeField(props: FieldProps<JSONSchemaEnum>): JSX.Element;
@@ -1,15 +1,8 @@
1
1
  "use strict";
2
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
- return c > 3 && r && Object.defineProperty(target, key, r), r;
7
- };
8
2
  Object.defineProperty(exports, "__esModule", { value: true });
9
3
  const React = require("react");
10
- const PropTypes = require("prop-types");
11
4
  const utils_1 = require("../../utils");
12
- const BaseComponent_1 = require("../BaseComponent");
5
+ const react_1 = require("react");
13
6
  /**
14
7
  * Constructs selects from given tree.
15
8
  * uiSchema = {"ui:options": {
@@ -17,127 +10,97 @@ const BaseComponent_1 = require("../BaseComponent");
17
10
  * labels: [<string>]
18
11
  * }
19
12
  */
20
- let SelectTreeField = class SelectTreeField extends React.Component {
21
- constructor() {
22
- super(...arguments);
23
- this.onChange = (formData) => {
24
- let selectNames = Object.keys(formData).sort((a, b) => { return b - a; });
25
- for (let i in selectNames) {
26
- if (formData[i] !== this.state.formData[i]) {
27
- let value;
28
- if (utils_1.isEmptyString(formData[i])) {
29
- value = (i > 0) ? formData[i - 1] : undefined;
30
- }
31
- else {
32
- value = formData[i];
33
- }
34
- this.props.onChange(value);
35
- break;
13
+ function SelectTreeField(props) {
14
+ const childProps = getChildProps(props);
15
+ const { onChange: parentOnChange } = props;
16
+ const { formData: childFormData } = childProps;
17
+ const onChange = react_1.useCallback((formData) => {
18
+ let selectNames = Object.keys(formData).sort((a, b) => { return +b - +a; });
19
+ for (let i in selectNames) {
20
+ if (formData[i] !== childFormData[i]) {
21
+ let value;
22
+ if (utils_1.isEmptyString(formData[i])) {
23
+ value = (+i > 0) ? formData[+i - 1] : undefined;
36
24
  }
25
+ else {
26
+ value = formData[i];
27
+ }
28
+ parentOnChange(value);
29
+ break;
37
30
  }
38
- };
39
- this.onKeyDown = (e) => {
40
- if (e.key == "Enter" && !e.ctrlKey) {
41
- e.preventDefault();
42
- e.stopPropagation();
43
- this.props.formContext.setTimeout(() => {
44
- this.props.formContext.services.focus.focusNextInput(e.shiftKey);
45
- });
46
- }
47
- };
48
- }
49
- getStateFromProps(props) {
50
- let schema = { "type": "object", title: props.schema.title };
51
- let { uiSchema } = props;
52
- uiSchema = utils_1.getInnerUiSchema(props.uiSchema);
53
- let formData = {};
54
- let idSchema = { $id: props.idSchema.$id };
55
- let dictionarifiedEnums = {};
56
- props.schema.oneOf.forEach(e => {
57
- dictionarifiedEnums[e.const] = e.title;
58
- });
59
- let { tree, labels } = utils_1.getUiOptions(props.uiSchema);
60
- let levels = [];
61
- let parentsMap = {};
62
- let childrenMap = {};
63
- let orderMap = {};
64
- function getLevels(tree, depth, root) {
65
- childrenMap[root] = {};
66
- if (tree.children)
67
- Object.keys(tree.children).forEach(key => {
68
- if (!levels[depth])
69
- levels[depth] = {};
70
- levels[depth][key] = true;
71
- parentsMap[key] = root;
72
- childrenMap[root][key] = true;
73
- getLevels(tree.children[key], depth + 1, key);
74
- });
75
- if (tree.order)
76
- orderMap[root] = tree.order;
77
31
  }
78
- getLevels(tree, 0);
79
- let properties = {};
80
- function addSelect(depth, key, childrenKeys) {
81
- let select = { "type": "string", oneOf: [{ const: "", title: "" }] };
82
- let order = orderMap[key];
83
- if (order)
84
- childrenKeys.sort((a, b) => { return order.indexOf(a) - order.indexOf(b); });
85
- childrenKeys.forEach(key => {
86
- select.oneOf.push({ const: key, title: dictionarifiedEnums[key] });
87
- });
88
- if (labels && labels[depth]) {
89
- select.title = labels[depth];
90
- }
91
- select.title = (labels && labels[depth]) ? labels[depth] : "";
92
- properties[depth] = select;
93
- idSchema[depth] = { $id: idSchema.$id + "_" + depth };
32
+ }, [childFormData, parentOnChange]);
33
+ const SchemaField = props.registry.fields.SchemaField;
34
+ return React.createElement(SchemaField, Object.assign({}, props, childProps, { onChange: onChange }));
35
+ }
36
+ exports.default = SelectTreeField;
37
+ const getChildProps = (props) => {
38
+ let schema = { "type": "object", title: props.schema.title };
39
+ let formData = {};
40
+ let idSchema = { $id: props.idSchema.$id };
41
+ let dictionarifiedEnums = {};
42
+ props.schema.oneOf.forEach(e => {
43
+ dictionarifiedEnums[e.const] = e.title;
44
+ });
45
+ const tree = utils_1.getUiOptions(props.uiSchema).tree;
46
+ let levels = [];
47
+ let parentsMap = {};
48
+ let childrenMap = {};
49
+ let orderMap = {};
50
+ function getLevels(tree, depth, root) {
51
+ childrenMap[root] = {};
52
+ if (!tree.children) {
53
+ return;
94
54
  }
95
- let searchTerm = props.formData;
96
- let depth = 0;
97
- if (!utils_1.isEmptyString(searchTerm))
98
- for (let i in levels) {
99
- let level = levels[i];
100
- if (level[searchTerm])
101
- break;
102
- depth++;
103
- }
104
- let n = searchTerm;
105
- let d = depth;
106
- while (d >= 0) {
107
- formData[d] = n;
108
- if (utils_1.isEmptyString(n))
109
- n = undefined; //object keys can't be "", so root key is in childrenMap 'undefined'.
110
- addSelect(d, n, Object.keys(childrenMap[parentsMap[n]]));
111
- d--;
112
- n = parentsMap[n];
55
+ Object.keys(tree.children).forEach(key => {
56
+ if (!levels[depth])
57
+ levels[depth] = {};
58
+ levels[depth][key] = true;
59
+ parentsMap[key] = root;
60
+ childrenMap[root][key] = true;
61
+ getLevels(tree.children[key], depth + 1, key);
62
+ });
63
+ orderMap[root] = tree.order;
64
+ }
65
+ getLevels(tree, 0);
66
+ let properties = {};
67
+ function addSelect(depth, key, childrenKeys) {
68
+ let select = { type: "string", oneOf: [{ const: "", title: "" }] };
69
+ let order = orderMap[key];
70
+ if (order) {
71
+ childrenKeys.sort((a, b) => { return order.indexOf(a) - order.indexOf(b); });
72
+ }
73
+ childrenKeys.forEach(key => {
74
+ select.oneOf.push({ const: key, title: dictionarifiedEnums[key] });
75
+ });
76
+ select.title = "";
77
+ properties[depth] = select;
78
+ idSchema[depth] = { $id: idSchema.$id + "_" + depth };
79
+ }
80
+ let searchTerm = props.formData;
81
+ let depth = 0;
82
+ if (!utils_1.isEmptyString(searchTerm)) {
83
+ for (const level of levels) {
84
+ if (level[searchTerm])
85
+ break;
86
+ depth++;
113
87
  }
114
- if (!utils_1.isEmptyString(searchTerm) && childrenMap[searchTerm] && Object.keys(childrenMap[searchTerm]).length) {
115
- addSelect(depth + 1, searchTerm, Object.keys(childrenMap[searchTerm]));
116
- formData[depth + 1] = undefined;
88
+ }
89
+ let n = searchTerm;
90
+ let d = depth;
91
+ while (d >= 0) {
92
+ formData[d] = n;
93
+ if (utils_1.isEmptyString(n)) {
94
+ n = undefined; //object keys can't be "", so root key is in childrenMap 'undefined'.
117
95
  }
118
- schema.properties = properties;
119
- return { schema, formData, uiSchema, idSchema };
96
+ addSelect(d, n, Object.keys(childrenMap[parentsMap[n]]));
97
+ d--;
98
+ n = parentsMap[n];
120
99
  }
121
- render() {
122
- const SchemaField = this.props.registry.fields.SchemaField;
123
- return (React.createElement("div", { onKeyDown: this.onKeyDown },
124
- React.createElement(SchemaField, Object.assign({}, this.props, this.state, { onChange: this.onChange }))));
100
+ if (!utils_1.isEmptyString(searchTerm) && childrenMap[searchTerm] && Object.keys(childrenMap[searchTerm]).length) {
101
+ addSelect(depth + 1, searchTerm, Object.keys(childrenMap[searchTerm]));
102
+ formData[depth + 1] = undefined;
125
103
  }
104
+ schema.properties = properties;
105
+ return { schema, formData, uiSchema: utils_1.getInnerUiSchema(props.uiSchema), idSchema };
126
106
  };
127
- SelectTreeField.propTypes = {
128
- uiSchema: PropTypes.shape({
129
- "ui:options": PropTypes.shape({
130
- tree: PropTypes.object.isRequired,
131
- labels: PropTypes.arrayOf(PropTypes.string),
132
- uiSchema: PropTypes.object
133
- }).isRequired
134
- }).isRequired,
135
- schema: PropTypes.shape({
136
- type: PropTypes.oneOf(["string"])
137
- }).isRequired,
138
- value: PropTypes.string
139
- };
140
- SelectTreeField = __decorate([
141
- BaseComponent_1.default
142
- ], SelectTreeField);
143
- exports.default = SelectTreeField;
@@ -55,17 +55,18 @@ function SelectWidget(props) {
55
55
  exports.default = SelectWidget;
56
56
  function SearchableDrowndown(props) {
57
57
  const { id, disabled, readonly, value, uiSchema, options, onChange, includeEmpty = true } = props;
58
- const { theme } = React.useContext(ReactContext_1.default);
59
- const containerRef = React.useRef(null);
60
- const inputRef = React.useRef(null);
61
- const dropdownRef = React.useRef(null);
62
- const enumOptions = React.useMemo(() =>
58
+ const { theme } = react_1.useContext(ReactContext_1.default);
59
+ const containerRef = react_1.useRef(null);
60
+ const inputRef = react_1.useRef(null);
61
+ const dropdownRef = react_1.useRef(null);
62
+ const enumOptions = react_1.useMemo(() =>
63
63
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
64
64
  getEnumOptions(options.enumOptions, uiSchema, includeEmpty), [options.enumOptions, uiSchema, includeEmpty]);
65
- const [inputValue, setInputValue] = react_1.useState(value
65
+ const getLabelFromValue = react_1.useCallback((value) => value !== undefined
66
66
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
67
67
  ? enumOptions.find(item => item.value === value).label
68
- : "");
68
+ : "", [enumOptions]);
69
+ const [inputValue, setInputValue] = react_1.useState(getLabelFromValue(value));
69
70
  const [inputTouched, setInputTouched] = react_1.useState(false);
70
71
  const [filterTerm, setFilterTerm] = react_1.useState("");
71
72
  const onInputChange = react_1.useCallback((e) => {
@@ -73,10 +74,17 @@ function SearchableDrowndown(props) {
73
74
  setInputValue(value);
74
75
  setInputTouched(true);
75
76
  }, []);
76
- React.useEffect(() => {
77
+ react_1.useEffect(() => {
77
78
  inputTouched && setFilterTerm(inputValue);
78
79
  }, [inputTouched, inputValue]);
79
- const displayedEnums = React.useMemo(() => {
80
+ // Sync inputValue if value changes.
81
+ react_1.useEffect(() => {
82
+ if (inputTouched) {
83
+ return;
84
+ }
85
+ setInputValue(getLabelFromValue(value));
86
+ }, [inputTouched, value, enumOptions, getLabelFromValue]);
87
+ const displayedEnums = react_1.useMemo(() => {
80
88
  return filterTerm !== ""
81
89
  ? enumOptions.filter(({ label }) => label.toLowerCase().match(filterTerm.toLowerCase()))
82
90
  : enumOptions;
@@ -86,7 +94,6 @@ function SearchableDrowndown(props) {
86
94
  const [activeIdx, activeIdxUp, activeIdxDown, setActiveIdx] = useRangeIncrementor((displayedEnums || []).length, getDefaultActiveIdx(displayedEnums, value));
87
95
  const onItemSelected = react_1.useCallback((item) => {
88
96
  onChange(item.value);
89
- setInputValue(item.label);
90
97
  setInputTouched(false);
91
98
  setActiveIdx(displayedEnums.findIndex(enu => enu.value === item.value));
92
99
  hide();
@@ -179,13 +186,11 @@ function SearchableMultiDrowndown(props) {
179
186
  const onItemSelected = react_1.useCallback((item) => {
180
187
  var _a;
181
188
  onChange([...(value || []), item.value]);
182
- setInputValue("");
183
189
  (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
184
190
  setActiveIdx(undefined);
185
191
  }, [onChange, setActiveIdx, value]);
186
192
  const onItemSelectedByBlur = react_1.useCallback((item) => {
187
193
  onChange([...(value || []), item.value]);
188
- setInputValue("");
189
194
  setActiveIdx(undefined);
190
195
  }, [onChange, setActiveIdx, value]);
191
196
  const [isFocused, setFocused, setBlurred] = utils_1.useBooleanSetter(false);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@luomus/laji-form",
3
- "version": "15.1.47",
3
+ "version": "15.1.49",
4
4
  "description": "React module capable of building dynamic forms from Laji form json schemas",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",