@explorer02/cfm-survey-sdk 0.2.1 → 0.2.3

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.
Files changed (95) hide show
  1. package/dist/cli/index.js +18 -18
  2. package/dist/cli/index.mjs +14 -14
  3. package/dist/index.d.mts +465 -580
  4. package/dist/index.d.ts +465 -580
  5. package/dist/index.js +1 -1
  6. package/dist/index.mjs +1 -1
  7. package/package.json +6 -4
  8. package/postinstall.js +96 -69
  9. package/templates/AGENT.md +18 -8
  10. package/templates/docs/00-integration/analytics-events-catalog.md +54 -0
  11. package/templates/docs/00-integration/answer-logic-and-navigation.md +50 -0
  12. package/templates/docs/00-integration/aws-deploy.md +281 -0
  13. package/templates/docs/00-integration/client-integration-guide.md +351 -0
  14. package/templates/docs/00-integration/component-checklist.md +55 -22
  15. package/templates/docs/00-integration/constraints.md +49 -4
  16. package/templates/docs/00-integration/custom-field-logic-and-navigation.md +174 -0
  17. package/templates/docs/00-integration/display-logic-and-navigation.md +64 -0
  18. package/templates/docs/00-integration/end-page-logic.md +64 -0
  19. package/templates/docs/00-integration/file-upload-aws.md +116 -0
  20. package/templates/docs/00-integration/logic-fields-catalog.md +105 -0
  21. package/templates/docs/00-integration/partial-save-and-recovery.md +98 -0
  22. package/templates/docs/00-integration/placeholders-and-tokens.md +116 -0
  23. package/templates/docs/00-integration/progress.md +61 -0
  24. package/templates/docs/00-integration/question-display-variants.md +65 -0
  25. package/templates/docs/00-integration/question-numbering.md +51 -0
  26. package/templates/docs/00-integration/question-type-sdk-matrix.md +244 -0
  27. package/templates/docs/00-integration/setup.md +84 -0
  28. package/templates/docs/00-integration/skip-logic-and-navigation.md +80 -0
  29. package/templates/docs/00-integration/survey-lifecycle-analytics.md +94 -0
  30. package/templates/docs/00-integration/useSurveySDK.md +151 -23
  31. package/templates/docs/01-components/01-survey-page.md +76 -54
  32. package/templates/docs/01-components/02-question.md +61 -58
  33. package/templates/docs/01-components/03-rating-scale.md +11 -1
  34. package/templates/docs/01-components/04-star-rating-scale.md +45 -0
  35. package/templates/docs/01-components/05-csat-matrix-scale.md +20 -11
  36. package/templates/docs/01-components/06-likert-matrix-scale.md +14 -4
  37. package/templates/docs/01-components/07-slider-matrix-scale.md +11 -2
  38. package/templates/docs/01-components/08-file-upload-scale.md +23 -51
  39. package/templates/docs/01-components/09-custom-slider-track.md +2 -2
  40. package/templates/docs/01-components/11-progress-bar.md +10 -4
  41. package/templates/docs/01-components/13-matrix-dropdown.md +29 -32
  42. package/templates/docs/01-components/14-intro-page.md +34 -0
  43. package/templates/docs/01-components/15-end-page.md +31 -0
  44. package/templates/docs/01-components/16-paused-page.md +27 -0
  45. package/templates/docs/01-components/17-heatmap-scale.md +75 -0
  46. package/templates/docs/01-components/18-rank-order-scale.md +93 -0
  47. package/templates/docs/01-components/README.md +42 -36
  48. package/templates/docs/02-reference/config-field-index.md +141 -139
  49. package/templates/docs/02-reference/exports.md +149 -0
  50. package/templates/docs/02-reference/question-types/01-rating.md +31 -32
  51. package/templates/docs/02-reference/question-types/04-csat.md +51 -42
  52. package/templates/docs/02-reference/question-types/05-rating-scale.md +16 -11
  53. package/templates/docs/02-reference/question-types/06-slider.md +2 -2
  54. package/templates/docs/02-reference/question-types/07-matrix-cfm.md +44 -30
  55. package/templates/docs/02-reference/question-types/08-matrix-csat.md +4 -26
  56. package/templates/docs/02-reference/question-types/09-matrix-rating.md +29 -13
  57. package/templates/docs/02-reference/question-types/10-slider-matrix.md +15 -4
  58. package/templates/docs/02-reference/question-types/11-file-upload.md +43 -17
  59. package/templates/docs/02-reference/question-types/12-heatmap.md +59 -0
  60. package/templates/docs/02-reference/question-types/13-rank-order.md +101 -0
  61. package/templates/docs/02-reference/question-types/README.md +96 -47
  62. package/templates/docs/02-reference/routing-table.md +33 -18
  63. package/templates/docs/02-reference/value-derivation.md +63 -0
  64. package/templates/docs/03-ui-specs/00-question-shell.md +19 -88
  65. package/templates/docs/03-ui-specs/01-rating.md +18 -52
  66. package/templates/docs/03-ui-specs/02-radio.md +80 -37
  67. package/templates/docs/03-ui-specs/03-text.md +2 -2
  68. package/templates/docs/03-ui-specs/04-csat.md +68 -33
  69. package/templates/docs/03-ui-specs/05-rating-scale.md +21 -18
  70. package/templates/docs/03-ui-specs/06-slider.md +3 -1
  71. package/templates/docs/03-ui-specs/07-matrix-cfm.md +44 -25
  72. package/templates/docs/03-ui-specs/08-matrix-csat-rating.md +19 -43
  73. package/templates/docs/03-ui-specs/09-slider-matrix.md +18 -1
  74. package/templates/docs/03-ui-specs/10-file-upload.md +42 -21
  75. package/templates/docs/03-ui-specs/11-text-and-media.md +29 -29
  76. package/templates/docs/03-ui-specs/12-survey-chrome.md +58 -14
  77. package/templates/docs/03-ui-specs/13-heatmap.md +80 -0
  78. package/templates/docs/03-ui-specs/14-rank-order.md +128 -0
  79. package/templates/docs/03-ui-specs/README.md +16 -14
  80. package/templates/docs/03-ui-specs/shared/custom-slider-track.md +28 -35
  81. package/templates/docs/03-ui-specs/shared/matrix-dropdown.md +5 -0
  82. package/templates/docs/MANIFEST.json +476 -69
  83. package/templates/docs/index.md +82 -30
  84. package/templates/docs/templates/CustomSliderTrack.tsx +144 -0
  85. package/templates/docs/templates/MatrixDropdown.tsx +216 -0
  86. package/templates/docs/templates/Question.tsx +221 -154
  87. package/templates/docs/templates/RankOrderScale.tsx +353 -0
  88. package/templates/docs/templates/deploy-to-aws.sh +114 -0
  89. package/templates/docs/templates/heatmapCoords.ts +58 -0
  90. package/templates/docs/templates/implementation_plan.md +126 -67
  91. package/templates/docs/templates/survey-inventory.schema.json +77 -0
  92. package/templates/docs/templates/surveyUiIcons.tsx +52 -0
  93. package/templates/docs/templates/verify-agent-build.sh +85 -0
  94. package/templates/docs/01-components/04-csat-scale.md +0 -40
  95. package/templates/docs/02-question-types/01-rating.md +0 -44
