@nolwenture/formik-jsonschema-form 0.20.0 → 0.21.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.
@@ -1,21 +1,48 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
1
12
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useState, useEffect, useRef, useContext, useMemo } from "react";
3
- import { useExtractUiSchema, useSetDefault } from "../hooks";
4
- import { FormRegistry } from "../Form";
13
+ import { useContext, useEffect, useMemo, useRef, useState, } from "react";
5
14
  import { useField } from "formik";
15
+ import { FormRegistry } from "../Form";
16
+ import { useExtractUiSchema, useSetDefault } from "../hooks";
6
17
  import { getEnums } from "../utils";
7
18
  export const SearchableSelectField = (props) => {
8
19
  const { templates: { FieldTemplate }, components: { SearchableSelectContainer, SearchDropdownContainer, SearchListOption, SearchListExpand, SearchNotFound, SearchInput, SearchClearButton, SearchInputContainer, }, } = useContext(FormRegistry);
9
20
  useSetDefault(props);
10
- const { name, uiSchema } = props;
11
- const { props: inputProps, placeholder, clearButtonText, expandText, notFoundMessage, } = useExtractUiSchema(uiSchema);
21
+ const ListOption = (props) => {
22
+ const { isActive, children } = props, rest = __rest(props, ["isActive", "children"]);
23
+ const ref = useRef();
24
+ useEffect(() => {
25
+ if (isActive) {
26
+ ref.current.scrollIntoView({
27
+ behavior: "smooth",
28
+ block: "center",
29
+ inline: "center",
30
+ });
31
+ }
32
+ }, [isActive]);
33
+ return (_jsx(SearchListOption, Object.assign({ ref: ref }, rest, { children: children })));
34
+ };
35
+ const { name, uiSchema, onChange } = props;
36
+ const { props: inputProps, placeholder, clearButtonText, expandText, notFoundMessage, hoverColors = {}, hideClearButton = false, showOptionsMenu = false, // makes CSS styling easier
37
+ } = useExtractUiSchema(uiSchema);
12
38
  const [{ value }, __, { setValue }] = useField(name);
13
39
  const enums = useMemo(() => getEnums(props), [props]);
14
40
  const options = (enums === null || enums === void 0 ? void 0 : enums.values) || [];
15
- const [showOptions, setShowOptions] = useState(false);
41
+ const [showOptions, setShowOptions] = useState(showOptionsMenu);
16
42
  const [searchTerm, setSearchTerm] = useState(() => { var _a, _b; return (_b = (_a = options.find((option) => option.const === value)) === null || _a === void 0 ? void 0 : _a.title) !== null && _b !== void 0 ? _b : ""; });
17
43
  const [displayedItems, setDisplayedItems] = useState([]);
18
44
  const [itemsToShow, setItemsToShow] = useState(10);
45
+ const [selectedItem, setSelectedItem] = useState(-1);
19
46
  const moreRef = useRef(null);
20
47
  const containerRef = useRef(null);
21
48
  const loadMoreItems = () => {
@@ -26,10 +53,48 @@ export const SearchableSelectField = (props) => {
26
53
  .filter((option) => { var _a, _b; return ((_b = (_a = option.title) === null || _a === void 0 ? void 0 : _a.toLowerCase()) !== null && _b !== void 0 ? _b : "").includes(searchTerm.toLowerCase()); })
27
54
  .slice(0, itemsToShow));
28
55
  }, [itemsToShow, options, searchTerm]);
56
+ const handleKeyPress = (event) => {
57
+ if (showOptions) {
58
+ switch (event.key) {
59
+ case "ArrowUp": {
60
+ const calcValue = selectedItem - 1;
61
+ const newValue = calcValue < -1 ? -1 : calcValue;
62
+ return setSelectedItem(newValue);
63
+ }
64
+ case "ArrowDown": {
65
+ const calcValue = selectedItem + 1;
66
+ const newValue = calcValue >= displayedItems.length - 1
67
+ ? displayedItems.length - 1
68
+ : calcValue;
69
+ return setSelectedItem(newValue);
70
+ }
71
+ case "Escape": {
72
+ return setShowOptions(false);
73
+ }
74
+ case "Enter": {
75
+ const item = displayedItems[selectedItem];
76
+ if (item) {
77
+ return handleSelect(item);
78
+ }
79
+ return;
80
+ }
81
+ }
82
+ }
83
+ };
84
+ useEffect(() => {
85
+ // attach the event listener
86
+ document.addEventListener("keydown", handleKeyPress);
87
+ // remove the event listener
88
+ return () => {
89
+ document.removeEventListener("keydown", handleKeyPress);
90
+ };
91
+ }, [handleKeyPress]);
29
92
  const handleSearchChange = (event) => {
30
93
  setSearchTerm(event.target.value);
31
94
  setItemsToShow(10);
32
95
  setShowOptions(true);
96
+ setSelectedItem(-1);
97
+ onChange === null || onChange === void 0 ? void 0 : onChange(event);
33
98
  };
