@tellescope/react-components 1.231.0 → 1.232.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.
- package/lib/cjs/Forms/forms.js +1 -1
- package/lib/cjs/Forms/forms.js.map +1 -1
- package/lib/cjs/Forms/forms.v2.d.ts +1 -1
- package/lib/cjs/Forms/forms.v2.js +1 -1
- package/lib/cjs/Forms/forms.v2.js.map +1 -1
- package/lib/cjs/Forms/hooks.d.ts.map +1 -1
- package/lib/cjs/Forms/hooks.js +24 -0
- package/lib/cjs/Forms/hooks.js.map +1 -1
- package/lib/cjs/Forms/inputs.d.ts +6 -3
- package/lib/cjs/Forms/inputs.d.ts.map +1 -1
- package/lib/cjs/Forms/inputs.js +171 -44
- package/lib/cjs/Forms/inputs.js.map +1 -1
- package/lib/cjs/Forms/inputs.v2.d.ts +7 -11
- package/lib/cjs/Forms/inputs.v2.d.ts.map +1 -1
- package/lib/cjs/Forms/inputs.v2.js +16 -445
- package/lib/cjs/Forms/inputs.v2.js.map +1 -1
- package/lib/esm/CMS/components.d.ts +0 -1
- package/lib/esm/CMS/components.d.ts.map +1 -1
- package/lib/esm/Forms/form_responses.d.ts +0 -1
- package/lib/esm/Forms/form_responses.d.ts.map +1 -1
- package/lib/esm/Forms/forms.d.ts +3 -3
- package/lib/esm/Forms/forms.js +1 -1
- package/lib/esm/Forms/forms.js.map +1 -1
- package/lib/esm/Forms/forms.v2.d.ts +4 -4
- package/lib/esm/Forms/forms.v2.js +1 -1
- package/lib/esm/Forms/forms.v2.js.map +1 -1
- package/lib/esm/Forms/hooks.d.ts +0 -1
- package/lib/esm/Forms/hooks.d.ts.map +1 -1
- package/lib/esm/Forms/hooks.js +24 -0
- package/lib/esm/Forms/hooks.js.map +1 -1
- package/lib/esm/Forms/inputs.d.ts +7 -4
- package/lib/esm/Forms/inputs.d.ts.map +1 -1
- package/lib/esm/Forms/inputs.js +173 -46
- package/lib/esm/Forms/inputs.js.map +1 -1
- package/lib/esm/Forms/inputs.v2.d.ts +8 -12
- package/lib/esm/Forms/inputs.v2.d.ts.map +1 -1
- package/lib/esm/Forms/inputs.v2.js +17 -446
- package/lib/esm/Forms/inputs.v2.js.map +1 -1
- package/lib/esm/controls.d.ts +2 -2
- package/lib/esm/inputs.d.ts +1 -1
- package/lib/esm/inputs.native.d.ts +0 -1
- package/lib/esm/inputs.native.d.ts.map +1 -1
- package/lib/esm/state.d.ts +315 -315
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +9 -9
- package/src/Forms/forms.tsx +1 -1
- package/src/Forms/forms.v2.tsx +1 -1
- package/src/Forms/hooks.tsx +33 -5
- package/src/Forms/inputs.tsx +224 -35
- package/src/Forms/inputs.v2.tsx +20 -639
package/lib/cjs/Forms/inputs.js
CHANGED
|
@@ -122,6 +122,15 @@ var react_stripe_js_1 = require("@stripe/react-stripe-js");
|
|
|
122
122
|
var stripe_js_1 = require("@stripe/stripe-js");
|
|
123
123
|
var icons_material_1 = require("@mui/icons-material");
|
|
124
124
|
var wysiwyg_1 = require("./wysiwyg");
|
|
125
|
+
// Debounce hook for search functionality
|
|
126
|
+
var useDebounce = function (value, delay) {
|
|
127
|
+
var _a = (0, react_1.useState)(value), debouncedValue = _a[0], setDebouncedValue = _a[1];
|
|
128
|
+
(0, react_1.useEffect)(function () {
|
|
129
|
+
var handler = setTimeout(function () { return setDebouncedValue(value); }, delay);
|
|
130
|
+
return function () { return clearTimeout(handler); };
|
|
131
|
+
}, [value, delay]);
|
|
132
|
+
return debouncedValue;
|
|
133
|
+
};
|
|
125
134
|
var LanguageSelect = function (_a) {
|
|
126
135
|
var value = _a.value, props = __rest(_a, ["value"]);
|
|
127
136
|
return ((0, jsx_runtime_1.jsxs)(material_1.Grid, __assign({ container: true, alignItems: "center", justifyContent: "center", wrap: "nowrap", spacing: 1 }, { children: [(0, jsx_runtime_1.jsx)(material_1.Grid, __assign({ item: true }, { children: (0, jsx_runtime_1.jsx)(Language_1.default, { color: "primary" }) })), (0, jsx_runtime_1.jsx)(material_1.Grid, __assign({ item: true, style: { width: 150 } }, { children: (0, jsx_runtime_1.jsx)(StringSelector, __assign({}, props, { options: ["English", "Español"], size: "small", value: value === 'Spanish' ? 'Español' : value, label: (value === 'Español' || value === 'Spanish') ? 'Idioma'
|
|
@@ -861,20 +870,59 @@ var MultipleChoiceInput = function (_a) {
|
|
|
861
870
|
} }) }))] })));
|
|
862
871
|
};
|
|
863
872
|
exports.MultipleChoiceInput = MultipleChoiceInput;
|
|
873
|
+
// Helper to emit GTM purchase event for Stripe payments (single source of truth)
|
|
874
|
+
var emitStripePurchaseEvent = function (field, cost) {
|
|
875
|
+
var _a;
|
|
876
|
+
(0, utilities_1.emit_gtm_event)({
|
|
877
|
+
event: 'form_purchase',
|
|
878
|
+
productIds: ((_a = field.options) === null || _a === void 0 ? void 0 : _a.productIds) || [],
|
|
879
|
+
fieldId: field.id,
|
|
880
|
+
value: cost / 100,
|
|
881
|
+
currency: 'USD',
|
|
882
|
+
});
|
|
883
|
+
};
|
|
864
884
|
var StripeInput = function (_a) {
|
|
865
|
-
var _b, _d;
|
|
866
|
-
var field = _a.field, value = _a.value, onChange = _a.onChange, setCustomerId = _a.setCustomerId, enduserId = _a.enduserId;
|
|
885
|
+
var _b, _d, _e;
|
|
886
|
+
var field = _a.field, value = _a.value, onChange = _a.onChange, setCustomerId = _a.setCustomerId, enduserId = _a.enduserId, form = _a.form, responses = _a.responses, enduser = _a.enduser;
|
|
867
887
|
var session = (0, __1.useResolvedSession)();
|
|
868
|
-
var
|
|
869
|
-
var
|
|
870
|
-
var
|
|
871
|
-
var
|
|
872
|
-
var
|
|
873
|
-
var
|
|
874
|
-
var
|
|
875
|
-
var
|
|
876
|
-
var
|
|
877
|
-
var
|
|
888
|
+
var _f = (0, react_1.useState)(''), clientSecret = _f[0], setClientSecret = _f[1];
|
|
889
|
+
var _g = (0, react_1.useState)(''), businessName = _g[0], setBusinessName = _g[1];
|
|
890
|
+
var _h = (0, react_1.useState)(false), isCheckout = _h[0], setIsCheckout = _h[1];
|
|
891
|
+
var _j = (0, react_1.useState)(), stripePromise = _j[0], setStripePromise = _j[1];
|
|
892
|
+
var _k = (0, react_1.useState)(''), answertext = _k[0], setAnswertext = _k[1];
|
|
893
|
+
var _l = (0, react_1.useState)(''), error = _l[0], setError = _l[1];
|
|
894
|
+
var _m = (0, react_1.useState)([]), selectedProducts = _m[0], setSelectedProducts = _m[1];
|
|
895
|
+
var _o = (0, react_1.useState)(false), showProductSelection = _o[0], setShowProductSelection = _o[1];
|
|
896
|
+
var _p = (0, react_1.useState)([]), availableProducts = _p[0], setAvailableProducts = _p[1];
|
|
897
|
+
var _q = (0, react_1.useState)(false), loadingProducts = _q[0], setLoadingProducts = _q[1];
|
|
898
|
+
// Compute visible products based on conditional logic
|
|
899
|
+
var visibleProducts = (0, react_1.useMemo)(function () {
|
|
900
|
+
if (!showProductSelection || availableProducts.length === 0) {
|
|
901
|
+
return availableProducts;
|
|
902
|
+
}
|
|
903
|
+
return availableProducts.filter(function (product) {
|
|
904
|
+
var _a, _b;
|
|
905
|
+
// Find condition for this product
|
|
906
|
+
var productCondition = (_b = (_a = field.options) === null || _a === void 0 ? void 0 : _a.productConditions) === null || _b === void 0 ? void 0 : _b.find(function (c) { return c.productId === product._id; });
|
|
907
|
+
// If no condition defined, show by default
|
|
908
|
+
if (!(productCondition === null || productCondition === void 0 ? void 0 : productCondition.showCondition) || (0, utilities_1.object_is_empty)(productCondition.showCondition)) {
|
|
909
|
+
return true;
|
|
910
|
+
}
|
|
911
|
+
// Evaluate condition against current form responses
|
|
912
|
+
return (0, utilities_1.responses_satisfy_conditions)(responses || [], productCondition.showCondition, {
|
|
913
|
+
dateOfBirth: enduser === null || enduser === void 0 ? void 0 : enduser.dateOfBirth,
|
|
914
|
+
gender: enduser === null || enduser === void 0 ? void 0 : enduser.gender,
|
|
915
|
+
state: enduser === null || enduser === void 0 ? void 0 : enduser.state,
|
|
916
|
+
form: form,
|
|
917
|
+
activeResponses: responses,
|
|
918
|
+
});
|
|
919
|
+
});
|
|
920
|
+
}, [availableProducts, (_b = field.options) === null || _b === void 0 ? void 0 : _b.productConditions, responses, showProductSelection, enduser, form]);
|
|
921
|
+
// Automatically deselect products that become hidden
|
|
922
|
+
(0, react_1.useEffect)(function () {
|
|
923
|
+
var visibleProductIds = visibleProducts.map(function (p) { return p._id; });
|
|
924
|
+
setSelectedProducts(function (prev) { return prev.filter(function (id) { return visibleProductIds.includes(id); }); });
|
|
925
|
+
}, [visibleProducts]);
|
|
878
926
|
var fetchRef = (0, react_1.useRef)(false);
|
|
879
927
|
(0, react_1.useEffect)(function () {
|
|
880
928
|
var _a, _b, _d;
|
|
@@ -940,6 +988,16 @@ var StripeInput = function (_a) {
|
|
|
940
988
|
}, 0)
|
|
941
989
|
: 0 // Will be calculated by existing Stripe flow when not in selection mode
|
|
942
990
|
);
|
|
991
|
+
// Emit GTM purchase event once when success screen is displayed
|
|
992
|
+
var purchaseEmittedRef = (0, react_1.useRef)(false);
|
|
993
|
+
(0, react_1.useEffect)(function () {
|
|
994
|
+
var _a;
|
|
995
|
+
// Only emit for actual purchases (chargeImmediately), not for saving card details
|
|
996
|
+
if (value && ((_a = field.options) === null || _a === void 0 ? void 0 : _a.chargeImmediately) && !purchaseEmittedRef.current) {
|
|
997
|
+
emitStripePurchaseEvent(field, cost);
|
|
998
|
+
purchaseEmittedRef.current = true;
|
|
999
|
+
}
|
|
1000
|
+
}, [value, field, cost]);
|
|
943
1001
|
// Handle product selection step
|
|
944
1002
|
if (showProductSelection) {
|
|
945
1003
|
if (error) {
|
|
@@ -948,7 +1006,11 @@ var StripeInput = function (_a) {
|
|
|
948
1006
|
if (loadingProducts) {
|
|
949
1007
|
return ((0, jsx_runtime_1.jsxs)(material_1.Grid, __assign({ container: true, direction: "column", spacing: 2, alignItems: "center" }, { children: [(0, jsx_runtime_1.jsx)(material_1.Grid, __assign({ item: true }, { children: (0, jsx_runtime_1.jsx)(LinearProgress_1.default, {}) })), (0, jsx_runtime_1.jsx)(material_1.Grid, __assign({ item: true }, { children: (0, jsx_runtime_1.jsx)(material_1.Typography, { children: "Loading product information..." }) }))] })));
|
|
950
1008
|
}
|
|
951
|
-
|
|
1009
|
+
// Check if all products are filtered out by conditional logic
|
|
1010
|
+
if (visibleProducts.length === 0) {
|
|
1011
|
+
return ((0, jsx_runtime_1.jsx)(material_1.Grid, __assign({ container: true, direction: "column", spacing: 2, alignItems: "center" }, { children: (0, jsx_runtime_1.jsx)(material_1.Grid, __assign({ item: true }, { children: (0, jsx_runtime_1.jsx)(material_1.Typography, __assign({ color: "textSecondary" }, { children: "No products are available based on your previous answers." })) })) })));
|
|
1012
|
+
}
|
|
1013
|
+
var isSingleSelection_1 = ((_d = field.options) === null || _d === void 0 ? void 0 : _d.radio) === true;
|
|
952
1014
|
var handleProductSelection_1 = function (productId) {
|
|
953
1015
|
if (isSingleSelection_1) {
|
|
954
1016
|
setSelectedProducts([productId]);
|
|
@@ -985,7 +1047,7 @@ var StripeInput = function (_a) {
|
|
|
985
1047
|
}
|
|
986
1048
|
});
|
|
987
1049
|
};
|
|
988
|
-
return ((0, jsx_runtime_1.jsxs)(material_1.Grid, __assign({ container: true, direction: "column", spacing: 2 }, { children: [(0, jsx_runtime_1.jsx)(material_1.Grid, __assign({ item: true }, { children: (0, jsx_runtime_1.jsxs)(material_1.Typography, __assign({ variant: "h6" }, { children: ["Select Product", isSingleSelection_1 ? '' : 's'] })) })),
|
|
1050
|
+
return ((0, jsx_runtime_1.jsxs)(material_1.Grid, __assign({ container: true, direction: "column", spacing: 2 }, { children: [(0, jsx_runtime_1.jsx)(material_1.Grid, __assign({ item: true }, { children: (0, jsx_runtime_1.jsxs)(material_1.Typography, __assign({ variant: "h6" }, { children: ["Select Product", isSingleSelection_1 ? '' : 's'] })) })), visibleProducts.map(function (product) {
|
|
989
1051
|
var _a, _b, _d;
|
|
990
1052
|
// Use real-time Stripe pricing if available, fallback to Tellescope pricing
|
|
991
1053
|
var price = product.currentPrice || product.cost;
|
|
@@ -998,7 +1060,7 @@ var StripeInput = function (_a) {
|
|
|
998
1060
|
return ((0, jsx_runtime_1.jsx)(material_1.Typography, __assign({ color: "error" }, { children: error })));
|
|
999
1061
|
}
|
|
1000
1062
|
if (value) {
|
|
1001
|
-
return ((0, jsx_runtime_1.jsxs)(material_1.Grid, __assign({ container: true, alignItems: "center", wrap: "nowrap" }, { children: [(0, jsx_runtime_1.jsx)(icons_material_1.CheckCircleOutline, { color: "success" }), (0, jsx_runtime_1.jsx)(material_1.Typography, __assign({ sx: { ml: 1, fontSize: 20 } }, { children: ((
|
|
1063
|
+
return ((0, jsx_runtime_1.jsxs)(material_1.Grid, __assign({ container: true, alignItems: "center", wrap: "nowrap" }, { children: [(0, jsx_runtime_1.jsx)(icons_material_1.CheckCircleOutline, { color: "success" }), (0, jsx_runtime_1.jsx)(material_1.Typography, __assign({ sx: { ml: 1, fontSize: 20 } }, { children: ((_e = field.options) === null || _e === void 0 ? void 0 : _e.chargeImmediately) ? 'Your purchase was successful' : "Your payment details have been saved!" }))] })));
|
|
1002
1064
|
}
|
|
1003
1065
|
if (!(clientSecret && stripePromise))
|
|
1004
1066
|
return (0, jsx_runtime_1.jsx)(LinearProgress_1.default, {});
|
|
@@ -1106,26 +1168,30 @@ exports.DropdownInput = DropdownInput;
|
|
|
1106
1168
|
var choicesForDatabase = {};
|
|
1107
1169
|
var preventRefetch = {};
|
|
1108
1170
|
var LOAD_CHOICES_LIMIT = 500;
|
|
1171
|
+
var MIN_SEARCH_CHARS = 3;
|
|
1172
|
+
var SEARCH_DEBOUNCE_MS = 300;
|
|
1109
1173
|
var useDatabaseChoices = function (_a) {
|
|
1110
|
-
var _b, _d
|
|
1111
|
-
var
|
|
1174
|
+
var _b, _d;
|
|
1175
|
+
var _e = _a.databaseId, databaseId = _e === void 0 ? '' : _e, field = _a.field, otherAnswers = _a.otherAnswers, _f = _a.searchQuery, searchQuery = _f === void 0 ? '' : _f;
|
|
1112
1176
|
var session = (0, __1.useResolvedSession)();
|
|
1113
|
-
var
|
|
1114
|
-
|
|
1177
|
+
var _g = (0, react_1.useState)(false), isSearching = _g[0], setIsSearching = _g[1];
|
|
1178
|
+
var _h = (0, react_1.useState)([]), searchResults = _h[0], setSearchResults = _h[1];
|
|
1179
|
+
var _j = (0, react_1.useState)(false), initialLoadComplete = _j[0], setInitialLoadComplete = _j[1];
|
|
1180
|
+
var debouncedSearch = useDebounce(searchQuery, SEARCH_DEBOUNCE_MS);
|
|
1181
|
+
// Load initial page on mount (only once, not recursively)
|
|
1182
|
+
var initialLoadRef = (0, react_1.useRef)(false);
|
|
1115
1183
|
(0, react_1.useEffect)(function () {
|
|
1116
|
-
var _a, _b, _d
|
|
1117
|
-
if (
|
|
1184
|
+
var _a, _b, _d;
|
|
1185
|
+
if (initialLoadRef.current)
|
|
1118
1186
|
return;
|
|
1119
|
-
if (
|
|
1120
|
-
|
|
1121
|
-
var choices = (_d = (_b = choicesForDatabase[databaseId]) === null || _b === void 0 ? void 0 : _b.records) !== null && _d !== void 0 ? _d : [];
|
|
1122
|
-
var lastId = (_e = choicesForDatabase[databaseId]) === null || _e === void 0 ? void 0 : _e.lastId;
|
|
1123
|
-
if (preventRefetch[databaseId + field.id + lastId])
|
|
1187
|
+
if (((_a = choicesForDatabase[databaseId]) === null || _a === void 0 ? void 0 : _a.done) || ((_d = (_b = choicesForDatabase[databaseId]) === null || _b === void 0 ? void 0 : _b.records) === null || _d === void 0 ? void 0 : _d.length)) {
|
|
1188
|
+
setInitialLoadComplete(true);
|
|
1124
1189
|
return;
|
|
1125
|
-
|
|
1190
|
+
}
|
|
1191
|
+
initialLoadRef.current = true;
|
|
1192
|
+
preventRefetch[databaseId + field.id] = true;
|
|
1126
1193
|
session.api.form_fields.load_choices_from_database({
|
|
1127
1194
|
fieldId: field.id,
|
|
1128
|
-
lastId: lastId,
|
|
1129
1195
|
limit: LOAD_CHOICES_LIMIT,
|
|
1130
1196
|
databaseId: databaseId,
|
|
1131
1197
|
})
|
|
@@ -1134,17 +1200,67 @@ var useDatabaseChoices = function (_a) {
|
|
|
1134
1200
|
var newChoices = _a.choices;
|
|
1135
1201
|
choicesForDatabase[databaseId] = {
|
|
1136
1202
|
lastId: (_b = newChoices === null || newChoices === void 0 ? void 0 : newChoices[newChoices.length - 1]) === null || _b === void 0 ? void 0 : _b.id,
|
|
1137
|
-
records:
|
|
1203
|
+
records: newChoices.sort(function (c1, c2) { return (label_for_database_record(field, c1)
|
|
1138
1204
|
.localeCompare(label_for_database_record(field, c2))); }),
|
|
1139
|
-
done:
|
|
1205
|
+
done: true, // Don't load more pages automatically
|
|
1140
1206
|
};
|
|
1141
|
-
|
|
1207
|
+
setInitialLoadComplete(true);
|
|
1208
|
+
})
|
|
1209
|
+
.catch(function (err) {
|
|
1210
|
+
console.error(err);
|
|
1211
|
+
preventRefetch[databaseId + field.id] = false;
|
|
1212
|
+
setInitialLoadComplete(true); // Mark as complete even on error to avoid infinite loading
|
|
1213
|
+
});
|
|
1214
|
+
}, [session, field, databaseId]);
|
|
1215
|
+
// Handle debounced search
|
|
1216
|
+
var searchRef = (0, react_1.useRef)(debouncedSearch);
|
|
1217
|
+
(0, react_1.useEffect)(function () {
|
|
1218
|
+
var trimmed = debouncedSearch.trim();
|
|
1219
|
+
// If search is cleared, return to initial results
|
|
1220
|
+
if (!trimmed) {
|
|
1221
|
+
setSearchResults([]);
|
|
1222
|
+
setIsSearching(false);
|
|
1223
|
+
searchRef.current = debouncedSearch;
|
|
1224
|
+
return;
|
|
1225
|
+
}
|
|
1226
|
+
// Only search if meets minimum character requirement
|
|
1227
|
+
if (trimmed.length < MIN_SEARCH_CHARS) {
|
|
1228
|
+
setSearchResults([]);
|
|
1229
|
+
setIsSearching(false);
|
|
1230
|
+
return;
|
|
1231
|
+
}
|
|
1232
|
+
// Avoid duplicate searches
|
|
1233
|
+
if (searchRef.current === debouncedSearch)
|
|
1234
|
+
return;
|
|
1235
|
+
searchRef.current = debouncedSearch;
|
|
1236
|
+
setIsSearching(true);
|
|
1237
|
+
session.api.form_fields.load_choices_from_database({
|
|
1238
|
+
fieldId: field.id,
|
|
1239
|
+
limit: LOAD_CHOICES_LIMIT,
|
|
1240
|
+
databaseId: databaseId,
|
|
1241
|
+
search: trimmed,
|
|
1242
|
+
})
|
|
1243
|
+
.then(function (_a) {
|
|
1244
|
+
var _b, _d;
|
|
1245
|
+
var newChoices = _a.choices;
|
|
1246
|
+
// Add search results to the same cache as initial load
|
|
1247
|
+
// This ensures selected search results persist even after search is cleared
|
|
1248
|
+
var existingRecords = (_d = (_b = choicesForDatabase[databaseId]) === null || _b === void 0 ? void 0 : _b.records) !== null && _d !== void 0 ? _d : [];
|
|
1249
|
+
var existingIds = new Set(existingRecords.map(function (r) { return r.id; }));
|
|
1250
|
+
var uniqueNewChoices = newChoices.filter(function (c) { return !existingIds.has(c.id); });
|
|
1251
|
+
if (uniqueNewChoices.length > 0) {
|
|
1252
|
+
choicesForDatabase[databaseId] = __assign(__assign({}, choicesForDatabase[databaseId]), { records: __spreadArray(__spreadArray([], existingRecords, true), uniqueNewChoices, true).sort(function (c1, c2) { return (label_for_database_record(field, c1)
|
|
1253
|
+
.localeCompare(label_for_database_record(field, c2))); }), done: true });
|
|
1254
|
+
}
|
|
1255
|
+
setSearchResults(newChoices.sort(function (c1, c2) { return (label_for_database_record(field, c1)
|
|
1256
|
+
.localeCompare(label_for_database_record(field, c2))); }));
|
|
1257
|
+
setIsSearching(false);
|
|
1142
1258
|
})
|
|
1143
1259
|
.catch(function (err) {
|
|
1144
1260
|
console.error(err);
|
|
1145
|
-
|
|
1261
|
+
setIsSearching(false);
|
|
1146
1262
|
});
|
|
1147
|
-
}, [session, field, databaseId,
|
|
1263
|
+
}, [session, field, databaseId, debouncedSearch]);
|
|
1148
1264
|
var addChoice = (0, react_1.useCallback)(function (record) {
|
|
1149
1265
|
if (!choicesForDatabase[databaseId]) {
|
|
1150
1266
|
choicesForDatabase[databaseId] = {
|
|
@@ -1154,10 +1270,15 @@ var useDatabaseChoices = function (_a) {
|
|
|
1154
1270
|
}
|
|
1155
1271
|
choicesForDatabase[databaseId].records.push(record);
|
|
1156
1272
|
}, [choicesForDatabase, databaseId]);
|
|
1273
|
+
// Use search results if searching, otherwise use cached initial results
|
|
1274
|
+
var activeChoices = debouncedSearch.trim().length >= MIN_SEARCH_CHARS
|
|
1275
|
+
? searchResults
|
|
1276
|
+
: ((_d = (_b = choicesForDatabase[databaseId]) === null || _b === void 0 ? void 0 : _b.records) !== null && _d !== void 0 ? _d : []);
|
|
1157
1277
|
return {
|
|
1158
1278
|
addChoice: addChoice,
|
|
1159
|
-
doneLoading:
|
|
1160
|
-
|
|
1279
|
+
doneLoading: initialLoadComplete,
|
|
1280
|
+
isSearching: isSearching,
|
|
1281
|
+
choices: __spreadArray(__spreadArray([], activeChoices, true), (otherAnswers || []).map(function (v) {
|
|
1161
1282
|
var _a;
|
|
1162
1283
|
return ({
|
|
1163
1284
|
id: v.text,
|
|
@@ -1165,7 +1286,7 @@ var useDatabaseChoices = function (_a) {
|
|
|
1165
1286
|
values: [{ label: ((_a = field.options) === null || _a === void 0 ? void 0 : _a.databaseLabel) || '', type: 'Text', value: v.text }],
|
|
1166
1287
|
});
|
|
1167
1288
|
}), true),
|
|
1168
|
-
|
|
1289
|
+
minSearchChars: MIN_SEARCH_CHARS,
|
|
1169
1290
|
};
|
|
1170
1291
|
};
|
|
1171
1292
|
var label_for_database_record = function (field, record) {
|
|
@@ -1197,13 +1318,15 @@ var get_other_answers = function (_value, typing) {
|
|
|
1197
1318
|
};
|
|
1198
1319
|
var DatabaseSelectInput = function (_a) {
|
|
1199
1320
|
var _b, _d, _e, _f, _g, _h, _j, _k;
|
|
1200
|
-
var AddToDatabase = _a.AddToDatabase, field = _a.field, _value = _a.value, onChange = _a.onChange, onDatabaseSelect = _a.onDatabaseSelect, responses = _a.responses, size = _a.size, disabled = _a.disabled, enduser = _a.enduser;
|
|
1321
|
+
var AddToDatabase = _a.AddToDatabase, field = _a.field, _value = _a.value, onChange = _a.onChange, onDatabaseSelect = _a.onDatabaseSelect, responses = _a.responses, size = _a.size, disabled = _a.disabled, enduser = _a.enduser, inputProps = _a.inputProps;
|
|
1201
1322
|
var _l = (0, react_1.useState)(''), typing = _l[0], setTyping = _l[1];
|
|
1202
|
-
var _m =
|
|
1323
|
+
var _m = (0, react_1.useState)(false), open = _m[0], setOpen = _m[1];
|
|
1324
|
+
var _o = useDatabaseChoices({
|
|
1203
1325
|
databaseId: (_b = field.options) === null || _b === void 0 ? void 0 : _b.databaseId,
|
|
1204
1326
|
field: field,
|
|
1205
1327
|
otherAnswers: get_other_answers(_value, ((_d = field === null || field === void 0 ? void 0 : field.options) === null || _d === void 0 ? void 0 : _d.other) ? typing : undefined),
|
|
1206
|
-
|
|
1328
|
+
searchQuery: typing,
|
|
1329
|
+
}), addChoice = _o.addChoice, choices = _o.choices, doneLoading = _o.doneLoading, isSearching = _o.isSearching, minSearchChars = _o.minSearchChars;
|
|
1207
1330
|
var value = react_1.default.useMemo(function () {
|
|
1208
1331
|
var _a, _b;
|
|
1209
1332
|
try {
|
|
@@ -1307,9 +1430,13 @@ var DatabaseSelectInput = function (_a) {
|
|
|
1307
1430
|
}
|
|
1308
1431
|
return filtered;
|
|
1309
1432
|
}, [field, stateFilteredChoices]);
|
|
1433
|
+
// Show placeholder when typing but below minimum search characters
|
|
1434
|
+
var charsNeeded = typing.trim().length > 0 && typing.trim().length < minSearchChars
|
|
1435
|
+
? minSearchChars - typing.trim().length
|
|
1436
|
+
: 0;
|
|
1310
1437
|
if (!doneLoading)
|
|
1311
1438
|
return (0, jsx_runtime_1.jsx)(LinearProgress_1.default, {});
|
|
1312
|
-
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(material_1.Autocomplete, { id: field.id, freeSolo: false, size: size, componentsProps: { popper: { sx: { wordBreak: "break-word" } } }, options: filteredChoices, multiple: true, getOptionLabel: function (o) { return (Array.isArray(o) // edge case
|
|
1439
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(material_1.Autocomplete, { id: field.id, freeSolo: false, size: size, componentsProps: { popper: { sx: { wordBreak: "break-word" } } }, options: filteredChoices, multiple: true, loading: isSearching, open: open, onOpen: function () { return setOpen(true); }, onClose: function () { return setOpen(false); }, getOptionLabel: function (o) { return (Array.isArray(o) // edge case
|
|
1313
1440
|
? ''
|
|
1314
1441
|
: label_for_database_record(field, o)); }, value: value, disabled: disabled, onChange: function (_, v) {
|
|
1315
1442
|
var _a, _b, _d, _e, _f;
|
|
@@ -1332,7 +1459,7 @@ var DatabaseSelectInput = function (_a) {
|
|
|
1332
1459
|
recordId: (_f = (_e = v[v.length - 1]) === null || _e === void 0 ? void 0 : _e.id) !== null && _f !== void 0 ? _f : '',
|
|
1333
1460
|
text: label_for_database_record(field, v[v.length - 1]),
|
|
1334
1461
|
}]), field.id);
|
|
1335
|
-
}, inputValue: typing, onInputChange: function (e, v) { return e && setTyping(v); }, renderInput: function (params) { return (0, jsx_runtime_1.jsx)(material_1.TextField, __assign({}, params, { InputProps: __assign(__assign({}, params.InputProps), { sx: exports.defaultInputProps.sx }) })); },
|
|
1462
|
+
}, inputValue: typing, onInputChange: function (e, v) { return e && setTyping(v); }, renderInput: function (params) { return ((0, jsx_runtime_1.jsx)(material_1.TextField, __assign({}, params, { InputProps: __assign(__assign({}, params.InputProps), { sx: (inputProps || exports.defaultInputProps).sx, endAdornment: ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [isSearching ? (0, jsx_runtime_1.jsx)(material_1.CircularProgress, { color: "inherit", size: 20 }) : null, params.InputProps.endAdornment] })) }), placeholder: charsNeeded > 0 ? "Type ".concat(charsNeeded, " more character").concat(charsNeeded > 1 ? 's' : '', " to search...") : undefined, helperText: charsNeeded > 0 ? "Type ".concat(charsNeeded, " more character").concat(charsNeeded > 1 ? 's' : '', " to search") : undefined }))); },
|
|
1336
1463
|
// use custom Chip to ensure very long entries break properly (whitespace: normal)
|
|
1337
1464
|
renderTags: function (value, getTagProps) {
|
|
1338
1465
|
return value.map(function (value, index) { return ((0, jsx_runtime_1.jsx)(material_1.Chip, __assign({ label: (0, jsx_runtime_1.jsx)(material_1.Typography, __assign({ style: { whiteSpace: 'normal' } }, { children: Array.isArray(value) ? '' : label_for_database_record(field, value) })) }, getTagProps({ index: index }), { sx: { height: "100%", py: 0.5 } }))); });
|
|
@@ -1713,7 +1840,7 @@ var contact_is_valid = function (e) {
|
|
|
1713
1840
|
exports.contact_is_valid = contact_is_valid;
|
|
1714
1841
|
var RelatedContactsInput = function (_a) {
|
|
1715
1842
|
var _b, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _w, _x;
|
|
1716
|
-
var field = _a.field, _value = _a.value, onChange = _a.onChange, props = __rest(_a, ["field", "value", "onChange"]);
|
|
1843
|
+
var field = _a.field, _value = _a.value, onChange = _a.onChange, parentError = _a.error, props = __rest(_a, ["field", "value", "onChange", "error"]);
|
|
1717
1844
|
// safeguard against any rogue values like empty string
|
|
1718
1845
|
var value = Array.isArray(_value) ? _value : [];
|
|
1719
1846
|
var _y = (0, react_1.useState)(value.length === 1 ? 0 : -1), editing = _y[0], setEditing = _y[1];
|
|
@@ -1732,7 +1859,7 @@ var RelatedContactsInput = function (_a) {
|
|
|
1732
1859
|
(0, jsx_runtime_1.jsx)(material_1.Grid, __assign({ item: true, xs: 4 }, { children: (0, jsx_runtime_1.jsx)(material_1.TextField, { label: "Last Name", size: "small", fullWidth: true, InputProps: exports.defaultInputProps, value: lname, onChange: function (e) { return onChange(value.map(function (v, i) { return i === editing ? __assign(__assign({}, v), { lname: e.target.value }) : v; }), field.id); } }) })), (0, jsx_runtime_1.jsx)(material_1.Grid, __assign({ item: true, xs: 4 }, { children: (0, jsx_runtime_1.jsx)(StringSelector, { options: ((_j = (_h = field.options) === null || _h === void 0 ? void 0 : _h.relatedContactTypes) === null || _j === void 0 ? void 0 : _j.length) ? field.options.relatedContactTypes : constants_1.RELATIONSHIP_TYPES, label: "Relationship", size: "small", disabled: ((_l = (_k = field === null || field === void 0 ? void 0 : field.options) === null || _k === void 0 ? void 0 : _k.relatedContactTypes) === null || _l === void 0 ? void 0 : _l.length) === 1, value: (_o = (_m = relationships === null || relationships === void 0 ? void 0 : relationships[0]) === null || _m === void 0 ? void 0 : _m.type) !== null && _o !== void 0 ? _o : '', onChange: function (type) { return onChange(value.map(function (v, i) { return i === editing ? __assign(__assign({}, v), { relationships: [{ type: type, id: '' /* to be filled on server-side */ }] }) : v; }), field.id); } }) }))] })) })), (0, jsx_runtime_1.jsx)(material_1.Grid, __assign({ item: true }, { children: (0, jsx_runtime_1.jsxs)(material_1.Grid, __assign({ container: true, alignItems: "center", wrap: "nowrap", spacing: 1 }, { children: [!((_q = (_p = field.options) === null || _p === void 0 ? void 0 : _p.hiddenDefaultFields) === null || _q === void 0 ? void 0 : _q.includes('Date of Birth')) &&
|
|
1733
1860
|
(0, jsx_runtime_1.jsx)(material_1.Grid, __assign({ item: true, xs: 4 }, { children: (0, jsx_runtime_1.jsx)(exports.DateStringInput, { value: dateOfBirth, field: __assign(__assign({}, field), { isOptional: true }), size: "small", label: "Date of Birth (MM-DD-YYYY)", onChange: function (dateOfBirth) { return onChange(value.map(function (v, i) { return i === editing ? __assign(__assign({}, v), { dateOfBirth: dateOfBirth }) : v; }), field.id); } }) })), !((_s = (_r = field.options) === null || _r === void 0 ? void 0 : _r.hiddenDefaultFields) === null || _s === void 0 ? void 0 : _s.includes('Email')) &&
|
|
1734
1861
|
(0, jsx_runtime_1.jsx)(material_1.Grid, __assign({ item: true, xs: 4 }, { children: (0, jsx_runtime_1.jsx)(material_1.TextField, { label: "Email", size: "small", fullWidth: true, type: "email", InputProps: exports.defaultInputProps, value: email, onChange: function (e) { return onChange(value.map(function (v, i) { return i === editing ? __assign(__assign({}, v), { email: e.target.value }) : v; }), field.id); } }) })), !((_u = (_t = field.options) === null || _t === void 0 ? void 0 : _t.hiddenDefaultFields) === null || _u === void 0 ? void 0 : _u.includes('Phone Number')) &&
|
|
1735
|
-
(0, jsx_runtime_1.jsx)(material_1.Grid, __assign({ item: true, xs: 4 }, { children: (0, jsx_runtime_1.jsx)(material_1.TextField, { label: "Phone Number", size: "small", fullWidth: true, InputProps: exports.defaultInputProps, value: phone, onChange: function (e) { return onChange(value.map(function (v, i) { return i === editing ? __assign(__assign({}, v), { phone: e.target.value }) : v; }), field.id); } }) }))] })) })), (((_w = field.options) === null || _w === void 0 ? void 0 : _w.tableChoices) || []).length > 0 &&
|
|
1862
|
+
(0, jsx_runtime_1.jsx)(material_1.Grid, __assign({ item: true, xs: 4 }, { children: (0, jsx_runtime_1.jsx)(material_1.TextField, { label: "Phone Number", size: "small", fullWidth: true, InputProps: exports.defaultInputProps, value: phone, onChange: function (e) { return onChange(value.map(function (v, i) { return i === editing ? __assign(__assign({}, v), { phone: e.target.value.trim() }) : v; }), field.id); } }) }))] })) })), (((_w = field.options) === null || _w === void 0 ? void 0 : _w.tableChoices) || []).length > 0 &&
|
|
1736
1863
|
(0, jsx_runtime_1.jsx)(material_1.Grid, __assign({ item: true }, { children: (0, jsx_runtime_1.jsx)(material_1.Grid, __assign({ container: true, spacing: 1 }, { children: (((_x = field.options) === null || _x === void 0 ? void 0 : _x.tableChoices) || []).map(function (_a, i) {
|
|
1737
1864
|
var info = _a.info, label = _a.label, type = _a.type;
|
|
1738
1865
|
return ((0, jsx_runtime_1.jsx)(material_1.Grid, __assign({ item: true, xs: 6 }, { children: type === 'Text'
|
|
@@ -1752,7 +1879,7 @@ var RelatedContactsInput = function (_a) {
|
|
|
1752
1879
|
return i === editing ? __assign(__assign({}, v), { fields: __assign(__assign({}, fields_1), (_a = {}, _a[label] = e.target.value, _a)) }) : v;
|
|
1753
1880
|
}), field.id); } }, { children: [(0, jsx_runtime_1.jsx)(material_1.MenuItem, __assign({ value: "" }, { children: (0, jsx_runtime_1.jsx)("em", { children: "None" }) })), info.choices.map(function (c) { return ((0, jsx_runtime_1.jsx)(material_1.MenuItem, __assign({ value: c }, { children: c }), c)); })] }))] })))
|
|
1754
1881
|
: null }), i));
|
|
1755
|
-
}) })) })), (0, jsx_runtime_1.jsx)(material_1.Grid, __assign({ item: true, sx: { my: 0.75 } }, { children: (0, jsx_runtime_1.jsx)(material_1.Button, __assign({ variant: "outlined", onClick: function () { return setEditing(-1); }, size: "small" }, { children: "Save Contact" })) })), errorMessage &&
|
|
1882
|
+
}) })) })), (0, jsx_runtime_1.jsx)(material_1.Grid, __assign({ item: true, sx: { my: 0.75 } }, { children: (0, jsx_runtime_1.jsx)(material_1.Button, __assign({ variant: "outlined", onClick: function () { return setEditing(-1); }, size: "small", disabled: !!errorMessage || !!parentError }, { children: "Save Contact" })) })), errorMessage &&
|
|
1756
1883
|
(0, jsx_runtime_1.jsx)(material_1.Grid, __assign({ item: true }, { children: (0, jsx_runtime_1.jsx)(material_1.Typography, __assign({ color: "error" }, { children: errorMessage })) }))] })));
|
|
1757
1884
|
}
|
|
1758
1885
|
return ((0, jsx_runtime_1.jsxs)(material_1.Grid, __assign({ container: true, direction: "column", spacing: 1 }, { children: [(0, jsx_runtime_1.jsx)(material_1.Grid, __assign({ item: true }, { children: value.map(function (contact, i) { return ((0, jsx_runtime_1.jsx)(material_1.Grid, __assign({ item: true }, { children: (0, jsx_runtime_1.jsxs)(material_1.Grid, __assign({ container: true, alignItems: "center", justifyContent: "space-between", wrap: "nowrap", spacing: 1 }, { children: [(0, jsx_runtime_1.jsx)(material_1.Grid, __assign({ item: true }, { children: (0, jsx_runtime_1.jsxs)(material_1.Grid, __assign({ container: true, alignItems: "center" }, { children: [(0, jsx_runtime_1.jsx)(__1.IconButton, __assign({ onClick: function () { return setEditing(i); }, color: "primary", size: "small" }, { children: (0, jsx_runtime_1.jsx)(icons_material_1.Edit, {}) })), (0, jsx_runtime_1.jsx)(material_1.Typography, __assign({ noWrap: true }, { children: (0, utilities_1.user_display_name)(contact) || "Unnamed Contact ".concat(i + 1) }))] })) })), (0, jsx_runtime_1.jsx)(material_1.Grid, __assign({ item: true }, { children: (0, jsx_runtime_1.jsx)(__1.LabeledIconButton, { Icon: icons_material_1.Delete, label: "Remove", onClick: function () { return onChange(value.filter(function (v, _i) { return i !== _i; }), field.id); } }) }))] })) }), i)); }) })), (0, jsx_runtime_1.jsx)(material_1.Grid, __assign({ item: true }, { children: (0, jsx_runtime_1.jsx)(material_1.Button, __assign({ variant: "contained", onClick: handleAddContact }, { children: "Add Contact" })) }))] })));
|