@nolwenture/formik-jsonschema-form 0.20.1 → 0.21.1

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, onSelect } = 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,16 +53,55 @@ 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;
36
101
  setSearchTerm((_a = item.title) !== null && _a !== void 0 ? _a : "");
37
102
  setValue(item.const);
38
103
  setShowOptions(false);
104
+ onSelect === null || onSelect === void 0 ? void 0 : onSelect(item.const);
39
105
  };
40
106
  const handleFocus = () => {
41
107
  setShowOptions(true);
@@ -53,5 +119,10 @@ export const SearchableSelectField = (props) => {
53
119
  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
120
  const showMoreOption = displayedItems.length < filteredOptions.length &&
55
121
  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..." }))] }))] }) })));
122
+ 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
123
+ ? {
124
+ backgroundColor: hoverColors.backgroundColor,
125
+ color: hoverColors.color,
126
+ }
127
+ : {}, 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
128
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nolwenture/formik-jsonschema-form",
3
- "version": "0.20.1",
3
+ "version": "0.21.1",
4
4
  "description": "Formik form generation from json schema",
5
5
  "author": "Antti Vikman <antti.vikman@nolwenture.com>",
6
6
  "contributors": [