@gpa-gemstone/react-forms 1.1.92 → 1.1.94
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.
- package/lib/FileUpload.d.ts +1 -1
- package/lib/FileUpload.js +31 -16
- package/lib/MultiSearchableSelect.d.ts +10 -0
- package/lib/MultiSearchableSelect.js +106 -0
- package/lib/MutliCheckBoxSelect.js +1 -1
- package/lib/SearchableSelect.d.ts +16 -8
- package/lib/SearchableSelect.js +33 -44
- package/lib/StylableSelect.d.ts +12 -0
- package/lib/StylableSelect.js +19 -8
- package/lib/ToggleSwitch.js +1 -1
- package/lib/index.d.ts +2 -1
- package/lib/index.js +3 -1
- package/package.json +3 -3
package/lib/FileUpload.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ interface IProps {
|
|
|
2
2
|
/**
|
|
3
3
|
* Callback function that will be called when a file is uploaded
|
|
4
4
|
* */
|
|
5
|
-
OnLoadHandler: (result: File) =>
|
|
5
|
+
OnLoadHandler: (result: File) => Promise<any>;
|
|
6
6
|
/**
|
|
7
7
|
* Callback function that will be called when clear button is clicked
|
|
8
8
|
* */
|
package/lib/FileUpload.js
CHANGED
|
@@ -28,9 +28,12 @@ var FileUpload = function (props) {
|
|
|
28
28
|
var _a = React.useState(null), fileName = _a[0], setFileName = _a[1];
|
|
29
29
|
var _b = React.useState(null), fileSize = _b[0], setFileSize = _b[1];
|
|
30
30
|
var _c = React.useState(false), isFileUpload = _c[0], setIsFileUploaded = _c[1];
|
|
31
|
+
var _d = React.useState('unintiated'), uploadStatus = _d[0], setUploadStatus = _d[1];
|
|
31
32
|
var handleFileUpload = function (evt) {
|
|
32
|
-
if (evt.target == null || evt.target.files == null || evt.target.files.length === 0)
|
|
33
|
+
if (evt.target == null || evt.target.files == null || evt.target.files.length === 0) {
|
|
34
|
+
setUploadStatus('unintiated');
|
|
33
35
|
return;
|
|
36
|
+
}
|
|
34
37
|
var file = evt.target.files[0];
|
|
35
38
|
setMetaData(file);
|
|
36
39
|
};
|
|
@@ -49,6 +52,7 @@ var FileUpload = function (props) {
|
|
|
49
52
|
e.stopPropagation();
|
|
50
53
|
};
|
|
51
54
|
var handleOnClear = function () {
|
|
55
|
+
setUploadStatus('unintiated');
|
|
52
56
|
setIsFileUploaded(false);
|
|
53
57
|
setFileName(null);
|
|
54
58
|
setFileSize(null);
|
|
@@ -57,31 +61,42 @@ var FileUpload = function (props) {
|
|
|
57
61
|
var setMetaData = function (file) {
|
|
58
62
|
setFileName(file.name);
|
|
59
63
|
setFileSize(file.size);
|
|
60
|
-
|
|
61
|
-
|
|
64
|
+
setUploadStatus('loading');
|
|
65
|
+
props.OnLoadHandler(file).then(function () {
|
|
66
|
+
setIsFileUploaded(true);
|
|
67
|
+
setUploadStatus('idle');
|
|
68
|
+
}).catch(function () {
|
|
69
|
+
setIsFileUploaded(false);
|
|
70
|
+
setUploadStatus('error');
|
|
71
|
+
});
|
|
62
72
|
};
|
|
63
73
|
return (React.createElement(React.Fragment, null,
|
|
64
74
|
React.createElement("div", { className: 'row' },
|
|
65
75
|
React.createElement("div", { className: 'col-auto mt-2 pl-0' },
|
|
66
76
|
React.createElement("label", { style: { cursor: 'pointer' } },
|
|
67
77
|
React.createElement(gpa_symbols_1.ReactIcons.ShareArrow, { Color: 'var(--info)' }),
|
|
68
|
-
React.createElement("input", { type: "file",
|
|
78
|
+
React.createElement("input", { type: "file", accept: props.FileTypeAttribute, style: { display: 'none' }, onChange: handleFileUpload }))),
|
|
69
79
|
React.createElement("div", { className: 'col-auto pl-0' },
|
|
70
80
|
React.createElement("button", { className: 'btn', onClick: handleOnClear },
|
|
71
81
|
React.createElement(gpa_symbols_1.ReactIcons.CircledX, { Color: 'red' })))),
|
|
72
|
-
|
|
73
|
-
React.createElement(
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
"File Size: ",
|
|
79
|
-
formatFileSize(fileSize))))
|
|
82
|
+
uploadStatus === 'error' ?
|
|
83
|
+
React.createElement("div", { className: "alert alert-danger fade show" }, "An error occured while uploading file.")
|
|
84
|
+
: null,
|
|
85
|
+
React.createElement("div", { className: 'row', onDragOver: handleDragOver, onDrop: handleDrop, style: { border: '2px dashed var(--secondary)', borderRadius: '0.5em' } }, uploadStatus === 'loading' ?
|
|
86
|
+
React.createElement("div", { className: 'd-flex col-12 align-items-center justify-content-center' },
|
|
87
|
+
React.createElement(gpa_symbols_1.ReactIcons.SpiningIcon, { Size: 200 }))
|
|
80
88
|
:
|
|
81
|
-
|
|
82
|
-
React.createElement(
|
|
83
|
-
React.createElement(
|
|
84
|
-
|
|
89
|
+
isFileUpload ?
|
|
90
|
+
React.createElement(React.Fragment, null,
|
|
91
|
+
React.createElement("div", { className: 'col-auto' },
|
|
92
|
+
"File Name: ", fileName !== null && fileName !== void 0 ? fileName : ''),
|
|
93
|
+
React.createElement("div", { className: 'col-auto' },
|
|
94
|
+
"File Size: ",
|
|
95
|
+
formatFileSize(fileSize)))
|
|
96
|
+
:
|
|
97
|
+
React.createElement("div", { className: 'col-12 pt-3 pb-3 d-flex justify-content-center align-items-center' },
|
|
98
|
+
React.createElement(gpa_symbols_1.ReactIcons.Image, { Size: 100 }),
|
|
99
|
+
React.createElement("span", null, "Drag and Drop")))));
|
|
85
100
|
};
|
|
86
101
|
//Helper Functions
|
|
87
102
|
var formatFileSize = function (size) {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { IProps as ISearchableSelectProps } from './SearchableSelect';
|
|
2
|
+
interface IProps<T> extends ISearchableSelectProps<T> {
|
|
3
|
+
/**
|
|
4
|
+
* Default value to use when adding an item and when value is null
|
|
5
|
+
* @type {number}
|
|
6
|
+
*/
|
|
7
|
+
DefaultValue: number | string;
|
|
8
|
+
}
|
|
9
|
+
declare function MultiSearchableSelect<T>(props: IProps<T>): JSX.Element;
|
|
10
|
+
export default MultiSearchableSelect;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
//******************************************************************************************************
|
|
3
|
+
// MultiSearchableSelect.tsx - Gbtc
|
|
4
|
+
//
|
|
5
|
+
// Copyright © 2024, Grid Protection Alliance. All Rights Reserved.
|
|
6
|
+
//
|
|
7
|
+
// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
|
|
8
|
+
// the NOTICE file distributed with this work for additional information regarding copyright ownership.
|
|
9
|
+
// The GPA may license this file to you under the MIT License (MIT), the "License"; you may not use this
|
|
10
|
+
// file except in compliance with the License. You may obtain a copy of the License at:
|
|
11
|
+
//
|
|
12
|
+
// http://opensource.org/licenses/MIT
|
|
13
|
+
//
|
|
14
|
+
// Unless agreed to in writing, the subject software distributed under the License is distributed on an
|
|
15
|
+
// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
|
|
16
|
+
// License for the specific language governing permissions and limitations.
|
|
17
|
+
//
|
|
18
|
+
// Code Modification History:
|
|
19
|
+
// ----------------------------------------------------------------------------------------------------
|
|
20
|
+
// 07/01/2025 - Preston Crawford
|
|
21
|
+
// Generated original version of source code.
|
|
22
|
+
//
|
|
23
|
+
//******************************************************************************************************
|
|
24
|
+
var __assign = (this && this.__assign) || function () {
|
|
25
|
+
__assign = Object.assign || function(t) {
|
|
26
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
27
|
+
s = arguments[i];
|
|
28
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
29
|
+
t[p] = s[p];
|
|
30
|
+
}
|
|
31
|
+
return t;
|
|
32
|
+
};
|
|
33
|
+
return __assign.apply(this, arguments);
|
|
34
|
+
};
|
|
35
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
36
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
37
|
+
if (ar || !(i in from)) {
|
|
38
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
39
|
+
ar[i] = from[i];
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
43
|
+
};
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
var React = require("react");
|
|
46
|
+
var SearchableSelect_1 = require("./SearchableSelect");
|
|
47
|
+
var ToolTip_1 = require("./ToolTip");
|
|
48
|
+
var gpa_symbols_1 = require("@gpa-gemstone/gpa-symbols");
|
|
49
|
+
var helper_functions_1 = require("@gpa-gemstone/helper-functions");
|
|
50
|
+
//Only supporting string/number arrays for now
|
|
51
|
+
function MultiSearchableSelect(props) {
|
|
52
|
+
var _a;
|
|
53
|
+
var guid = React.useState((0, helper_functions_1.CreateGuid)())[0];
|
|
54
|
+
var _b = React.useState(false), showHelp = _b[0], setShowHelp = _b[1];
|
|
55
|
+
var fieldArray = props.Record[props.Field];
|
|
56
|
+
if ((fieldArray === null || fieldArray === void 0 ? void 0 : fieldArray.constructor) !== Array) {
|
|
57
|
+
console.warn("MultiInput: ".concat(props.Field.toString(), " is not of type array."));
|
|
58
|
+
return React.createElement(React.Fragment, null);
|
|
59
|
+
}
|
|
60
|
+
return (React.createElement(React.Fragment, null,
|
|
61
|
+
fieldArray.length === 0 ?
|
|
62
|
+
React.createElement(React.Fragment, null,
|
|
63
|
+
React.createElement("label", { className: 'd-flex align-items-center' },
|
|
64
|
+
React.createElement("span", null, (_a = props.Label) !== null && _a !== void 0 ? _a : props.Field),
|
|
65
|
+
props.Help != null ?
|
|
66
|
+
React.createElement("span", { className: "ml-2 d-flex align-items-center", onMouseEnter: function () { return setShowHelp(true); }, onMouseLeave: function () { return setShowHelp(false); }, "data-tooltip": guid },
|
|
67
|
+
React.createElement(gpa_symbols_1.ReactIcons.QuestionMark, { Color: "var(--info)", Size: 20 }))
|
|
68
|
+
: null,
|
|
69
|
+
React.createElement("button", { className: 'btn', onClick: function () {
|
|
70
|
+
var _a;
|
|
71
|
+
return props.Setter(__assign(__assign({}, props.Record), (_a = {}, _a[props.Field] = [props.DefaultValue], _a)));
|
|
72
|
+
} },
|
|
73
|
+
" ",
|
|
74
|
+
React.createElement(gpa_symbols_1.ReactIcons.CirclePlus, null),
|
|
75
|
+
" ")),
|
|
76
|
+
React.createElement(ToolTip_1.default, { Show: showHelp && props.Help != null, Target: guid, Class: "info", Position: "bottom" }, props.Help))
|
|
77
|
+
: null,
|
|
78
|
+
fieldArray.map(function (r, index) {
|
|
79
|
+
var _a, _b;
|
|
80
|
+
return (React.createElement("div", { className: 'row align-items-center', key: index },
|
|
81
|
+
React.createElement("div", { className: 'col' },
|
|
82
|
+
React.createElement(SearchableSelect_1.default, { Record: fieldArray, Field: index, Label: index === 0 ? props.Label : '', Help: index === 0 ? props.Help : undefined, Feedback: props.Feedback, Valid: function () { return props.Valid != null ? props.Valid(props.Field) : true; }, Style: props.Style, Disabled: props.Disabled, Setter: function (record) {
|
|
83
|
+
var _a;
|
|
84
|
+
var newArray = __spreadArray([], fieldArray, true);
|
|
85
|
+
newArray[index] = record[index];
|
|
86
|
+
props.Setter(__assign(__assign({}, props.Record), (_a = {}, _a[props.Field] = newArray, _a)));
|
|
87
|
+
}, Search: props.Search, BtnStyle: props.BtnStyle, GetLabel: props.GetLabel, ResetSearchOnSelect: props.ResetSearchOnSelect, AllowCustom: props.AllowCustom })),
|
|
88
|
+
React.createElement("div", { className: 'col-auto' },
|
|
89
|
+
React.createElement("button", { className: 'btn', style: ((_a = props.Disabled) !== null && _a !== void 0 ? _a : false) ? { display: 'none' } : undefined, onClick: function () {
|
|
90
|
+
var _a;
|
|
91
|
+
var newRecords = __spreadArray([], fieldArray, true).filter(function (_, i) { return i !== index; });
|
|
92
|
+
props.Setter(__assign(__assign({}, props.Record), (_a = {}, _a[props.Field] = newRecords, _a)));
|
|
93
|
+
} },
|
|
94
|
+
React.createElement(gpa_symbols_1.ReactIcons.TrashCan, { Color: 'red' }))),
|
|
95
|
+
index === __spreadArray([], fieldArray, true).length - 1 ?
|
|
96
|
+
React.createElement("div", { className: 'col-auto' },
|
|
97
|
+
React.createElement("button", { className: 'btn', style: ((_b = props.Disabled) !== null && _b !== void 0 ? _b : false) ? { display: 'none' } : undefined, onClick: function () {
|
|
98
|
+
var _a;
|
|
99
|
+
var newRecords = __spreadArray(__spreadArray([], __spreadArray([], fieldArray, true), true), [props.DefaultValue], false);
|
|
100
|
+
props.Setter(__assign(__assign({}, props.Record), (_a = {}, _a[props.Field] = newRecords, _a)));
|
|
101
|
+
} },
|
|
102
|
+
React.createElement(gpa_symbols_1.ReactIcons.CirclePlus, null)))
|
|
103
|
+
: null));
|
|
104
|
+
})));
|
|
105
|
+
}
|
|
106
|
+
exports.default = MultiSearchableSelect;
|
|
@@ -108,7 +108,7 @@ var MultiSelect = function (props) {
|
|
|
108
108
|
((_a = props.ItemTooltip) !== null && _a !== void 0 ? _a : 'no-tip') !== 'no-tip' ?
|
|
109
109
|
React.createElement(ToolTip_1.default, { Show: showItems, Target: guid, Position: "bottom" },
|
|
110
110
|
React.createElement("p", null, "Selected Options:"),
|
|
111
|
-
selectedOptions.slice(0, 10).map(function (opt) { return React.createElement("p",
|
|
111
|
+
selectedOptions.slice(0, 10).map(function (opt, i) { return React.createElement("p", { key: i }, opt.Label); }),
|
|
112
112
|
selectedOptions.length > 10 ? React.createElement("p", null, "and ".concat(selectedOptions.length - 10, " other(s)")) : null)
|
|
113
113
|
: null,
|
|
114
114
|
React.createElement("div", { ref: multiSelect, style: { position: 'relative', display: 'block', width: 'inherit' } },
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { Gemstone } from '@gpa-gemstone/application-typings';
|
|
3
|
-
export interface
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
export interface IProps<T> extends Gemstone.TSX.Interfaces.IBaseFormProps<T> {
|
|
4
|
+
/**
|
|
5
|
+
* Function to determine the validity of a field
|
|
6
|
+
* @param field - Field of the record to check
|
|
7
|
+
* @returns {boolean}
|
|
8
|
+
*/
|
|
9
|
+
Valid?: (field: keyof T) => boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Feedback message to show when input is invalid
|
|
12
|
+
* @type {string}
|
|
13
|
+
* @optional
|
|
14
|
+
*/
|
|
15
|
+
Feedback?: string;
|
|
7
16
|
/**
|
|
8
17
|
* Flag to allow custom input values
|
|
9
18
|
* @type {boolean}
|
|
@@ -15,7 +24,7 @@ interface IProps<T> extends Gemstone.TSX.Interfaces.IBaseFormProps<T> {
|
|
|
15
24
|
* @param search - Search string
|
|
16
25
|
* @returns {AbortablePromise<T>}
|
|
17
26
|
*/
|
|
18
|
-
Search: (search: string) => AbortablePromise<Gemstone.TSX.Interfaces.ILabelValue<string | number>[]>;
|
|
27
|
+
Search: (search: string) => Gemstone.TSX.Interfaces.AbortablePromise<Gemstone.TSX.Interfaces.ILabelValue<string | number>[]>;
|
|
19
28
|
/**
|
|
20
29
|
* CSS styles to apply to the form group
|
|
21
30
|
* @type {React.CSSProperties}
|
|
@@ -28,11 +37,10 @@ interface IProps<T> extends Gemstone.TSX.Interfaces.IBaseFormProps<T> {
|
|
|
28
37
|
* @optional
|
|
29
38
|
*/
|
|
30
39
|
BtnStyle?: React.CSSProperties;
|
|
31
|
-
GetLabel?: () => AbortablePromise<string>;
|
|
40
|
+
GetLabel?: () => Gemstone.TSX.Interfaces.AbortablePromise<string>;
|
|
32
41
|
/**
|
|
33
|
-
* Flag to reset search text to an empty string when a user selects an option. Defaulting to false
|
|
42
|
+
* Flag to reset search text to an empty string when a user selects an option or when the element loses focus. Defaulting to false
|
|
34
43
|
*/
|
|
35
44
|
ResetSearchOnSelect?: boolean;
|
|
36
45
|
}
|
|
37
46
|
export default function SearchableSelect<T>(props: IProps<T>): JSX.Element;
|
|
38
|
-
export {};
|
package/lib/SearchableSelect.js
CHANGED
|
@@ -30,33 +30,35 @@ var getInitialSearchText = function (useBlankString, recordValue) {
|
|
|
30
30
|
return useBlankString ? '' : recordValue;
|
|
31
31
|
};
|
|
32
32
|
function SearchableSelect(props) {
|
|
33
|
-
var _a, _b;
|
|
34
|
-
var
|
|
35
|
-
var
|
|
36
|
-
var
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
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];
|
|
34
|
+
var _b = React.useState([]), searchOptions = _b[0], setSearchOptions = _b[1];
|
|
35
|
+
var _c = React.useState(false), loading = _c[0], setLoading = _c[1];
|
|
36
|
+
var setter = React.useCallback(function (record, selectedOption) {
|
|
37
|
+
handleSetSearch(selectedOption);
|
|
38
|
+
props.Setter(record);
|
|
39
|
+
}, [props.Setter, props.Field]);
|
|
40
|
+
var handleSetSearch = React.useCallback(function (selectedOption) {
|
|
39
41
|
var _a, _b, _c;
|
|
40
|
-
if (props.
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
else
|
|
44
|
-
setLabel((_c = (_b = props.Record[props.Field]) === null || _b === void 0 ? void 0 : _b.toString()) !== null && _c !== void 0 ? _c : '');
|
|
42
|
+
if ((_a = props.ResetSearchOnSelect) !== null && _a !== void 0 ? _a : false) {
|
|
43
|
+
setSearch('');
|
|
44
|
+
return;
|
|
45
45
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
setLabel(lab);
|
|
51
|
-
setSearch(lab);
|
|
52
|
-
setLoading(false);
|
|
53
|
-
});
|
|
54
|
-
return function () {
|
|
55
|
-
if ((handle_1 === null || handle_1 === void 0 ? void 0 : handle_1.abort) != null)
|
|
56
|
-
handle_1.abort();
|
|
57
|
-
};
|
|
46
|
+
if (props.GetLabel === undefined) {
|
|
47
|
+
var newSearch = (_c = selectedOption !== null && selectedOption !== void 0 ? selectedOption : (_b = props.Record[props.Field]) === null || _b === void 0 ? void 0 : _b.toString()) !== null && _c !== void 0 ? _c : '';
|
|
48
|
+
setSearch(newSearch);
|
|
49
|
+
return;
|
|
58
50
|
}
|
|
59
|
-
|
|
51
|
+
setLoading(true);
|
|
52
|
+
var handle = props.GetLabel();
|
|
53
|
+
handle.then(function (lab) {
|
|
54
|
+
setSearch(lab);
|
|
55
|
+
setLoading(false);
|
|
56
|
+
}, function () { return setLoading(false); });
|
|
57
|
+
}, [props.ResetSearchOnSelect, props.GetLabel, props.Record[props.Field]]);
|
|
58
|
+
//Effect to set search when props.Record[props.Field] changes externally
|
|
59
|
+
React.useEffect(function () {
|
|
60
|
+
handleSetSearch();
|
|
61
|
+
}, [props.Record[props.Field], handleSetSearch]);
|
|
60
62
|
// Call props.Search every 500ms to avoid hammering the server while typing
|
|
61
63
|
React.useEffect(function () {
|
|
62
64
|
setLoading(true);
|
|
@@ -64,7 +66,7 @@ function SearchableSelect(props) {
|
|
|
64
66
|
var timeoutHandle = setTimeout(function () {
|
|
65
67
|
searchHandle = props.Search(search);
|
|
66
68
|
searchHandle.then(function (d) {
|
|
67
|
-
|
|
69
|
+
setSearchOptions(d.map(function (o) { return ({ Value: o.Value, Element: o.Label }); }));
|
|
68
70
|
setLoading(false);
|
|
69
71
|
}, function () {
|
|
70
72
|
setLoading(false);
|
|
@@ -77,38 +79,25 @@ function SearchableSelect(props) {
|
|
|
77
79
|
clearTimeout(timeoutHandle);
|
|
78
80
|
};
|
|
79
81
|
}, [search]);
|
|
80
|
-
var update = React.useCallback(function (record, selectedOption) {
|
|
81
|
-
var _a, _b, _c;
|
|
82
|
-
var stringVal = (_b = (_a = record[props.Field]) === null || _a === void 0 ? void 0 : _a.toString()) !== null && _b !== void 0 ? _b : '';
|
|
83
|
-
var newLabel = stringVal;
|
|
84
|
-
if (!React.isValidElement(selectedOption.Element))
|
|
85
|
-
newLabel = selectedOption.Element;
|
|
86
|
-
setLabel(newLabel);
|
|
87
|
-
props.Setter(record);
|
|
88
|
-
if ((_c = props.ResetSearchOnSelect) !== null && _c !== void 0 ? _c : false)
|
|
89
|
-
setSearch('');
|
|
90
|
-
else
|
|
91
|
-
setSearch(newLabel);
|
|
92
|
-
}, [props.Setter, props.Field, label]);
|
|
93
82
|
var options = React.useMemo(function () {
|
|
94
|
-
var _a, _b;
|
|
83
|
+
var _a, _b, _c, _d;
|
|
95
84
|
var ops = [];
|
|
96
85
|
ops.push({
|
|
97
86
|
Value: props.Record[props.Field],
|
|
98
87
|
Element: React.createElement("div", { className: 'input-group' },
|
|
99
|
-
React.createElement("input", { type: "text", className: "form-control", value: search, onChange: function (d) { return setSearch(d.target.value); }, onBlur: function () { return
|
|
88
|
+
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 }),
|
|
100
89
|
loading ?
|
|
101
90
|
React.createElement("div", { className: "input-group-append" },
|
|
102
91
|
React.createElement("span", { className: "input-group-text" },
|
|
103
92
|
React.createElement(gpa_symbols_1.ReactIcons.SpiningIcon, null)))
|
|
104
93
|
: null)
|
|
105
94
|
});
|
|
106
|
-
if ((
|
|
95
|
+
if ((_d = props.AllowCustom) !== null && _d !== void 0 ? _d : false)
|
|
107
96
|
ops.push({ Value: search, Element: React.createElement(React.Fragment, null,
|
|
108
97
|
search,
|
|
109
98
|
" (Entered Value)") });
|
|
110
|
-
ops.push.apply(ops,
|
|
99
|
+
ops.push.apply(ops, searchOptions.filter(function (f) { return f.Value !== search && f.Value !== props.Record[props.Field]; }));
|
|
111
100
|
return ops;
|
|
112
|
-
}, [search, props.Record[props.Field],
|
|
113
|
-
return React.createElement(StylableSelect_1.default, { Record: props.Record, Field: props.Field, Setter:
|
|
101
|
+
}, [search, props.Record[props.Field], props.Field, searchOptions, props.Disabled, loading, props.Valid, handleSetSearch]);
|
|
102
|
+
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 });
|
|
114
103
|
}
|
package/lib/StylableSelect.d.ts
CHANGED
|
@@ -4,6 +4,18 @@ export interface IOption {
|
|
|
4
4
|
Element: React.ReactElement<any> | string;
|
|
5
5
|
}
|
|
6
6
|
interface IProps<T> {
|
|
7
|
+
/**
|
|
8
|
+
* Function to determine the validity of a field
|
|
9
|
+
* @param field - Field of the record to check
|
|
10
|
+
* @returns {boolean}
|
|
11
|
+
*/
|
|
12
|
+
Valid?: (field: keyof T) => boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Feedback message to show when input is invalid
|
|
15
|
+
* @type {string}
|
|
16
|
+
* @optional
|
|
17
|
+
*/
|
|
18
|
+
Feedback?: string;
|
|
7
19
|
/**
|
|
8
20
|
* Record to be used in form
|
|
9
21
|
* @type {T}
|
package/lib/StylableSelect.js
CHANGED
|
@@ -42,17 +42,17 @@ var react_portal_1 = require("react-portal");
|
|
|
42
42
|
var _ = require("lodash");
|
|
43
43
|
var gpa_symbols_1 = require("@gpa-gemstone/gpa-symbols");
|
|
44
44
|
function StylableSelect(props) {
|
|
45
|
-
var _a;
|
|
45
|
+
var _a, _b, _c;
|
|
46
46
|
// State hooks and ref for managing component state and interactions.
|
|
47
47
|
var stylableSelect = React.useRef(null);
|
|
48
48
|
var selectTable = React.useRef(null);
|
|
49
49
|
var tableContainer = React.useRef(null);
|
|
50
|
-
var
|
|
51
|
-
var
|
|
52
|
-
var
|
|
53
|
-
var
|
|
54
|
-
var
|
|
55
|
-
React.
|
|
50
|
+
var _d = React.useState(false), show = _d[0], setShow = _d[1];
|
|
51
|
+
var _e = React.useState(props.Options[0].Element), selected = _e[0], setSelected = _e[1];
|
|
52
|
+
var _f = React.useState(""), guid = _f[0], setGuid = _f[1];
|
|
53
|
+
var _g = React.useState(false), showHelp = _g[0], setShowHelp = _g[1];
|
|
54
|
+
var _h = React.useState({ Top: 0, Left: 0, Width: 0, Height: 0 }), position = _h[0], setPosition = _h[1];
|
|
55
|
+
React.useLayoutEffect(function () {
|
|
56
56
|
var updatePosition = _.debounce(function () {
|
|
57
57
|
if (stylableSelect.current != null) {
|
|
58
58
|
var rect = stylableSelect.current.getBoundingClientRect();
|
|
@@ -82,6 +82,16 @@ function StylableSelect(props) {
|
|
|
82
82
|
// Ignore if disabled or not a mousedown event
|
|
83
83
|
if ((props.Disabled === undefined ? false : props.Disabled) || evt.type !== 'mousedown' || stylableSelect.current == null)
|
|
84
84
|
return;
|
|
85
|
+
// if we’re about to OPEN it, measure right now
|
|
86
|
+
if (!show && stylableSelect.current != null) {
|
|
87
|
+
var rect = stylableSelect.current.getBoundingClientRect();
|
|
88
|
+
setPosition({
|
|
89
|
+
Top: rect.bottom,
|
|
90
|
+
Left: rect.left,
|
|
91
|
+
Width: rect.width,
|
|
92
|
+
Height: rect.height
|
|
93
|
+
});
|
|
94
|
+
}
|
|
85
95
|
//ignore the click if it was inside the table or table container
|
|
86
96
|
if ((selectTable.current != null && selectTable.current.contains(evt.target)) || (tableContainer.current != null && tableContainer.current.contains(evt.target)))
|
|
87
97
|
return;
|
|
@@ -131,8 +141,9 @@ function StylableSelect(props) {
|
|
|
131
141
|
props.Help !== undefined ?
|
|
132
142
|
React.createElement(ToolTip_1.default, { Show: showHelp, Target: guid, Class: "info", Position: "bottom" }, props.Help)
|
|
133
143
|
: null,
|
|
134
|
-
React.createElement("button", { type: "button", style: __assign({
|
|
144
|
+
React.createElement("button", { type: "button", style: __assign({ padding: '.375rem .75rem' }, ((_a = props.BtnStyle) !== null && _a !== void 0 ? _a : {})), className: "dropdown-toggle form-control ".concat(((_c = (_b = props.Valid) === null || _b === void 0 ? void 0 : _b.call(props, props.Field)) !== null && _c !== void 0 ? _c : true) ? '' : 'is-invalid'), onClick: HandleShow, disabled: props.Disabled === undefined ? false : props.Disabled },
|
|
135
145
|
React.createElement("div", { style: props.Style }, selected)),
|
|
146
|
+
React.createElement("div", { className: "invalid-feedback" }, props.Feedback == null ? props.Field.toString() + ' is a required field.' : props.Feedback),
|
|
136
147
|
React.createElement(react_portal_1.Portal, null,
|
|
137
148
|
React.createElement("div", { ref: tableContainer, className: 'popover', style: {
|
|
138
149
|
maxHeight: window.innerHeight - position.Top,
|
package/lib/ToggleSwitch.js
CHANGED
|
@@ -45,7 +45,7 @@ function ToggleSwitch(props) {
|
|
|
45
45
|
// Variables to control the rendering of label and help icon.
|
|
46
46
|
var showHelpIcon = props.Help !== undefined;
|
|
47
47
|
var label = props.Label === undefined ? props.Field : props.Label;
|
|
48
|
-
return (React.createElement("div", { className: "custom-control custom-switch", style: props.Style },
|
|
48
|
+
return (React.createElement("div", { className: "custom-control custom-switch form-group", style: props.Style },
|
|
49
49
|
React.createElement("input", { type: "checkbox", className: "custom-control-input", onChange: function (evt) {
|
|
50
50
|
var record = __assign({}, props.Record);
|
|
51
51
|
record[props.Field] = evt.target.checked;
|
package/lib/index.d.ts
CHANGED
|
@@ -19,4 +19,5 @@ import RadioButtons from './RadioButtons';
|
|
|
19
19
|
import FileUpload from './FileUpload';
|
|
20
20
|
import MultiInput from './MultiInput';
|
|
21
21
|
import ToolTip from './ToolTip';
|
|
22
|
-
|
|
22
|
+
import MultiSearchableSelect from './MultiSearchableSelect';
|
|
23
|
+
export { CheckBox, Input, DatePicker, Select, TextArea, DateRangePicker, EnumCheckBoxes, ArrayMultiSelect, ArrayCheckBoxes, MultiCheckBoxSelect, DoubleInput, TimePicker, StylableSelect, ColorPicker, SearchableSelect, ToggleSwitch, InputWithButton, RadioButtons, FileUpload, MultiInput, ToolTip, MultiSearchableSelect };
|
package/lib/index.js
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
//
|
|
23
23
|
// ******************************************************************************************************
|
|
24
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
-
exports.ToolTip = exports.MultiInput = exports.FileUpload = exports.RadioButtons = exports.InputWithButton = exports.ToggleSwitch = exports.SearchableSelect = exports.ColorPicker = exports.StylableSelect = exports.TimePicker = exports.DoubleInput = exports.MultiCheckBoxSelect = exports.ArrayCheckBoxes = exports.ArrayMultiSelect = exports.EnumCheckBoxes = exports.DateRangePicker = exports.TextArea = exports.Select = exports.DatePicker = exports.Input = exports.CheckBox = void 0;
|
|
25
|
+
exports.MultiSearchableSelect = exports.ToolTip = exports.MultiInput = exports.FileUpload = exports.RadioButtons = exports.InputWithButton = exports.ToggleSwitch = exports.SearchableSelect = exports.ColorPicker = exports.StylableSelect = exports.TimePicker = exports.DoubleInput = exports.MultiCheckBoxSelect = exports.ArrayCheckBoxes = exports.ArrayMultiSelect = exports.EnumCheckBoxes = exports.DateRangePicker = exports.TextArea = exports.Select = exports.DatePicker = exports.Input = exports.CheckBox = void 0;
|
|
26
26
|
var CheckBox_1 = require("./CheckBox");
|
|
27
27
|
exports.CheckBox = CheckBox_1.default;
|
|
28
28
|
var Input_1 = require("./Input");
|
|
@@ -65,3 +65,5 @@ var MultiInput_1 = require("./MultiInput");
|
|
|
65
65
|
exports.MultiInput = MultiInput_1.default;
|
|
66
66
|
var ToolTip_1 = require("./ToolTip");
|
|
67
67
|
exports.ToolTip = ToolTip_1.default;
|
|
68
|
+
var MultiSearchableSelect_1 = require("./MultiSearchableSelect");
|
|
69
|
+
exports.MultiSearchableSelect = MultiSearchableSelect_1.default;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gpa-gemstone/react-forms",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.94",
|
|
4
4
|
"description": "React Form modules for gpa webapps",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -45,9 +45,9 @@
|
|
|
45
45
|
"typescript": "5.5.3"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@gpa-gemstone/application-typings": "0.0.
|
|
48
|
+
"@gpa-gemstone/application-typings": "0.0.87",
|
|
49
49
|
"@gpa-gemstone/gpa-symbols": "0.0.52",
|
|
50
|
-
"@gpa-gemstone/helper-functions": "0.0.
|
|
50
|
+
"@gpa-gemstone/helper-functions": "0.0.44",
|
|
51
51
|
"@types/react": "^17.0.14",
|
|
52
52
|
"@types/styled-components": "^5.1.11",
|
|
53
53
|
"lodash": "^4.17.21",
|