@@ -0,0 +1,149 @@
1
+ # SDK Public Exports
2
+
3
+ > Import **only** from the package root. Never from `/src/` paths.
4
+
5
+ ```typescript
6
+ import {
7
+ useSurveySDK,
8
+ ACTIONS,
9
+ QUESTION_TYPE,
10
+ type SurveyAction,
11
+ type UseSurveySDKProps,
12
+ type UseSurveySDKReturn,
13
+ type Survey,
14
+ type SurveyQuestion,
15
+ type SurveyPage,
16
+ type SurveyLanguage,
17
+ type SurveyPhase,
18
+ type SpecialPage,
19
+ type SkipLogic,
20
+ type DisplayLogic,
21
+ type AnswerLogic,
22
+ type QuestionDisplayVariant,
23
+ type CustomFieldType,
24
+ type CustomFieldValue,
25
+ type CustomFieldValueMap,
26
+ type LogicConditionEntity,
27
+ type McqQuestion,
28
+ type McqOption,
29
+ type NpsQuestion,
30
+ type NpsScalePoint,
31
+ type CsatQuestion,
32
+ type CsatStatementRow,
33
+ type CsatScaleColumn,
34
+ type TextInputQuestion,
35
+ type CfmMatrixQuestion,
36
+ type CfmMatrixStatementRow,
37
+ type CfmMatrixScaleColumn,
38
+ type RatingMatrixQuestion,
39
+ type RatingMatrixStatementRow,
40
+ type RatingMatrixScaleColumn,
41
+ type SliderMatrixQuestion,
42
+ type SliderMatrixStatementRow,
43
+ type SliderMatrixTickMark,
44
+ type FileUploadQuestion,
45
+ type UploadedFile,
46
+ type TextAndMediaQuestion,
47
+ type HeatmapQuestion,
48
+ type HeatmapRegion,
49
+ type HeatmapClickPoint,
50
+ type HeatmapAnswer,
51
+ type RankOrderQuestion,
52
+ type RankOrderOption,
53
+ type RankOrderAnswers,
54
+ type AnswerValue,
55
+ type MatrixRowAnswers,
56
+ type SurveyAnswers,
57
+ type UploadedFileAnswer,
58
+ type StatementRow,
59
+ type ScaleColumn,
60
+ type ContainerMedia,
61
+ type QuestionMedia,
62
+ matrixColumnStoredValue,
63
+ resolveSurveyQuestionPlaceholders,
64
+ formatAnswerForDisplay,
65
+ resolveQuestionDisplayText,
66
+ applyQuestionDisplayVariants,
67
+ computeActivePathQuestionNumbers,
68
+ applyActivePathQuestionNumbers,
69
+ getVisibleStatementRowsForAnswers,
70
+ getVisibleMcqOptionsForAnswers,
71
+ getVisibleScaleColumnsForAnswers,
72
+ getVisibleMatrixItemsForAnswers,
73
+ getVisibleRankOrderOptionsForAnswers,
74
+ assignRankWithoutDuplicates,
75
+ buildRankOrderFromOrderedOptionIds,
76
+ getOrderedOptionIdsFromRanks,
77
+ normalizeRankOrderAnswers,
78
+ } from '@explorer02/cfm-survey-sdk'; // or @repo/sdk
79
+ ```
80
+
81
+ > **CSAT emoji UI** is **not** exported from the SDK. Implement emoji/star icons client-side (typically `react-icons`). See `03-ui-specs/04-csat.md`.
82
+
83
+ ## Hook contract (authoritative)
84
+
85
+ | Item | Value |
86
+ |------|-------|
87
+ | Answers field | `state.answers` (`SurveyAnswers`) |
88
+ | Custom fields | `options.customFieldValues` (`CustomFieldValueMap`) — stable ref; see [`custom-field-logic-and-navigation.md`](../00-integration/custom-field-logic-and-navigation.md) |
89
+ | Change action | `{ type: 'CHANGE', payload: { questionId, answerValue } }` |
90
+ | Navigation | `'START'`, `'NEXT'`, `'PREVIOUS'`, `'SUBMIT'` |
91
+ | Phase | `state.phase`, `state.specialPage`, `state.canGoBack`, `state.primaryButtonType` |
92
+
93
+ See `MANIFEST.json` `hookContract` and `00-integration/useSurveySDK.md`.
94
+
95
+ ## Question type literals
96
+
97
+ All **11** values of `question.type` (from `QUESTION_TYPE`):
98
+
99
+ `MCQ` · `TEXTFIELD` · `NPS_SCALE` · `CFM_MATRIX` · `CSAT_MATRIX` · `RATING_MATRIX` · `SLIDER_MATRIX` · `FILE_UPLOAD` · `TEXT_AND_MEDIA` · `HEATMAP` · `RANK_ORDER`
100
+
101
+ Dispatch with `question.type === QUESTION_TYPE.CSAT_MATRIX` (or string literal `'CSAT_MATRIX'`).
102
+
103
+ > **Note:** Legacy mapper types `star_rating` / `slider` are not in the `SurveyQuestion` union. API RATING/SLIDER pages map into `NPS_SCALE`, matrix display styles, or `SLIDER_MATRIX`.
104
+
105
+ See `MANIFEST.json` `typeLiterals` and [`question-type-sdk-matrix.md`](../00-integration/question-type-sdk-matrix.md) for routing to docs and components.
106
+
107
+ ## Value derivation
108
+
109
+ - Matrix storage: import `matrixColumnStoredValue` from the package root (do not reimplement).
110
+ - Rank order: `assignRankWithoutDuplicates`, `buildRankOrderFromOrderedOptionIds`, `getOrderedOptionIdsFromRanks`, `normalizeRankOrderAnswers`.
111
+ - Submit mapping: SDK derives API strings at submit/partial-save time — see [`value-derivation.md`](value-derivation.md).
112
+
113
+ ## Visibility helpers (answer logic UI)
114
+
115
+ Pass `customFieldValues` as the optional 4th argument when logic rules reference `CUSTOM_FIELD` entities:
116
+
117
+ ```typescript
118
+ getVisibleMcqOptionsForAnswers(question, answers, allQuestions, customFieldValues?);
119
+ getVisibleMatrixItemsForAnswers(question, answers, allQuestions, customFieldValues?);
120
+ getVisibleStatementRowsForAnswers(question, answers, allQuestions, customFieldValues?);
121
+ getVisibleScaleColumnsForAnswers(question, answers, allQuestions, customFieldValues?);
122
+ getVisibleRankOrderOptionsForAnswers(question, answers, allQuestions, customFieldValues?);
123
+ ```
124
+
125
+ See [`answer-logic-and-navigation.md`](../00-integration/answer-logic-and-navigation.md) and [`custom-field-logic-and-navigation.md`](../00-integration/custom-field-logic-and-navigation.md).
126
+
127
+ ## Question display variants
128
+
129
+ The SDK resolves conditional question text on `state.currentQuestions`. Clients render `question.questionText` as-is — no variant checks required. See [`question-display-variants.md`](../00-integration/question-display-variants.md).
130
+
131
+ Optional helpers: `resolveQuestionDisplayText`, `applyQuestionDisplayVariants`, type `QuestionDisplayVariant`.
132
+
133
+ ## Question numbering
134
+
135
+ Active-path ordinals are on `state.currentQuestions[].questionNumber`. Optional: `computeActivePathQuestionNumbers`, `applyActivePathQuestionNumbers`. See [`question-numbering.md`](../00-integration/question-numbering.md).
136
+
137
+ ## Related integration docs
138
+
139
+ - [`client-integration-guide.md`](../00-integration/client-integration-guide.md)
140
+ - [`question-type-sdk-matrix.md`](../00-integration/question-type-sdk-matrix.md)
141
+ - [`placeholders-and-tokens.md`](../00-integration/placeholders-and-tokens.md)
142
+ - [`partial-save-and-recovery.md`](../00-integration/partial-save-and-recovery.md)
143
+ - [`survey-lifecycle-analytics.md`](../00-integration/survey-lifecycle-analytics.md)
144
+ - [`skip-logic-and-navigation.md`](../00-integration/skip-logic-and-navigation.md)
145
+ - [`display-logic-and-navigation.md`](../00-integration/display-logic-and-navigation.md)
146
+ - [`question-display-variants.md`](../00-integration/question-display-variants.md)
147
+ - [`question-numbering.md`](../00-integration/question-numbering.md)
148
+ - [`answer-logic-and-navigation.md`](../00-integration/answer-logic-and-navigation.md)
149
+ - [`progress.md`](../00-integration/progress.md)
@@ -1,52 +1,51 @@
1
- # Rating Question (NPS 0-10)
1
+ # NPS Question (010)
2
2
 
