@explorer02/cfm-survey-sdk 0.2.1 → 0.2.2
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/cli/index.js +18 -18
- package/dist/cli/index.mjs +14 -14
- package/dist/index.d.mts +465 -580
- package/dist/index.d.ts +465 -580
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +6 -4
- package/postinstall.js +96 -69
- package/templates/AGENT.md +14 -8
- package/templates/docs/00-integration/answer-logic-and-navigation.md +50 -0
- package/templates/docs/00-integration/aws-deploy.md +281 -0
- package/templates/docs/00-integration/client-integration-guide.md +351 -0
- package/templates/docs/00-integration/component-checklist.md +45 -22
- package/templates/docs/00-integration/constraints.md +49 -4
- package/templates/docs/00-integration/custom-field-logic-and-navigation.md +174 -0
- package/templates/docs/00-integration/display-logic-and-navigation.md +49 -0
- package/templates/docs/00-integration/end-page-logic.md +64 -0
- package/templates/docs/00-integration/partial-save-and-recovery.md +74 -0
- package/templates/docs/00-integration/placeholders-and-tokens.md +116 -0
- package/templates/docs/00-integration/progress.md +61 -0
- package/templates/docs/00-integration/question-display-variants.md +65 -0
- package/templates/docs/00-integration/question-numbering.md +51 -0
- package/templates/docs/00-integration/question-type-sdk-matrix.md +242 -0
- package/templates/docs/00-integration/setup.md +84 -0
- package/templates/docs/00-integration/skip-logic-and-navigation.md +80 -0
- package/templates/docs/00-integration/survey-lifecycle-analytics.md +94 -0
- package/templates/docs/00-integration/useSurveySDK.md +151 -23
- package/templates/docs/01-components/01-survey-page.md +76 -54
- package/templates/docs/01-components/02-question.md +61 -58
- package/templates/docs/01-components/03-rating-scale.md +11 -1
- package/templates/docs/01-components/04-star-rating-scale.md +45 -0
- package/templates/docs/01-components/05-csat-matrix-scale.md +20 -11
- package/templates/docs/01-components/06-likert-matrix-scale.md +12 -3
- package/templates/docs/01-components/07-slider-matrix-scale.md +11 -2
- package/templates/docs/01-components/08-file-upload-scale.md +10 -1
- package/templates/docs/01-components/09-custom-slider-track.md +2 -2
- package/templates/docs/01-components/11-progress-bar.md +10 -4
- package/templates/docs/01-components/13-matrix-dropdown.md +3 -1
- package/templates/docs/01-components/14-intro-page.md +34 -0
- package/templates/docs/01-components/15-end-page.md +31 -0
- package/templates/docs/01-components/16-paused-page.md +27 -0
- package/templates/docs/01-components/17-heatmap-scale.md +75 -0
- package/templates/docs/01-components/18-rank-order-scale.md +100 -0
- package/templates/docs/01-components/README.md +42 -36
- package/templates/docs/02-reference/config-field-index.md +141 -139
- package/templates/docs/02-reference/exports.md +149 -0
- package/templates/docs/02-reference/question-types/01-rating.md +31 -32
- package/templates/docs/02-reference/question-types/04-csat.md +51 -42
- package/templates/docs/02-reference/question-types/05-rating-scale.md +16 -11
- package/templates/docs/02-reference/question-types/06-slider.md +2 -2
- package/templates/docs/02-reference/question-types/07-matrix-cfm.md +44 -30
- package/templates/docs/02-reference/question-types/08-matrix-csat.md +4 -26
- package/templates/docs/02-reference/question-types/09-matrix-rating.md +29 -13
- package/templates/docs/02-reference/question-types/10-slider-matrix.md +15 -4
- package/templates/docs/02-reference/question-types/11-file-upload.md +13 -2
- package/templates/docs/02-reference/question-types/12-heatmap.md +59 -0
- package/templates/docs/02-reference/question-types/13-rank-order.md +101 -0
- package/templates/docs/02-reference/question-types/README.md +86 -47
- package/templates/docs/02-reference/routing-table.md +33 -18
- package/templates/docs/02-reference/value-derivation.md +63 -0
- package/templates/docs/03-ui-specs/00-question-shell.md +19 -88
- package/templates/docs/03-ui-specs/01-rating.md +12 -54
- package/templates/docs/03-ui-specs/02-radio.md +21 -33
- package/templates/docs/03-ui-specs/03-text.md +2 -2
- package/templates/docs/03-ui-specs/04-csat.md +38 -33
- package/templates/docs/03-ui-specs/05-rating-scale.md +21 -18
- package/templates/docs/03-ui-specs/06-slider.md +3 -1
- package/templates/docs/03-ui-specs/07-matrix-cfm.md +24 -21
- package/templates/docs/03-ui-specs/08-matrix-csat-rating.md +17 -45
- package/templates/docs/03-ui-specs/09-slider-matrix.md +1 -1
- package/templates/docs/03-ui-specs/10-file-upload.md +1 -1
- package/templates/docs/03-ui-specs/11-text-and-media.md +29 -29
- package/templates/docs/03-ui-specs/12-survey-chrome.md +20 -14
- package/templates/docs/03-ui-specs/13-heatmap.md +73 -0
- package/templates/docs/03-ui-specs/14-rank-order.md +59 -0
- package/templates/docs/03-ui-specs/README.md +13 -13
- package/templates/docs/03-ui-specs/shared/custom-slider-track.md +2 -2
- package/templates/docs/03-ui-specs/shared/matrix-dropdown.md +5 -0
- package/templates/docs/MANIFEST.json +451 -69
- package/templates/docs/index.md +80 -29
- package/templates/docs/templates/Question.tsx +221 -154
- package/templates/docs/templates/deploy-to-aws.sh +114 -0
- package/templates/docs/templates/heatmapCoords.ts +58 -0
- package/templates/docs/templates/implementation_plan.md +108 -69
- package/templates/docs/templates/survey-inventory.schema.json +72 -0
- package/templates/docs/templates/verify-agent-build.sh +53 -0
- package/templates/docs/01-components/04-csat-scale.md +0 -40
- package/templates/docs/02-question-types/01-rating.md +0 -44
|
@@ -1,26 +1,31 @@
|
|
|
1
|
-
# Rating
|
|
1
|
+
# Star Rating Question (Stars/Emoji)
|
|
2
2
|
|
|
3
|
-
> **Type**: `'
|
|
4
|
-
> **
|
|
3
|
+
> **Type**: `'star_rating'` | **API Source**: page `RATING`
|
|
4
|
+
> **SDK type file**: `fetchSurvey/types/starRating.ts` | **Component**: `RatingScale`
|
|
5
5
|
|
|
6
6
|
## TypeScript Type
|
|
7
7
|
|
|
8
8
|
```typescript
|
|
9
|
-
type
|
|
10
|
-
type: '
|
|
11
|
-
|
|
9
|
+
type StarRatingQuestion = {
|
|
10
|
+
type: 'star_rating';
|
|
11
|
+
id: string;
|
|
12
|
+
questionText: string;
|
|
13
|
+
options: StarRatingPoint[];
|
|
12
14
|
minLabel?: string;
|
|
13
15
|
midLabel?: string;
|
|
14
16
|
maxLabel?: string;
|
|
15
17
|
midLabelIndex?: number;
|
|
16
|
-
reverseScaleOrder
|
|
17
|
-
scaleStyle
|
|
18
|
+
reverseScaleOrder: boolean;
|
|
19
|
+
scaleStyle: 'star' | 'emoji';
|
|
20
|
+
required: boolean;
|
|
21
|
+
// ... shell fields
|
|
18
22
|
};
|
|
19
23
|
```
|
|
20
24
|
|
|
21
25
|
## Answer Shape: `number`
|
|
22
26
|
|
|
23
|
-
## Key Difference from `'
|
|
27
|
+
## Key Difference from `'nps'`
|
|
28
|
+
|
|
24
29
|
- No NPS traffic-light colors on options
|
|
25
|
-
- Rendered as stars
|
|
26
|
-
-
|
|
30
|
+
- Rendered as stars or emojis per `scaleStyle`
|
|
31
|
+
- See `03-ui-specs/05-rating-scale.md`
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Slider Question (Single Range)
|
|
2
2
|
|
|
3
|
-
> **Type**: `'slider'` | **API Source**:
|
|
4
|
-
> **Mapper**: `
|
|
3
|
+
> **Type**: `'slider'` | **API Source**: page `SLIDER`
|
|
4
|
+
> **Mapper**: `sliderMapper.ts` | **Component**: `CustomSliderTrack` or native `<input type="range">`
|
|
5
5
|
|
|
6
6
|
## TypeScript Type
|
|
7
7
|
|
|
@@ -1,43 +1,57 @@
|
|
|
1
|
-
# Matrix
|
|
1
|
+
# CFM Matrix Question (Likert Grid)
|
|
2
2
|
|
|
3
|
-
> **Type**: `'
|
|
4
|
-
> **
|
|
3
|
+
> **Type**: `'CFM_MATRIX'` | **API Source**: `CFM_MATRIX`
|
|
4
|
+
> **SDK type file**: `fetchSurvey/types/cfmMatrix.ts` | **Component**: `LikertMatrixScale`
|
|
5
5
|
|
|
6
6
|
## TypeScript Type
|
|
7
7
|
|
|
8
8
|
```typescript
|
|
9
|
-
type
|
|
10
|
-
type: '
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
9
|
+
type CfmMatrixQuestion = {
|
|
10
|
+
type: 'CFM_MATRIX';
|
|
11
|
+
id: string;
|
|
12
|
+
questionText: string;
|
|
13
|
+
statementRows: CfmMatrixStatementRow[];
|
|
14
|
+
scaleColumns: CfmMatrixScaleColumn[];
|
|
15
|
+
statementLayout: 'likert' | 'bipolar';
|
|
16
|
+
selectionMode: 'single' | 'multiple';
|
|
17
|
+
gridLayout: 'standard' | 'carousel' | 'dropdown';
|
|
18
|
+
transposeTable: boolean;
|
|
19
|
+
repeatColumnHeaders: boolean;
|
|
20
|
+
hasNotApplicableOption: boolean;
|
|
21
|
+
showColumnHeaders: boolean;
|
|
22
|
+
scaleAnchorLabels?: string[];
|
|
23
|
+
required: boolean;
|
|
24
|
+
// ... shell fields
|
|
24
25
|
};
|
|
25
26
|
|
|
26
|
-
type
|
|
27
|
-
|
|
27
|
+
type CfmMatrixStatementRow = {
|
|
28
|
+
id: string;
|
|
29
|
+
statementText: string;
|
|
30
|
+
oppositeStatementText?: string;
|
|
31
|
+
};
|
|
28
32
|
```
|
|
29
33
|
|
|
30
|
-
## Answer Shape: `
|
|
34
|
+
## Answer Shape: `MatrixRowAnswers`
|
|
35
|
+
|
|
31
36
|
```typescript
|
|
32
|
-
{ "row1_id":
|
|
33
|
-
// null = N/A selected for that row
|
|
37
|
+
{ "row1_id": columnValue, "row2_id": null }
|
|
34
38
|
```
|
|
35
39
|
|
|
36
40
|
## Rendering Guidance
|
|
37
|
-
|
|
38
|
-
- **
|
|
39
|
-
- **
|
|
40
|
-
-
|
|
41
|
-
-
|
|
42
|
-
-
|
|
43
|
-
|
|
41
|
+
|
|
42
|
+
- **standard**: Grid table — rows on left, columns as headers
|
|
43
|
+
- **carousel**: One row at a time with prev/next
|
|
44
|
+
- **dropdown**: Each row has a dropdown (`MatrixDropdown`)
|
|
45
|
+
- **bipolar**: `statementText` left + `oppositeStatementText` right
|
|
46
|
+
- `onSelect` receives the full `MatrixRowAnswers` object on each change
|
|
47
|
+
|
|
48
|
+
## SDK Integration Checklist (agent)
|
|
49
|
+
|
|
50
|
+
- [ ] Type literal: `QUESTION_TYPE.CFM_MATRIX`
|
|
51
|
+
- [ ] Answer stored as: `MatrixRowAnswers` — column **`id`** via `matrixColumnStoredValue`
|
|
52
|
+
- [ ] onAction CHANGE payload: `{ questionId, answerValue: MatrixRowAnswers }`
|
|
53
|
+
- [ ] Visibility helper: `getVisibleMatrixItemsForAnswers(question, answers, allQuestions, customFieldValues?)`
|
|
54
|
+
- [ ] Custom fields: 4th arg on matrix visibility helper when logic references CRM fields
|
|
55
|
+
- [ ] Logic features: skip ✓ display ✓ answer ✓ (rows + columns) variants ✓ numbering ✓
|
|
56
|
+
- [ ] Performance: filter rows/cols before render; lazy-load large matrices
|
|
57
|
+
- [ ] Matrix row: [`question-type-sdk-matrix.md#cfm_matrix`](../../00-integration/question-type-sdk-matrix.md#cfm_matrix)
|
|
@@ -1,29 +1,7 @@
|
|
|
1
|
-
# Matrix
|
|
1
|
+
# CSAT Matrix Question (legacy reference)
|
|
2
2
|
|
|
3
|
-
> **
|
|
4
|
-
> **Mapper**: `csatMatrixMapper.ts` | **Component**: `CsatMatrixScale`
|
|
3
|
+
> **Deprecated alias.** CSAT matrix grids use `type: 'CSAT_MATRIX'` — see [04-csat.md](04-csat.md).
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
Same as `MatrixQuestion` (see `07-matrix-cfm.md`) but with `subType: 'CSAT_MATRIX'`.
|
|
5
|
+
For rating-style matrix grids use `type: 'RATING_MATRIX'` — see [09-matrix-rating.md](09-matrix-rating.md).
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
- Columns represent satisfaction levels (not text labels)
|
|
11
|
-
- Uses `buttonType` to determine visual: emoji faces, stars, numbered, etc.
|
|
12
|
-
- Uses `getEmojiForIndex(colIndex, totalCols)` for emoji rendering per cell
|
|
13
|
-
|
|
14
|
-
## Rendering by `buttonType`
|
|
15
|
-
|
|
16
|
-
| `buttonType` | Cell Rendering |
|
|
17
|
-
|-------------|---------------|
|
|
18
|
-
| `'emoji'` | Sentiment face icons via `getEmojiForIndex` |
|
|
19
|
-
| `'star'` | Star icons via `CsatStarIcons` |
|
|
20
|
-
| `'numbered'` | Numeric badge buttons |
|
|
21
|
-
| `'radio'` | Standard radio circles |
|
|
22
|
-
| `'dropdown'` | Dropdown per row (uses `MatrixDropdown`) |
|
|
23
|
-
| `'graphics'` | Emoji slider per row (uses `CustomSliderTrack`) |
|
|
24
|
-
|
|
25
|
-
## Answer Shape: `MatrixAnswerMap`
|
|
26
|
-
Same as CFM_MATRIX — `{ "row_id": column_value | null }`
|
|
27
|
-
|
|
28
|
-
## N/A Column
|
|
29
|
-
If `hasNotApplicable` is true, the last column has `value: null`. Selecting it records `null` for that row, which is a valid answer (passes validation).
|
|
7
|
+
There is no `subType` field. Each matrix variant is a flat `question.type` literal.
|
|
@@ -1,28 +1,44 @@
|
|
|
1
1
|
# Rating Matrix Question
|
|
2
2
|
|
|
3
|
-
> **Type**: `'
|
|
4
|
-
> **
|
|
3
|
+
> **Type**: `'RATING_MATRIX'` | **API Source**: `RATING_MATRIX`
|
|
4
|
+
> **Component**: `CsatMatrixScale`
|
|
5
5
|
|
|
6
6
|
## TypeScript Type
|
|
7
7
|
|
|
8
8
|
```typescript
|
|
9
|
-
type RatingMatrixQuestion =
|
|
10
|
-
type: '
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
type RatingMatrixQuestion = {
|
|
10
|
+
type: 'RATING_MATRIX';
|
|
11
|
+
statementRows: StatementRow[];
|
|
12
|
+
scaleColumns: ScaleColumn[];
|
|
13
13
|
minLabel?: string;
|
|
14
14
|
maxLabel?: string;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
displayStyle: CsatQuestion['displayStyle'];
|
|
16
|
+
gridLayout: 'standard' | 'carousel' | 'dropdown';
|
|
17
|
+
hasNotApplicableOption: boolean;
|
|
18
|
+
reverseScaleOrder: boolean;
|
|
19
|
+
scaleAnchorLabels?: string[];
|
|
20
|
+
// + shell fields (id, questionText, required, containerMedia?, etc.)
|
|
19
21
|
};
|
|
20
22
|
```
|
|
21
23
|
|
|
22
24
|
## Key Difference from CSAT_MATRIX
|
|
23
|
-
|
|
25
|
+
|
|
24
26
|
- Has `minLabel`/`maxLabel` endpoint labels
|
|
27
|
+
- Column badge colors derived client-side via `columnAccentColor(col)` — see `02-reference/value-derivation.md`
|
|
25
28
|
- Rendered by the same `CsatMatrixScale` component
|
|
26
29
|
|
|
27
|
-
## Answer Shape: `
|
|
28
|
-
|
|
30
|
+
## Answer Shape: `MatrixRowAnswers`
|
|
31
|
+
|
|
32
|
+
`Record<statementRows[].id, matrixColumnStoredValue(col) | null>` — stored value is always the column **`id`**; submit maps id → label/number via `resolveSubmitValues`.
|
|
33
|
+
|
|
34
|
+
## SDK Integration Checklist (agent)
|
|
35
|
+
|
|
36
|
+
- [ ] Type literal: `QUESTION_TYPE.RATING_MATRIX`
|
|
37
|
+
- [ ] Answer stored as: `MatrixRowAnswers` — column **`id`** via `matrixColumnStoredValue`
|
|
38
|
+
- [ ] onAction CHANGE payload: `{ questionId, answerValue: MatrixRowAnswers }`
|
|
39
|
+
- [ ] Visibility helper: `getVisibleMatrixItemsForAnswers(question, answers, allQuestions, customFieldValues?)`
|
|
40
|
+
- [ ] Custom fields: 4th arg on matrix visibility helper when logic references CRM fields
|
|
41
|
+
- [ ] Logic features: skip ✓ display ✓ answer ✓ (rows; column logic may be limited) variants ✓ numbering ✓
|
|
42
|
+
- [ ] Performance: reuse `CsatMatrixScale`; render only visible rows/cols
|
|
43
|
+
- [ ] Known limitation: column-level answer logic gap — verify fetched survey rules
|
|
44
|
+
- [ ] Matrix row: [`question-type-sdk-matrix.md#rating_matrix`](../../00-integration/question-type-sdk-matrix.md#rating_matrix)
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# Slider Matrix Question
|
|
2
2
|
|
|
3
|
-
> **Type**: `'
|
|
3
|
+
> **Type**: `'SLIDER_MATRIX'` | **API Source**: `SLIDER_MATRIX`
|
|
4
4
|
> **Mapper**: `sliderMatrixMapper.ts` | **Component**: `SliderMatrixScale`
|
|
5
5
|
|
|
6
6
|
## TypeScript Type
|
|
7
7
|
|
|
8
8
|
```typescript
|
|
9
9
|
type SliderMatrixQuestion = QuestionBase & {
|
|
10
|
-
type: '
|
|
10
|
+
type: 'SLIDER_MATRIX';
|
|
11
11
|
rows: SliderMatrixRow[]; // Each row has independent slider config
|
|
12
12
|
labels?: string[]; // Anchor labels above track
|
|
13
13
|
ticks?: number; // Number of tick marks (default 10)
|
|
@@ -25,7 +25,7 @@ type SliderMatrixRow = MatrixRow & {
|
|
|
25
25
|
type TickValue = { value: number; label: string; color: string; };
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
-
## Answer Shape: `
|
|
28
|
+
## Answer Shape: `MatrixRowAnswers`
|
|
29
29
|
```typescript
|
|
30
30
|
{ "row1_id": 75, "row2_id": 30, "row3_id": null }
|
|
31
31
|
// number = slider position, null = N/A
|
|
@@ -37,4 +37,15 @@ type TickValue = { value: number; label: string; color: string; };
|
|
|
37
37
|
- If `tickValues` available → render tick marks with labels and colors
|
|
38
38
|
- If `enableInputBox` → show numeric input alongside slider
|
|
39
39
|
- If `enableNotApplicable` → add N/A checkbox per row
|
|
40
|
-
- `onSelect` receives the full `
|
|
40
|
+
- `onSelect` receives the full `MatrixRowAnswers` with all row values
|
|
41
|
+
|
|
42
|
+
## SDK Integration Checklist (agent)
|
|
43
|
+
|
|
44
|
+
- [ ] Type literal: `QUESTION_TYPE.SLIDER_MATRIX`
|
|
45
|
+
- [ ] Answer stored as: `MatrixRowAnswers` — numeric slider value or `null` for N/A per row
|
|
46
|
+
- [ ] onAction CHANGE payload: `{ questionId, answerValue: MatrixRowAnswers }`
|
|
47
|
+
- [ ] Visibility helper: `getVisibleStatementRowsForAnswers(question, answers, allQuestions, customFieldValues?)`
|
|
48
|
+
- [ ] Custom fields: 4th arg on statement-row helper when logic references CRM fields
|
|
49
|
+
- [ ] Logic features: skip ✓ display ✓ answer ✓ (rows) variants ✓ numbering ✓
|
|
50
|
+
- [ ] Performance: debounce drag events if partial save enabled; one slider per visible row
|
|
51
|
+
- [ ] Matrix row: [`question-type-sdk-matrix.md#slider_matrix`](../../00-integration/question-type-sdk-matrix.md#slider_matrix)
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# File Upload Question
|
|
2
2
|
|
|
3
|
-
> **Type**: `'
|
|
3
|
+
> **Type**: `'FILE_UPLOAD'` | **API Source**: `FILE_UPLOAD`
|
|
4
4
|
> **Mapper**: `fileUploadMapper.ts` | **Component**: `FileUploadScale`
|
|
5
5
|
|
|
6
6
|
## TypeScript Type
|
|
7
7
|
|
|
8
8
|
```typescript
|
|
9
9
|
type FileUploadQuestion = QuestionBase & {
|
|
10
|
-
type: '
|
|
10
|
+
type: 'FILE_UPLOAD';
|
|
11
11
|
uploadMessage?: string; // Instruction text (HTML)
|
|
12
12
|
supportedFileFormats?: string[]; // ['PDF', 'PNG', 'DOCX'] (uppercase, no dots)
|
|
13
13
|
maxFileCount?: number; // Max files allowed
|
|
@@ -32,3 +32,14 @@ Array of uploaded file descriptors. Submitted via `quesIdVsAttachmentDetails` (N
|
|
|
32
32
|
- Show file list with name, size, and remove button
|
|
33
33
|
- Enforce `fileSizeLimit` with appropriate error messages
|
|
34
34
|
- `onSelect` receives the full `UploadedFile[]` array
|
|
35
|
+
|
|
36
|
+
## SDK Integration Checklist (agent)
|
|
37
|
+
|
|
38
|
+
- [ ] Type literal: `QUESTION_TYPE.FILE_UPLOAD`
|
|
39
|
+
- [ ] Answer stored as: `UploadedFile[]`
|
|
40
|
+
- [ ] onAction CHANGE payload: `{ questionId, answerValue: UploadedFile[] }` after upload completes
|
|
41
|
+
- [ ] Visibility helper: N/A
|
|
42
|
+
- [ ] Custom fields: skip/display rules only — no visibility helper
|
|
43
|
+
- [ ] Logic features: skip ✓ display ✓ answer ✗ variants ✓ numbering ✓
|
|
44
|
+
- [ ] Performance: upload to presigned URL before CHANGE; show progress UI
|
|
45
|
+
- [ ] Matrix row: [`question-type-sdk-matrix.md#file_upload`](../../00-integration/question-type-sdk-matrix.md#file_upload)
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Heatmap Question (`HEATMAP`)
|
|
2
|
+
|
|
3
|
+
> **SDK type:** `HeatmapQuestion` in `fetchSurvey/types/heatmap.ts`
|
|
4
|
+
> **UI spec:** `03-ui-specs/13-heatmap.md`
|
|
5
|
+
|
|
6
|
+
## API Source
|
|
7
|
+
|
|
8
|
+
- `answerType: "HEATMAP"`
|
|
9
|
+
- `questionAssets[0]` → image URL
|
|
10
|
+
- `surveyHeatmapMetadata` → regions, max clicks, canvas dimensions
|
|
11
|
+
|
|
12
|
+
## Question Fields
|
|
13
|
+
|
|
14
|
+
| Field | Type | Description |
|
|
15
|
+
|-------|------|-------------|
|
|
16
|
+
| `type` | `'HEATMAP'` | Dispatch literal |
|
|
17
|
+
| `imageUrl` | `string` | Required image for click map |
|
|
18
|
+
| `regions` | `HeatmapRegion[]` | Normalized 0–1 rects for logic |
|
|
19
|
+
| `maxClicksAllowed` | `number` | 1–20, from `totalClickAllowed` |
|
|
20
|
+
| `referenceWidth` | `number` | Canvas width used for region normalization |
|
|
21
|
+
| `referenceHeight` | `number` | Canvas height used for region normalization |
|
|
22
|
+
|
|
23
|
+
## Answer Shape
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
type HeatmapClickPoint = { id: string; x: number; y: number };
|
|
27
|
+
type HeatmapAnswer = HeatmapClickPoint[];
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Stored in `state.answers[questionId]`. Submit serializes to:
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
questionToAnswers[questionId] = [JSON.stringify(clicks)];
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Logic Fields
|
|
37
|
+
|
|
38
|
+
| Field | Operators | Semantics |
|
|
39
|
+
|-------|-----------|-----------|
|
|
40
|
+
| `HEATMAP` | EXISTS / MISSING | Any click points present |
|
|
41
|
+
| `HEATMAP_REGION` | CONTAINS / DOES_NOT_CONTAIN | Any listed region label has ≥1 click inside |
|
|
42
|
+
|
|
43
|
+
Logic values use region **labels** (e.g. `"Region 1"`), not shape ids.
|
|
44
|
+
|
|
45
|
+
## Component
|
|
46
|
+
|
|
47
|
+
`HeatmapScale` — see `01-components/17-heatmap-scale.md`
|
|
48
|
+
|
|
49
|
+
## SDK Integration Checklist (agent)
|
|
50
|
+
|
|
51
|
+
- [ ] Type literal: `QUESTION_TYPE.HEATMAP`
|
|
52
|
+
- [ ] Answer stored as: `HeatmapAnswer` (`HeatmapClickPoint[]`)
|
|
53
|
+
- [ ] onAction CHANGE payload: `{ questionId, answerValue: HeatmapClickPoint[] }` on click add/remove
|
|
54
|
+
- [ ] Visibility helper: N/A
|
|
55
|
+
- [ ] Custom fields: skip/display rules only
|
|
56
|
+
- [ ] Logic features: skip ✓ display ✓ answer ✗ variants ✓ numbering ✓
|
|
57
|
+
- [ ] Performance: normalize coords 0–1; copy [`templates/heatmapCoords.ts`](../../templates/heatmapCoords.ts)
|
|
58
|
+
- [ ] Respect `maxClicksAllowed`; use `findSpotNearClick` for spot hit testing
|
|
59
|
+
- [ ] Matrix row: [`question-type-sdk-matrix.md#heatmap`](../../00-integration/question-type-sdk-matrix.md#heatmap)
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# Rank Order Question (`RANK_ORDER`)
|
|
2
|
+
|
|
3
|
+
> **SDK type:** `RankOrderQuestion` in `fetchSurvey/types/rankOrder.ts`
|
|
4
|
+
> **UI spec:** `03-ui-specs/14-rank-order.md`
|
|
5
|
+
|
|
6
|
+
## API Source
|
|
7
|
+
|
|
8
|
+
- `answerType: "RANK_ORDER"`
|
|
9
|
+
- `answerDetails[]` → options (text + optional `answerAsset`)
|
|
10
|
+
- `questionConfigs`:
|
|
11
|
+
- `RANK_ORDER_ANSWER_TYPE` → `DROPDOWN` | `DRAG_AND_DROP`
|
|
12
|
+
- `OPTION_TYPE` → `TEXT_ONLY` | `IMAGE_ONLY` | `TEXT_AND_IMAGE`
|
|
13
|
+
- `REQUIRE_RANK_ALL` → boolean
|
|
14
|
+
- `SHUFFLE_ORDER` → boolean
|
|
15
|
+
- `additionalInfo.hasOptionLevelAnswers: true` → submit uses `optionLevelAnswers`
|
|
16
|
+
|
|
17
|
+
## Question Fields
|
|
18
|
+
|
|
19
|
+
| Field | Type | API config |
|
|
20
|
+
|-------|------|------------|
|
|
21
|
+
| `type` | `'RANK_ORDER'` | `answerType` |
|
|
22
|
+
| `options` | `RankOrderOption[]` | `answerDetails[]` |
|
|
23
|
+
| `interactionMode` | `'dropdown' \| 'dragAndDrop'` | `RANK_ORDER_ANSWER_TYPE` |
|
|
24
|
+
| `optionDisplay` | `'textOnly' \| 'imageOnly' \| 'textAndImage'` | `OPTION_TYPE` |
|
|
25
|
+
| `requireRankAll` | `boolean` | `REQUIRE_RANK_ALL` |
|
|
26
|
+
| `shuffleOptions` | `boolean` | `SHUFFLE_ORDER` |
|
|
27
|
+
|
|
28
|
+
### RankOrderOption
|
|
29
|
+
|
|
30
|
+
| Field | Source |
|
|
31
|
+
|-------|--------|
|
|
32
|
+
| `id` | `answerDetails[].id` |
|
|
33
|
+
| `optionLabel` | `answerDetails[].answerText` |
|
|
34
|
+
| `imageUrl` | `answerAsset.source` |
|
|
35
|
+
| `previewImageUrl` | `answerAsset.previewImageUrl` |
|
|
36
|
+
| `answerLogic` | option `controlConfig.displayLogic` |
|
|
37
|
+
|
|
38
|
+
## Answer Shape
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
/** optionId → 1-based rank. Partial map allowed when requireRankAll is false. */
|
|
42
|
+
type RankOrderAnswers = Record<string, number>;
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Stored in `state.answers[questionId]`.
|
|
46
|
+
|
|
47
|
+
## Submit Shape
|
|
48
|
+
|
|
49
|
+
Both fields are populated for rank-order questions:
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
// Ordered option ids from rank 1 → N
|
|
53
|
+
questionToAnswers[questionId] = ['optionIdRank1', 'optionIdRank2', ...];
|
|
54
|
+
|
|
55
|
+
// Per-option rank (API key uses -:- separator)
|
|
56
|
+
optionLevelAnswers[`${questionId}-:-${optionId}`] = [String(rank)];
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Logic Field: `RANK_ORDER`
|
|
60
|
+
|
|
61
|
+
Conditions target a **specific option** via `details.subConditionEntity` (`entityType: 'OPTION'`).
|
|
62
|
+
|
|
63
|
+
| UI label | API operator | Values | Semantics |
|
|
64
|
+
|----------|--------------|--------|-----------|
|
|
65
|
+
| Ranked as | `EQUALS` | rank number | Subject option rank equals value |
|
|
66
|
+
| Ranked more than | `GT` | rank number | Subject rank > value |
|
|
67
|
+
| Ranked less than | `LT` | rank number | Subject rank < value |
|
|
68
|
+
| Ranked above | `BEFORE` | reference option id | Subject rank < reference rank |
|
|
69
|
+
| Ranked below | `AFTER` | reference option id | Subject rank > reference rank |
|
|
70
|
+
|
|
71
|
+
Also supports `EXISTS` / `MISSING` for the whole question answer.
|
|
72
|
+
|
|
73
|
+
Works in skip, display, answer, question variant, and end-page logic via the shared `evaluateCondition` pipeline.
|
|
74
|
+
|
|
75
|
+
## SDK Helpers (client-safe)
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
import {
|
|
79
|
+
assignRankWithoutDuplicates,
|
|
80
|
+
buildRankOrderFromOrderedOptionIds,
|
|
81
|
+
getOrderedOptionIdsFromRanks,
|
|
82
|
+
getVisibleRankOrderOptionsForAnswers,
|
|
83
|
+
normalizeRankOrderAnswers,
|
|
84
|
+
} from '@explorer02/cfm-survey-sdk';
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Component
|
|
88
|
+
|
|
89
|
+
`RankOrderScale` — see `01-components/18-rank-order-scale.md`
|
|
90
|
+
|
|
91
|
+
## SDK Integration Checklist (agent)
|
|
92
|
+
|
|
93
|
+
- [ ] Type literal: `QUESTION_TYPE.RANK_ORDER`
|
|
94
|
+
- [ ] Answer stored as: `RankOrderAnswers` (`Record<optionId, rank>`)
|
|
95
|
+
- [ ] onAction CHANGE payload: `{ questionId, answerValue: RankOrderAnswers }` after reorder
|
|
96
|
+
- [ ] Visibility helper: `getVisibleRankOrderOptionsForAnswers(question, answers, allQuestions, customFieldValues?)`
|
|
97
|
+
- [ ] Custom fields: 4th arg on rank visibility helper when logic references CRM fields
|
|
98
|
+
- [ ] Logic features: skip ✓ display ✓ answer ✓ (options) variants ✓ numbering ✓
|
|
99
|
+
- [ ] Performance: prefer `option.imageUrl` over `previewImageUrl`; install `@dnd-kit/*` for drag mode
|
|
100
|
+
- [ ] Value utils: `assignRankWithoutDuplicates`, `buildRankOrderFromOrderedOptionIds`, `getOrderedOptionIdsFromRanks`, `normalizeRankOrderAnswers`
|
|
101
|
+
- [ ] Matrix row: [`question-type-sdk-matrix.md#rank_order`](../../00-integration/question-type-sdk-matrix.md#rank_order)
|
|
@@ -1,71 +1,110 @@
|
|
|
1
1
|
# Question Types Reference
|
|
2
2
|
|
|
3
3
|
> Read **on demand** — only for types present in the fetched survey.
|
|
4
|
-
> UI implementation: `01-components/`. Routing table: `02-reference/routing-table.md`.
|
|
5
4
|
|
|
6
|
-
## Discriminated Union
|
|
5
|
+
## Discriminated Union (11 types)
|
|
7
6
|
|
|
8
7
|
```typescript
|
|
9
8
|
type SurveyQuestion =
|
|
10
|
-
|
|
|
11
|
-
|
|
|
12
|
-
|
|
|
13
|
-
| CsatQuestion // '
|
|
14
|
-
|
|
|
15
|
-
|
|
|
16
|
-
|
|
|
17
|
-
|
|
|
18
|
-
|
|
|
19
|
-
|
|
|
20
|
-
|
|
|
9
|
+
| McqQuestion // 'MCQ'
|
|
10
|
+
| NpsQuestion // 'NPS_SCALE'
|
|
11
|
+
| TextInputQuestion // 'TEXTFIELD'
|
|
12
|
+
| CsatQuestion // 'CSAT_MATRIX'
|
|
13
|
+
| CfmMatrixQuestion // 'CFM_MATRIX'
|
|
14
|
+
| RatingMatrixQuestion // 'RATING_MATRIX'
|
|
15
|
+
| SliderMatrixQuestion // 'SLIDER_MATRIX'
|
|
16
|
+
| FileUploadQuestion // 'FILE_UPLOAD'
|
|
17
|
+
| TextAndMediaQuestion // 'TEXT_AND_MEDIA'
|
|
18
|
+
| HeatmapQuestion // 'HEATMAP'
|
|
19
|
+
| RankOrderQuestion; // 'RANK_ORDER'
|
|
21
20
|
```
|
|
22
21
|
|
|
23
|
-
|
|
22
|
+
Use `QUESTION_TYPE` from the SDK for dispatch comparisons.
|
|
24
23
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
|
32
|
-
|
|
24
|
+
Each type is **standalone** — open its file in exported SDK types for the complete field list.
|
|
25
|
+
|
|
26
|
+
> **Legacy:** `StarRatingQuestion` / `SliderQuestion` mapper types are not in the `SurveyQuestion` union. API RATING/SLIDER pages map into `NPS_SCALE`, matrix display styles, or `SLIDER_MATRIX`.
|
|
27
|
+
|
|
28
|
+
## Shared field names (duplicated per type file)
|
|
29
|
+
|
|
30
|
+
| Property | Meaning |
|
|
31
|
+
|----------|---------|
|
|
32
|
+
| `id` | DOM `id` on wrapper |
|
|
33
|
+
| `questionText` | Main prompt (HTML) |
|
|
34
|
+
| `questionDescription?` | Supplementary HTML |
|
|
35
|
+
| `questionHint?` | Hint text |
|
|
36
|
+
| `required` | Mandatory flag |
|
|
37
|
+
| `requiredErrorMessage?` | Custom validation message |
|
|
38
|
+
| `questionNumber?` | 1-indexed position |
|
|
39
|
+
| `skipLogics?` | Forward skip rules evaluated on page leave |
|
|
40
|
+
| `displayLogic?` | Question-level show/hide (dynamic or page-level) |
|
|
41
|
+
| `displayVariants?` | Alternate `questionText` prompts selected by condition (SDK resolves on `currentQuestions`; see [`question-display-variants.md`](../../00-integration/question-display-variants.md)) |
|
|
42
|
+
| `answerLogic?` | On `McqOption`, `StatementRow`, or `ScaleColumn` — sub-entity show/hide (see [`answer-logic-and-navigation.md`](../../00-integration/answer-logic-and-navigation.md)) |
|
|
33
43
|
|
|
34
44
|
---
|
|
35
45
|
|
|
36
|
-
##
|
|
46
|
+
## MCQ {#mcq}
|
|
47
|
+
|
|
48
|
+
- **Type:** `McqQuestion` — `type: 'MCQ'`
|
|
49
|
+
- **Answer:** `string` or `string[]` (`option.id` values)
|
|
50
|
+
- **Options:** `McqOption[]` with `id`, `optionLabel`
|
|
51
|
+
|
|
52
|
+
### SDK Integration Checklist (agent)
|
|
37
53
|
|
|
38
|
-
-
|
|
39
|
-
-
|
|
40
|
-
-
|
|
41
|
-
-
|
|
54
|
+
- [ ] Type literal: `QUESTION_TYPE.MCQ`
|
|
55
|
+
- [ ] Answer stored as: `option.id` (string/number) or array when multi-select
|
|
56
|
+
- [ ] onAction CHANGE payload: `{ questionId, answerValue: optionId | optionId[] }`
|
|
57
|
+
- [ ] Visibility helper: `getVisibleMcqOptionsForAnswers(question, answers, allQuestions, customFieldValues?)`
|
|
58
|
+
- [ ] Custom fields: 4th arg when logic references CRM fields
|
|
59
|
+
- [ ] Logic features: skip ✓ display ✓ answer ✓ (options) variants ✓ numbering ✓
|
|
60
|
+
- [ ] Performance: filter options via helper before render
|
|
61
|
+
- [ ] Matrix row: [`question-type-sdk-matrix.md#mcq`](../../00-integration/question-type-sdk-matrix.md#mcq)
|
|
42
62
|
|
|
43
|
-
##
|
|
63
|
+
## TEXTFIELD {#textfield}
|
|
44
64
|
|
|
45
|
-
- **Type:** `
|
|
65
|
+
- **Type:** `TextInputQuestion` — `type: 'TEXTFIELD'`
|
|
46
66
|
- **Answer:** `string`
|
|
47
|
-
- **UI:** Inline `<textarea>` or `<input>` in `Question.tsx`
|
|
48
|
-
- **No separate reference doc needed**
|
|
49
67
|
|
|
50
|
-
|
|
68
|
+
### SDK Integration Checklist (agent)
|
|
51
69
|
|
|
52
|
-
-
|
|
53
|
-
-
|
|
54
|
-
-
|
|
55
|
-
-
|
|
70
|
+
- [ ] Type literal: `QUESTION_TYPE.TEXTFIELD`
|
|
71
|
+
- [ ] Answer stored as: `string`
|
|
72
|
+
- [ ] onAction CHANGE payload: `{ questionId, answerValue: string }`
|
|
73
|
+
- [ ] Visibility helper: N/A
|
|
74
|
+
- [ ] Custom fields: skip/display only
|
|
75
|
+
- [ ] Logic features: skip ✓ display ✓ answer ✗ variants ✓ numbering ✓
|
|
76
|
+
- [ ] Performance: debounce long textarea onChange if partial save enabled
|
|
77
|
+
- [ ] Matrix row: [`question-type-sdk-matrix.md#textfield`](../../00-integration/question-type-sdk-matrix.md#textfield)
|
|
78
|
+
|
|
79
|
+
## TEXT_AND_MEDIA {#text_and_media}
|
|
80
|
+
|
|
81
|
+
- **Type:** `TextAndMediaQuestion` — `type: 'TEXT_AND_MEDIA'`
|
|
82
|
+
- **Answer:** none — display-only
|
|
83
|
+
|
|
84
|
+
### SDK Integration Checklist (agent)
|
|
85
|
+
|
|
86
|
+
- [ ] Type literal: `QUESTION_TYPE.TEXT_AND_MEDIA`
|
|
87
|
+
- [ ] Answer stored as: none — no CHANGE action
|
|
88
|
+
- [ ] onAction: user advances with NEXT only
|
|
89
|
+
- [ ] Visibility helper: N/A
|
|
90
|
+
- [ ] Custom fields: skip/display only
|
|
91
|
+
- [ ] Logic features: skip ✓ display ✓ answer ✗ variants ✓ numbering ✓
|
|
92
|
+
- [ ] Performance: lazy-load media; respect `media.alignment`
|
|
93
|
+
- [ ] Matrix row: [`question-type-sdk-matrix.md#text_and_media`](../../00-integration/question-type-sdk-matrix.md#text_and_media)
|
|
56
94
|
|
|
57
95
|
---
|
|
58
96
|
|
|
59
97
|
## Detailed Reference Docs
|
|
60
98
|
|
|
61
|
-
| File | Type | When to read |
|
|
62
|
-
|
|
63
|
-
| `01-rating.md` | `
|
|
64
|
-
| `04-csat.md` | `
|
|
65
|
-
| `
|
|
66
|
-
| `
|
|
67
|
-
| `
|
|
68
|
-
| `
|
|
69
|
-
| `
|
|
70
|
-
| `
|
|
71
|
-
|
|
99
|
+
| File | Type literal | When to read |
|
|
100
|
+
|------|--------------|--------------|
|
|
101
|
+
| `01-rating.md` | `NPS_SCALE` | NPS 0–10 scales |
|
|
102
|
+
| `04-csat.md` | `CSAT_MATRIX` | CSAT matrix grid |
|
|
103
|
+
| `07-matrix-cfm.md` | `CFM_MATRIX` | CFM matrix grid |
|
|
104
|
+
| `09-matrix-rating.md` | `RATING_MATRIX` | NPS-style rating matrix |
|
|
105
|
+
| `10-slider-matrix.md` | `SLIDER_MATRIX` | Slider grid |
|
|
106
|
+
| `11-file-upload.md` | `FILE_UPLOAD` | File attachments |
|
|
107
|
+
| `12-heatmap.md` | `HEATMAP` | Click-map heatmap |
|
|
108
|
+
| `13-rank-order.md` | `RANK_ORDER` | Rank order options |
|
|
109
|
+
|
|
110
|
+
Legacy docs (deprecated API mappings): `05-rating-scale.md`, `06-slider.md`
|