@nolwenture/formik-jsonschema-form 0.20.1 → 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
  };
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.0",
4
4
  "description": "Formik form generation from json schema",
5
5
  "author": "Antti Vikman <antti.vikman@nolwenture.com>",
6
6
  "contributors": [