3
- > **Type**: `'rating'` | **API Source**: `SCALE` with `SCALE_TYPE=TEN_POINT` or `NPS_SCALE`
4
- > **Mapper**: `ratingMapper.ts` | **Component**: `RatingScale`
3
+ > **Type**: `'NPS_SCALE'` | **API Source**: `SCALE` / `NPS_SCALE`
4
+ > **SDK type file**: `fetchSurvey/types/nps.ts` | **Component**: `RatingScale`
5
5
 
6
6
  ## TypeScript Type
7
7
 
8
8
  ```typescript
9
- type RatingQuestion = QuestionBase & {
10
- type: 'rating';
11
- options: SurveyOption[]; // 0-10 with NPS traffic-light colors
12
- minLabel?: string; // Left label (e.g. "Not Likely")
13
- midLabel?: string; // Middle label (e.g. "Neutral")
14
- maxLabel?: string; // Right label (e.g. "Extremely Likely")
15
- midLabelIndex?: number; // Fractional position for mid-label CSS
16
- reverseScaleOrder?: boolean; // Render high→low
17
- buttonVariant?: 'radio' | 'numbered' | 'emoji';
9
+ type NpsQuestion = {
10
+ type: 'NPS_SCALE';
11
+ id: string;
12
+ questionText: string;
13
+ questionDescription?: string;
14
+ options: NpsScalePoint[];
15
+ minLabel?: string;
16
+ midLabel?: string;
17
+ maxLabel?: string;
18
+ midLabelIndex?: number;
19
+ reverseScaleOrder: boolean;
20
+ buttonStyle: 'standard' | 'numbered' | 'emoji';
21
+ required: boolean;
22
+ // ... shell fields
18
23
  };
19
24
  ```
