@gpa-gemstone/react-forms
Version:
React Form modules for gpa webapps
106 lines (105 loc) • 6.55 kB
JavaScript
// ******************************************************************************************************
// SearchableSelect.tsx - Gbtc
//
// Copyright © 2024, Grid Protection Alliance. All Rights Reserved.
//
// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
// the NOTICE file distributed with this work for additional information regarding copyright ownership.
// The GPA licenses this file to you under the MIT License (MIT), the "License"; you may not use this
// file except in compliance with the License. You may obtain a copy of the License at:
//
// http://opensource.org/licenses/MIT
//
// Unless agreed to in writing, the subject software distributed under the License is distributed on an
// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
// License for the specific language governing permissions and limitations.
//
// Code Modification History:
// ----------------------------------------------------------------------------------------------------
// 03/17/2024 - C. Lackner
// Generated original version of source code.
//
// ******************************************************************************************************
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = SearchableSelect;
var React = require("react");
var StylableSelect_1 = require("./StylableSelect");
var gpa_symbols_1 = require("@gpa-gemstone/gpa-symbols");
var getInitialSearchText = function (useBlankString, recordValue) {
return useBlankString ? '' : recordValue;
};
function SearchableSelect(props) {
var _a = React.useState(function () { var _a, _b, _c; return getInitialSearchText((_a = props.ResetSearchOnSelect) !== null && _a !== void 0 ? _a : false, (_c = (_b = props.Record[props.Field]) === null || _b === void 0 ? void 0 : _b.toString()) !== null && _c !== void 0 ? _c : ''); }), search = _a[0], setSearch = _a[1];
var _b = React.useState([]), searchOptions = _b[0], setSearchOptions = _b[1];
var _c = React.useState(false), loading = _c[0], setLoading = _c[1];
var setter = React.useCallback(function (record, selectedOption) {
var selectedOptionCasted = selectedOption; //we can safely cast here because we control the options going in..
handleSetSearch(selectedOptionCasted);
props.Setter(record, { Label: selectedOptionCasted.Label, Value: selectedOptionCasted.Value });
}, [props.Setter, props.Field]);
var handleSetSearch = React.useCallback(function (selectedOption) {
var _a, _b, _c, _d;
if ((_a = props.ResetSearchOnSelect) !== null && _a !== void 0 ? _a : false) {
setSearch('');
return;
}
if (props.GetLabel === undefined) {
var newSearch = (_d = (_b = selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.Label) !== null && _b !== void 0 ? _b : (_c = props.Record[props.Field]) === null || _c === void 0 ? void 0 : _c.toString()) !== null && _d !== void 0 ? _d : '';
setSearch(newSearch);
return;
}
setLoading(true);
var handle = props.GetLabel();
handle.then(function (lab) {
setSearch(lab);
setLoading(false);
}, function () { return setLoading(false); });
}, [props.ResetSearchOnSelect, props.GetLabel, props.Record[props.Field]]);
//Effect to set search when props.Record[props.Field] changes externally
React.useEffect(function () {
handleSetSearch();
}, [props.Record[props.Field], handleSetSearch]);
// Call props.Search every 500ms to avoid hammering the server while typing
React.useEffect(function () {
setLoading(true);
var searchHandle;
var timeoutHandle = setTimeout(function () {
searchHandle = props.Search(search);
searchHandle.then(function (d) {
setSearchOptions(d.map(function (o) { return ({ Value: o.Value, Element: o.Label, Label: o.Label }); }));
setLoading(false);
}, function () {
setLoading(false);
});
}, 500);
return function () {
if ((searchHandle === null || searchHandle === void 0 ? void 0 : searchHandle.abort) != null)
searchHandle.abort();
if (timeoutHandle != null)
clearTimeout(timeoutHandle);
};
}, [search]);
var options = React.useMemo(function () {
var _a, _b, _c, _d;
var ops = [];
ops.push({
Value: props.Record[props.Field],
Label: "", //Label doesnt matter in this case because you cant select this option
Element: React.createElement("div", { className: 'input-group' },
React.createElement("input", { type: "text", className: "form-control ".concat(((_b = (_a = props.Valid) === null || _a === void 0 ? void 0 : _a.call(props, props.Field)) !== null && _b !== void 0 ? _b : true) ? '' : 'border-danger'), value: search, onChange: function (d) { return setSearch(d.target.value); }, onBlur: function () { return handleSetSearch(); }, onClick: function (evt) { evt.preventDefault(); evt.stopPropagation(); }, disabled: (_c = props.Disabled) !== null && _c !== void 0 ? _c : false }),
loading ?
React.createElement("div", { className: "input-group-append" },
React.createElement("span", { className: "input-group-text" },
React.createElement(gpa_symbols_1.ReactIcons.SpiningIcon, null)))
: null)
});
if ((_d = props.AllowCustom) !== null && _d !== void 0 ? _d : false)
ops.push({ Value: search, Element: React.createElement(React.Fragment, null,
search,
" (Entered Value)"), Label: search });
ops.push.apply(ops, searchOptions.filter(function (f) { return f.Value !== search && f.Value !== props.Record[props.Field]; }));
return ops;
}, [search, props.Record[props.Field], props.Field, searchOptions, props.Disabled, loading, props.Valid, handleSetSearch]);
return React.createElement(StylableSelect_1.default, { Record: props.Record, Field: props.Field, Setter: setter, Label: props.Label, Disabled: props.Disabled, Help: props.Help, Style: props.Style, Options: options, BtnStyle: props.BtnStyle, Valid: props.Valid, Feedback: props.Feedback });
}
;