@explorer02/cfm-survey-sdk 0.1.9 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/package.json +1 -1
  2. package/postinstall.js +5 -0
  3. package/templates/AGENT.md +4 -2
  4. package/templates/docs/00-integration/component-checklist.md +61 -0
  5. package/templates/docs/00-integration/constraints.md +17 -0
  6. package/templates/docs/01-components/01-survey-page.md +2 -0
  7. package/templates/docs/01-components/02-question.md +43 -56
  8. package/templates/docs/01-components/03-rating-scale.md +2 -0
  9. package/templates/docs/01-components/04-csat-scale.md +3 -1
  10. package/templates/docs/01-components/05-csat-matrix-scale.md +2 -0
  11. package/templates/docs/01-components/06-likert-matrix-scale.md +2 -0
  12. package/templates/docs/01-components/07-slider-matrix-scale.md +2 -0
  13. package/templates/docs/01-components/08-file-upload-scale.md +2 -0
  14. package/templates/docs/01-components/09-custom-slider-track.md +2 -0
  15. package/templates/docs/01-components/10-header-footer.md +3 -1
  16. package/templates/docs/01-components/11-progress-bar.md +2 -0
  17. package/templates/docs/01-components/12-language-selector.md +2 -0
  18. package/templates/docs/01-components/13-matrix-dropdown.md +2 -0
  19. package/templates/docs/01-components/README.md +4 -2
  20. package/templates/docs/02-reference/config-field-index.md +158 -0
  21. package/templates/docs/02-reference/routing-table.md +16 -16
  22. package/templates/docs/03-ui-specs/00-question-shell.md +102 -0
  23. package/templates/docs/03-ui-specs/01-rating.md +80 -0
  24. package/templates/docs/03-ui-specs/02-radio.md +57 -0
  25. package/templates/docs/03-ui-specs/03-text.md +51 -0
  26. package/templates/docs/03-ui-specs/04-csat.md +57 -0
  27. package/templates/docs/03-ui-specs/05-rating-scale.md +49 -0
  28. package/templates/docs/03-ui-specs/06-slider.md +42 -0
  29. package/templates/docs/03-ui-specs/07-matrix-cfm.md +66 -0
  30. package/templates/docs/03-ui-specs/08-matrix-csat-rating.md +65 -0
  31. package/templates/docs/03-ui-specs/09-slider-matrix.md +61 -0
  32. package/templates/docs/03-ui-specs/10-file-upload.md +54 -0
  33. package/templates/docs/03-ui-specs/11-text-and-media.md +49 -0
  34. package/templates/docs/03-ui-specs/12-survey-chrome.md +60 -0
  35. package/templates/docs/03-ui-specs/README.md +80 -0
  36. package/templates/docs/03-ui-specs/shared/custom-slider-track.md +52 -0
  37. package/templates/docs/03-ui-specs/shared/matrix-dropdown.md +38 -0
  38. package/templates/docs/MANIFEST.json +27 -1
  39. package/templates/docs/index.md +28 -13
  40. package/templates/docs/templates/Question.tsx +243 -0
  41. package/templates/docs/templates/implementation_plan.md +40 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@explorer02/cfm-survey-sdk",
3
- "version": "0.1.9",
3
+ "version": "0.2.1",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.mjs",
6
6
  "types": "dist/index.d.ts",
package/postinstall.js CHANGED
@@ -53,8 +53,13 @@ Do NOT run `cfm-sdk init`, read `survey-config.json`, or use any setup wizard.
53
53
 
54
54
  RULE 2 — DEEP CONTEXT BEFORE CODE:
55
55
  Before writing React code, read EVERY file in `node_modules/@explorer02/cfm-survey-sdk/docs/01-components/`.
56
+ Read `docs/00-integration/component-checklist.md` and `docs/03-ui-specs/` for EVERY question type in the fetched survey (blocking for matrix, slider_matrix, file_upload).
57
+ Copy `docs/templates/Question.tsx` as your Question dispatcher — do NOT use stub/default fallback branches.
56
58
  Copy `node_modules/@explorer02/cfm-survey-sdk/docs/templates/implementation_plan.md` to project root and fill it in.
57
59
 
60
+ RULE 2b — NO STUB PLACEHOLDERS:
61
+ Never render "not yet implemented" or similar placeholder text. If a type is in the survey, implement its scale component.
62
+
58
63
  RULE 3 — AUTO-PROCEED:
59
64
  After the implementation plan is complete, proceed to build without waiting for approval.
60
65
  The workflow requires 3 client inputs: Prompt/Mockup, Instance ID (JWT), Deploy Confirmation.
@@ -21,11 +21,13 @@ Import from whatever appears in `package.json`:
21
21
  | 1 | Scaffold React app — `00-integration/setup.md` |
22
22
  | 2 | Ask client for instanceId JWT |
23
23
  | 3 | Read `useSurveySDK.md` — hook contract |
24
- | 4 | Read all `01-components/`; copy `templates/implementation_plan.md` → project root |
25
- | 5 | Build UI per blueprints + `constraints.md` |
24
+ | 4 | Read all `01-components/`; inventory survey types; read `03-ui-specs/` per type; copy `templates/Question.tsx` + `implementation_plan.md` |
25
+ | 5 | Build UI create all scale files from `component-checklist.md`; no stub placeholders |
26
26
  | 6 | Verify build checklist |