34
99
  const handleSelect = (item) => {
35
100
  var _a;
@@ -53,5 +118,10 @@ export const SearchableSelectField = (props) => {
53
118
  const filteredOptions = options.filter((option) => { var _a, _b; return ((_b = (_a = option.title) === null || _a === void 0 ? void 0 : _a.toLowerCase()) !== null && _b !== void 0 ? _b : "").includes(searchTerm.toLowerCase()); });
54
119
  const showMoreOption = displayedItems.length < filteredOptions.length &&
55
120
  displayedItems.length >= 10;
56
- return (_jsx(FieldTemplate, Object.assign({}, props, { children: _jsxs(SearchableSelectContainer, { ref: containerRef, onBlur: handleBlur, children: [_jsxs(SearchInputContainer, { children: [_jsx(SearchInput, Object.assign({}, inputProps, { name: name, type: "text", placeholder: placeholder, value: searchTerm, onChange: handleSearchChange, onFocus: handleFocus })), searchTerm && (_jsx(SearchClearButton, { onClick: handleClear, children: clearButtonText !== null && clearButtonText !== void 0 ? clearButtonText : "x" }))] }), showOptions && (_jsxs(SearchDropdownContainer, { role: "dropdown-list", ref: moreRef, children: [displayedItems.length > 0 ? (displayedItems.map((item, index) => (_jsx(SearchListOption, { role: "filtered-list", onClick: () => handleSelect(item), onMouseDown: (e) => e.preventDefault(), children: item.title }, index)))) : (_jsx(SearchNotFound, { onMouseDown: (e) => e.preventDefault(), children: notFoundMessage !== null && notFoundMessage !== void 0 ? notFoundMessage : "No match found" })), showMoreOption && (_jsx(SearchListExpand, { ref: moreRef, onMouseDown: (e) => e.preventDefault(), onClick: loadMoreItems, children: expandText !== null && expandText !== void 0 ? expandText : "More..." }))] }))] }) })));
121
+ return (_jsx(FieldTemplate, Object.assign({}, props, { children: _jsxs(SearchableSelectContainer, { ref: containerRef, onBlur: handleBlur, children: [_jsxs(SearchInputContainer, { children: [_jsx(SearchInput, Object.assign({}, inputProps, { name: name, type: "text", placeholder: placeholder, value: searchTerm, onChange: handleSearchChange, onFocus: handleFocus })), searchTerm && !hideClearButton && (_jsx(SearchClearButton, { onClick: handleClear, children: clearButtonText !== null && clearButtonText !== void 0 ? clearButtonText : "x" }))] }), showOptions && (_jsxs(SearchDropdownContainer, { role: "dropdown-list", ref: moreRef, children: [displayedItems.length > 0 ? (displayedItems.map((item, index) => (_jsx(ListOption, { isActive: index === selectedItem, style: index === selectedItem
122
+ ? {
123
+ backgroundColor: hoverColors.backgroundColor,
124
+ color: hoverColors.color,
125
+ }
126
+ : {}, role: "filtered-list", onClick: () => handleSelect(item), onMouseDown: (e) => e.preventDefault(), children: item.title }, index)))) : (_jsx(SearchNotFound, { onMouseDown: (e) => e.preventDefault(), children: notFoundMessage !== null && notFoundMessage !== void 0 ? notFoundMessage : "No match found" })), showMoreOption && (_jsx(SearchListExpand, { ref: moreRef, onMouseDown: (e) => e.preventDefault(), onClick: loadMoreItems, children: expandText !== null && expandText !== void 0 ? expandText : "More..." }))] }))] }) })));
57
127
  };
@@ -123,10 +123,11 @@ export function createValidationSchema(schema, definitions = {}, condition) {
123
123
  const schemaDefinitions = Object.assign(Object.assign({}, definitions), ((_a = schema.definitions) !== null && _a !== void 0 ? _a : {}));
124
124
  const requiredFields = schema.required;
125
125
  function getValue(schema, key) {
126
- const type = schema.type;
126
+ let type = schema.type;
127
127
  let yupSchema;
128
128
  if (schema.properties) {
129
129
  yupSchema = createValidationSchema(schema, schemaDefinitions);
130
+ type = type !== null && type !== void 0 ? type : "object";
130
131
  }
131
132
  else {
132
133
  yupSchema = getYupType(type);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nolwenture/formik-jsonschema-form",
3
- "version": "0.20.0",
3
+ "version": "0.21.0",
4
4
  "description": "Formik form generation from json schema",
5
5
  "author": "Antti Vikman <antti.vikman@nolwenture.com>",
6
6
  "contributors": [