20
25
 
21
26
  ## Answer Shape: `number`
22
- Example: `7` (the selected badge value)
23
-
24
- ## Options Auto-Generation
25
- If the API provides no explicit options, the SDK generates 0-10:
26
- ```typescript
27
- Array.from({ length: 11 }, (_, i) => ({
28
- id: String(i), label: String(i), value: i, color: getColor(i)
29
- }));
30
- ```
31
27
 
32
- ## NPS Traffic-Light Colors
33
- ```
34
- 0: #e2001a (red) 3: #f18b00 (orange) 6: #fcd900 (yellow)
35
- 1: #e4251b 4: #f7b200 7: #9fca00 (lime)
36
- 2: #ec610a 5: #fcd900 8: #6bb300 (green)
37
- 9: #339a00
38
- 10: #008000
39
- ```
28
+ Example: `7` (the selected badge value)
40
29
 
41
30
  ## Mid-Label Positioning
31
+
42
32
  ```typescript
43
- // CSS left percentage for mid-label
44
33
  const left = (midLabelIndex / (options.length - 1)) * 100;
45
- // For 11-point scale: midLabelIndex defaults to 7.5
46
34
  ```
47
35
 
48
36
  ## Rendering Guidance
37
+
49
38
  - Display as horizontal row of numbered badge buttons
