@cxpinsight/react-native 0.5.0 → 0.8.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.
- package/CHANGELOG.md +53 -0
- package/README.md +23 -0
- package/lib/CXPinsight.d.ts +33 -3
- package/lib/CXPinsight.d.ts.map +1 -1
- package/lib/CXPinsight.js +57 -3
- package/lib/CXPinsight.js.map +1 -1
- package/lib/CXPinsightProvider.d.ts.map +1 -1
- package/lib/CXPinsightProvider.js +13 -1
- package/lib/CXPinsightProvider.js.map +1 -1
- package/lib/consent/ConsentBanner.d.ts +18 -0
- package/lib/consent/ConsentBanner.d.ts.map +1 -0
- package/lib/consent/ConsentBanner.js +90 -0
- package/lib/consent/ConsentBanner.js.map +1 -0
- package/lib/core/consent.d.ts +16 -1
- package/lib/core/consent.d.ts.map +1 -1
- package/lib/core/consent.js +79 -32
- package/lib/core/consent.js.map +1 -1
- package/lib/index.d.ts +4 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +5 -1
- package/lib/index.js.map +1 -1
- package/lib/survey/SurveyModal.d.ts.map +1 -1
- package/lib/survey/SurveyModal.js +94 -55
- package/lib/survey/SurveyModal.js.map +1 -1
- package/lib/survey/pagesFromV1.d.ts.map +1 -1
- package/lib/survey/pagesFromV1.js +30 -76
- package/lib/survey/pagesFromV1.js.map +1 -1
- package/lib/survey/questions/FileUploadQuestion.d.ts +32 -0
- package/lib/survey/questions/FileUploadQuestion.d.ts.map +1 -0
- package/lib/survey/questions/FileUploadQuestion.js +105 -0
- package/lib/survey/questions/FileUploadQuestion.js.map +1 -0
- package/lib/survey/questions/SignatureQuestion.d.ts +15 -0
- package/lib/survey/questions/SignatureQuestion.d.ts.map +1 -0
- package/lib/survey/questions/SignatureQuestion.js +138 -0
- package/lib/survey/questions/SignatureQuestion.js.map +1 -0
- package/lib/survey/validate.d.ts.map +1 -1
- package/lib/survey/validate.js +13 -163
- package/lib/survey/validate.js.map +1 -1
- package/lib/survey/voiceParsers.d.ts +12 -42
- package/lib/survey/voiceParsers.d.ts.map +1 -1
- package/lib/survey/voiceParsers.js +60 -284
- package/lib/survey/voiceParsers.js.map +1 -1
- package/lib/types.d.ts +24 -0
- package/lib/types.d.ts.map +1 -1
- package/lib/types.js.map +1 -1
- package/package.json +12 -4
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ConsentBanner = ConsentBanner;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
/**
|
|
6
|
+
* The consent banner — "Accept all / Customize", and behind Customize a toggle
|
|
7
|
+
* per category.
|
|
8
|
+
*
|
|
9
|
+
* The same two views and the same categories as the web SDK's, so a company
|
|
10
|
+
* shipping both channels asks its users one question, not two versions of one
|
|
11
|
+
* question. Only the rendering differs, which is the whole point of keeping the
|
|
12
|
+
* decision rules in core/consent.ts.
|
|
13
|
+
*
|
|
14
|
+
* OPT-IN, per app: `consentBanner: true` in init(). Most apps have their own
|
|
15
|
+
* privacy flow and call CXPinsight.consent(...) from it, and showing ours
|
|
16
|
+
* unasked would give their users two.
|
|
17
|
+
*/
|
|
18
|
+
const react_1 = require("react");
|
|
19
|
+
const react_native_1 = require("react-native");
|
|
20
|
+
const consent_1 = require("../core/consent");
|
|
21
|
+
/** What each category means in the user's terms, not ours. */
|
|
22
|
+
const COPY = {
|
|
23
|
+
analytics: {
|
|
24
|
+
label: 'Product analytics',
|
|
25
|
+
hint: 'Which screens you open and what you tap, so we can see what needs fixing.',
|
|
26
|
+
},
|
|
27
|
+
recording: {
|
|
28
|
+
label: 'Session replay',
|
|
29
|
+
hint: 'A timeline of your visit. Anything you type is hidden.',
|
|
30
|
+
},
|
|
31
|
+
network: {
|
|
32
|
+
label: 'Performance',
|
|
33
|
+
hint: 'How long our own requests take. Never their contents.',
|
|
34
|
+
},
|
|
35
|
+
surveys: {
|
|
36
|
+
label: 'Feedback surveys',
|
|
37
|
+
hint: 'Lets us ask you a short question now and then.',
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
const all = (granted) => consent_1.CONSENT_CATEGORIES.reduce((m, c) => { m[c] = granted; return m; }, {});
|
|
41
|
+
function ConsentBanner({ visible, accent = '#2b6cb0', text = {}, onDecide }) {
|
|
42
|
+
const [customizing, setCustomizing] = (0, react_1.useState)(false);
|
|
43
|
+
const [choices, setChoices] = (0, react_1.useState)(() => all(false));
|
|
44
|
+
// Recomputed only when the accent changes, because StyleSheet.create on every
|
|
45
|
+
// render defeats the caching it exists for.
|
|
46
|
+
const s = (0, react_1.useMemo)(() => styles(accent), [accent]);
|
|
47
|
+
const decide = (map) => {
|
|
48
|
+
setCustomizing(false);
|
|
49
|
+
setChoices(all(false));
|
|
50
|
+
onDecide(map);
|
|
51
|
+
};
|
|
52
|
+
return ((0, jsx_runtime_1.jsx)(react_native_1.Modal, { visible: visible, transparent: true, animationType: "fade",
|
|
53
|
+
// Android's back button declines rather than dismissing. A banner that
|
|
54
|
+
// can be waved away without answering collects data from someone who
|
|
55
|
+
// never agreed, so the dismissal has to mean something and "no" is the
|
|
56
|
+
// only safe reading.
|
|
57
|
+
onRequestClose: () => decide(all(false)), children: (0, jsx_runtime_1.jsx)(react_native_1.View, { style: s.backdrop, children: (0, jsx_runtime_1.jsx)(react_native_1.View, { style: s.panel, accessibilityViewIsModal: true, accessibilityRole: "alert", children: !customizing ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(react_native_1.Text, { style: s.title, children: text.title ?? 'Your privacy choices' }), (0, jsx_runtime_1.jsx)(react_native_1.Text, { style: s.body, children: text.body ?? 'We collect a little information to understand how the app is used. You choose what.' }), (0, jsx_runtime_1.jsxs)(react_native_1.View, { style: s.actions, children: [(0, jsx_runtime_1.jsx)(react_native_1.Pressable, { style: [s.btn, s.accept], accessibilityRole: "button", onPress: () => decide(all(true)), children: (0, jsx_runtime_1.jsx)(react_native_1.Text, { style: s.acceptLabel, children: text.acceptAll ?? 'Accept all' }) }), (0, jsx_runtime_1.jsx)(react_native_1.Pressable, { style: [s.btn, s.secondary], accessibilityRole: "button", onPress: () => setCustomizing(true), children: (0, jsx_runtime_1.jsx)(react_native_1.Text, { style: s.secondaryLabel, children: text.customize ?? 'Customize' }) })] })] })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(react_native_1.Text, { style: s.title, children: text.customizeTitle ?? 'Choose what to allow' }), (0, jsx_runtime_1.jsx)(react_native_1.ScrollView, { style: s.list, children: consent_1.CONSENT_CATEGORIES.map((c) => ((0, jsx_runtime_1.jsxs)(react_native_1.View, { style: s.row, children: [(0, jsx_runtime_1.jsxs)(react_native_1.View, { style: s.rowText, children: [(0, jsx_runtime_1.jsx)(react_native_1.Text, { style: s.label, children: COPY[c].label }), (0, jsx_runtime_1.jsx)(react_native_1.Text, { style: s.hint, children: COPY[c].hint })] }), (0, jsx_runtime_1.jsx)(react_native_1.Switch, { value: choices[c], onValueChange: (v) => setChoices((prev) => ({ ...prev, [c]: v })), accessibilityLabel: COPY[c].label, trackColor: { true: accent, false: '#cfcfcf' } })] }, c))) }), (0, jsx_runtime_1.jsxs)(react_native_1.View, { style: s.actions, children: [(0, jsx_runtime_1.jsx)(react_native_1.Pressable, { style: [s.btn, s.accept], accessibilityRole: "button", onPress: () => decide(choices), children: (0, jsx_runtime_1.jsx)(react_native_1.Text, { style: s.acceptLabel, children: text.save ?? 'Save choices' }) }), (0, jsx_runtime_1.jsx)(react_native_1.Pressable, { style: [s.btn, s.secondary], accessibilityRole: "button", onPress: () => decide(all(false)), children: (0, jsx_runtime_1.jsx)(react_native_1.Text, { style: s.secondaryLabel, children: text.rejectAll ?? 'Reject all' }) })] })] })) }) }) }));
|
|
58
|
+
}
|
|
59
|
+
const styles = (accent) => react_native_1.StyleSheet.create({
|
|
60
|
+
backdrop: {
|
|
61
|
+
flex: 1, backgroundColor: 'rgba(0,0,0,0.35)',
|
|
62
|
+
justifyContent: 'flex-end', padding: 16,
|
|
63
|
+
},
|
|
64
|
+
panel: {
|
|
65
|
+
backgroundColor: '#fff', borderRadius: 14, padding: 22,
|
|
66
|
+
maxHeight: '86%',
|
|
67
|
+
shadowColor: '#000', shadowOpacity: 0.28, shadowRadius: 20, shadowOffset: { width: 0, height: 12 },
|
|
68
|
+
elevation: 12,
|
|
69
|
+
},
|
|
70
|
+
title: { fontSize: 18, fontWeight: '600', color: '#1a1a1a', marginBottom: 8 },
|
|
71
|
+
body: { fontSize: 14, lineHeight: 21, color: '#5c5c5c', marginBottom: 18 },
|
|
72
|
+
actions: { flexDirection: 'row', flexWrap: 'wrap', gap: 10 },
|
|
73
|
+
btn: {
|
|
74
|
+
flexGrow: 1, flexBasis: 130, paddingVertical: 12, paddingHorizontal: 18,
|
|
75
|
+
borderRadius: 8, alignItems: 'center', borderWidth: 1, borderColor: 'transparent',
|
|
76
|
+
},
|
|
77
|
+
accept: { backgroundColor: accent },
|
|
78
|
+
acceptLabel: { color: '#fff', fontWeight: '600', fontSize: 15 },
|
|
79
|
+
secondary: { backgroundColor: 'transparent', borderColor: '#d4d4d4' },
|
|
80
|
+
secondaryLabel: { color: '#1a1a1a', fontWeight: '600', fontSize: 15 },
|
|
81
|
+
list: { marginBottom: 18 },
|
|
82
|
+
row: {
|
|
83
|
+
flexDirection: 'row', alignItems: 'flex-start', gap: 12,
|
|
84
|
+
paddingVertical: 12, borderBottomWidth: react_native_1.StyleSheet.hairlineWidth, borderBottomColor: '#ececec',
|
|
85
|
+
},
|
|
86
|
+
rowText: { flex: 1 },
|
|
87
|
+
label: { fontSize: 14.5, fontWeight: '600', color: '#1a1a1a' },
|
|
88
|
+
hint: { fontSize: 13, lineHeight: 19, color: '#5c5c5c', marginTop: 2 },
|
|
89
|
+
});
|
|
90
|
+
//# sourceMappingURL=ConsentBanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConsentBanner.js","sourceRoot":"","sources":["../../src/consent/ConsentBanner.tsx"],"names":[],"mappings":"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"}
|
package/lib/core/consent.d.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
export type ConsentState = 'granted' | 'denied' | null;
|
|
2
|
+
/** Only what this SDK can actually do. Same list as the web SDK. */
|
|
3
|
+
export declare const CONSENT_CATEGORIES: readonly ['analytics', 'recording', 'network', 'surveys'];
|
|
4
|
+
export type ConsentCategory = (typeof CONSENT_CATEGORIES)[number];
|
|
5
|
+
export type ConsentMap = Record<ConsentCategory, boolean>;
|
|
2
6
|
/** Restore any prior decision. Call once during init, before capture starts. */
|
|
3
7
|
export declare function initConsent(requireConsent?: boolean): Promise<void>;
|
|
4
8
|
/** Notified when consent flips, so the SDK can start or stop capture. */
|
|
@@ -9,11 +13,22 @@ export declare function setConsentHandler(cb: ((granted: boolean) => void) | nul
|
|
|
9
13
|
* An explicit denial always wins, even when requireConsent is off — a host that
|
|
10
14
|
* calls optOut() means it, regardless of how the SDK was configured.
|
|
11
15
|
*/
|
|
16
|
+
export declare function mayUse(category: ConsentCategory): boolean;
|
|
17
|
+
/** Kept for call sites that predate categories; analytics is the broadest. */
|
|
12
18
|
export declare function mayCapture(): boolean;
|
|
13
19
|
/** True when events should be held rather than sent (awaiting a decision). */
|
|
14
20
|
export declare function isPending(): boolean;
|
|
15
21
|
export declare function consentRequired(): boolean;
|
|
16
|
-
|
|
22
|
+
/**
|
|
23
|
+
* The per-category decision, or null when the visitor has not decided.
|
|
24
|
+
*
|
|
25
|
+
* Null rather than an all-false map: "declined" and "not asked yet" need
|
|
26
|
+
* different UI, and a banner that cannot tell them apart re-prompts someone who
|
|
27
|
+
* already said no.
|
|
28
|
+
*/
|
|
29
|
+
export declare function getConsent(): ConsentMap | null;
|
|
30
|
+
/** Set some categories, leaving the rest as they are. Unknown keys are ignored. */
|
|
31
|
+
export declare function setConsent(partial: Partial<ConsentMap>): void;
|
|
17
32
|
export declare function grantConsent(): void;
|
|
18
33
|
export declare function revokeConsent(): void;
|
|
19
34
|
/** Reset to "no decision yet" — used by CXPinsight.reset(). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consent.d.ts","sourceRoot":"","sources":["../../src/core/consent.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"consent.d.ts","sourceRoot":"","sources":["../../src/core/consent.ts"],"names":[],"mappings":"AAsCA,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,QAAQ,GAAG,IAAI,CAAC;AAEvD,oEAAoE;AACpE,eAAO,MAAM,kBAAkB,YAAI,WAAW,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,CAAU,CAAC;AAC5F,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAClE,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;AAS1D,gFAAgF;AAChF,wBAAsB,WAAW,CAAC,cAAc,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAczE;AAED,yEAAyE;AACzE,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI,CAE/E;AAED;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,QAAQ,EAAE,eAAe,GAAG,OAAO,CAIzD;AAED,8EAA8E;AAC9E,wBAAgB,UAAU,IAAI,OAAO,CAEpC;AAED,8EAA8E;AAC9E,wBAAgB,SAAS,IAAI,OAAO,CAEnC;AAED,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,IAAI,UAAU,GAAG,IAAI,CAM9C;AAED,mFAAmF;AACnF,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,IAAI,CAiB7D;AAED,wBAAgB,YAAY,IAAI,IAAI,CAAqC;AACzE,wBAAgB,aAAa,IAAI,IAAI,CAAsC;AAE3E,+DAA+D;AAC/D,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAGlD"}
|
package/lib/core/consent.js
CHANGED
|
@@ -33,12 +33,15 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.CONSENT_CATEGORIES = void 0;
|
|
36
37
|
exports.initConsent = initConsent;
|
|
37
38
|
exports.setConsentHandler = setConsentHandler;
|
|
39
|
+
exports.mayUse = mayUse;
|
|
38
40
|
exports.mayCapture = mayCapture;
|
|
39
41
|
exports.isPending = isPending;
|
|
40
42
|
exports.consentRequired = consentRequired;
|
|
41
43
|
exports.getConsent = getConsent;
|
|
44
|
+
exports.setConsent = setConsent;
|
|
42
45
|
exports.grantConsent = grantConsent;
|
|
43
46
|
exports.revokeConsent = revokeConsent;
|
|
44
47
|
exports.clearConsent = clearConsent;
|
|
@@ -60,23 +63,48 @@ exports.clearConsent = clearConsent;
|
|
|
60
63
|
* `requireConsent` is opt-in and defaults to false, so nothing changes for an
|
|
61
64
|
* app that does not set it. With it on, capture stays OFF until the host grants.
|
|
62
65
|
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
66
|
+
* Consent is PER CATEGORY, on both channels. "Do you accept tracking?" is not
|
|
67
|
+
* one question: someone happy to be counted may not be happy to be recorded,
|
|
68
|
+
* and a single yes/no makes them refuse everything to refuse one thing.
|
|
69
|
+
*
|
|
70
|
+
* analytics screens, taps, scroll depth, custom events, lifecycle
|
|
71
|
+
* recording session replay (the mobile timeline recorder)
|
|
72
|
+
* network the shape of outbound requests: method, host, path, status
|
|
73
|
+
* surveys showing a survey and collecting the response
|
|
74
|
+
*
|
|
75
|
+
* There is deliberately no "push notifications" category — neither SDK has that
|
|
76
|
+
* capability, and a toggle for something that does nothing promises what the
|
|
77
|
+
* product cannot deliver.
|
|
78
|
+
*
|
|
79
|
+
* Analytics events are still BUFFERED rather than dropped while a decision is
|
|
80
|
+
* pending, so a visitor who accepts a few seconds in keeps the opening of their
|
|
81
|
+
* session. Revoking clears that buffer instead of sending it.
|
|
69
82
|
*/
|
|
70
83
|
const types_1 = require("../types");
|
|
71
84
|
const storage = __importStar(require("./storage"));
|
|
85
|
+
/** Only what this SDK can actually do. Same list as the web SDK. */
|
|
86
|
+
exports.CONSENT_CATEGORIES = ['analytics', 'recording', 'network', 'surveys'];
|
|
72
87
|
let required = false;
|
|
73
|
-
let
|
|
88
|
+
let categories = null;
|
|
74
89
|
let onChange = null;
|
|
90
|
+
const allCategories = (granted) => exports.CONSENT_CATEGORIES.reduce((m, c) => { m[c] = granted; return m; }, {});
|
|
75
91
|
/** Restore any prior decision. Call once during init, before capture starts. */
|
|
76
92
|
async function initConsent(requireConsent) {
|
|
77
93
|
required = requireConsent === true;
|
|
78
94
|
const saved = await storage.get(types_1.STORAGE_KEYS.CONSENT);
|
|
79
|
-
|
|
95
|
+
// Migrate the old scalar. A device storing 'granted' had consented to
|
|
96
|
+
// everything the SDK then did; reading it as undecided would re-prompt
|
|
97
|
+
// someone who has already answered, and as denied would stop collection they
|
|
98
|
+
// agreed to.
|
|
99
|
+
if (saved === 'granted' || saved === 'denied') {
|
|
100
|
+
categories = allCategories(saved === 'granted');
|
|
101
|
+
}
|
|
102
|
+
else if (saved && typeof saved === 'object') {
|
|
103
|
+
categories = saved;
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
categories = null;
|
|
107
|
+
}
|
|
80
108
|
}
|
|
81
109
|
/** Notified when consent flips, so the SDK can start or stop capture. */
|
|
82
110
|
function setConsentHandler(cb) {
|
|
@@ -88,44 +116,63 @@ function setConsentHandler(cb) {
|
|
|
88
116
|
* An explicit denial always wins, even when requireConsent is off — a host that
|
|
89
117
|
* calls optOut() means it, regardless of how the SDK was configured.
|
|
90
118
|
*/
|
|
119
|
+
function mayUse(category) {
|
|
120
|
+
const decided = categories?.[category];
|
|
121
|
+
if (typeof decided === 'boolean')
|
|
122
|
+
return decided;
|
|
123
|
+
return !required;
|
|
124
|
+
}
|
|
125
|
+
/** Kept for call sites that predate categories; analytics is the broadest. */
|
|
91
126
|
function mayCapture() {
|
|
92
|
-
|
|
93
|
-
return false;
|
|
94
|
-
return !required || state === 'granted';
|
|
127
|
+
return mayUse('analytics');
|
|
95
128
|
}
|
|
96
129
|
/** True when events should be held rather than sent (awaiting a decision). */
|
|
97
130
|
function isPending() {
|
|
98
|
-
return required &&
|
|
131
|
+
return required && categories === null;
|
|
99
132
|
}
|
|
100
133
|
function consentRequired() {
|
|
101
134
|
return required;
|
|
102
135
|
}
|
|
136
|
+
/**
|
|
137
|
+
* The per-category decision, or null when the visitor has not decided.
|
|
138
|
+
*
|
|
139
|
+
* Null rather than an all-false map: "declined" and "not asked yet" need
|
|
140
|
+
* different UI, and a banner that cannot tell them apart re-prompts someone who
|
|
141
|
+
* already said no.
|
|
142
|
+
*/
|
|
103
143
|
function getConsent() {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
return;
|
|
109
|
-
|
|
110
|
-
void storage.set(types_1.STORAGE_KEYS.CONSENT, state);
|
|
111
|
-
try {
|
|
112
|
-
onChange?.(true);
|
|
113
|
-
}
|
|
114
|
-
catch { /* host callback must not break the gate */ }
|
|
144
|
+
if (!categories)
|
|
145
|
+
return null;
|
|
146
|
+
return exports.CONSENT_CATEGORIES.reduce((m, c) => {
|
|
147
|
+
m[c] = categories?.[c] === true;
|
|
148
|
+
return m;
|
|
149
|
+
}, {});
|
|
115
150
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
151
|
+
/** Set some categories, leaving the rest as they are. Unknown keys are ignored. */
|
|
152
|
+
function setConsent(partial) {
|
|
153
|
+
const next = exports.CONSENT_CATEGORIES.reduce((m, c) => {
|
|
154
|
+
m[c] = typeof partial[c] === 'boolean' ? partial[c] : categories?.[c] === true;
|
|
155
|
+
return m;
|
|
156
|
+
}, {});
|
|
157
|
+
// Notify when the MAP changed, not when a summary boolean did. Comparing a
|
|
158
|
+
// single boolean would miss turning recording off while analytics stays on —
|
|
159
|
+
// the exact case categories exist for — while comparing nothing at all would
|
|
160
|
+
// fire on a repeated grant that changed nothing.
|
|
161
|
+
const changed = !categories || exports.CONSENT_CATEGORIES.some((c) => (categories?.[c] === true) !== next[c]);
|
|
162
|
+
categories = next;
|
|
163
|
+
void storage.set(types_1.STORAGE_KEYS.CONSENT, next);
|
|
164
|
+
if (changed) {
|
|
165
|
+
try {
|
|
166
|
+
onChange?.(exports.CONSENT_CATEGORIES.some((c) => next[c]));
|
|
167
|
+
}
|
|
168
|
+
catch { /* a host callback must not break the gate */ }
|
|
123
169
|
}
|
|
124
|
-
catch { /* best-effort */ }
|
|
125
170
|
}
|
|
171
|
+
function grantConsent() { setConsent(allCategories(true)); }
|
|
172
|
+
function revokeConsent() { setConsent(allCategories(false)); }
|
|
126
173
|
/** Reset to "no decision yet" — used by CXPinsight.reset(). */
|
|
127
174
|
async function clearConsent() {
|
|
128
|
-
|
|
175
|
+
categories = null;
|
|
129
176
|
await storage.remove(types_1.STORAGE_KEYS.CONSENT);
|
|
130
177
|
}
|
|
131
178
|
//# sourceMappingURL=consent.js.map
|
package/lib/core/consent.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consent.js","sourceRoot":"","sources":["../../src/core/consent.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"consent.js","sourceRoot":"","sources":["../../src/core/consent.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,oCAAwC;AACxC,MAAY,OAAO,sCAAkB;AAIrC,oEAAoE;AACvD,QAAA,kBAAkB,GAAG,CAAC,WAAW,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,CAAU,CAAC;AAI5F,IAAI,QAAQ,GAAG,KAAK,CAAC;AACrB,IAAI,UAAU,GAA+B,IAAI,CAAC;AAClD,IAAI,QAAQ,GAAwC,IAAI,CAAC;AAEzD,MAAM,aAAa,GAAG,CAAC,OAAgB,EAAc,EAAE,CACrD,QAAA,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,EAAgB,CAAC,CAAC;AAEvF,gFAAgF;AACzE,KAAK,sBAAsB,cAAwB;IACxD,QAAQ,GAAG,cAAc,KAAK,IAAI,CAAC;IACnC,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,GAAG,CAAU,oBAAY,CAAC,OAAO,CAAC,CAAC;IAC/D,sEAAsE;IACtE,uEAAuE;IACvE,6EAA6E;IAC7E,aAAa;IACb,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9C,UAAU,GAAG,aAAa,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC;IAClD,CAAC;SAAM,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9C,UAAU,GAAG,KAA4B,CAAC;IAC5C,CAAC;SAAM,CAAC;QACN,UAAU,GAAG,IAAI,CAAC;IACpB,CAAC;AACH,CAAC;AAED,yEAAyE;AACzE,2BAAkC,EAAuC;IACvE,QAAQ,GAAG,EAAE,CAAC;AAChB,CAAC;AAED;;;;;GAKG;AACH,gBAAuB,QAAyB;IAC9C,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC,QAAQ,CAAC,CAAC;IACvC,IAAI,OAAO,OAAO,KAAK,SAAS;QAAE,OAAO,OAAO,CAAC;IACjD,OAAO,CAAC,QAAQ,CAAC;AACnB,CAAC;AAED,8EAA8E;AAC9E;IACE,OAAO,MAAM,CAAC,WAAW,CAAC,CAAC;AAC7B,CAAC;AAED,8EAA8E;AAC9E;IACE,OAAO,QAAQ,IAAI,UAAU,KAAK,IAAI,CAAC;AACzC,CAAC;AAED;IACE,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;;GAMG;AACH;IACE,IAAI,CAAC,UAAU;QAAE,OAAO,IAAI,CAAC;IAC7B,OAAO,QAAA,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACxC,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;QAChC,OAAO,CAAC,CAAC;IACX,CAAC,EAAE,EAAgB,CAAC,CAAC;AACvB,CAAC;AAED,mFAAmF;AACnF,oBAA2B,OAA4B;IACrD,MAAM,IAAI,GAAG,QAAA,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QAC9C,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,OAAO,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAY,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;QAC1F,OAAO,CAAC,CAAC;IACX,CAAC,EAAE,EAAgB,CAAC,CAAC;IACrB,2EAA2E;IAC3E,6EAA6E;IAC7E,6EAA6E;IAC7E,iDAAiD;IACjD,MAAM,OAAO,GAAG,CAAC,UAAU,IAAI,QAAA,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACtG,UAAU,GAAG,IAAI,CAAC;IAClB,KAAK,OAAO,CAAC,GAAG,CAAC,oBAAY,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC7C,IAAI,OAAO,EAAE,CAAC;QACZ,IAAI,CAAC;YACH,QAAQ,EAAE,CAAC,QAAA,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACtD,CAAC;QAAC,MAAM,CAAC,CAAC,6CAA6C,CAAC,CAAC;IAC3D,CAAC;AACH,CAAC;AAED,0BAAuC,UAAU,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AACzE,2BAAwC,UAAU,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAE3E,+DAA+D;AACxD,KAAK;IACV,UAAU,GAAG,IAAI,CAAC;IAClB,MAAM,OAAO,CAAC,MAAM,CAAC,oBAAY,CAAC,OAAO,CAAC,CAAC;AAC7C,CAAC"}
|
package/lib/index.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
export { CXPinsight } from './CXPinsight';
|
|
2
2
|
export { CXPinsightProvider } from './CXPinsightProvider';
|
|
3
|
+
export { ConsentBanner } from './consent/ConsentBanner';
|
|
4
|
+
export type { ConsentBannerProps, ConsentBannerText } from './consent/ConsentBanner';
|
|
5
|
+
export { CONSENT_CATEGORIES } from './core/consent';
|
|
6
|
+
export type { ConsentCategory, ConsentMap } from './core/consent';
|
|
3
7
|
export type { CXPinsightConfig, UserIdentity, CXPinsightCallbacks, FunnelStepOptions, ExperimentOptions, ConversionOptions, } from './types';
|
|
4
8
|
export { useCXPElement } from './setup/useCXPElement';
|
|
5
9
|
export type { ElementInfo, StoredElementIdentifier } from './setup/ElementIdentifier';
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,YAAY,EACV,gBAAgB,EAChB,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,YAAY,EAAE,WAAW,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACtF,YAAY,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACrF,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,YAAY,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAClE,YAAY,EACV,gBAAgB,EAChB,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,YAAY,EAAE,WAAW,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACtF,YAAY,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC"}
|
package/lib/index.js
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.useCXPElement = exports.CXPinsightProvider = exports.CXPinsight = void 0;
|
|
3
|
+
exports.useCXPElement = exports.CONSENT_CATEGORIES = exports.ConsentBanner = exports.CXPinsightProvider = exports.CXPinsight = void 0;
|
|
4
4
|
var CXPinsight_1 = require("./CXPinsight");
|
|
5
5
|
Object.defineProperty(exports, "CXPinsight", { enumerable: true, get: function () { return CXPinsight_1.CXPinsight; } });
|
|
6
6
|
var CXPinsightProvider_1 = require("./CXPinsightProvider");
|
|
7
7
|
Object.defineProperty(exports, "CXPinsightProvider", { enumerable: true, get: function () { return CXPinsightProvider_1.CXPinsightProvider; } });
|
|
8
|
+
var ConsentBanner_1 = require("./consent/ConsentBanner");
|
|
9
|
+
Object.defineProperty(exports, "ConsentBanner", { enumerable: true, get: function () { return ConsentBanner_1.ConsentBanner; } });
|
|
10
|
+
var consent_1 = require("./core/consent");
|
|
11
|
+
Object.defineProperty(exports, "CONSENT_CATEGORIES", { enumerable: true, get: function () { return consent_1.CONSENT_CATEGORIES; } });
|
|
8
12
|
// Setup mode exports
|
|
9
13
|
var useCXPElement_1 = require("./setup/useCXPElement");
|
|
10
14
|
Object.defineProperty(exports, "useCXPElement", { enumerable: true, get: function () { return useCXPElement_1.useCXPElement; } });
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,2CAA0C;AAAjC,wGAAA,UAAU,OAAA;AACnB,2DAA0D;AAAjD,wHAAA,kBAAkB,OAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,2CAA0C;AAAjC,wGAAA,UAAU,OAAA;AACnB,2DAA0D;AAAjD,wHAAA,kBAAkB,OAAA;AAC3B,yDAAwD;AAA/C,8GAAA,aAAa,OAAA;AAEtB,0CAAoD;AAA3C,6GAAA,kBAAkB,OAAA;AAW3B,qBAAqB;AACrB,uDAAsD;AAA7C,8GAAA,aAAa,OAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SurveyModal.d.ts","sourceRoot":"","sources":["../../src/survey/SurveyModal.tsx"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,gBAAgB,EAAkB,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"SurveyModal.d.ts","sourceRoot":"","sources":["../../src/survey/SurveyModal.tsx"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,gBAAgB,EAAkB,MAAM,UAAU,CAAC;AAiCjE,UAAU,KAAK;IACb,MAAM,EAAE,gBAAgB,CAAC;IACzB,OAAO,EAAE,OAAO,CAAC;IAIjB,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IACjF,SAAS,EAAE,MAAM,IAAI,CAAC;CACvB;AAgCD,wBAAgB,WAAW,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,KAAK,2CAuqD1E"}
|
|
@@ -51,6 +51,8 @@ const MatrixDropdownQuestion_1 = require("./questions/MatrixDropdownQuestion");
|
|
|
51
51
|
const MatrixDynamicQuestion_1 = require("./questions/MatrixDynamicQuestion");
|
|
52
52
|
const PanelDynamicQuestion_1 = require("./questions/PanelDynamicQuestion");
|
|
53
53
|
const DateQuestion_1 = require("./questions/DateQuestion");
|
|
54
|
+
const SignatureQuestion_1 = require("./questions/SignatureQuestion");
|
|
55
|
+
const FileUploadQuestion_1 = require("./questions/FileUploadQuestion");
|
|
54
56
|
const MultiTextQuestion_1 = require("./questions/MultiTextQuestion");
|
|
55
57
|
const expressionEval_1 = require("./expressionEval");
|
|
56
58
|
const interpolate_1 = require("./interpolate");
|
|
@@ -500,18 +502,35 @@ function SurveyModal({ survey, visible, onSubmit, onDismiss }) {
|
|
|
500
502
|
function renderQuestion(question) {
|
|
501
503
|
const key = question.id || question.name;
|
|
502
504
|
const val = responses[key];
|
|
503
|
-
|
|
504
|
-
|
|
505
|
+
// Shown when a question type needs an optional peer the host app did not
|
|
506
|
+
// install. Not a failure: the respondent can still finish the survey on a
|
|
507
|
+
// device that has it, which is better than a blank space or a crash.
|
|
508
|
+
const renderDesktopHint = () => ((0, jsx_runtime_1.jsx)(react_native_1.Text, { style: styles.desktopHint, children: "This question type isn't supported on mobile yet \u2014 please complete this survey on desktop." }));
|
|
509
|
+
// ── Question renderers ────────────────────────────────────────────
|
|
510
|
+
//
|
|
511
|
+
// One entry per question type instead of a switch, matching the shape the
|
|
512
|
+
// React renderer uses: adding a type is one entry plus one view component.
|
|
513
|
+
//
|
|
514
|
+
// Built inside the component ON PURPOSE. Every body below closes over
|
|
515
|
+
// `responses`, `updateResponse`, `contract`, `styles`, `t` and the two
|
|
516
|
+
// local helpers; hoisting the table to module scope would mean threading
|
|
517
|
+
// all of that through a context object and rewriting 290 lines of JSX to
|
|
518
|
+
// read from it — a large edit with nothing to verify it against. Rebuilding
|
|
519
|
+
// an object literal per render costs nothing measurable next to the tree it
|
|
520
|
+
// returns.
|
|
521
|
+
const RENDERERS = {
|
|
522
|
+
'nps': () => {
|
|
505
523
|
return ((0, jsx_runtime_1.jsx)(NPSQuestion_1.NPSQuestion, { value: val ?? null, onChange: (v) => updateResponse(key, v), contract: contract }));
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
case 'ces':
|
|
524
|
+
},
|
|
525
|
+
'rating': () => {
|
|
509
526
|
return ((0, jsx_runtime_1.jsx)(CSATQuestion_1.CSATQuestion, { value: val ?? null, onChange: (v) => updateResponse(key, v), maxStars: question.maxValue ?? question.rateMax ?? 5, contract: contract }));
|
|
510
|
-
|
|
527
|
+
},
|
|
528
|
+
'csat': () => RENDERERS['rating'](),
|
|
529
|
+
'ces': () => RENDERERS['rating'](),
|
|
530
|
+
'comment': () => {
|
|
511
531
|
return ((0, jsx_runtime_1.jsx)(TextQuestion_1.TextQuestion, { value: val ?? '', onChange: (v) => updateResponse(key, v), placeholder: question.placeholder, multiline: true, contract: contract }));
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
case 'number':
|
|
532
|
+
},
|
|
533
|
+
'text': () => {
|
|
515
534
|
return ((0, jsx_runtime_1.jsx)(TextQuestion_1.TextQuestion, { value: val ?? '', onChange: (v) => updateResponse(key, v), placeholder: question.placeholder, multiline: false, contract: contract,
|
|
516
535
|
// Two shapes reach here and both must produce the right keyboard:
|
|
517
536
|
// the legacy one where the TYPE is 'email'/'number', and the current
|
|
@@ -519,20 +538,26 @@ function SurveyModal({ survey, visible, onSubmit, onDismiss }) {
|
|
|
519
538
|
// "Answer format" picker. Fall back to the type so the legacy shape
|
|
520
539
|
// keeps working.
|
|
521
540
|
inputType: question.inputType ?? (question.type === 'text' ? undefined : question.type) }));
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
541
|
+
},
|
|
542
|
+
'email': () => RENDERERS['text'](),
|
|
543
|
+
'number': () => RENDERERS['text'](),
|
|
544
|
+
'radio': () => {
|
|
525
545
|
return ((0, jsx_runtime_1.jsx)(MultipleChoiceQuestion_1.MultipleChoiceQuestion, { choices: normalizeChoices(question), value: val ?? '', onChange: (v) => updateResponse(key, v), mode: "radiogroup", isRtl: isRtl, contract: contract }));
|
|
526
|
-
|
|
546
|
+
},
|
|
547
|
+
'radiogroup': () => RENDERERS['radio'](),
|
|
548
|
+
'dropdown': () => RENDERERS['radio'](),
|
|
549
|
+
'checkbox': () => {
|
|
527
550
|
return ((0, jsx_runtime_1.jsx)(MultipleChoiceQuestion_1.MultipleChoiceQuestion, { choices: normalizeChoices(question), value: val ?? [], onChange: (v) => updateResponse(key, v), mode: "checkbox", isRtl: isRtl, contract: contract }));
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
case 'yesno':
|
|
551
|
+
},
|
|
552
|
+
'binary': () => {
|
|
531
553
|
return ((0, jsx_runtime_1.jsx)(MultipleChoiceQuestion_1.MultipleChoiceQuestion, { choices: [
|
|
532
554
|
{ value: 'true', text: question.yesLabel || 'Yes' },
|
|
533
555
|
{ value: 'false', text: question.noLabel || 'No' },
|
|
534
556
|
], value: val ?? '', onChange: (v) => updateResponse(key, v), mode: "radiogroup", isRtl: isRtl, contract: contract }));
|
|
535
|
-
|
|
557
|
+
},
|
|
558
|
+
'boolean': () => RENDERERS['binary'](),
|
|
559
|
+
'yesno': () => RENDERERS['binary'](),
|
|
560
|
+
'date': () => {
|
|
536
561
|
// Native picker when the optional peer dep
|
|
537
562
|
// (@react-native-community/datetimepicker) is installed; falls
|
|
538
563
|
// back to a text input with an ISO-8601 hint otherwise. Consumer
|
|
@@ -542,18 +567,18 @@ function SurveyModal({ survey, visible, onSubmit, onDismiss }) {
|
|
|
542
567
|
return ((0, jsx_runtime_1.jsx)(DateQuestion_1.DateQuestion, { value: val ?? '', onChange: (v) => updateResponse(key, v), min: typeof question.min === 'string' ? question.min : undefined, max: typeof question.max === 'string' ? question.max : undefined, placeholder: question.placeholder || 'Select a date', contract: contract, isRtl: isRtl }));
|
|
543
568
|
}
|
|
544
569
|
return ((0, jsx_runtime_1.jsx)(TextQuestion_1.TextQuestion, { value: val ?? '', onChange: (v) => updateResponse(key, v), placeholder: question.placeholder || 'YYYY-MM-DD', multiline: false, contract: contract }));
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
case 'description':
|
|
548
|
-
case 'pageBreak':
|
|
549
|
-
case 'expression':
|
|
570
|
+
},
|
|
571
|
+
'content': () => {
|
|
550
572
|
// Display-only — the title/description block already covers
|
|
551
573
|
// section headers and static content. pageBreak items are
|
|
552
574
|
// filtered out of pages before we get here; guarding anyway.
|
|
553
575
|
return null;
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
576
|
+
},
|
|
577
|
+
'html': () => RENDERERS['content'](),
|
|
578
|
+
'description': () => RENDERERS['content'](),
|
|
579
|
+
'pageBreak': () => RENDERERS['content'](),
|
|
580
|
+
'expression': () => RENDERERS['content'](),
|
|
581
|
+
'multiText': () => {
|
|
557
582
|
// Multi-text — labeled sub-inputs, one answer object keyed by item
|
|
558
583
|
// id. Matches the web renderer's MultiTextRenderer shape. Note the
|
|
559
584
|
// builder emits camelCase 'multiText'; the earlier snake_case-only
|
|
@@ -561,10 +586,13 @@ function SurveyModal({ survey, visible, onSubmit, onDismiss }) {
|
|
|
561
586
|
// raw (unlike SurveyModal's other type-family switches which lower).
|
|
562
587
|
const items = (Array.isArray(question.items) ? question.items : []);
|
|
563
588
|
return ((0, jsx_runtime_1.jsx)(MultiTextQuestion_1.MultiTextQuestion, { items: items, value: val ?? {}, onChange: (v) => updateResponse(key, v), contract: contract, isRtl: isRtl }));
|
|
564
|
-
}
|
|
565
|
-
|
|
589
|
+
},
|
|
590
|
+
'multi_text': () => RENDERERS['multiText'](),
|
|
591
|
+
'multipletext': () => RENDERERS['multiText'](),
|
|
592
|
+
'ranking': () => {
|
|
566
593
|
return ((0, jsx_runtime_1.jsx)(RankingQuestion_1.RankingQuestion, { options: question.options || [], value: val ?? null, onChange: (v) => updateResponse(key, v), contract: contract, isRtl: isRtl }));
|
|
567
|
-
|
|
594
|
+
},
|
|
595
|
+
'matrix': () => {
|
|
568
596
|
return ((0, jsx_runtime_1.jsx)(MatrixQuestion_1.MatrixQuestion
|
|
569
597
|
/* SurveyQuestion.rows is typed `number` (textarea line count) and
|
|
570
598
|
`columns` isn't on the type at all — matrix was never modelled on
|
|
@@ -580,50 +608,61 @@ function SurveyModal({ survey, visible, onSubmit, onDismiss }) {
|
|
|
580
608
|
them through a shape-specific view; MatrixQuestion guards with
|
|
581
609
|
Array.isArray, so a wrong shape renders empty rather than throws. */
|
|
582
610
|
rows: (question.rows) || [], columns: (question.columns) || [], value: val ?? null, onChange: (v) => updateResponse(key, v), contract: contract, isRtl: isRtl }));
|
|
583
|
-
|
|
611
|
+
},
|
|
612
|
+
'image': () => {
|
|
584
613
|
// Display-only; collects no answer. Reads through a shape-specific view
|
|
585
614
|
// because these fields aren't on SurveyQuestion (same gap as matrix).
|
|
586
615
|
const img = question;
|
|
587
616
|
return ((0, jsx_runtime_1.jsx)(ImageQuestion_1.ImageQuestion, { imageUrl: img.imageUrl, alt: img.alt, width: img.width, height: img.height, contract: contract }));
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
case 'imagePicker': {
|
|
617
|
+
},
|
|
618
|
+
'image_picker': () => {
|
|
591
619
|
const ip = question;
|
|
592
620
|
return ((0, jsx_runtime_1.jsx)(ImagePickerQuestion_1.ImagePickerQuestion, { options: question.options || [], multiSelect: ip.multiSelect, value: val, onChange: (v) => updateResponse(key, v), contract: contract, isRtl: isRtl }));
|
|
593
|
-
}
|
|
621
|
+
},
|
|
622
|
+
'imagePicker': () => RENDERERS['image_picker'](),
|
|
594
623
|
// The server's canonical names are camelCase (survey.routes.js:77-81).
|
|
595
624
|
// Only the snake_case aliases were listed here, so these cases never
|
|
596
625
|
// matched a real payload and fell through to `default` — which renders a
|
|
597
626
|
// TEXT INPUT. A signature or file-upload question showed a text box the
|
|
598
627
|
// respondent could type anything into. Both spellings are handled now.
|
|
599
|
-
|
|
600
|
-
case 'matrix_dropdown': {
|
|
628
|
+
'matrixDropdown': () => {
|
|
601
629
|
const md = question;
|
|
602
630
|
return ((0, jsx_runtime_1.jsx)(MatrixDropdownQuestion_1.MatrixDropdownQuestion, { rows: md.rows || [], columns: md.columns || [], value: val ?? null, onChange: (v) => updateResponse(key, v), contract: contract, isRtl: isRtl }));
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
|
|
631
|
+
},
|
|
632
|
+
'matrix_dropdown': () => RENDERERS['matrixDropdown'](),
|
|
633
|
+
'matrixDynamic': () => {
|
|
606
634
|
const mdy = question;
|
|
607
635
|
return ((0, jsx_runtime_1.jsx)(MatrixDynamicQuestion_1.MatrixDynamicQuestion, { columns: mdy.columns || [], value: val ?? null, onChange: (v) => updateResponse(key, v), minRowCount: mdy.minRowCount, maxRowCount: mdy.maxRowCount, addRowLabel: mdy.addRowLabel, removeRowLabel: mdy.removeRowLabel, contract: contract, isRtl: isRtl }));
|
|
608
|
-
}
|
|
609
|
-
|
|
610
|
-
|
|
636
|
+
},
|
|
637
|
+
'matrix_dynamic': () => RENDERERS['matrixDynamic'](),
|
|
638
|
+
'panelDynamic': () => {
|
|
611
639
|
const pd = question;
|
|
612
640
|
return ((0, jsx_runtime_1.jsx)(PanelDynamicQuestion_1.PanelDynamicQuestion, { template: pd.template, value: val ?? null, onChange: (v) => updateResponse(key, v), minPanelCount: pd.minPanelCount, maxPanelCount: pd.maxPanelCount, addPanelLabel: pd.addPanelLabel, removePanelLabel: pd.removePanelLabel, panelTitle: pd.panelTitle, contract: contract, isRtl: isRtl }));
|
|
613
|
-
}
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
641
|
+
},
|
|
642
|
+
'panel_dynamic': () => RENDERERS['panelDynamic'](),
|
|
643
|
+
// Both of these need an optional peer. When the host app installed it
|
|
644
|
+
// they render for real; when it did not, they fall back to the hint that
|
|
645
|
+
// used to be the ONLY behaviour. Nothing is forced into an app's bundle
|
|
646
|
+
// for a question type it never asks.
|
|
647
|
+
'signature': () => {
|
|
648
|
+
if (!(0, SignatureQuestion_1.isSignatureAvailable)())
|
|
649
|
+
return renderDesktopHint();
|
|
650
|
+
return ((0, jsx_runtime_1.jsx)(SignatureQuestion_1.SignatureQuestion, { value: val ?? '', onChange: (v) => updateResponse(key, v || null), contract: contract }));
|
|
651
|
+
},
|
|
652
|
+
'fileUpload': () => {
|
|
653
|
+
if (!(0, FileUploadQuestion_1.isFileUploadAvailable)())
|
|
654
|
+
return renderDesktopHint();
|
|
655
|
+
return ((0, jsx_runtime_1.jsx)(FileUploadQuestion_1.FileUploadQuestion, { value: val ?? null, onChange: (v) => updateResponse(key, v), multiple: question.multiple === true, accept: question.accept, contract: contract }));
|
|
656
|
+
},
|
|
657
|
+
'file_upload': () => RENDERERS['fileUpload'](),
|
|
658
|
+
};
|
|
659
|
+
const renderUnsupported = () => {
|
|
660
|
+
// Unknown type — fall back to a text input so the survey
|
|
661
|
+
// still runs. Server-side validation will reject any junk.
|
|
662
|
+
return ((0, jsx_runtime_1.jsx)(TextQuestion_1.TextQuestion, { value: val ?? '', onChange: (v) => updateResponse(key, v), placeholder: question.placeholder, contract: contract }));
|
|
663
|
+
};
|
|
664
|
+
const _fn = RENDERERS[String(question.type || '')] || renderUnsupported;
|
|
665
|
+
return _fn();
|
|
627
666
|
}
|
|
628
667
|
// Device-conditional palette variations. Author defines an ordered list
|
|
629
668
|
// of `{when: [{attr, op, value}], overrides: {theme?, primaryColor?}}`;
|