@cxpinsight/survey-spec 0.6.0 → 0.7.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/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/messages.d.ts.map +1 -1
- package/dist/messages.js +5 -0
- package/dist/validate.d.ts +95 -0
- package/dist/validate.d.ts.map +1 -1
- package/dist/validate.js +122 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -15,8 +15,8 @@ export { evaluateTree, compareValues, MAX_TREE_DEPTH } from './evaluateTree';
|
|
|
15
15
|
export type { ConditionNode, Operand, TreeContext } from './evaluateTree';
|
|
16
16
|
export { resolveVariable } from './resolveVariable';
|
|
17
17
|
export { splitIntoPages } from './pageFlow';
|
|
18
|
-
export { validateAnswer, impliedChoices, impliedActions, impliedStepActions, impliedEqualProminence, safeActionHref, safeImageSrc, isDeferChoice, canSwipeToDismiss, autoDismissMs, deadlineCountdown, formatCountdown, outcomeFor, voiceUsable, rewardToShow, cardClickTarget, cardHoverEffect, resolveAction } from './validate';
|
|
19
|
-
export type { ValidatableQuestion, OutcomeKind, OutcomeInput, ActionKind, RawAction, ResolvedAction } from './validate';
|
|
18
|
+
export { complianceGate, questionForValidation, validateAnswer, impliedChoices, impliedActions, impliedStepActions, impliedEqualProminence, safeActionHref, safeImageSrc, isDeferChoice, canSwipeToDismiss, autoDismissMs, deadlineCountdown, formatCountdown, outcomeFor, voiceUsable, rewardToShow, cardClickTarget, cardHoverEffect, resolveAction } from './validate';
|
|
19
|
+
export type { ComplianceState, EscapeHatch, ComplianceInput, ComplianceVerdict, ValidatableQuestion, OutcomeKind, OutcomeInput, ActionKind, RawAction, ResolvedAction } from './validate';
|
|
20
20
|
export { validateAnswerCode } from './validate';
|
|
21
21
|
export { wordMessage, EN_MESSAGES, MESSAGE_CODES } from './messages';
|
|
22
22
|
export type { ValidationMessage } from './messages';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACtF,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC7E,YAAY,EAAE,aAAa,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC1E,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,cAAc,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,cAAc,EAAE,YAAY,EAAE,aAAa,EAAE,iBAAiB,EAAE,aAAa,EAAE,iBAAiB,EAAE,eAAe,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACtF,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC7E,YAAY,EAAE,aAAa,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC1E,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,cAAc,EAAE,cAAc,EAAE,cAAc,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,cAAc,EAAE,YAAY,EAAE,aAAa,EAAE,iBAAiB,EAAE,aAAa,EAAE,iBAAiB,EAAE,eAAe,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC1W,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,eAAe,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC1L,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACrE,YAAY,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACpD,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,eAAe,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC7F,OAAO,EACL,mBAAmB,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EACzE,kBAAkB,EAAE,SAAS,EAAE,iBAAiB,EAChD,YAAY,EAAE,cAAc,EAAE,mBAAmB,EACjD,eAAe,EAAE,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,SAAS,EACtE,aAAa,EAAE,aAAa,EAAE,cAAc,EAAE,cAAc,GAC7D,MAAM,SAAS,CAAC;AACjB,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACvF,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.optionValueOf = exports.optionLabelOf = exports.shortCode = exports.buildPromptText = exports.scaffoldFor = exports.skipNoteText = exports.voiceDisclaimer = exports.auditVoiceQuestions = exports.voiceCanHandle = exports.voiceSupport = exports.distinctiveLabels = exports.matchDate = exports.matchNumberInRange = exports.rankOptions = exports.matchOptions = exports.matchOption = exports.matchBoolean = exports.normalizeTranscript = exports.MESSAGE_CODES = exports.EN_MESSAGES = exports.wordMessage = exports.validateAnswerCode = exports.resolveAction = exports.cardHoverEffect = exports.cardClickTarget = exports.rewardToShow = exports.voiceUsable = exports.outcomeFor = exports.formatCountdown = exports.deadlineCountdown = exports.autoDismissMs = exports.canSwipeToDismiss = exports.isDeferChoice = exports.safeImageSrc = exports.safeActionHref = exports.impliedEqualProminence = exports.impliedStepActions = exports.impliedActions = exports.impliedChoices = exports.validateAnswer = exports.questionForValidation = exports.complianceGate = exports.splitIntoPages = exports.resolveVariable = exports.MAX_TREE_DEPTH = exports.compareValues = exports.evaluateTree = exports.isParseable = exports.evaluateCondition = exports.evaluateExpression = void 0;
|
|
4
|
+
exports.optionLabelsOf = exports.voiceOptionsOf = void 0;
|
|
4
5
|
/**
|
|
5
6
|
* @cxpinsight/survey-spec
|
|
6
7
|
*
|
|
@@ -26,6 +27,8 @@ Object.defineProperty(exports, "resolveVariable", { enumerable: true, get: funct
|
|
|
26
27
|
var pageFlow_1 = require("./pageFlow");
|
|
27
28
|
Object.defineProperty(exports, "splitIntoPages", { enumerable: true, get: function () { return pageFlow_1.splitIntoPages; } });
|
|
28
29
|
var validate_1 = require("./validate");
|
|
30
|
+
Object.defineProperty(exports, "complianceGate", { enumerable: true, get: function () { return validate_1.complianceGate; } });
|
|
31
|
+
Object.defineProperty(exports, "questionForValidation", { enumerable: true, get: function () { return validate_1.questionForValidation; } });
|
|
29
32
|
Object.defineProperty(exports, "validateAnswer", { enumerable: true, get: function () { return validate_1.validateAnswer; } });
|
|
30
33
|
Object.defineProperty(exports, "impliedChoices", { enumerable: true, get: function () { return validate_1.impliedChoices; } });
|
|
31
34
|
Object.defineProperty(exports, "impliedActions", { enumerable: true, get: function () { return validate_1.impliedActions; } });
|
package/dist/messages.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../src/messages.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED,4EAA4E;AAC5E,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,
|
|
1
|
+
{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../src/messages.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED,4EAA4E;AAC5E,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAiC9E,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAI5E;AAED,0EAA0E;AAC1E,eAAO,MAAM,aAAa,UAA2B,CAAC"}
|
package/dist/messages.js
CHANGED
|
@@ -25,6 +25,11 @@ exports.wordMessage = wordMessage;
|
|
|
25
25
|
/** English wording, one entry per code. The only prose in the validator. */
|
|
26
26
|
exports.EN_MESSAGES = {
|
|
27
27
|
required: () => 'This field is required',
|
|
28
|
+
// Compliance. Written for someone who is being held, not for a developer:
|
|
29
|
+
// say what is happening and what happens next, never just "blocked".
|
|
30
|
+
compliance_under_review: () => 'Thanks — someone is reviewing this now. '
|
|
31
|
+
+ 'You do not need to do anything else, and this will update when the review is done.',
|
|
32
|
+
compliance_blocked: () => 'This needs to be accepted before you can continue.',
|
|
28
33
|
choose_option: () => 'Please choose an option',
|
|
29
34
|
format_email: () => 'Please enter a valid email address (e.g., you@example.com)',
|
|
30
35
|
format_url: () => 'Please enter a full URL, including https://',
|
package/dist/validate.d.ts
CHANGED
|
@@ -259,6 +259,101 @@ export interface OutcomeInput {
|
|
|
259
259
|
* surface you get past by saying no is not a compliance surface.
|
|
260
260
|
*/
|
|
261
261
|
export declare function outcomeFor(input: OutcomeInput): OutcomeKind;
|
|
262
|
+
/**
|
|
263
|
+
* The question as it should be validated RIGHT NOW.
|
|
264
|
+
*
|
|
265
|
+
* `requiredWhen` — "required only if they said yes earlier" — was compiled by
|
|
266
|
+
* the server and read by no renderer at all. An author who set it got a question
|
|
267
|
+
* that was never required, on every channel, with nothing reporting it. The last
|
|
268
|
+
* of the four conditions to be inert everywhere rather than somewhere.
|
|
269
|
+
*
|
|
270
|
+
* ADDITIVE, deliberately: a question already marked required stays required. The
|
|
271
|
+
* alternative reading — that requiredWhen REPLACES required — would let a
|
|
272
|
+
* condition make an existing question optional, so a survey that collects an
|
|
273
|
+
* answer today could quietly stop collecting it. This direction can only ever
|
|
274
|
+
* ask for more, never less, which is the safe way to turn on a rule that has
|
|
275
|
+
* never run.
|
|
276
|
+
*
|
|
277
|
+
* The caller supplies the evaluator because each renderer has its own, already
|
|
278
|
+
* wired to its answers and its compiled trees. What lives here is the decision,
|
|
279
|
+
* which is the part that must not differ between them.
|
|
280
|
+
*
|
|
281
|
+
* @param evaluate must FAIL OPEN by returning false for a condition it cannot
|
|
282
|
+
* read — an unreadable requiredWhen leaves the question optional rather than
|
|
283
|
+
* blocking a respondent behind a rule nobody can see.
|
|
284
|
+
*/
|
|
285
|
+
export declare function questionForValidation<T extends {
|
|
286
|
+
required?: unknown;
|
|
287
|
+
isRequired?: unknown;
|
|
288
|
+
requiredWhen?: unknown;
|
|
289
|
+
}>(question: T, evaluate: (expr: string) => boolean): T;
|
|
290
|
+
/** Where a compliance interaction has got to. */
|
|
291
|
+
export type ComplianceState = 'open' | 'blocked' | 'under_review' | 'cleared';
|
|
292
|
+
/** What a respondent is offered when they cannot simply proceed. */
|
|
293
|
+
export type EscapeHatch = 'none' | 'contact' | 'defer';
|
|
294
|
+
export interface ComplianceInput {
|
|
295
|
+
interactionType?: string | null;
|
|
296
|
+
/** The implied choice taken, or null before they have answered. */
|
|
297
|
+
action?: string | null;
|
|
298
|
+
/** True when the chosen action is the affirmative one. */
|
|
299
|
+
affirmative?: boolean;
|
|
300
|
+
compliance?: {
|
|
301
|
+
reviewRequired?: unknown;
|
|
302
|
+
onDecline?: unknown;
|
|
303
|
+
blockedMessage?: unknown;
|
|
304
|
+
reviewMessage?: unknown;
|
|
305
|
+
escapeHatch?: unknown;
|
|
306
|
+
contactHref?: unknown;
|
|
307
|
+
} | null;
|
|
308
|
+
}
|
|
309
|
+
export interface ComplianceVerdict {
|
|
310
|
+
state: ComplianceState;
|
|
311
|
+
/** May the respondent close the surface? */
|
|
312
|
+
dismissible: boolean;
|
|
313
|
+
escape: EscapeHatch;
|
|
314
|
+
/** Where `escape: 'contact'` sends them. Null when there is nowhere. */
|
|
315
|
+
contactHref: string | null;
|
|
316
|
+
/** A wording code, or null when there is nothing to say. */
|
|
317
|
+
messageCode: 'compliance_blocked' | 'compliance_under_review' | null;
|
|
318
|
+
/** The author's own prose, which travels verbatim and is never translated. */
|
|
319
|
+
authorMessage: string | null;
|
|
320
|
+
/** True when this state is worth recording — see the monitoring note. */
|
|
321
|
+
reportable: boolean;
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Decide whether a compliance interaction lets the respondent go.
|
|
325
|
+
*
|
|
326
|
+
* This is the half of compliance that was never built. `outcomeFor` already
|
|
327
|
+
* returns `hold`, meaning "do not let them through yet", and all three renderers
|
|
328
|
+
* read it — to choose a closing message. Nothing anywhere connected it to
|
|
329
|
+
* whether the surface could be CLOSED, so a compliance check was dismissed
|
|
330
|
+
* exactly like a rating prompt. A compliance surface you get past by ignoring it
|
|
331
|
+
* is not a compliance surface.
|
|
332
|
+
*
|
|
333
|
+
* Three states hold, and they are not the same thing to the person looking at
|
|
334
|
+
* them:
|
|
335
|
+
*
|
|
336
|
+
* open they have not answered yet
|
|
337
|
+
* blocked they declined, and the author chose to hold them
|
|
338
|
+
* under_review they accepted, and a person has to look at it
|
|
339
|
+
*
|
|
340
|
+
* `under_review` matters most and is the easiest to get wrong. Letting someone
|
|
341
|
+
* through on submit tells them they are finished when they are not, and defeats
|
|
342
|
+
* the check; saying nothing leaves them staring at a surface that looks stuck.
|
|
343
|
+
* So it holds AND it says so.
|
|
344
|
+
*
|
|
345
|
+
* ── The escape hatch ──
|
|
346
|
+
* A surface that cannot be closed can trap someone whose answer will never be
|
|
347
|
+
* accepted — a failed document check at 2am with nobody to ask. The author
|
|
348
|
+
* chooses which way out exists, and the default is `contact` rather than `none`,
|
|
349
|
+
* because a route to a human costs the check nothing while a dead end costs a
|
|
350
|
+
* customer everything. `defer` is the only one that actually releases them; it
|
|
351
|
+
* is a postponement, and the interaction comes back.
|
|
352
|
+
*
|
|
353
|
+
* Anything unrecognised falls back to `contact` rather than to `none`: a
|
|
354
|
+
* mis-typed setting must not silently become a trap.
|
|
355
|
+
*/
|
|
356
|
+
export declare function complianceGate(input: ComplianceInput): ComplianceVerdict;
|
|
262
357
|
/**
|
|
263
358
|
* Can voice mode do anything on this step?
|
|
264
359
|
*
|
package/dist/validate.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"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"}
|
package/dist/validate.js
CHANGED
|
@@ -14,6 +14,8 @@ exports.autoDismissMs = autoDismissMs;
|
|
|
14
14
|
exports.deadlineCountdown = deadlineCountdown;
|
|
15
15
|
exports.formatCountdown = formatCountdown;
|
|
16
16
|
exports.outcomeFor = outcomeFor;
|
|
17
|
+
exports.questionForValidation = questionForValidation;
|
|
18
|
+
exports.complianceGate = complianceGate;
|
|
17
19
|
exports.voiceUsable = voiceUsable;
|
|
18
20
|
exports.rewardToShow = rewardToShow;
|
|
19
21
|
exports.cardClickTarget = cardClickTarget;
|
|
@@ -738,6 +740,126 @@ function outcomeFor(input) {
|
|
|
738
740
|
// for something we do not recognise: it acknowledges without promising.
|
|
739
741
|
return 'thanks';
|
|
740
742
|
}
|
|
743
|
+
/**
|
|
744
|
+
* The question as it should be validated RIGHT NOW.
|
|
745
|
+
*
|
|
746
|
+
* `requiredWhen` — "required only if they said yes earlier" — was compiled by
|
|
747
|
+
* the server and read by no renderer at all. An author who set it got a question
|
|
748
|
+
* that was never required, on every channel, with nothing reporting it. The last
|
|
749
|
+
* of the four conditions to be inert everywhere rather than somewhere.
|
|
750
|
+
*
|
|
751
|
+
* ADDITIVE, deliberately: a question already marked required stays required. The
|
|
752
|
+
* alternative reading — that requiredWhen REPLACES required — would let a
|
|
753
|
+
* condition make an existing question optional, so a survey that collects an
|
|
754
|
+
* answer today could quietly stop collecting it. This direction can only ever
|
|
755
|
+
* ask for more, never less, which is the safe way to turn on a rule that has
|
|
756
|
+
* never run.
|
|
757
|
+
*
|
|
758
|
+
* The caller supplies the evaluator because each renderer has its own, already
|
|
759
|
+
* wired to its answers and its compiled trees. What lives here is the decision,
|
|
760
|
+
* which is the part that must not differ between them.
|
|
761
|
+
*
|
|
762
|
+
* @param evaluate must FAIL OPEN by returning false for a condition it cannot
|
|
763
|
+
* read — an unreadable requiredWhen leaves the question optional rather than
|
|
764
|
+
* blocking a respondent behind a rule nobody can see.
|
|
765
|
+
*/
|
|
766
|
+
function questionForValidation(question, evaluate) {
|
|
767
|
+
if (!question)
|
|
768
|
+
return question;
|
|
769
|
+
if (question.required === true || question.isRequired === true)
|
|
770
|
+
return question;
|
|
771
|
+
const expr = question.requiredWhen;
|
|
772
|
+
if (typeof expr !== 'string' || !expr.trim())
|
|
773
|
+
return question;
|
|
774
|
+
let now = false;
|
|
775
|
+
try {
|
|
776
|
+
now = evaluate(expr) === true;
|
|
777
|
+
}
|
|
778
|
+
catch {
|
|
779
|
+
now = false;
|
|
780
|
+
}
|
|
781
|
+
return now ? { ...question, required: true } : question;
|
|
782
|
+
}
|
|
783
|
+
const ESCAPES = ['none', 'contact', 'defer'];
|
|
784
|
+
/**
|
|
785
|
+
* Decide whether a compliance interaction lets the respondent go.
|
|
786
|
+
*
|
|
787
|
+
* This is the half of compliance that was never built. `outcomeFor` already
|
|
788
|
+
* returns `hold`, meaning "do not let them through yet", and all three renderers
|
|
789
|
+
* read it — to choose a closing message. Nothing anywhere connected it to
|
|
790
|
+
* whether the surface could be CLOSED, so a compliance check was dismissed
|
|
791
|
+
* exactly like a rating prompt. A compliance surface you get past by ignoring it
|
|
792
|
+
* is not a compliance surface.
|
|
793
|
+
*
|
|
794
|
+
* Three states hold, and they are not the same thing to the person looking at
|
|
795
|
+
* them:
|
|
796
|
+
*
|
|
797
|
+
* open they have not answered yet
|
|
798
|
+
* blocked they declined, and the author chose to hold them
|
|
799
|
+
* under_review they accepted, and a person has to look at it
|
|
800
|
+
*
|
|
801
|
+
* `under_review` matters most and is the easiest to get wrong. Letting someone
|
|
802
|
+
* through on submit tells them they are finished when they are not, and defeats
|
|
803
|
+
* the check; saying nothing leaves them staring at a surface that looks stuck.
|
|
804
|
+
* So it holds AND it says so.
|
|
805
|
+
*
|
|
806
|
+
* ── The escape hatch ──
|
|
807
|
+
* A surface that cannot be closed can trap someone whose answer will never be
|
|
808
|
+
* accepted — a failed document check at 2am with nobody to ask. The author
|
|
809
|
+
* chooses which way out exists, and the default is `contact` rather than `none`,
|
|
810
|
+
* because a route to a human costs the check nothing while a dead end costs a
|
|
811
|
+
* customer everything. `defer` is the only one that actually releases them; it
|
|
812
|
+
* is a postponement, and the interaction comes back.
|
|
813
|
+
*
|
|
814
|
+
* Anything unrecognised falls back to `contact` rather than to `none`: a
|
|
815
|
+
* mis-typed setting must not silently become a trap.
|
|
816
|
+
*/
|
|
817
|
+
function complianceGate(input) {
|
|
818
|
+
const free = {
|
|
819
|
+
state: 'cleared', dismissible: true, escape: 'none',
|
|
820
|
+
contactHref: null, messageCode: null, authorMessage: null, reportable: false,
|
|
821
|
+
};
|
|
822
|
+
if (String(input?.interactionType || '').toLowerCase() !== 'comply')
|
|
823
|
+
return free;
|
|
824
|
+
const c = input.compliance || {};
|
|
825
|
+
const raw = String(c.escapeHatch ?? '').toLowerCase();
|
|
826
|
+
const escape = ESCAPES.includes(raw) ? raw : 'contact';
|
|
827
|
+
// Through safeActionHref, not raw: this is a destination the host page is told
|
|
828
|
+
// to follow, so `javascript:` and friends are refused the same way an action
|
|
829
|
+
// button's destination is. `mailto:` passes, which is the common case for a
|
|
830
|
+
// route to a human.
|
|
831
|
+
const contactHref = (escape === 'contact' ? safeActionHref({ type: 'url', value: c.contactHref }) : null) ?? null;
|
|
832
|
+
const authorPose = (v) => (typeof v === 'string' && v.trim() ? v : null);
|
|
833
|
+
// `defer` is the only hatch that releases them — closing IS the postponement.
|
|
834
|
+
const canLeave = escape === 'defer';
|
|
835
|
+
const answered = input.action !== null && input.action !== undefined && input.action !== '';
|
|
836
|
+
if (!answered) {
|
|
837
|
+
return {
|
|
838
|
+
state: 'open', dismissible: canLeave, escape, contactHref,
|
|
839
|
+
messageCode: null, authorMessage: null, reportable: false,
|
|
840
|
+
};
|
|
841
|
+
}
|
|
842
|
+
if (input.affirmative === false) {
|
|
843
|
+
// A decline the author chose to accept is simply the end of it.
|
|
844
|
+
if (String(c.onDecline || 'block') !== 'block')
|
|
845
|
+
return free;
|
|
846
|
+
return {
|
|
847
|
+
state: 'blocked', dismissible: canLeave, escape, contactHref,
|
|
848
|
+
messageCode: 'compliance_blocked',
|
|
849
|
+
authorMessage: authorPose(c.blockedMessage),
|
|
850
|
+
reportable: true,
|
|
851
|
+
};
|
|
852
|
+
}
|
|
853
|
+
if (c.reviewRequired === true) {
|
|
854
|
+
return {
|
|
855
|
+
state: 'under_review', dismissible: canLeave, escape, contactHref,
|
|
856
|
+
messageCode: 'compliance_under_review',
|
|
857
|
+
authorMessage: authorPose(c.reviewMessage),
|
|
858
|
+
reportable: true,
|
|
859
|
+
};
|
|
860
|
+
}
|
|
861
|
+
return free;
|
|
862
|
+
}
|
|
741
863
|
/**
|
|
742
864
|
* Can voice mode do anything on this step?
|
|
743
865
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cxpinsight/survey-spec",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "The survey specification the renderers share — expression evaluation first. Source of truth for behaviour that must be identical on web, links and mobile.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|