50
- - Each badge uses `option.color` as background
51
39
  - Selected badge: emphasized border/scale, all others dimmed
52
40
  - Labels positioned: minLabel (left), midLabel (calculated %), maxLabel (right)
41
+
42
+ ## SDK Integration Checklist (agent)
43
+
44
+ - [ ] Type literal: `QUESTION_TYPE.NPS_SCALE`
45
+ - [ ] Answer stored as: `number` (selected scale point value)
46
+ - [ ] onAction CHANGE payload: `{ questionId, answerValue: number }`
47
+ - [ ] Visibility helper: `getVisibleScaleColumnsForAnswers` when scale points have answer logic
48
+ - [ ] Custom fields: pass `customFieldValues` as 4th arg to scale visibility helper when rules reference CRM fields
49
+ - [ ] Logic features: skip ✓ display ✓ answer ✓ (columns) variants ✓ numbering ✓
50
+ - [ ] Performance: single horizontal row — no matrix filtering overhead
51
+ - [ ] Matrix row: [`question-type-sdk-matrix.md#nps_scale`](../../00-integration/question-type-sdk-matrix.md#nps_scale)
@@ -1,54 +1,63 @@
1
- # CSAT Question (Satisfaction Scale)
1
+ # CSAT Matrix Question (Satisfaction Grid)
2
2
 
3
- > **Type**: `'csat'` | **API Source**: `SCALE` with `SCALE_TYPE=CSAT` or ≤5 options
4
- > **Mapper**: `ratingMapper.ts` (CSAT branch) | **Component**: `CsatScale`
3
+ > **Type**: `'CSAT_MATRIX'` | **API Source**: `CSAT_MATRIX`
4
+ > **SDK type**: `CsatQuestion` | **Component**: `CsatMatrixScale`
5
5
 
6
6
  ## TypeScript Type
7
7
 
8
8
  ```typescript
9
- type CsatQuestion = QuestionBase & {
10
- type: 'csat';
11
- options: SurveyOption[]; // Usually 1-5 satisfaction levels
12
- minLabel?: string; // "Very Dissatisfied"
13
- maxLabel?: string; // "Very Satisfied"
14
- buttonType?: SurveyButtonType; // 'emoji' | 'star' | 'numbered' | 'radio'
15
- hasNotApplicable?: boolean; // N/A option available
16
- reverseScaleOrder?: boolean; // Render high→low
17
- labelPosition?: 'top' | 'bottom' | 'hidden';
9
+ type CsatQuestion = {
10
+ type: 'CSAT_MATRIX';
11
+ id: string;
12
+ statementRows: CsatStatementRow[];
13
+ scaleColumns: CsatScaleColumn[];
14
+ displayStyle: 'emoji' | 'star' | 'standard' | 'numbered' | 'dropdown' | 'selectbox' | 'graphics';
15
+ gridLayout: 'standard' | 'carousel' | 'dropdown';
16
+ hasNotApplicableOption: boolean;
17
+ reverseScaleOrder: boolean;
18
+ // ... shell fields, skipLogics?, displayLogic?
18
19
  };
20
+
21
+ type CsatStatementRow = { id: string; statementText: string; answerLogic?: AnswerLogic };
22
+ type CsatScaleColumn = { id: string; label: string; answerLogic?: AnswerLogic };
19
23
  ```
20
24
 
21
- ## Answer Shape: `number | null`
22
- Example: `4` or `null` (N/A selected)
25
+ Filter visible rows/columns with `getVisibleMatrixItemsForAnswers` before rendering (see [`answer-logic-and-navigation.md`](../../00-integration/answer-logic-and-navigation.md)).
23
26
 
24
- ## Rendering by `buttonType`
27
+ ## Answer Shape: `MatrixRowAnswers`
25
28
 
26
- | `buttonType` | Render As |
27
- |-------------|-----------|
28
- | `'emoji'` | Sentiment face icons from `CsatEmojiMapping` |
29
- | `'star'` | Star icons from `CsatStarIcons` (filled/empty) |
30
- | `'numbered'` | Numeric badge buttons |
31
- | `'radio'` | Standard radio circles |
32
- | `'graphics'` | Emoji slider (use `CustomSliderTrack`) |
33
-
34
- ## Star Rating Pattern
35
- ```tsx
36
- {options.map((opt, i) => {
37
- const numericValue = typeof opt.value === 'number' ? opt.value : i + 1;
38
- const isActive = typeof selectedValue === 'number' && numericValue <= selectedValue;
39
- return (
40
- <button onClick={() => onSelect(opt.value)}>
41
- {isActive ? CsatStarIcons.filled : CsatStarIcons.empty}
42
- </button>
43
- );
44
- })}
45
- ```
29
+ Store column **`id`** per row (not label text):
46
30
 
47
- ## Emoji Pattern
48
- ```tsx
49
- {options.map((opt, i) => (
50
- <button onClick={() => onSelect(opt.value)}>
51
- {CsatEmojiMapping[typeof opt.value === 'number' ? opt.value : i + 1]}
52
- </button>
53
- ))}
31
+ ```typescript
32
+ import { matrixColumnStoredValue } from '@explorer02/cfm-survey-sdk';
33
+
34
+ // { [rowId]: columnId | columnId[] | null }
35
+ { "row_1": "col_5", "row_2": null }
54
36
  ```
37
+
38
+ Submit maps ids → API label/number via SDK `resolveSubmitValues`.
39
+
40
+ ## Rendering by `displayStyle`
41
+
42
+ | `displayStyle` | Cell Rendering |
43
+ |----------------|----------------|
44
+ | `'emoji'` | Sentiment faces — implement client-side with `react-icons` (not SDK exports) |
45
+ | `'star'` | Star icons — implement client-side with `react-icons` |
46
+ | `'numbered'` | Numeric badge buttons |
47
+ | `'dropdown'` | Dropdown per row (`MatrixDropdown`) |
48
+ | `'graphics'` | Emoji slider per row (`CustomSliderTrack`) |
49
+
50
+ ## N/A Column
51
+
52
+ When `hasNotApplicableOption` is true, selecting N/A stores `null` for that row — a valid answer.
53
+
54
+ ## SDK Integration Checklist (agent)
55
+
56
+ - [ ] Type literal: `QUESTION_TYPE.CSAT_MATRIX`
57
+ - [ ] Answer stored as: `MatrixRowAnswers` — column **`id`** per row via `matrixColumnStoredValue`
58
+ - [ ] onAction CHANGE payload: `{ questionId, answerValue: MatrixRowAnswers }` (merge row updates)
59
+ - [ ] Visibility helper: `getVisibleMatrixItemsForAnswers(question, answers, allQuestions, customFieldValues?)`
60
+ - [ ] Custom fields: 4th arg on matrix visibility helper when logic references CRM fields
61
+ - [ ] Logic features: skip ✓ display ✓ answer ✓ (rows + columns) variants ✓ numbering ✓
62
+ - [ ] Performance: render only visible rows/cols; memoize emoji/star maps for graphics mode
63
+ - [ ] Matrix row: [`question-type-sdk-matrix.md#csat_matrix`](../../00-integration/question-type-sdk-matrix.md#csat_matrix)
@@ -1,26 +1,31 @@
1
- # Rating Scale Question (Stars/Emoji)
1
+ # Star Rating Question (Stars/Emoji)
2
2
 
3
- > **Type**: `'rating_scale'` | **API Source**: `SCALE` with `SCALE_TYPE=STAR/EMOJI/FIVE_POINT`
4
- > **Mapper**: `ratingMapper.ts` (rating_scale branch) | **Component**: `RatingScale`
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 RatingScaleQuestion = QuestionBase & {
10
- type: 'rating_scale';
11
- options: SurveyOption[]; // Typically 1-5 or 1-10 (no NPS colors)
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?: boolean;
17
- scaleStyle?: 'star' | 'emoji';
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 `'rating'`
27
+ ## Key Difference from `'nps'`
28
+
24
29
  - No NPS traffic-light colors on options
25
- - Rendered as stars, emojis, or plain icons — not numbered badges
26
- - Use `scaleStyle` to determine icon type
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**: `SCALE` with `INPUT_TYPE=SLIDER`
4
- > **Mapper**: `ratingMapper.ts` (slider branch) | **Component**: `CustomSliderTrack` or native `<input type="range">`
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 CFM Question (Likert Grid)
1
+ # CFM Matrix Question (Likert Grid)
2
2
 
3
- > **Type**: `'matrix'` with `subType: 'CFM_MATRIX'` | **API Source**: `CFM_MATRIX`
4
- > **Mapper**: `cfmMatrixMapper.ts` | **Component**: `LikertMatrixScale`
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 MatrixQuestion = QuestionBase & {
10
- type: 'matrix';
11
- subType: 'CFM_MATRIX';
12
- rows: MatrixRow[]; // Statements to rate
13
- columns: MatrixColumn[]; // Shared answer options per row
14
- buttonType?: SurveyButtonType;
15
- hasNotApplicable?: boolean;
16
- reverseScaleOrder?: boolean;
17
- labels?: string[]; // Anchor labels above columns
18
- matrixFormat?: 'standard' | 'carousel' | 'dropdown';
19
- matrixType?: 'likert' | 'bipolar';
20
- answerType?: 'single' | 'multiple';
21
- transposeTable?: boolean;
22
- repeatScale?: boolean;
23
- enableScale?: boolean;
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 MatrixRow = { id: string; text: string; rightText?: string; };
27
- type MatrixColumn = { id: string; label: string; value: string | number | null; color?: string; };
27
+ type CfmMatrixStatementRow = {
28
+ id: string;
29
+ statementText: string;
30
+ oppositeStatementText?: string;
31
+ };
28
32
  ```
29
33
 
30
- ## Answer Shape: `MatrixAnswerMap`
34
+ ## Answer Shape: `MatrixRowAnswers`
35
+
31
36
  ```typescript
32
- { "row1_id": "column_value", "row2_id": "column_value", "row3_id": null }
33
- // null = N/A selected for that row
37
+ { "row1_id": columnValue, "row2_id": null }
34
38
  ```
35
39
 
36
40
  ## Rendering Guidance
37
- - **Standard format**: Grid table — rows on left, columns as headers
38
- - **Carousel format**: Show one row at a time with prev/next
39
- - **Dropdown format**: Each row has a dropdown selector for its column value
40
- - Likert: unipolar text labels (e.g. "Strongly Disagree" → "Strongly Agree")
41
- - Bipolar: `row.text` on left + `row.rightText` on right
42
- - If `hasNotApplicable` add N/A column with `value: null`
43
- - `onSelect` receives the full `MatrixAnswerMap` object on each change
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 CSAT Question (Satisfaction Grid)
1
+ # CSAT Matrix Question (legacy reference)
2
2
 
3
- > **Type**: `'matrix'` with `subType: 'CSAT_MATRIX'` | **API Source**: `CSAT_MATRIX`
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
- ## TypeScript Type
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
- ## Key Difference from CFM_MATRIX
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**: `'rating_matrix'` | **API Source**: `RATING_MATRIX`
4
- > **Mapper**: `ratingMatrixMapper.ts` → routed to `mapMatrixQuestion` | **Component**: `CsatMatrixScale`
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 = QuestionBase & {
10
- type: 'rating_matrix';
11
- rows: MatrixRow[];
12
- columns: MatrixColumn[]; // Rating columns with NPS-style colors
9
+ type RatingMatrixQuestion = {
10
+ type: 'RATING_MATRIX';
11
+ statementRows: StatementRow[];
12
+ scaleColumns: ScaleColumn[];
13
13
  minLabel?: string;
14
14
  maxLabel?: string;
15
- buttonType?: SurveyButtonType;
16
- hasNotApplicable?: boolean;
17
- reverseScaleOrder?: boolean;
18
- labels?: string[];
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
- - Columns carry traffic-light `color` values (like NPS rating)
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: `MatrixAnswerMap`
28
- Same pattern: `{ "row_id": column_value | null }`
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**: `'slider_matrix'` | **API Source**: `SLIDER_MATRIX`
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: 'slider_matrix';
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: `MatrixAnswerMap`
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 `MatrixAnswerMap` with all row values
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)