@gpa-gemstone/react-forms 1.1.84 → 1.1.86
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/DatePicker.js +73 -40
- package/lib/FileUpload.js +2 -2
- package/lib/SearchableSelect.d.ts +3 -3
- package/lib/SearchableSelect.js +35 -43
- package/lib/StylableSelect.js +1 -1
- package/package.json +2 -2
package/lib/DatePicker.js
CHANGED
|
@@ -44,6 +44,11 @@ var gpa_symbols_1 = require("@gpa-gemstone/gpa-symbols");
|
|
|
44
44
|
* Component that allows a user to pick a date or datetime.
|
|
45
45
|
*/
|
|
46
46
|
function DateTimePicker(props) {
|
|
47
|
+
var inputRef = React.useRef(null);
|
|
48
|
+
var width = (0, helper_functions_1.useGetContainerPosition)(inputRef).width;
|
|
49
|
+
var _a = React.useState(false), isTextOverflowing = _a[0], setIsTextOverflowing = _a[1];
|
|
50
|
+
var _b = React.useState(false), isInputHovered = _b[0], setIsInputHovered = _b[1];
|
|
51
|
+
var overflowGUID = React.useState((0, helper_functions_1.CreateGuid)())[0];
|
|
47
52
|
// Formats for displaying dates in the input box and storing in the record.
|
|
48
53
|
var boxFormat = getBoxFormat(props.Type, props.Accuracy);
|
|
49
54
|
var recordFormat = props.Format !== undefined ? props.Format : "YYYY-MM-DD" + (props.Type === undefined || props.Type === 'date' ? "" : "[T]HH:mm:ss.SSS[Z]");
|
|
@@ -51,15 +56,15 @@ function DateTimePicker(props) {
|
|
|
51
56
|
var parse = function (r) { return moment(props.Record[props.Field], recordFormat); };
|
|
52
57
|
// State and ref declarations.
|
|
53
58
|
var divRef = React.useRef(null);
|
|
54
|
-
var
|
|
55
|
-
var
|
|
59
|
+
var helpGuid = React.useState((0, helper_functions_1.CreateGuid)())[0];
|
|
60
|
+
var _c = React.useState(false), showHelp = _c[0], setShowHelp = _c[1];
|
|
56
61
|
// Adds a buffer between the outside props and what the box is reading to prevent box overwriting every render with a keystroke
|
|
57
|
-
var
|
|
58
|
-
var
|
|
59
|
-
var
|
|
60
|
-
var
|
|
61
|
-
var
|
|
62
|
-
var
|
|
62
|
+
var _d = React.useState(parse(props.Record).format(boxFormat)), boxRecord = _d[0], setBoxRecord = _d[1];
|
|
63
|
+
var _e = React.useState(parse(props.Record)), pickerRecord = _e[0], setPickerRecord = _e[1];
|
|
64
|
+
var _f = React.useState(""), feedbackMessage = _f[0], setFeedbackMessage = _f[1];
|
|
65
|
+
var _g = React.useState(false), showOverlay = _g[0], setShowOverlay = _g[1];
|
|
66
|
+
var _h = React.useState(0), top = _h[0], setTop = _h[1];
|
|
67
|
+
var _j = React.useState(0), left = _j[0], setLeft = _j[1];
|
|
63
68
|
var allowNull = React.useMemo(function () { var _a; return (_a = props.AllowEmpty) !== null && _a !== void 0 ? _a : false; }, [props.AllowEmpty]);
|
|
64
69
|
React.useEffect(function () {
|
|
65
70
|
if (props.Record[props.Field] !== null) {
|
|
@@ -128,35 +133,6 @@ function DateTimePicker(props) {
|
|
|
128
133
|
}
|
|
129
134
|
}
|
|
130
135
|
}
|
|
131
|
-
function getBoxFormat(type, accuracy) {
|
|
132
|
-
var dateTime = type !== null && type !== void 0 ? type : 'date';
|
|
133
|
-
var timeUnit = accuracy !== null && accuracy !== void 0 ? accuracy : 'second';
|
|
134
|
-
if (dateTime === 'time') {
|
|
135
|
-
if (timeUnit === 'minute') {
|
|
136
|
-
return "HH:mm";
|
|
137
|
-
}
|
|
138
|
-
else if (timeUnit === 'second') {
|
|
139
|
-
return "HH:mm:ss";
|
|
140
|
-
}
|
|
141
|
-
else {
|
|
142
|
-
return "HH:mm:ss.SSS";
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
else if (dateTime === 'datetime-local') {
|
|
146
|
-
if (timeUnit === 'minute') {
|
|
147
|
-
return "YYYY-MM-DD[T]HH:mm";
|
|
148
|
-
}
|
|
149
|
-
else if (timeUnit === 'second') {
|
|
150
|
-
return "YYYY-MM-DD[T]HH:mm:ss";
|
|
151
|
-
}
|
|
152
|
-
else {
|
|
153
|
-
return "YYYY-MM-DD[T]HH:mm:ss.SSS";
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
else {
|
|
157
|
-
return "YYYY-MM-DD";
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
136
|
function getFeedbackMessage() {
|
|
161
137
|
if (feedbackMessage.length != 0) {
|
|
162
138
|
return feedbackMessage;
|
|
@@ -214,23 +190,80 @@ function DateTimePicker(props) {
|
|
|
214
190
|
}
|
|
215
191
|
setBoxRecord(value);
|
|
216
192
|
}
|
|
193
|
+
React.useEffect(function () {
|
|
194
|
+
if (inputRef.current == null)
|
|
195
|
+
return;
|
|
196
|
+
var inputWidth = getInputWidth(inputRef.current, boxRecord, step);
|
|
197
|
+
setIsTextOverflowing(inputWidth > width);
|
|
198
|
+
}, [width, boxRecord, step]);
|
|
217
199
|
return (React.createElement("div", { className: "form-group", ref: divRef },
|
|
218
200
|
showHelpIcon || showLabel ?
|
|
219
201
|
React.createElement("label", { className: "d-flex align-items-center" },
|
|
220
202
|
React.createElement("span", null, showLabel ? label : ''),
|
|
221
|
-
showHelpIcon && (React.createElement("span", { className: "ml-2 d-flex align-items-center", onMouseEnter: function () { return setShowHelp(true); }, onMouseLeave: function () { return setShowHelp(false); }, "data-tooltip":
|
|
203
|
+
showHelpIcon && (React.createElement("span", { className: "ml-2 d-flex align-items-center", onMouseEnter: function () { return setShowHelp(true); }, onMouseLeave: function () { return setShowHelp(false); }, "data-tooltip": helpGuid },
|
|
222
204
|
React.createElement(gpa_symbols_1.ReactIcons.QuestionMark, { Color: "var(--info)", Size: 20 }))))
|
|
223
205
|
: null,
|
|
224
206
|
showHelpIcon ?
|
|
225
|
-
React.createElement(ToolTip_1.default, { Show: showHelp, Target:
|
|
207
|
+
React.createElement(ToolTip_1.default, { Show: showHelp, Target: helpGuid, Class: "info", Position: "bottom" }, props.Help)
|
|
226
208
|
: null,
|
|
227
209
|
React.createElement("input", { className: "gpa-gemstone-datetime form-control ".concat(IsValid() ? '' : 'is-invalid'), type: props.Type === undefined ? 'date' : props.Type, onChange: function (evt) {
|
|
228
210
|
valueChange(evt.target.value);
|
|
229
|
-
}, onFocus: function () { setShowOverlay(true); }, value: boxRecord, disabled: props.Disabled === undefined ? false : props.Disabled, onClick: function (e) { e.preventDefault(); }, step: step }),
|
|
211
|
+
}, onFocus: function () { setShowOverlay(true); }, value: boxRecord, disabled: props.Disabled === undefined ? false : props.Disabled, onClick: function (e) { e.preventDefault(); }, step: step, ref: inputRef, "data-tooltip": overflowGUID, onMouseOver: function () { return setIsInputHovered(true); }, onMouseOut: function () { return setIsInputHovered(false); } }),
|
|
230
212
|
React.createElement("div", { className: "invalid-feedback" }, getFeedbackMessage()),
|
|
213
|
+
React.createElement(ToolTip_1.default, { Show: isTextOverflowing && isInputHovered, Target: overflowGUID }, props.Format != null ? moment(boxRecord).format(props.Format) : boxRecord),
|
|
231
214
|
React.createElement(DateTimePopup_1.default, { Setter: function (d) {
|
|
232
215
|
setPickerAndRecord(d);
|
|
233
216
|
if (props.Type === 'date')
|
|
234
217
|
setShowOverlay(false);
|
|
235
218
|
}, Show: showOverlay, DateTime: pickerRecord, Valid: props.Valid(props.Field), Top: top, Center: left, Type: props.Type === undefined ? 'date' : props.Type, Accuracy: props.Accuracy })));
|
|
236
219
|
}
|
|
220
|
+
function getBoxFormat(type, accuracy) {
|
|
221
|
+
var dateTime = type !== null && type !== void 0 ? type : 'date';
|
|
222
|
+
var timeUnit = accuracy !== null && accuracy !== void 0 ? accuracy : 'second';
|
|
223
|
+
if (dateTime === 'time') {
|
|
224
|
+
if (timeUnit === 'minute') {
|
|
225
|
+
return "HH:mm";
|
|
226
|
+
}
|
|
227
|
+
else if (timeUnit === 'second') {
|
|
228
|
+
return "HH:mm:ss";
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
return "HH:mm:ss.SSS";
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
else if (dateTime === 'datetime-local') {
|
|
235
|
+
if (timeUnit === 'minute') {
|
|
236
|
+
return "YYYY-MM-DD[T]HH:mm";
|
|
237
|
+
}
|
|
238
|
+
else if (timeUnit === 'second') {
|
|
239
|
+
return "YYYY-MM-DD[T]HH:mm:ss";
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
return "YYYY-MM-DD[T]HH:mm:ss.SSS";
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
return "YYYY-MM-DD";
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
var getInputWidth = function (inputRef, currentValue, currentStep) {
|
|
250
|
+
var computedStyle = window.getComputedStyle(inputRef);
|
|
251
|
+
var dummyInput = document.createElement('input');
|
|
252
|
+
dummyInput.type = inputRef.type;
|
|
253
|
+
dummyInput.value = currentValue;
|
|
254
|
+
dummyInput.step = currentStep;
|
|
255
|
+
dummyInput.style.font = computedStyle.font;
|
|
256
|
+
dummyInput.style.fontSize = computedStyle.fontSize;
|
|
257
|
+
dummyInput.style.fontFamily = computedStyle.fontFamily;
|
|
258
|
+
dummyInput.style.fontWeight = computedStyle.fontWeight;
|
|
259
|
+
dummyInput.style.letterSpacing = computedStyle.letterSpacing;
|
|
260
|
+
dummyInput.style.whiteSpace = 'nowrap';
|
|
261
|
+
// Position it off-screen and hide it so it doesn't affect layout
|
|
262
|
+
dummyInput.style.position = 'absolute';
|
|
263
|
+
dummyInput.style.visibility = 'hidden';
|
|
264
|
+
document.body.appendChild(dummyInput);
|
|
265
|
+
var width = dummyInput.getBoundingClientRect().width;
|
|
266
|
+
// Clean up
|
|
267
|
+
document.body.removeChild(dummyInput);
|
|
268
|
+
return width;
|
|
269
|
+
};
|
package/lib/FileUpload.js
CHANGED
|
@@ -71,14 +71,14 @@ var FileUpload = function (props) {
|
|
|
71
71
|
React.createElement(gpa_symbols_1.ReactIcons.CircledX, { Color: 'red' })))),
|
|
72
72
|
isFileUpload ?
|
|
73
73
|
React.createElement(React.Fragment, null,
|
|
74
|
-
React.createElement("div", { className: 'row align-items-center justify-content-center', style: { border: '2px dashed var(--secondary)' } },
|
|
74
|
+
React.createElement("div", { className: 'row align-items-center justify-content-center', style: { border: '2px dashed var(--secondary)', borderRadius: '0.5em' } },
|
|
75
75
|
React.createElement("div", { className: 'col-auto' },
|
|
76
76
|
"File Name: ", fileName !== null && fileName !== void 0 ? fileName : ''),
|
|
77
77
|
React.createElement("div", { className: 'col-auto' },
|
|
78
78
|
"File Size: ",
|
|
79
79
|
formatFileSize(fileSize))))
|
|
80
80
|
:
|
|
81
|
-
React.createElement("div", { className: 'row', onDragOver: handleDragOver, onDrop: handleDrop, style: { border: '2px dashed var(--secondary)' } },
|
|
81
|
+
React.createElement("div", { className: 'row', onDragOver: handleDragOver, onDrop: handleDrop, style: { border: '2px dashed var(--secondary)', borderRadius: '0.5em' } },
|
|
82
82
|
React.createElement("div", { className: 'col-12 pt-3 pb-3 d-flex justify-content-center align-items-center' },
|
|
83
83
|
React.createElement(gpa_symbols_1.ReactIcons.Image, { Size: 100 }),
|
|
84
84
|
React.createElement("span", null, "Drag and Drop")))));
|
|
@@ -12,11 +12,11 @@ interface IProps<T> extends Gemstone.TSX.Interfaces.IBaseFormProps<T> {
|
|
|
12
12
|
*/
|
|
13
13
|
AllowCustom?: boolean;
|
|
14
14
|
/**
|
|
15
|
-
* Function to perform a search and return a
|
|
15
|
+
* Function to perform a search and return a promiselike object with a list of IOption and an optional callback
|
|
16
16
|
* @param search - Search string
|
|
17
|
-
* @returns {[promise:
|
|
17
|
+
* @returns {[promise: PromiseLike<IOption[]>, callback?: () => void]}
|
|
18
18
|
*/
|
|
19
|
-
Search: (search: string) => [
|
|
19
|
+
Search: (search: string) => [PromiseLike<IOption[]>, () => void];
|
|
20
20
|
/**
|
|
21
21
|
* CSS styles to apply to the form group
|
|
22
22
|
* @type {React.CSSProperties}
|
package/lib/SearchableSelect.js
CHANGED
|
@@ -21,17 +21,6 @@
|
|
|
21
21
|
// Generated original version of source code.
|
|
22
22
|
//
|
|
23
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
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
25
|
exports.default = SearchableSelect;
|
|
37
26
|
var React = require("react");
|
|
@@ -58,54 +47,57 @@ function SearchableSelect(props) {
|
|
|
58
47
|
return callback;
|
|
59
48
|
}
|
|
60
49
|
}, [props.GetLabel]);
|
|
50
|
+
// Call props.Search every 500ms to avoid hammering the server while typing
|
|
61
51
|
React.useEffect(function () {
|
|
62
52
|
setLoading(true);
|
|
63
|
-
var
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
53
|
+
var searchHandle;
|
|
54
|
+
var searchCallback;
|
|
55
|
+
var timeoutHandle = setTimeout(function () {
|
|
56
|
+
var _a;
|
|
57
|
+
_a = props.Search(search), searchHandle = _a[0], searchCallback = _a[1];
|
|
58
|
+
searchHandle.then(function (d) {
|
|
59
|
+
setResults(d.map(function (o) { return ({ Value: o.Value, Element: o.Label }); }));
|
|
60
|
+
setLoading(false);
|
|
61
|
+
}, function () {
|
|
62
|
+
setLoading(false);
|
|
63
|
+
});
|
|
64
|
+
}, 500);
|
|
65
|
+
return function () {
|
|
66
|
+
if (searchCallback != null)
|
|
67
|
+
searchCallback();
|
|
68
|
+
if (timeoutHandle != null)
|
|
69
|
+
clearTimeout(timeoutHandle);
|
|
70
|
+
};
|
|
69
71
|
}, [search]);
|
|
70
|
-
var
|
|
71
|
-
|
|
72
|
-
|
|
72
|
+
var update = React.useCallback(function (record, selectedOption) {
|
|
73
|
+
var _a, _b;
|
|
74
|
+
var stringVal = (_b = (_a = record[props.Field]) === null || _a === void 0 ? void 0 : _a.toString()) !== null && _b !== void 0 ? _b : '';
|
|
75
|
+
var newLabel = stringVal;
|
|
76
|
+
if (!React.isValidElement(selectedOption.Element))
|
|
77
|
+
newLabel = selectedOption.Element;
|
|
78
|
+
setLabel(newLabel);
|
|
79
|
+
props.Setter(record);
|
|
80
|
+
setSearch(newLabel);
|
|
81
|
+
}, [props.Setter, props.Field, label]);
|
|
73
82
|
var options = React.useMemo(function () {
|
|
74
83
|
var _a, _b;
|
|
75
84
|
var ops = [];
|
|
76
85
|
ops.push({
|
|
77
86
|
Value: props.Record[props.Field],
|
|
78
87
|
Element: React.createElement("div", { className: 'input-group' },
|
|
79
|
-
React.createElement("input", { type: "text", className: "form-control", value: search, onChange: function (d) { return setSearch(d.target.value); }, onBlur:
|
|
88
|
+
React.createElement("input", { type: "text", className: "form-control", value: search, onChange: function (d) { return setSearch(d.target.value); }, onBlur: function () { return setSearch(label); }, onClick: function (evt) { evt.preventDefault(); evt.stopPropagation(); }, disabled: (_a = props.Disabled) !== null && _a !== void 0 ? _a : false }),
|
|
80
89
|
loading ?
|
|
81
90
|
React.createElement("div", { className: "input-group-append" },
|
|
82
91
|
React.createElement("span", { className: "input-group-text" },
|
|
83
92
|
React.createElement(gpa_symbols_1.ReactIcons.SpiningIcon, null)))
|
|
84
93
|
: null)
|
|
85
94
|
});
|
|
86
|
-
if (
|
|
87
|
-
ops.push({ Value:
|
|
88
|
-
|
|
89
|
-
|
|
95
|
+
if ((_b = props.AllowCustom) !== null && _b !== void 0 ? _b : false)
|
|
96
|
+
-ops.push({ Value: search, Element: React.createElement(React.Fragment, null,
|
|
97
|
+
search,
|
|
98
|
+
" (Entered Value)") });
|
|
90
99
|
ops.push.apply(ops, results.filter(function (f) { return f.Value !== search && f.Value !== props.Record[props.Field]; }));
|
|
91
100
|
return ops;
|
|
92
|
-
}, [search, props.Record[props.Field], results, props.Disabled, loading, label
|
|
93
|
-
var update = React.useCallback(function (record, selectedOption) {
|
|
94
|
-
var _a;
|
|
95
|
-
var _b, _c;
|
|
96
|
-
var stringVal = (_c = (_b = record[props.Field]) === null || _b === void 0 ? void 0 : _b.toString()) !== null && _c !== void 0 ? _c : '';
|
|
97
|
-
var newLabel = stringVal;
|
|
98
|
-
if (!React.isValidElement(selectedOption.Element))
|
|
99
|
-
newLabel = selectedOption.Element;
|
|
100
|
-
setLabel(newLabel);
|
|
101
|
-
if (stringVal.startsWith('search-')) {
|
|
102
|
-
var value = stringVal.replace('search-', '');
|
|
103
|
-
props.Setter(__assign(__assign({}, record), (_a = {}, _a[props.Field] = value, _a)));
|
|
104
|
-
setSearch(newLabel !== null && newLabel !== void 0 ? newLabel : value);
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
props.Setter(record);
|
|
108
|
-
setSearch(newLabel);
|
|
109
|
-
}, [props.Setter, props.Field, label]);
|
|
101
|
+
}, [search, props.Record[props.Field], results, props.Disabled, loading, label]);
|
|
110
102
|
return React.createElement(StylableSelect_1.default, { Record: props.Record, Field: props.Field, Setter: update, Label: props.Label, Disabled: props.Disabled, Help: props.Help, Style: props.Style, Options: options, BtnStyle: props.BtnStyle });
|
|
111
103
|
}
|
package/lib/StylableSelect.js
CHANGED
|
@@ -121,7 +121,7 @@ function StylableSelect(props) {
|
|
|
121
121
|
var showLabel = props.Label !== "";
|
|
122
122
|
var showHelpIcon = props.Help !== undefined;
|
|
123
123
|
var label = props.Label === undefined ? props.Field : props.Label;
|
|
124
|
-
return (React.createElement("div", { ref: stylableSelect, style: { position: 'relative', display: 'inline-block', width: 'inherit' } },
|
|
124
|
+
return (React.createElement("div", { ref: stylableSelect, className: "form-group", style: { position: 'relative', display: 'inline-block', width: 'inherit' } },
|
|
125
125
|
showHelpIcon || showLabel ?
|
|
126
126
|
React.createElement("label", { className: "d-flex align-items-center" },
|
|
127
127
|
React.createElement("span", null, showLabel ? label : ''),
|
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.86",
|
|
4
4
|
"description": "React Form modules for gpa webapps",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@gpa-gemstone/application-typings": "0.0.83",
|
|
49
49
|
"@gpa-gemstone/gpa-symbols": "0.0.49",
|
|
50
|
-
"@gpa-gemstone/helper-functions": "0.0.
|
|
50
|
+
"@gpa-gemstone/helper-functions": "0.0.39",
|
|
51
51
|
"@types/react": "^17.0.14",
|
|
52
52
|
"@types/styled-components": "^5.1.11",
|
|
53
53
|
"lodash": "^4.17.21",
|