27
27
  | 7 | Deploy on client confirmation |
28
28
 
29
29
  **Do NOT** run `cfm-sdk init`, read `survey-config.json`, or use any setup wizard.
30
30
 
31
+ **Do NOT** render `"not yet implemented"` or default fallback stubs in `Question.tsx`. Copy `docs/templates/Question.tsx` and create all required scale components.
32
+
31
33
  Follow the master index strictly. Do not guess SDK internals. Do not import from `/src/` paths.
@@ -0,0 +1,61 @@
1
+ # Required Component Files Checklist
2
+
3
+ > **Blocking gate before Phase 5 (BUILD).** After fetching the survey with `instanceId`, list every `(type, subType)` pair and ensure all required files exist.
4
+
5
+ ## Step 1: Inventory Question Types
6
+
7
+ From `survey.pages`, collect unique combinations:
8
+
9
+ | questionId | type | subType (if matrix) |
10
+ |------------|------|---------------------|
11
+ | | | |
12
+
13
+ ## Step 2: Create Required Files
14
+
15
+ | If survey contains | Agent MUST create before `npm run build` | UI spec |
16
+ |--------------------|------------------------------------------|---------|
17
+ | `rating` | `RatingScale.tsx` | `03-ui-specs/01-rating.md` |
18
+ | `csat` | `CsatScale.tsx` | `03-ui-specs/04-csat.md` |
19
+ | `rating_scale` | Reuse `CsatScale.tsx` or dedicated component | `03-ui-specs/05-rating-scale.md` |
20
+ | `slider` | `CustomSliderTrack.tsx` + wrapper | `03-ui-specs/06-slider.md` |
21
+ | `matrix` + `CFM_MATRIX` | `LikertMatrixScale.tsx`, `MatrixDropdown.tsx` | `03-ui-specs/07-matrix-cfm.md` |
22
+ | `matrix` + `CSAT_MATRIX` or `RATING_MATRIX` | `CsatMatrixScale.tsx`, `MatrixDropdown.tsx`, `CustomSliderTrack.tsx` | `03-ui-specs/08-matrix-csat-rating.md` |
23
+ | `slider_matrix` | `SliderMatrixScale.tsx`, `CustomSliderTrack.tsx` | `03-ui-specs/09-slider-matrix.md` |
24
+ | `file_upload` | `FileUploadScale.tsx` | `03-ui-specs/10-file-upload.md` |
25
+ | `radio`, `text`, `text_and_media` | Inline in `Question.tsx` | `03-ui-specs/02-radio.md`, `03-text.md`, `11-text-and-media.md` |
26
+
27
+ Always create **`Question.tsx`** from [`templates/Question.tsx`](../templates/Question.tsx).
28
+
29
+ ## Matrix subType Routing (CRITICAL)
30
+
31
+ `question.type === 'matrix'` alone renders **nothing**. You MUST branch on `subType`:
32
+
33
+ ```tsx
34
+ {question.type === 'matrix' && question.subType === 'CFM_MATRIX' && (
35
+ <LikertMatrixScale question={question} selectedValue={...} onSelect={onSelect} />
36
+ )}
37
+
38
+ {question.type === 'matrix' && (question.subType === 'CSAT_MATRIX' || question.subType === 'RATING_MATRIX') && (
39
+ <CsatMatrixScale question={question} selectedValue={...} onSelect={onSelect} />
40
+ )}
41
+ ```
42
+
43
+ ## Shared Primitives
44
+
45
+ | File | Used by |
46
+ |------|---------|
47
+ | `CustomSliderTrack.tsx` | `slider_matrix`, CSAT matrix `graphics`, standalone `slider` |
48
+ | `MatrixDropdown.tsx` | `LikertMatrixScale`, `CsatMatrixScale` vertical/dropdown modes |
49
+
50
+ Specs: `03-ui-specs/shared/custom-slider-track.md`, `03-ui-specs/shared/matrix-dropdown.md`
51
+
52
+ ## Step 3: Verify Before Build
53
+
54
+ - [ ] Every type in the survey inventory has a matching component file
55
+ - [ ] `Question.tsx` copied from `docs/templates/Question.tsx` with all branches wired
56
+ - [ ] No `default` fallback rendering stub text (see `constraints.md` §7)
57
+ - [ ] Grep project: `not yet implemented` → **zero matches**
58
+
59
+ ```bash
60
+ grep -r "not yet implemented" src/ components/ app/ 2>/dev/null || true
61
+ ```
@@ -40,6 +40,22 @@ Survey UI files importing the SDK must be client components. Next.js: `'use clie
40
40
 
41
41
  Define `SURVEY_PLACEHOLDERS` outside the component — inline objects cause infinite re-fetch.
42
42
 
43
+ ## 7. No Stub Placeholders (CRITICAL)
44
+
45
+ **FORBIDDEN** in `Question.tsx` or any scale component:
46
+
47
+ - Text like `"not yet implemented"`, `"coming soon"`, or any placeholder error message
48
+ - `default` / `else` branches in the dispatcher that render stub UI instead of the real component
49
+ - Empty `<div>` where an interactive scale component should be
50
+
51
+ If a question type appears in the fetched survey, its component **must** be fully implemented before shipping. Read the matching `03-ui-specs/` doc and create the required files listed in `component-checklist.md`.
52
+
53
+ **Phase 6 verification:** grep the project for stub text — must return zero matches:
54
+
55
+ ```bash
56
+ grep -r "not yet implemented" src/ components/ app/ 2>/dev/null || true
57
+ ```
58
+
43
59
  ---
44
60
 
45
61
  ## Troubleshooting
@@ -52,3 +68,4 @@ Define `SURVEY_PLACEHOLDERS` outside the component — inline objects cause infi
52
68
  | Validation errors but no scroll | Add `id={question.id}` to question wrapper |
53
69
  | Survey data is null, no error | Invalid/expired `instanceId` — ask client for fresh JWT |
54
70
  | CSAT emojis missing | `npm install react-icons` |
71
+ | Grey "not yet implemented" text on questions | Copy `docs/templates/Question.tsx`; create scale components per `component-checklist.md`; route matrix by `subType` |
@@ -1,5 +1,7 @@
1
1
  # Survey Page Orchestrator Architectural Blueprint
2
2
 
3
+ > **UI spec (authoritative):** `03-ui-specs/12-survey-chrome.md`
4
+ > **Reference implementation:** `apps/client/src/components/SurveyPage.tsx`
3
5
  > **Target Component**: `SurveyPage`
4
6
  > **Role**: The main entry point that wires the UI to the `useSurveySDK` hook, manages loading/error states, orchestrates pagination, and controls submission.
5
7
 
@@ -1,8 +1,19 @@
1
1
  # Question Dispatcher Architectural Blueprint
2
2
 
3
+ > **UI spec (authoritative):** `03-ui-specs/00-question-shell.md`
4
+ > **Canonical template:** [`templates/Question.tsx`](../templates/Question.tsx) — copy verbatim, then create imported components
5
+ > **Monorepo reference:** `apps/client/src/components/Question.tsx` (not available in npm installs)
3
6
  > **Target Component**: `Question`
4
7
  > **Role**: Wrapper card component that routes to the correct scale component based on `question.type`.
5
8
 
9
+ ## Start Here (CRITICAL)
10
+
11
+ 1. Copy [`docs/templates/Question.tsx`](../templates/Question.tsx) into your project.
12
+ 2. Create every imported scale component — see [`component-checklist.md`](../00-integration/component-checklist.md).
13
+ 3. Read `03-ui-specs/` for each type in your fetched survey **before** editing the dispatcher.
14
+
15
+ **Do NOT** write a partial skeleton with `default` fallbacks or `"not yet implemented"` messages.
16
+
6
17
  ## Core Responsibility
7
18
  Render a visually separated container (card) for each question. Handle rich text parsing, required asterisks, description text, and error validation messages. Most importantly, it MUST act as an exhaustive switch statement dispatching to ALL supported question types.
8
19
 
@@ -10,17 +21,34 @@ Render a visually separated container (card) for each question. Handle rich text
10
21
 
11
22
  The agent MUST handle EVERY SINGLE ONE of these `question.type` values. Failure to handle them will result in blank UI or broken surveys.
12
23
 
13
- 1. **`rating`**: Renders `RatingScale`. This covers NPS, Stars, Emoji, and generic numeric scales.
24
+ 1. **`rating`**: Renders `RatingScale`. This covers NPS scales.
14
25
  2. **`csat`**: Renders `CsatScale`. This covers CSAT specific faces/icons.
15
- 3. **`radio`**: Renders inline MCQ radio buttons. (Can be implemented inside this file or separately).
26
+ 3. **`radio`**: Renders inline MCQ radio buttons.
16
27
  4. **`text`**: Renders an inline `<textarea>` or `<input>`.
17
- 5. **`matrix`**:
28
+ 5. **`matrix`** — **requires `subType`**:
18
29
  - If `subType === 'CFM_MATRIX'`, render `LikertMatrixScale`
19
30
  - If `subType === 'CSAT_MATRIX'` or `'RATING_MATRIX'`, render `CsatMatrixScale`
31
+ - Routing on `type === 'matrix'` alone renders **nothing**
20
32
  6. **`slider_matrix`**: Renders `SliderMatrixScale`
21
33
  7. **`file_upload`**: Renders `FileUploadScale`
22
- 8. **`text_and_media`**: Renders inline `<video>` or `<img>` based on `question.mediaUrl`.
23
- - *Note: `text_and_media` questions may NOT have user input. Do not render a scale for them.*
34
+ 8. **`text_and_media`**: Renders inline `<video>` or `<img>` based on `question.mediaUrl`. No answer input.
35
+ 9. **`rating_scale`**: Star/emoji scale see `03-ui-specs/05-rating-scale.md`
36
+ 10. **`slider`**: Standalone slider — see `03-ui-specs/06-slider.md`
37
+
38
+ ## Forbidden Anti-Patterns
39
+
40
+ ```tsx
41
+ // ❌ FORBIDDEN — never ship this
42
+ default:
43
+ return <p>Question type "{question.type}" is not yet implemented in this client.</p>;
44
+
45
+ // ❌ FORBIDDEN — matrix without subType
46
+ {question.type === 'matrix' && <SomeMatrix />}
47
+
48
+ // ✅ REQUIRED — matrix with subType
49
+ {question.type === 'matrix' && question.subType === 'CFM_MATRIX' && <LikertMatrixScale ... />}
50
+ {question.type === 'matrix' && (question.subType === 'CSAT_MATRIX' || question.subType === 'RATING_MATRIX') && <CsatMatrixScale ... />}
51
+ ```
24
52
 
25
53
  ## Container UI Structure
26
54
 
@@ -45,61 +73,20 @@ Every question MUST be wrapped in a standard HTML `<section>` to visually separa
45
73
 
46
74
  4. **Validation Error Banner**:
47
75
  - If `validationError` prop is passed, render a highly visible banner below the scale.
48
- - Example: Red border-left, red background, bold text.
49
76
 
50
77
  ## Hover Tooltips & Micro-interactions
51
78
  - Focus states on text inputs MUST use the brand primary color (e.g., magenta `#e20074` for Telekom).
52
79
  - Radio button wrappers should have a subtle background hover effect (e.g., `hover:bg-pink-50`).
53
80
 
54
- ## Example Architectural Skeleton
81
+ ## Props Contract
55
82
 
56
- ```tsx
57
- <section id={question.id} className="space-y-6 rounded-xl border border-gray-200 bg-white p-6 md:p-8 shadow-sm transition-all hover:shadow-md">
58
-
59
- {/* HEADING */}
60
- <h2 className="text-lg md:text-xl font-semibold leading-relaxed text-gray-900 flex items-start gap-1">
61
- <span dangerouslySetInnerHTML={{ __html: question.text }} className="prose prose-sm max-w-none" />
62
- {question.required && <span className="text-[#e20074] shrink-0">*</span>}
63
- </h2>
64
-
65
- {/* DESCRIPTION */}
66
- {question.description && (
67
- <div className="text-sm text-gray-600 mt-2 leading-relaxed prose prose-sm max-w-none" dangerouslySetInnerHTML={{ __html: question.description }} />
68
- )}
69
-
70
- {/* DISPATCHER */}
71
- <div className="pt-4">
72
- {question.type === 'rating' && <RatingScale ... />}
73
- {question.type === 'csat' && <CsatScale ... />}
74
- {question.type === 'slider_matrix' && <SliderMatrixScale ... />}
75
- {question.type === 'file_upload' && <FileUploadScale ... />}
76
- {question.type === 'matrix' && question.subType === 'CFM_MATRIX' && <LikertMatrixScale ... />}
77
- {question.type === 'matrix' && (question.subType === 'CSAT_MATRIX' || question.subType === 'RATING_MATRIX') && <CsatMatrixScale ... />}
78
-
79
- {question.type === 'radio' && (
80
- // Inline Radio implementation
81
- // Make sure to match brand hover colors!
82
- )}
83
-
84
- {question.type === 'text' && (
85
- // Inline Textarea implementation
86
- // Handle character limit `question.maxCharacterCount`
87
- )}
88
-
89
- {question.type === 'text_and_media' && (
90
- // Display media (image/video) based on question properties
91
- // This handles CONTENT blocks.
92
- )}
93
- </div>
94
-
95
- {/* ERROR BANNER */}
96
- {validationError && (
97
- <div className="mt-6 rounded-lg border-l-4 border-l-[#e20074] bg-red-50 p-4">
98
- <p className="text-sm font-bold text-gray-900 leading-tight flex items-center gap-2">
99
- <span className="text-[#e20074]">⚠</span> {validationError}
100
- </p>
101
- </div>
102
- )}
103
-
104
- </section>
83
+ ```typescript
84
+ type QuestionProps = {
85
+ question: SurveyQuestion;
86
+ selectedValue?: AnswerValue;
87
+ validationError?: string;
88
+ onSelect: (value: AnswerValue) => void;
89
+ };
105
90
  ```
91
+
92
+ Wire `onSelect` → `onAction({ type: 'CHANGE', payload: { questionId, value } })`.
@@ -1,5 +1,7 @@
1
1
  # Rating Scale Architectural Blueprint
2
2
 
3
+ > **UI spec (authoritative):** `03-ui-specs/01-rating.md` (NPS) · `03-ui-specs/05-rating-scale.md` (star/emoji gap)
4
+ > **Reference implementation:** `apps/client/src/components/RatingScale.tsx`
3
5
  > **Target Component**: `RatingScale`
4
6
  > **Handles**: `type: 'rating'`, `type: 'rating_scale'`
5
7
 
@@ -1,6 +1,8 @@
1
1
  # CSAT & Rating Architectural Blueprints
2
2
 
3
- > **Target Components**: `CsatScale`, `RatingScale`, `CsatMatrixScale`
3
+ > **UI spec (authoritative):** `03-ui-specs/04-csat.md`
4
+ > **Reference implementation:** `apps/client/src/components/CsatScale.tsx`
5
+ > **Target Components**: `CsatScale`
4
6
  > **Handles**: `type: 'csat'`, `'rating'`, `'rating_scale'`, CSAT matrices.
5
7
 
6
8
  ## Core Responsibility
@@ -1,5 +1,7 @@
1
1
  # CSAT Matrix Architectural Blueprint
2
2
 
3
+ > **UI spec (authoritative):** `03-ui-specs/08-matrix-csat-rating.md`
4
+ > **Reference implementation:** `apps/client/src/components/CsatMatrixScale.tsx`
3
5
  > **Target Component**: `CsatMatrixScale`
4
6
  > **Handles**: `type: 'matrix'` (CSAT_MATRIX and RATING_MATRIX subTypes)
5
7
 
@@ -1,5 +1,7 @@
1
1
  # Likert Matrix Architectural Blueprint
2
2
 
3
+ > **UI spec (authoritative):** `03-ui-specs/07-matrix-cfm.md`
4
+ > **Reference implementation:** `apps/client/src/components/LikertMatrixScale.tsx`
3
5
  > **Target Component**: `LikertMatrixScale`
4
6
  > **Handles**: `type: 'matrix'` (CFM_MATRIX subType)
5
7
 
@@ -1,5 +1,7 @@
1
1
  # Slider Matrix Architectural Blueprint
2
2
 
3
+ > **UI spec (authoritative):** `03-ui-specs/09-slider-matrix.md`
4
+ > **Reference implementation:** `apps/client/src/components/SliderMatrixScale.tsx`
3
5
  > **Target Component**: `SliderMatrixScale`
4
6
  > **Handles**: `type: 'slider_matrix'`
5
7
 
@@ -1,5 +1,7 @@
1
1
  # File Upload Architectural Blueprint
2
2
 
3
+ > **UI spec (authoritative):** `03-ui-specs/10-file-upload.md`
4
+ > **Reference implementation:** `apps/client/src/components/FileUploadScale.tsx`
3
5
  > **Target Component**: `FileUploadScale`
4
6
  > **Handles**: `type: 'file_upload'`
5
7
 
@@ -1,5 +1,7 @@
1
1
  # Custom Slider Track Architectural Blueprint
2
2
 
3
+ > **UI spec (authoritative):** `03-ui-specs/shared/custom-slider-track.md`
4
+ > **Reference implementation:** `apps/client/src/components/CustomSliderTrack.tsx`
3
5
  > **Target Component**: `CustomSliderTrack`
4
6
  > **Used By**: `SliderMatrixScale`, `CsatMatrixScale`, `CsatScale`
5
7
 
@@ -1,6 +1,8 @@
1
1
  # Theme & Logo Engineering Blueprint
2
2
 
3
- > **Target Components**: `Header`, Global Styles
3
+ > **UI spec (authoritative):** `03-ui-specs/12-survey-chrome.md`
4
+ > **Reference implementation:** `apps/client/src/components/Header.tsx`, `Footer.tsx`
5
+ > **Target Components**: `Header`, `Footer`
4
6
  > **Handles**: Branding, Mockup Replication
5
7
 
6
8
  ## Core Responsibility
@@ -1,5 +1,7 @@
1
1
  # Progress Bar
2
2
 
3
+ > **UI spec (authoritative):** `03-ui-specs/12-survey-chrome.md`
4
+ > **Reference implementation:** `apps/client/src/components/ProgressBar.tsx`
3
5
  > **Component**: `ProgressBar`
4
6
  > **Role**: Displays completion status at the top of the survey.
5
7
 
@@ -1,5 +1,7 @@
1
1
  # Language Selector
2
2
 
3
+ > **UI spec (authoritative):** `03-ui-specs/12-survey-chrome.md`
4
+ > **Reference implementation:** `apps/client/src/components/LanguageSelector.tsx`
3
5
  > **Component**: `LanguageSelector`
4
6
  > **Role**: Allows the user to switch the survey language.
5
7
 
@@ -1,5 +1,7 @@
1
1
  # Matrix Dropdown
2
2
 
3
+ > **UI spec (authoritative):** `03-ui-specs/shared/matrix-dropdown.md`
4
+ > **Reference implementation:** `apps/client/src/components/MatrixDropdown.tsx`
3
5
  > **Component**: `MatrixDropdown`
4
6
  > **Used by**: `CsatMatrixScale`, `LikertMatrixScale`
5
7
 
@@ -1,7 +1,9 @@
1
1
  # Client Components Overview
2
2
 
3
- > This folder documents the React client components that render the survey UI.
4
- > It explains the architecture, the dispatcher (`Question.tsx`), and all 11 individual question scale components.
3
+ > Wiring blueprints for React components. **Authoritative UI details** are in [`03-ui-specs/`](../03-ui-specs/README.md) (reference-client driven).
4
+ > **Required files gate:** [`component-checklist.md`](../00-integration/component-checklist.md)
5
+ > **Dispatcher template:** [`templates/Question.tsx`](../templates/Question.tsx)
6
+ > This folder documents props, `onSelect` wiring, and dispatcher architecture.
5
7
 
6
8
  ## Component Architecture
7
9
 
@@ -0,0 +1,158 @@
1
+ # Config Field Index
2
+
3
+ > Master map: every SDK config field → reference client file → implemented? → UI spec doc.
4
+ > Cross-check this when building any question with non-default config.
5
+
6
+ ## QuestionBase (all types)
7
+
8
+ | Field | Types | Client file | Implemented? | Spec doc |
9
+ |-------|-------|-------------|--------------|----------|
10
+ | `id` | all | Question.tsx | ✅ | 00-question-shell |
11
+ | `text` | all | Question.tsx | ✅ | 00-question-shell |
12
+ | `description` | all | Question.tsx | ✅ | 00-question-shell |
13
+ | `required` | all | Question.tsx | ✅ | 00-question-shell |
14
+ | `requiredErrorMessage` | all | Question.tsx | ✅ | 00-question-shell |
15
+ | `questionNumber` | all | — | ❌ | 00-question-shell |
16
+ | `containerMediaUrl` | all | — | ❌ | 00-question-shell |
17
+ | `containerMediaMimeType` | all | — | ❌ | 00-question-shell |
18
+ | `containerMediaAlignment` | all | — | ❌ | 00-question-shell |
19
+ | `containerMediaSize` | all | — | ❌ | 00-question-shell |
20
+
21
+ ## rating
22
+
23
+ | Field | Values | Client file | Implemented? | Spec doc |
24
+ |-------|--------|-------------|--------------|----------|
25
+ | `options[]` | SurveyOption[] | RatingScale.tsx | ✅ | 01-rating |
26
+ | `options[].color` | hex | RatingScale.tsx | ✅ | 01-rating |
27
+ | `minLabel` | string | Question.tsx | ✅ | 01-rating |
28
+ | `midLabel` | string | Question.tsx | ✅ | 01-rating |
29
+ | `maxLabel` | string | Question.tsx | ✅ | 01-rating |
30
+ | `midLabelIndex` | number | Question.tsx | ✅ | 01-rating |
31
+ | `reverseScaleOrder` | boolean | — | ❌ | 01-rating |
32
+ | `buttonVariant` | radio/numbered/emoji | — | ❌ | 01-rating |
33
+
34
+ ## radio
35
+
36
+ | Field | Values | Client file | Implemented? | Spec doc |
37
+ |-------|--------|-------------|--------------|----------|
38
+ | `options[]` | SurveyOption[] | Question.tsx | ✅ | 02-radio |
39
+ | `isMultiSelect` | boolean | — | ❌ | 02-radio |
40
+
41
+ ## text
42
+
43
+ | Field | Values | Client file | Implemented? | Spec doc |
44
+ |-------|--------|-------------|--------------|----------|
45
+ | `placeholder` | string | Question.tsx | ✅ | 03-text |
46
+ | `maxCharacterCount` | number | Question.tsx | ✅ | 03-text |
47
+ | `inputVariant` | long/short | Question.tsx | partial | 03-text |
48
+
49
+ ## csat
50
+
51
+ | Field | Values | Client file | Implemented? | Spec doc |
52
+ |-------|--------|-------------|--------------|----------|
53
+ | `options[]` | SurveyOption[] | CsatScale.tsx | ✅ | 04-csat |
54
+ | `buttonType` | emoji/star/numbered/... | CsatScale.tsx | ✅ | 04-csat |
55
+ | `labelPosition` | top/bottom/hidden | CsatScale.tsx | ✅ | 04-csat |
56
+ | `minLabel` / `maxLabel` | string | Question.tsx | ✅ | 04-csat |
57
+ | `hasNotApplicable` | boolean | — | ❌ | 04-csat |
58
+ | `reverseScaleOrder` | boolean | — | ❌ | 04-csat |
59
+
60
+ ## rating_scale
61
+
62
+ | Field | Values | Client file | Implemented? | Spec doc |
63
+ |-------|--------|-------------|--------------|----------|
64
+ | `options[]` | SurveyOption[] | — | ❌ | 05-rating-scale |
65
+ | `scaleStyle` | star/emoji | — | ❌ | 05-rating-scale |
66
+ | `minLabel` / `midLabel` / `maxLabel` | string | — | ❌ | 05-rating-scale |
67
+ | `midLabelIndex` | number | — | ❌ | 05-rating-scale |
68
+ | `reverseScaleOrder` | boolean | — | ❌ | 05-rating-scale |
69
+
70
+ ## slider
71
+
72
+ | Field | Values | Client file | Implemented? | Spec doc |
73
+ |-------|--------|-------------|--------------|----------|
74
+ | `min` / `max` / `step` | number | — | ❌ | 06-slider |
75
+ | `defaultValue` | number | — | ❌ | 06-slider |
76
+ | `minLabel` / `maxLabel` | string | — | ❌ | 06-slider |
77
+ | `enableInputBox` | boolean | SliderMatrixScale.tsx | partial | 06-slider |
78
+ | `displayValues` | boolean | CustomSliderTrack.tsx | partial | 06-slider, shared/custom-slider-track |
79
+
80
+ ## matrix (shared)
81
+
82
+ | Field | Values | Client file | Implemented? | Spec doc |
83
+ |-------|--------|-------------|--------------|----------|
84
+ | `subType` | CFM/CSAT/RATING | Question.tsx | ✅ | 07, 08 |
85
+ | `rows[]` | MatrixRow[] | Likert/CsatMatrix | ✅ | 07, 08 |
86
+ | `columns[]` | MatrixColumn[] | Likert/CsatMatrix | ✅ | 07, 08 |
87
+ | `matrixFormat` | standard/carousel/dropdown | Likert/CsatMatrix | ✅ | 07, 08 |
88
+ | `hasNotApplicable` | boolean | Likert/CsatMatrix | ✅ | 07, 08 |
89
+ | `reverseScaleOrder` | boolean | CsatMatrixScale | ✅ | 08 |
90
+ | `labels[]` | string[] | Likert/CsatMatrix | ✅ | 07, 08 |
91
+ | `buttonType` | SurveyButtonType | CsatMatrixScale | ✅ | 08 |
92
+
93
+ ## matrix — CFM only
94
+
95
+ | Field | Values | Client file | Implemented? | Spec doc |
96
+ |-------|--------|-------------|--------------|----------|
97
+ | `matrixType` | likert/bipolar | LikertMatrixScale | ✅ | 07-matrix-cfm |
98
+ | `answerType` | single/multiple | LikertMatrixScale | ✅ | 07-matrix-cfm |
99
+ | `transposeTable` | boolean | LikertMatrixScale | ✅ | 07-matrix-cfm |
100
+ | `repeatScale` | boolean | LikertMatrixScale | ✅ | 07-matrix-cfm |
101
+ | `enableScale` | boolean | LikertMatrixScale | ✅ | 07-matrix-cfm |
102
+
103
+ ## slider_matrix
104
+
105
+ | Field | Values | Client file | Implemented? | Spec doc |
106
+ |-------|--------|-------------|--------------|----------|
107
+ | `rows[].min/max/step` | number | SliderMatrixScale | ✅ | 09-slider-matrix |
108
+ | `labels[]` | string[] | SliderMatrixScale | ✅ | 09-slider-matrix |
109
+ | `ticks` | number | SliderMatrixScale | ✅ | 09-slider-matrix |
110
+ | `tickValues[]` | TickValue[] | SliderMatrixScale | ✅ | 09-slider-matrix |
111
+ | `enableInputBox` | boolean | SliderMatrixScale | ✅ | 09-slider-matrix |
112
+ | `displayValues` | boolean | CustomSliderTrack | ✅ | 09-slider-matrix |
113
+ | `enableNotApplicable` | boolean | SliderMatrixScale | ✅ | 09-slider-matrix |
114
+ | `sliderType` | graphics | SliderMatrixScale | ✅ | 09-slider-matrix |
115
+
116
+ ## file_upload
117
+
118
+ | Field | Values | Client file | Implemented? | Spec doc |
119
+ |-------|--------|-------------|--------------|----------|
120
+ | `uploadMessage` | HTML string | FileUploadScale | ✅ | 10-file-upload |
121
+ | `supportedFileFormats` | string[] | FileUploadScale | ✅ | 10-file-upload |
122
+ | `maxFileCount` | number | FileUploadScale | ✅ | 10-file-upload |
123
+ | `fileSizeLimit` | number (MB) | FileUploadScale | ✅ | 10-file-upload |
124
+ | `fileSizeLimitType` | PER_FILE/IN_TOTAL | FileUploadScale | ✅ | 10-file-upload |
125
+
126
+ ## text_and_media
127
+
128
+ | Field | Values | Client file | Implemented? | Spec doc |
129
+ |-------|--------|-------------|--------------|----------|
130
+ | `mediaUrl` | string | Question.tsx | ✅ | 11-text-and-media |
131
+ | `mediaMimeType` | string | Question.tsx | ✅ | 11-text-and-media |
132
+ | `mediaTitle` | string | Question.tsx | ✅ | 11-text-and-media |
133
+ | `mediaAlignment` | string | Question.tsx | ✅ | 11-text-and-media |
134
+ | `mediaSize` | number (%) | Question.tsx | ✅ | 11-text-and-media |
135
+
136
+ ## Implementation Gaps (no client branch yet)
137
+
138
+ | Gap | SDK type/field | Extend from |
139
+ |-----|----------------|-------------|
140
+ | `rating_scale` dispatcher | `type: 'rating_scale'` | CsatScale star/emoji patterns |
141
+ | `slider` dispatcher | `type: 'slider'` | CustomSliderTrack + SliderMatrixScale row |
142
+ | `radio.isMultiSelect` | checkbox cards | 02-radio card styling |
143
+ | `text.inputVariant: 'short'` | single-line input | 03-text focus tokens |
144
+ | `rating.reverseScaleOrder` | reverse options array | 01-rating |
145
+ | `rating.buttonVariant` | numbered clickable badges | 01-rating |
146
+ | `csat.hasNotApplicable` / `reverseScaleOrder` | standalone CSAT | 04-csat, 08-matrix N/A |
147
+ | `containerMedia*` on any type | container asset | 11-text-and-media media block |
148
+
149
+ ## buttonType × matrixFormat Quick Reference
150
+
151
+ | buttonType | matrixFormat | Layout component | Spec |
152
+ |------------|--------------|------------------|------|
153
+ | (CFM default) | standard | LikertMatrixGrid | 07 |
154
+ | (CFM default) | carousel | LikertMatrixCarousel | 07 |
155
+ | (CFM default) | dropdown | LikertMatrixDropdown | 07 |
156
+ | emoji/star/numbered | standard | CsatMatrixGrid | 08 |
157
+ | emoji/star/numbered/graphics | carousel | CsatMatrixCarousel | 08 |
158
+ | dropdown/selectbox/radio | any | CsatMatrixVerticalList | 08 |
@@ -1,22 +1,22 @@
1
1
  # Question Type → Component Routing
2
2
 
3
- > Canonical mapping. For UI implementation details, read `01-components/`. For data shapes, read `02-reference/question-types/`.
3
+ > Canonical mapping. For **UI implementation** (config branches, tokens, states), read `03-ui-specs/`. For wiring, read `01-components/`. For data shapes, read `02-reference/question-types/`. For field audit, read `config-field-index.md`.
4
4
 
5
- | `question.type` | `question.subType` | Component | Answer Shape | Reference Doc |
6
- |-----------------|-------------------|-----------|--------------|---------------|
7
- | `'rating'` | — | `RatingScale` | `number` | `question-types/01-rating.md` |
8
- | `'radio'` | — | Inline in `Question` | `string \| number` | `question-types/README.md#radio` |
9
- | `'text'` | — | Inline in `Question` | `string` | `question-types/README.md#text` |
10
- | `'csat'` | — | `CsatScale` | `number \| null` | `question-types/04-csat.md` |
11
- | `'rating_scale'` | — | `RatingScale` | `number` | `question-types/05-rating-scale.md` |
12
- | `'slider'` | — | `CustomSliderTrack` | `number` | `question-types/06-slider.md` |
13
- | `'matrix'` | `'CFM_MATRIX'` | `LikertMatrixScale` | `MatrixAnswerMap` | `question-types/07-matrix-cfm.md` |
14
- | `'matrix'` | `'CSAT_MATRIX'` | `CsatMatrixScale` | `MatrixAnswerMap` | `question-types/08-matrix-csat.md` |
15
- | `'matrix'` | `'RATING_MATRIX'` | `CsatMatrixScale` | `MatrixAnswerMap` | `question-types/08-matrix-csat.md` |
16
- | `'rating_matrix'` | — | `CsatMatrixScale` | `MatrixAnswerMap` | `question-types/09-matrix-rating.md` |
17
- | `'slider_matrix'` | — | `SliderMatrixScale` | `MatrixAnswerMap` | `question-types/10-slider-matrix.md` |
18
- | `'file_upload'` | — | `FileUploadScale` | `UploadedFile[]` | `question-types/11-file-upload.md` |
19
- | `'text_and_media'` | — | Inline in `Question` | (no answer) | `question-types/README.md#text_and_media` |
5
+ | `question.type` | `question.subType` | Component | Answer Shape | Reference Doc | UI Spec |
6
+ |-----------------|-------------------|-----------|--------------|---------------|---------|
7
+ | `'rating'` | — | `RatingScale` | `number` | `question-types/01-rating.md` | `03-ui-specs/01-rating.md` |
8
+ | `'radio'` | — | Inline in `Question` | `string \| number` | `question-types/README.md#radio` | `03-ui-specs/02-radio.md` |
9
+ | `'text'` | — | Inline in `Question` | `string` | `question-types/README.md#text` | `03-ui-specs/03-text.md` |
10
+ | `'csat'` | — | `CsatScale` | `number \| null` | `question-types/04-csat.md` | `03-ui-specs/04-csat.md` |
11
+ | `'rating_scale'` | — | `RatingScale` | `number` | `question-types/05-rating-scale.md` | `03-ui-specs/05-rating-scale.md` |
12
+ | `'slider'` | — | `CustomSliderTrack` | `number` | `question-types/06-slider.md` | `03-ui-specs/06-slider.md` |
13
+ | `'matrix'` | `'CFM_MATRIX'` | `LikertMatrixScale` | `MatrixAnswerMap` | `question-types/07-matrix-cfm.md` | `03-ui-specs/07-matrix-cfm.md` |
14
+ | `'matrix'` | `'CSAT_MATRIX'` | `CsatMatrixScale` | `MatrixAnswerMap` | `question-types/08-matrix-csat.md` | `03-ui-specs/08-matrix-csat-rating.md` |
15
+ | `'matrix'` | `'RATING_MATRIX'` | `CsatMatrixScale` | `MatrixAnswerMap` | `question-types/08-matrix-csat.md` | `03-ui-specs/08-matrix-csat-rating.md` |
16
+ | `'rating_matrix'` | — | `CsatMatrixScale` | `MatrixAnswerMap` | `question-types/09-matrix-rating.md` | `03-ui-specs/08-matrix-csat-rating.md` |
17
+ | `'slider_matrix'` | — | `SliderMatrixScale` | `MatrixAnswerMap` | `question-types/10-slider-matrix.md` | `03-ui-specs/09-slider-matrix.md` |
18
+ | `'file_upload'` | — | `FileUploadScale` | `UploadedFile[]` | `question-types/11-file-upload.md` | `03-ui-specs/10-file-upload.md` |
19
+ | `'text_and_media'` | — | Inline in `Question` | (no answer) | `question-types/README.md#text_and_media` | `03-ui-specs/11-text-and-media.md` |
20
20
 
21
21
  ## Component Blueprint Docs
22
22