@explorer02/cfm-survey-sdk 0.2.3 → 0.2.5
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 +141 -33
- package/dist/cli/index.mjs +141 -33
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +3 -1
- package/postinstall.js +9 -5
- package/templates/AGENT.md +60 -19
- package/templates/deploy-wizard-to-s3.sh +52 -0
- package/templates/docs/00-integration/agent-execution-flow.md +293 -0
- package/templates/docs/00-integration/agent-operating-contract.md +268 -0
- package/templates/docs/00-integration/apply-ui-config.md +390 -0
- package/templates/docs/00-integration/aws-deploy.md +117 -3
- package/templates/docs/00-integration/canonical-survey-fixtures.md +94 -0
- package/templates/docs/00-integration/client-integration-guide.md +9 -7
- package/templates/docs/00-integration/client-lib-folder.md +115 -0
- package/templates/docs/00-integration/component-checklist.md +90 -62
- package/templates/docs/00-integration/constraints.md +14 -5
- package/templates/docs/00-integration/custom-field-logic-and-navigation.md +56 -0
- package/templates/docs/00-integration/mockup-ui-extraction.md +113 -0
- package/templates/docs/00-integration/placeholders-and-custom-fields-wiring.md +192 -0
- package/templates/docs/00-integration/placeholders-and-tokens.md +2 -1
- package/templates/docs/00-integration/progress.md +4 -2
- package/templates/docs/00-integration/setup.md +12 -0
- package/templates/docs/00-integration/ui-customization-wizard.md +123 -0
- package/templates/docs/00-integration/useSurveySDK.md +35 -1
- package/templates/docs/00-integration/wizard-api.md +126 -0
- package/templates/docs/00-integration/wizard-config-handoff.md +292 -0
- package/templates/docs/00-integration/wizard-preview-build-guide.md +405 -0
- package/templates/docs/00-integration/wizard-question-type-styling.md +197 -0
- package/templates/docs/00-integration/wizard-troubleshooting.md +80 -0
- package/templates/docs/01-components/01-survey-page.md +18 -8
- package/templates/docs/01-components/02-question.md +2 -2
- package/templates/docs/01-components/03-rating-scale.md +12 -18
- package/templates/docs/01-components/05-csat-matrix-scale.md +18 -26
- package/templates/docs/01-components/06-likert-matrix-scale.md +19 -39
- package/templates/docs/01-components/07-slider-matrix-scale.md +48 -33
- package/templates/docs/01-components/09-custom-slider-track.md +15 -25
- package/templates/docs/01-components/10-header-footer.md +23 -4
- package/templates/docs/01-components/11-progress-bar.md +14 -6
- package/templates/docs/01-components/19-survey-sticky-chrome.md +79 -0
- package/templates/docs/01-components/README.md +2 -2
- package/templates/docs/02-reference/question-types/10-slider-matrix.md +38 -26
- package/templates/docs/02-reference/routing-table.md +1 -0
- package/templates/docs/02-reference/value-derivation.md +1 -1
- package/templates/docs/03-ui-specs/00-question-shell.md +10 -0
- package/templates/docs/03-ui-specs/01-rating.md +18 -0
- package/templates/docs/03-ui-specs/02-radio.md +16 -1
- package/templates/docs/03-ui-specs/03-text.md +12 -1
- package/templates/docs/03-ui-specs/04-csat.md +84 -50
- package/templates/docs/03-ui-specs/06-slider.md +3 -1
- package/templates/docs/03-ui-specs/07-matrix-cfm.md +71 -48
- package/templates/docs/03-ui-specs/08-matrix-csat-rating.md +48 -18
- package/templates/docs/03-ui-specs/09-slider-matrix.md +59 -32
- package/templates/docs/03-ui-specs/10-file-upload.md +11 -0
- package/templates/docs/03-ui-specs/11-text-and-media.md +4 -0
- package/templates/docs/03-ui-specs/12-survey-chrome.md +54 -5
- package/templates/docs/03-ui-specs/13-heatmap.md +12 -1
- package/templates/docs/03-ui-specs/14-rank-order.md +11 -0
- package/templates/docs/03-ui-specs/README.md +4 -2
- package/templates/docs/03-ui-specs/shared/matrix-dropdown.md +1 -1
- package/templates/docs/MANIFEST.json +180 -7
- package/templates/docs/index.md +114 -117
- package/templates/docs/templates/CsatMatrixScale.tsx +637 -0
- package/templates/docs/templates/FileUploadScale.tsx +262 -0
- package/templates/docs/templates/HeatmapScale.tsx +114 -0
- package/templates/docs/templates/LikertMatrixScale.tsx +414 -0
- package/templates/docs/templates/Question.tsx +3 -0
- package/templates/docs/templates/RatingScale.tsx +129 -0
- package/templates/docs/templates/SliderMatrixScale.tsx +248 -0
- package/templates/docs/templates/SurveyStickyChrome.tsx +24 -0
- package/templates/docs/templates/customFieldValues.ts +36 -0
- package/templates/docs/templates/deploy-to-aws.sh +74 -0
- package/templates/docs/templates/implementation_plan.md +64 -10
- package/templates/docs/templates/labelStyles.ts +33 -0
- package/templates/docs/templates/selectionStyles.ts +100 -0
- package/templates/docs/templates/surveyUiIcons.tsx +11 -0
- package/templates/docs/templates/surveyUiScaleUtils.ts +51 -0
- package/templates/docs/templates/verify-agent-build.sh +119 -0
- package/templates/preview-harness/preview-bridge.inline.js +201 -0
- package/templates/preview-harness/previewPages.js +108 -0
- package/templates/preview-harness/previewPages.ts +298 -0
- package/templates/preview-harness/vite-app/src/PreviewConfigContext.tsx +67 -0
- package/templates/preview-harness/vite-app/src/QuestionPreview.tsx +122 -0
- package/templates/preview-harness/vite-app/src/SurveyPagePreview.tsx +75 -0
- package/templates/preview-harness/vite-app/src/fixtures/questions.ts +311 -0
- package/templates/preview-harness/vite-app/src/globals.css +16 -0
- package/templates/preview-harness/vite-app/src/mount.tsx +9 -0
- package/templates/preview-harness/vite-app/src/preview-live-overrides.css +101 -0
- package/templates/preview-harness/vite-app/stubs/next-dynamic.tsx +25 -0
- package/templates/preview-harness/vite-app/stubs/next-image.tsx +29 -0
- package/templates/previewBridge.ts +153 -0
- package/templates/survey-theme.css +295 -0
- package/templates/survey-ui-config.schema.json +213 -0
- package/templates/wizard-dist/assets/PreviewMock-AoZdAEPZ.js +1 -0
- package/templates/wizard-dist/assets/TypePanel-39FnbtvG.js +1 -0
- package/templates/wizard-dist/assets/index-BhWM50Yu.css +1 -0
- package/templates/wizard-dist/assets/index-CWKdsJOp.js +34 -0
- package/templates/wizard-dist/assets/vendor-BwkXDkd3.js +17 -0
- package/templates/wizard-dist/index.html +20 -0
- package/templates/wizard.html +13 -1129
|
@@ -110,13 +110,104 @@ Set `OUT_DIR` to `dist/`. Ensure asset paths in built HTML are **relative** (no
|
|
|
110
110
|
|
|
111
111
|
| Rule | Detail |
|
|
112
112
|
|------|--------|
|
|
113
|
-
| Public logos | Use relative paths (
|
|
113
|
+
| Public logos | Use **relative** paths (`./logo.svg` for AWS static export), not `/logo.svg` or `https://…` |
|
|
114
|
+
| Wizard logos | Must exist in `public/` **and** `out/` before deploy — see § Logos & local assets below |
|
|
114
115
|
| Rank-order images | Prefer `option.imageUrl` over `option.previewImageUrl` — preview `*_p.*` URLs often return 403 |
|
|
115
116
|
| Footer hash links | Use plain `<a href="#">`, not `next/link` — avoids RSC prefetch on static export |
|
|
116
117
|
| No AWS keys in code | JWT only in `Authorization: Bearer` header at deploy time |
|
|
117
118
|
|
|
118
119
|
---
|
|
119
120
|
|
|
121
|
+
## Logos & local assets (wizard → S3 → CloudFront)
|
|
122
|
+
|
|
123
|
+
### Why logos break on CloudFront
|
|
124
|
+
|
|
125
|
+
The wizard **preview** shows logos from **browser memory** (`data:` URLs / base64). That works on `localhost:4200` only. CloudFront serves files from the **deploy bundle** at:
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
https://<cloudfront>/sites/{surveyId}/{deployId}/<filename>
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
It does **not** read wizard preview memory, and it does **not** automatically include logos stored under the separate wizard asset path (`sites/{surveyId}/assets/{fileName}`). Those S3 assets are for wizard handoff / re-download — the agent must copy the file into `public/` and ship it inside `out/` on every deploy.
|
|
132
|
+
|
|
133
|
+
```mermaid
|
|
134
|
+
flowchart LR
|
|
135
|
+
subgraph wizard [Wizard session]
|
|
136
|
+
Upload[Client uploads logo]
|
|
137
|
+
Mem[Preview: base64 in memory]
|
|
138
|
+
Disk[public/logo_*.jpg local OR S3 assets/ EC2]
|
|
139
|
+
end
|
|
140
|
+
subgraph agent [Agent Phase 6c]
|
|
141
|
+
Apply[Header data-cfm-logo src=./fileName]
|
|
142
|
+
Build[yarn build copies public to out/]
|
|
143
|
+
end
|
|
144
|
+
subgraph deploy [Phase 7 AWS]
|
|
145
|
+
S3[sites/surveyId/deployId/logo_*.jpg]
|
|
146
|
+
CF[CloudFront serves same prefix as index.html]
|
|
147
|
+
end
|
|
148
|
+
Upload --> Mem
|
|
149
|
+
Upload --> Disk
|
|
150
|
+
Disk --> Apply
|
|
151
|
+
Apply --> Build
|
|
152
|
+
Build --> S3
|
|
153
|
+
S3 --> CF
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Two storage locations (do not confuse)
|
|
157
|
+
|
|
158
|
+
| Location | When written | Served on live survey? |
|
|
159
|
+
|----------|--------------|------------------------|
|
|
160
|
+
| `public/{fileName}` on dev machine | `customize` upload-logo API, or `confirm-ui-config` download | **Only after** `build` copies into `out/` and deploy uploads |
|
|
161
|
+
| `sites/{surveyId}/assets/{fileName}` on S3 | EC2 wizard **Review & Build** complete | **No** — not in deploy prefix; use only as download source for `confirm-ui-config` |
|
|
162
|
+
|
|
163
|
+
### Correct agent flow (mandatory when wizard uploaded a logo)
|
|
164
|
+
|
|
165
|
+
**After Phase 6c apply, before Phase 7 deploy:**
|
|
166
|
+
|
|
167
|
+
1. Read `global.logo.fileName` from `survey-ui-config.json` (local) or `.final.json` (EC2).
|
|
168
|
+
2. Ensure the binary exists in `public/{fileName}`:
|
|
169
|
+
- **Local `customize`:** file written by `POST /api/upload-logo` when client uploaded in wizard.
|
|
170
|
+
- **EC2 `customize-ui`:** run `npx cfm-sdk confirm-ui-config` — downloads from `global.logo.url` (CloudFront assets URL) to `public/`.
|
|
171
|
+
3. Update `Header.tsx`:
|
|
172
|
+
|
|
173
|
+
```tsx
|
|
174
|
+
<img data-cfm-logo src="./logo_1783069846059_download2.jpg" alt="Brand" />
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Use `./{fileName}` for AWS static export (`assetPrefix: './'`). **Never** set `src` to:
|
|
178
|
+
- `global.logo.url` when it is a `data:` URL (preview memory)
|
|
179
|
+
- `https://…/sites/.../assets/...` (wrong path — outside deploy folder)
|
|
180
|
+
- `/logo.png` (absolute — breaks under nested CloudFront prefix)
|
|
181
|
+
|
|
182
|
+
4. Rebuild and verify file is in static output:
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
yarn build
|
|
186
|
+
LOGO=$(python3 -c "import json; print(json.load(open('survey-ui-config.json'))['global']['logo']['fileName'])")
|
|
187
|
+
test -f "public/$LOGO" && test -f "out/$LOGO" && echo "Logo ready for deploy"
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
5. Deploy — `deploy-to-aws.sh` uploads **every file under `out/`**, including the logo.
|
|
191
|
+
|
|
192
|
+
6. Post-deploy verify (same deploy prefix as `index.html`):
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
# If index.html is .../66593925-.../index.html, logo must be:
|
|
196
|
+
# .../66593925-.../logo_*.jpg → HTTP 200
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### Pre-deploy checklist (logo)
|
|
200
|
+
|
|
201
|
+
- [ ] `global.logo.fileName` set in active config
|
|
202
|
+
- [ ] `public/{fileName}` exists on disk
|
|
203
|
+
- [ ] `Header.tsx` `data-cfm-logo` `src="./{fileName}"` (or `./your-seed-logo.svg` if no wizard upload)
|
|
204
|
+
- [ ] `out/{fileName}` exists after `yarn build`
|
|
205
|
+
- [ ] No `data:` or `https://` logo `src` in Header/Footer
|
|
206
|
+
|
|
207
|
+
See also: [`apply-ui-config.md`](apply-ui-config.md) § Logo file, [`wizard-config-handoff.md`](wizard-config-handoff.md) § Logo capture.
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
120
211
|
## Deploy Procedure (agent executes in order)
|
|
121
212
|
|
|
122
213
|
### Step 0 — Build
|
|
@@ -253,7 +344,26 @@ bash templates/deploy-to-aws.sh
|
|
|
253
344
|
|
|
254
345
|
---
|
|
255
346
|
|
|
256
|
-
##
|
|
347
|
+
## EC2 operator setup (one-time)
|
|
348
|
+
|
|
349
|
+
On `43.204.26.213`, `/home/ec2-user/deploy-api/.env` must use **real** CloudFront values (not `.env.example` placeholders):
|
|
350
|
+
|
|
351
|
+
```bash
|
|
352
|
+
HOSTING_BUCKET=sprinklr-cfm-survey-sites-prod-unnat
|
|
353
|
+
CLOUDFRONT_DISTRIBUTION_ID=EY6QXOHVFMVZ2
|
|
354
|
+
CLOUDFRONT_BASE_URL=https://d81qbkjijbkjd.cloudfront.net
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
Verify after `pm2 restart sprinklr-api`:
|
|
358
|
+
|
|
359
|
+
```bash
|
|
360
|
+
curl -s http://43.204.26.213:3000/health/cloudfront | python3 -m json.tool
|
|
361
|
+
# expect "ok": true
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
Placeholder IDs like `E1234567890ABC` cause `STORAGE_UNAVAILABLE` on `/deploy/complete` even when S3 uploads succeed.
|
|
365
|
+
|
|
366
|
+
---
|
|
257
367
|
|
|
258
368
|
Each deploy creates a **new** `deployId` folder under `sites/{surveyId}/`. Old deploys remain in S3.
|
|
259
369
|
|
|
@@ -269,9 +379,13 @@ After UI changes: rebuild → re-run Steps 1–3 (same `CFM_INSTANCE_ID` if same
|
|
|
269
379
|
| 403 on `index.html.txt?_rsc` | Missing RSC payload file | Add `cp out/index.txt out/index.html.txt` to build script |
|
|
270
380
|
| 403 on `*_p.png` / `*_p.jpg` images | Preview URL used | Use `option.imageUrl \|\| option.previewImageUrl` in RankOrderScale |
|
|
271
381
|
| 401 `TOKEN_EXPIRED` | JWT expired | Ask client for new instanceId |
|
|
272
|
-
| 503 `
|
|
382
|
+
| 503 `STORAGE_UNAVAILABLE` on `/deploy/complete` | EC2 `.env` has placeholder `CLOUDFRONT_*` values | Fix `.env` with real distribution ID + domain; `pm2 restart` |
|
|
383
|
+
| 503 `DEPLOY_UNAVAILABLE` | EC2 hosting env misconfigured — report to operator |
|
|
273
384
|
| Some PUTs 403 | Presigned URLs expired (default 5 min) | Restart from Step 1; complete within window |
|
|
274
385
|
| Blank page, HTML 200 | JS/CSS not uploaded or wrong paths | Re-check Channel 2 logs |
|
|
386
|
+
| Broken logo on live site, HTML 200 | Logo only in wizard preview memory or wrong `src` | Apply `global.logo.fileName` to `data-cfm-logo` as `./fileName`; verify `out/{fileName}` before deploy |
|
|
387
|
+
| Logo 404 under deploy URL | File not in `out/` or absolute `/logo.png` path | Rebuild after copying to `public/`; use `./fileName` not `/fileName` |
|
|
388
|
+
| Used `global.logo.url` as img src | Often `data:` base64 or `/assets/` path outside deploy | Use local `./fileName` only — see § Logos & local assets |
|
|
275
389
|
| Survey API errors in browser | Deploy JWT ≠ SurveyPage JWT | Align `SURVEY_INSTANCE_ID` |
|
|
276
390
|
|
|
277
391
|
---
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Canonical Survey Fixtures
|
|
2
|
+
|
|
3
|
+
> Ground-truth UI expectations for integration-test surveys. When your fetched survey matches these patterns, **copy portable templates** from [`templates/`](../templates/) — do not rebuild matrix/slider UI from prose.
|
|
4
|
+
|
|
5
|
+
Related: [`component-checklist.md`](component-checklist.md) · [`question-type-sdk-matrix.md`](question-type-sdk-matrix.md)
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Template copy order (all matrix types)
|
|
10
|
+
|
|
11
|
+
0. `customFieldValues.ts` → `src/lib/` when survey logic references `_c_…` ids
|
|
12
|
+
1. `surveyUiScaleUtils.ts` + `surveyUiIcons.tsx`
|
|
13
|
+
2. `CustomSliderTrack.tsx` + `MatrixDropdown.tsx`
|
|
14
|
+
3. Scale component for each type in survey
|
|
15
|
+
4. `Question.tsx` from template (includes `questionNumber`, matrix visibility helpers, `customFieldValues` prop)
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Page-by-page fixture map
|
|
20
|
+
|
|
21
|
+
| Page | Type | Key config | Expected UI | Copy |
|
|
22
|
+
|------|------|------------|-------------|------|
|
|
23
|
+
| 1 | `NPS_SCALE` | 11 options 0–10, `minLabel`/`maxLabel` | Traffic-light badges + anchor labels | `RatingScale.tsx` |
|
|
24
|
+
| 2 | `SLIDER_MATRIX` | 1 row, `ticks.count: 11`; skip uses `_c_67199096d294be011a2b4773` | Colored 0–10 header + gray row + track; CRM field in `customFieldValues.ts` | `SliderMatrixScale.tsx` + `customFieldValues.ts` |
|
|
25
|
+
| 3 | `FILE_UPLOAD` | `maxFileCount: 1` | Dropzone → presigned upload → `UploadedFileAnswer[]` | `FileUploadScale.tsx` |
|
|
26
|
+
| 4 | `MCQ` | `selectionMode: single`, `defaultOptionIds` | Radio; pre-select default | `Question.tsx` inline |
|
|
27
|
+
| 6 | `MCQ` | `minSelections`/`maxSelections` | Checkbox + validation message | `Question.tsx` inline |
|
|
28
|
+
| 7 | `CFM_MATRIX` | `statementLayout: bipolar`, `showColumnHeaders: false`, 3 anchor labels, 10 cols | 25% left stmt \| radios \| 25% right stmt | `LikertMatrixScale.tsx` |
|
|
29
|
+
| 9 | `CSAT_MATRIX` | `displayStyle: emoji`, 5 anchors, N/A | 180px stmt column + emoji row + anchors | `CsatMatrixScale.tsx` |
|
|
30
|
+
| 10 | `CFM_MATRIX` | `transposeTable: true`, `selectionMode: multiple` | Rows=Scale Items, cols=Statement Items, **checkboxes** | `LikertMatrixScale.tsx` |
|
|
31
|
+
| 11 | `RATING_MATRIX` | `displayStyle: graphics` | Per-row `CustomSliderTrack` (NOT SliderMatrixScale) | `CsatMatrixScale.tsx` |
|
|
32
|
+
| 12 | `SLIDER_MATRIX` | 2 rows + 2 anchor labels | Shared header + 2 row bands with visible statements | `SliderMatrixScale.tsx` |
|
|
33
|
+
| 14 | multi | star + slider + numbered rating | Three separate components; all labels visible | all three templates |
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Common agent failures
|
|
38
|
+
|
|
39
|
+
| Symptom | Cause | Fix |
|
|
40
|
+
|---------|-------|-----|
|
|
41
|
+
| Lone pink circle, no slider track | Built stub thumb instead of `SliderMatrixScale` | Copy template |
|
|
42
|
+
| Matrix with no row labels | Omitted 180px / 25% statement column | See ui-spec statement visibility |
|
|
43
|
+
| Matrix with no column labels | Ignored `scaleAnchorLabels` and `showColumnHeaders` | Render header row |
|
|
44
|
+
| CSAT shows radios instead of emojis | Skipped `displayStyle: emoji` branch | Copy `CsatMatrixScale` |
|
|
45
|
+
| RATING numbered shows native radios | Skipped `displayStyle: numbered` branch | 40×40 badges |
|
|
46
|
+
| Bipolar missing right text | Ignored `oppositeStatementText` | 25% right column |
|
|
47
|
+
| Transposed matrix wrong orientation | Ignored `transposeTable` | Swap gridRows/gridCols |
|
|
48
|
+
| Custom-field skip never fires | `customFieldValues` omitted from hook or wrong `_c_` id | Copy `customFieldValues.ts`; wire hook + Question |
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Custom field fixture (Page 2)
|
|
53
|
+
|
|
54
|
+
SLIDER_MATRIX skip when CRM field `_c_67199096d294be011a2b4773` `CASE_SENSITIVE_TEXT` equals `"abc"`:
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
// src/lib/customFieldValues.ts
|
|
58
|
+
export const CUSTOM_FIELD_VALUES = {
|
|
59
|
+
'_c_67199096d294be011a2b4773': 'abc',
|
|
60
|
+
};
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Import in `SurveyPage` and pass to `useSurveySDK` + `Question`. See [`custom-field-logic-and-navigation.md`](custom-field-logic-and-navigation.md).
|
|
64
|
+
|
|
65
|
+
## Statement text rules (all matrix types)
|
|
66
|
+
|
|
67
|
+
```tsx
|
|
68
|
+
// Always render — never hide statementRows[].statementText
|
|
69
|
+
<span dangerouslySetInnerHTML={{ __html: row.statementText }} />
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
For CFM bipolar, also render `row.oppositeStatementText` on the right.
|
|
73
|
+
|
|
74
|
+
For CFM transposed, row labels come from `scaleColumns[].label`; column headers from `statementRows[].statementText`.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Label header rules
|
|
79
|
+
|
|
80
|
+
At least one header row MUST be visible when configured:
|
|
81
|
+
|
|
82
|
+
- `scaleAnchorLabels.length > 0` → anchor row (positioning formulas in ui-specs)
|
|
83
|
+
- `showColumnHeaders === true` → column label row from `scaleColumns[].label` or transposed `statementText`
|
|
84
|
+
- CSAT without anchors → column header row from `scaleColumns[].label`
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Agent checklist
|
|
89
|
+
|
|
90
|
+
- [ ] Read this doc when survey contains matrix or slider types
|
|
91
|
+
- [ ] Copied all required templates before Phase 5 BUILD
|
|
92
|
+
- [ ] Verified row labels + column/anchor labels render on every matrix question
|
|
93
|
+
- [ ] Verified slider has header badges + track (not orphan circle)
|
|
94
|
+
- [ ] `customFieldValues.ts` populated and wired to hook + Question when survey uses CRM logic
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Client Integration Guide
|
|
2
2
|
|
|
3
|
-
> **Start here** after Phase 2 (instanceId).
|
|
3
|
+
> **Start here** after Phase 2 (instanceId). Full pipeline order: [`agent-execution-flow.md`](agent-execution-flow.md).
|
|
4
4
|
|
|
5
5
|
Import only from the package root (`@explorer02/cfm-survey-sdk` or `@repo/sdk`). Never from `/src/` paths.
|
|
6
6
|
|
|
@@ -34,7 +34,7 @@ flowchart TB
|
|
|
34
34
|
| Dispatcher | `Question.tsx` | Route on `question.type`; filter options/rows via visibility helpers; placeholder text |
|
|
35
35
|
| Scales | `*Scale.tsx` | Render one question type; store answers via `onSelect` callback |
|
|
36
36
|
|
|
37
|
-
Reference implementation: `apps/client
|
|
37
|
+
Reference implementation: portable templates in `docs/templates/` — not `apps/client` (monorepo snapshot only).
|
|
38
38
|
|
|
39
39
|
---
|
|
40
40
|
|
|
@@ -51,7 +51,7 @@ Reference implementation: `apps/client/src/components/SurveyPage.tsx`.
|
|
|
51
51
|
| Question display variants | Render `question.questionText` from `currentQuestions` (no client variant logic) | Conditional variant text via same logic engine |
|
|
52
52
|
| Answer logic UI | `getVisible*ForAnswers` + pass `customFieldValues` | Condition evaluation engine |
|
|
53
53
|
| Custom fields | Stable `customFieldValues` → hook **and** `Question` | Skip/display/validation/progress evaluation |
|
|
54
|
-
| Progress |
|
|
54
|
+
| Progress | `SurveyStickyChrome` with `state.progressPercentage` | Sticky header + bar; active-path denominator + earned credits |
|
|
55
55
|
| Question numbering | Render `question.questionNumber` from `currentQuestions` | Active-path ordinals (same denominator as progress); see [`question-numbering.md`](question-numbering.md) |
|
|
56
56
|
| Placeholders | Stable `placeholders` ref + `language` option | Token replacement at map time |
|
|
57
57
|
| Mark as started | `onAction(SCROLL)` once on first scroll | One-time API call (also fires on CHANGE) |
|
|
@@ -161,10 +161,11 @@ function SurveyContent({
|
|
|
161
161
|
}, [state.currentQuestions, onAction]);
|
|
162
162
|
|
|
163
163
|
return (
|
|
164
|
-
|
|
165
|
-
<
|
|
164
|
+
<>
|
|
165
|
+
<SurveyStickyChrome progressPercentage={state.progressPercentage} />
|
|
166
166
|
|
|
167
|
-
|
|
167
|
+
<main className="mx-auto w-full max-w-4xl flex-1 px-4 py-10">
|
|
168
|
+
{state.currentQuestions.map(question => (
|
|
168
169
|
<Question
|
|
169
170
|
key={question.id}
|
|
170
171
|
question={question}
|
|
@@ -189,7 +190,8 @@ function SurveyContent({
|
|
|
189
190
|
>
|
|
190
191
|
{state.primaryButtonType === 'submit' ? 'Submit' : 'Next'}
|
|
191
192
|
</button>
|
|
192
|
-
|
|
193
|
+
</main>
|
|
194
|
+
</>
|
|
193
195
|
);
|
|
194
196
|
}
|
|
195
197
|
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Client Lib Folder — Portable Templates
|
|
2
|
+
|
|
3
|
+
> Maps the reference monorepo [`apps/client/src/lib/`](../../../../apps/client/src/lib/) layout to portable templates agents copy into their project. **Do not import from `apps/client/` in npm installs.**
|
|
4
|
+
|
|
5
|
+
Related: [`custom-field-logic-and-navigation.md`](custom-field-logic-and-navigation.md) · [`component-checklist.md`](component-checklist.md) · [`constraints.md`](constraints.md)
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Reference → portable mapping
|
|
10
|
+
|
|
11
|
+
| Reference file (monorepo) | Portable template | Used by | Agent action |
|
|
12
|
+
|---------------------------|-------------------|---------|--------------|
|
|
13
|
+
| `lib/customFieldValues.ts` | [`templates/customFieldValues.ts`](../templates/customFieldValues.ts) | `SurveyPage` → `useSurveySDK` + `Question` | Copy to `src/lib/`; populate `_c_…` ids from fetched survey |
|
|
14
|
+
| `lib/surveyUi/getAccentColor.ts` + `scaleValues.ts` | [`templates/surveyUiScaleUtils.ts`](../templates/surveyUiScaleUtils.ts) | NPS colors, slider tick colors, matrix column helpers | Copy to `src/lib/` or co-locate with scale components |
|
|
15
|
+
| `lib/surveyUi/icons.tsx` | [`templates/surveyUiIcons.tsx`](../templates/surveyUiIcons.tsx) | CSAT emoji/star (`CsatMatrixScale`) | Copy; add `react-icons` to `package.json` |
|
|
16
|
+
| `lib/surveyUi/heatmapCoords.ts` | [`templates/heatmapCoords.ts`](../templates/heatmapCoords.ts) | `HeatmapScale` | Copy to `src/lib/heatmapCoords.ts` |
|
|
17
|
+
| — (wizard styling) | [`templates/selectionStyles.ts`](../templates/selectionStyles.ts) | All scale radio/numbered selections | Copy to `src/lib/surveyUi/selectionStyles.ts` |
|
|
18
|
+
| — (wizard styling) | [`templates/labelStyles.ts`](../templates/labelStyles.ts) | Matrix/slider label items | Copy to `src/lib/surveyUi/labelStyles.ts` |
|
|
19
|
+
|
|
20
|
+
Scale **components** live in `src/components/` — see [`component-checklist.md`](component-checklist.md). Lib files are shared utilities and CRM data, not React components.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Recommended project layout
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
src/
|
|
28
|
+
├── lib/
|
|
29
|
+
│ ├── customFieldValues.ts ← CRM map for useSurveySDK (copy template)
|
|
30
|
+
│ ├── surveyUiScaleUtils.ts ← NPS/tick/matrix helpers
|
|
31
|
+
│ ├── surveyUiIcons.tsx ← emoji/star icons (optional co-locate)
|
|
32
|
+
│ ├── surveyUi/selectionStyles.ts ← wizard: focus ring + cell selected (copy template)
|
|
33
|
+
│ ├── surveyUi/labelStyles.ts ← wizard: label item colors (copy template)
|
|
34
|
+
│ └── heatmapCoords.ts ← when survey has HEATMAP
|
|
35
|
+
└── components/
|
|
36
|
+
├── SurveyPage.tsx
|
|
37
|
+
├── Question.tsx
|
|
38
|
+
├── RatingScale.tsx
|
|
39
|
+
└── ...scale components from templates/
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Placeholders follow the same stable-ref rule — define **`SURVEY_PLACEHOLDERS`** outside the component (often in `SurveyPage.tsx` module scope or a separate `lib/placeholders.ts`).
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## `customFieldValues.ts` — CRM input for SDK logic
|
|
47
|
+
|
|
48
|
+
Custom field values are **not** survey UI inputs. They come from CRM/transaction context (API payload, JWT claims, host app state) and are passed to the SDK so skip, display, progress, end-page, and answer logic can evaluate rules referencing `entityType: 'CUSTOM_FIELD'`.
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
import type { CustomFieldValueMap } from '@explorer02/cfm-survey-sdk';
|
|
52
|
+
import { CUSTOM_FIELD_VALUES } from '@/lib/customFieldValues';
|
|
53
|
+
|
|
54
|
+
const surveyOptions = useMemo(
|
|
55
|
+
() => ({
|
|
56
|
+
instanceId,
|
|
57
|
+
placeholders: SURVEY_PLACEHOLDERS,
|
|
58
|
+
customFieldValues: CUSTOM_FIELD_VALUES,
|
|
59
|
+
}),
|
|
60
|
+
[instanceId, selectedLanguage]
|
|
61
|
+
);
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Pass the **same map** to `Question`:
|
|
65
|
+
|
|
66
|
+
```tsx
|
|
67
|
+
<Question customFieldValues={CUSTOM_FIELD_VALUES} ... />
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
See [`custom-field-logic-and-navigation.md`](custom-field-logic-and-navigation.md) for discovery, value shapes, and the two wiring points.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## `surveyUiScaleUtils.ts` — scale UI helpers
|
|
75
|
+
|
|
76
|
+
Exports used by portable scale templates:
|
|
77
|
+
|
|
78
|
+
| Export | Purpose |
|
|
79
|
+
|--------|---------|
|
|
80
|
+
| `getAccentColor(value)` | NPS 0–10 traffic-light badge colors |
|
|
81
|
+
| `tickColorFromIndex(index, total)` | SLIDER_MATRIX header tick badge colors |
|
|
82
|
+
| `matrixColumnStoredValue(col)` | Matrix answer storage — column `id` or `null` for N/A |
|
|
83
|
+
| `npsValueFromOption` / `starValueFromOption` | NPS badge numeric values |
|
|
84
|
+
| `nonNaScaleColumns` | Filter N/A column from scale columns |
|
|
85
|
+
|
|
86
|
+
Prefer SDK `matrixColumnStoredValue` when importing from package; template re-exports the same contract for co-located components.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## `surveyUiIcons.tsx` — CSAT emoji and star icons
|
|
91
|
+
|
|
92
|
+
- `getEmojiForIndex(index, totalColumns)` — CSAT emoji matrix cells
|
|
93
|
+
- `CsatStarIcons` — filled/empty star nodes for `displayStyle: 'star'`
|
|
94
|
+
|
|
95
|
+
Requires `react-icons` (`fa6`, `fa`).
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## `heatmapCoords.ts` — normalized click coordinates
|
|
100
|
+
|
|
101
|
+
Used by `HeatmapScale`:
|
|
102
|
+
|
|
103
|
+
- `getNormalizedClickFromImage(event, imageElement)`
|
|
104
|
+
- `findSpotNearClick(clickX, clickY, spots, imageRect)`
|
|
105
|
+
- `createNewSpot(x, y)`
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Agent checklist
|
|
110
|
+
|
|
111
|
+
- [ ] Copied lib templates before Phase 5 BUILD — do not read `apps/client/src/lib` at runtime
|
|
112
|
+
- [ ] `customFieldValues.ts` created when survey logic references any `_c_…` custom field id
|
|
113
|
+
- [ ] `CUSTOM_FIELD_VALUES` defined **outside** React components (stable ref)
|
|
114
|
+
- [ ] Same map passed to `useSurveySDK` options **and** `Question` prop
|
|
115
|
+
- [ ] Scale utils/icons copied when survey contains NPS, matrix emoji/star, SLIDER_MATRIX, or HEATMAP
|
|
@@ -1,94 +1,122 @@
|
|
|
1
1
|
# Required Component Files Checklist
|
|
2
2
|
|
|
3
|
-
> **Blocking gate before Phase 5 (BUILD).**
|
|
3
|
+
> **Blocking gate before Phase 5 (BUILD).** Read [`agent-operating-contract.md`](agent-operating-contract.md) §2–§3 first — do not invent files or paths from memory.
|
|
4
|
+
>
|
|
5
|
+
> **Wizard-ready build (Phase 5 — mandatory):** Every agent build wires live-preview contract per [`agent-execution-flow.md`](agent-execution-flow.md), [`wizard-preview-build-guide.md`](wizard-preview-build-guide.md), and [`wizard-question-type-styling.md`](wizard-question-type-styling.md) — `var(--cfm-*)`, `data-cfm-*` hooks, `selectionStyles.ts`, `labelStyles.ts`, draft `survey-ui-config.json`. Running the wizard (Phase 6b) is optional; wizard-ready artifacts are not.
|
|
6
|
+
>
|
|
7
|
+
> Read [`canonical-survey-fixtures.md`](canonical-survey-fixtures.md) when matrix/slider labels are missing.
|
|
4
8
|
|
|
5
9
|
## Step 1: Inventory Question Types
|
|
6
10
|
|
|
7
11
|
From `survey.pages`, collect unique `question.type` values — see `MANIFEST.json` `typeLiterals`:
|
|
8
12
|
|
|
9
|
-
| questionId | type |
|
|
10
|
-
|
|
11
|
-
| | |
|
|
13
|
+
| questionId | type | displayStyle / statementLayout / transposeTable |
|
|
14
|
+
|------------|------|--------------------------------------------------|
|
|
15
|
+
| | | |
|
|
12
16
|
|
|
13
|
-
|
|
17
|
+
Note matrix variants: `displayStyle`, `statementLayout`, `transposeTable`, `selectionMode`.
|
|
14
18
|
|
|
15
|
-
|
|
19
|
+
## Step 2: Copy Portable Templates (CRITICAL)
|
|
16
20
|
|
|
17
|
-
|
|
18
|
-
|-------------------|---------|
|
|
19
|
-
| `templates/Question.tsx` | `src/components/Question.tsx` |
|
|
20
|
-
| `templates/RankOrderScale.tsx` | `src/components/RankOrderScale.tsx` |
|
|
21
|
-
| `templates/MatrixDropdown.tsx` | `src/components/MatrixDropdown.tsx` |
|
|
22
|
-
| `templates/CustomSliderTrack.tsx` + `surveyUiIcons.tsx` | same folder |
|
|
23
|
-
| `templates/heatmapCoords.ts` | `src/lib/heatmapCoords.ts` |
|
|
21
|
+
**Copy from [`templates/`](../templates/) before customizing branding.** Do not implement matrix/slider UI from scratch.
|
|
24
22
|
|
|
25
|
-
|
|
26
|
-
|--------------------|------------------------------------------|---------|
|
|
27
|
-
| `NPS_SCALE` | `RatingScale.tsx` | `03-ui-specs/01-rating.md` |
|
|
28
|
-
| `CFM_MATRIX` | `LikertMatrixScale.tsx`, `MatrixDropdown.tsx` | `03-ui-specs/07-matrix-cfm.md` |
|
|
29
|
-
| `CSAT_MATRIX` | `CsatMatrixScale.tsx`, `MatrixDropdown.tsx`, `CustomSliderTrack.tsx` | `03-ui-specs/04-csat.md` |
|
|
30
|
-
| `RATING_MATRIX` | `CsatMatrixScale.tsx`, `MatrixDropdown.tsx`, `CustomSliderTrack.tsx` | `03-ui-specs/08-matrix-csat-rating.md` |
|
|
31
|
-
| `SLIDER_MATRIX` | `SliderMatrixScale.tsx`, `CustomSliderTrack.tsx` | `03-ui-specs/09-slider-matrix.md` |
|
|
32
|
-
| `FILE_UPLOAD` | `FileUploadScale.tsx` | `03-ui-specs/10-file-upload.md` |
|
|
33
|
-
| `MCQ`, `TEXTFIELD`, `TEXT_AND_MEDIA` | Inline in `Question.tsx` | `03-ui-specs/02-radio.md`, `03-text.md`, `11-text-and-media.md` |
|
|
34
|
-
| `RANK_ORDER` | `RankOrderScale.tsx` (+ `@dnd-kit/*`) | `03-ui-specs/14-rank-order.md` |
|
|
35
|
-
| `HEATMAP` | `HeatmapScale.tsx`, `lib/heatmapCoords.ts` (copy from `templates/heatmapCoords.ts`) | `03-ui-specs/13-heatmap.md` |
|
|
23
|
+
### Copy order
|
|
36
24
|
|
|
37
|
-
|
|
25
|
+
0. **`customFieldValues.ts`** → `src/lib/` when any `_c_…` id in survey logic (see [`custom-field-logic-and-navigation.md`](custom-field-logic-and-navigation.md))
|
|
26
|
+
0b. **`selectionStyles.ts`**, **`labelStyles.ts`** → `src/lib/surveyUi/` (**required** — see [`wizard-question-type-styling.md`](wizard-question-type-styling.md))
|
|
27
|
+
1. `surveyUiScaleUtils.ts` → `src/lib/` (or co-locate with components)
|
|
28
|
+
2. `surveyUiIcons.tsx` → same folder as scale components
|
|
29
|
+
3. `CustomSliderTrack.tsx`, `MatrixDropdown.tsx`, `heatmapCoords.ts`
|
|
30
|
+
4. Scale components per survey types
|
|
31
|
+
5. `Question.tsx` from template
|
|
38
32
|
|
|
39
|
-
|
|
|
40
|
-
|
|
41
|
-
| `
|
|
42
|
-
| `
|
|
43
|
-
| `
|
|
33
|
+
| `templates/customFieldValues.ts` | `src/lib/customFieldValues.ts` | Any `CUSTOM_FIELD` in skip/display/answer/end logic |
|
|
34
|
+
| `templates/selectionStyles.ts` | `src/lib/surveyUi/selectionStyles.ts` | **Required** — radio/scale selection colors |
|
|
35
|
+
| `templates/labelStyles.ts` | `src/lib/surveyUi/labelStyles.ts` | **Required** — matrix/slider label items |
|
|
36
|
+
| `templates/survey-theme.css` | `src/styles/survey-theme.css` | **Required** — full `--cfm-*` defaults |
|
|
37
|
+
| `templates/previewBridge.ts` | `src/lib/previewBridge.ts` | **Required** — local `customize` live preview |
|
|
44
38
|
|
|
45
|
-
|
|
39
|
+
See [`client-lib-folder.md`](client-lib-folder.md) for full lib layout.
|
|
46
40
|
|
|
47
|
-
|
|
41
|
+
| Portable template | Copy to | When survey contains |
|
|
42
|
+
|-------------------|---------|----------------------|
|
|
43
|
+
| `templates/Question.tsx` | `src/components/Question.tsx` | Always |
|
|
44
|
+
| `templates/RatingScale.tsx` | `src/components/RatingScale.tsx` | `NPS_SCALE` |
|
|
45
|
+
| `templates/LikertMatrixScale.tsx` | `src/components/LikertMatrixScale.tsx` | `CFM_MATRIX` |
|
|
46
|
+
| `templates/CsatMatrixScale.tsx` | `src/components/CsatMatrixScale.tsx` | `CSAT_MATRIX`, `RATING_MATRIX` |
|
|
47
|
+
| `templates/SliderMatrixScale.tsx` | `src/components/SliderMatrixScale.tsx` | `SLIDER_MATRIX` |
|
|
48
|
+
| `templates/FileUploadScale.tsx` | `src/components/FileUploadScale.tsx` | `FILE_UPLOAD` |
|
|
49
|
+
| `templates/HeatmapScale.tsx` | `src/components/HeatmapScale.tsx` | `HEATMAP` |
|
|
50
|
+
| `templates/RankOrderScale.tsx` | `src/components/RankOrderScale.tsx` | `RANK_ORDER` |
|
|
48
51
|
|
|
49
|
-
|
|
52
|
+
### Matrix label visibility gate
|
|
50
53
|
|
|
51
|
-
|
|
52
|
-
import { QUESTION_TYPE } from '@explorer02/cfm-survey-sdk';
|
|
54
|
+
Before `npm run build`, confirm every matrix question in your inventory will render:
|
|
53
55
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
- [ ] **Row labels**: `statementRows[].statementText` in 180px (or 25% bipolar) column
|
|
57
|
+
- [ ] **Column labels**: `scaleColumns[].label` header row OR `scaleAnchorLabels` anchor row
|
|
58
|
+
- [ ] **Bipolar**: `oppositeStatementText` in 25% right column
|
|
59
|
+
- [ ] **Transposed**: row labels from `scaleColumns[].label`; column headers from `statementRows[].statementText`
|
|
57
60
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
)
|
|
62
|
-
|
|
61
|
+
### Slider visibility gate
|
|
62
|
+
|
|
63
|
+
- [ ] Colored tick header row (0–10 badges from `ticks.marks`)
|
|
64
|
+
- [ ] Gray row band with statement text + `CustomSliderTrack` (not orphan circle)
|
|
65
|
+
|
|
66
|
+
| If survey contains | Also copy | UI spec |
|
|
67
|
+
|--------------------|-----------|---------|
|
|
68
|
+
| `SLIDER_MATRIX` | `CustomSliderTrack.tsx`, `surveyUiScaleUtils.ts` | `03-ui-specs/09-slider-matrix.md` |
|
|
69
|
+
| `CFM_MATRIX` | `MatrixDropdown.tsx` (if dropdown layout) | `03-ui-specs/07-matrix-cfm.md` |
|
|
70
|
+
| `CSAT_MATRIX` / `RATING_MATRIX` | `surveyUiIcons.tsx`, `CustomSliderTrack.tsx` (graphics) | `03-ui-specs/04-csat.md`, `08-matrix-csat-rating.md` |
|
|
71
|
+
| `RANK_ORDER` | `@dnd-kit/*` in package.json | `03-ui-specs/14-rank-order.md` |
|
|
72
|
+
| `HEATMAP` | `heatmapCoords.ts` | `03-ui-specs/13-heatmap.md` |
|
|
73
|
+
| `MCQ`, `TEXTFIELD`, `TEXT_AND_MEDIA` | inline in `Question.tsx` | `03-ui-specs/02-radio.md`, etc. |
|
|
74
|
+
|
|
75
|
+
## Flat Type Routing (CRITICAL)
|
|
76
|
+
|
|
77
|
+
Use `QUESTION_TYPE` — **no `subType`**. Pass filtered matrix questions from `getVisibleMatrixItemsForAnswers`.
|
|
63
78
|
|
|
64
79
|
## Shared Primitives
|
|
65
80
|
|
|
66
81
|
| File | Used by |
|
|
67
82
|
|------|---------|
|
|
68
|
-
| `CustomSliderTrack.tsx` | `SLIDER_MATRIX`,
|
|
69
|
-
| `MatrixDropdown.tsx` |
|
|
83
|
+
| `CustomSliderTrack.tsx` | `SLIDER_MATRIX`, RATING/CSAT `displayStyle: graphics` |
|
|
84
|
+
| `MatrixDropdown.tsx` | Matrix dropdown/selectbox modes |
|
|
85
|
+
| `surveyUiScaleUtils.ts` | NPS colors, tick colors, matrix column values |
|
|
86
|
+
| `surveyUiIcons.tsx` | CSAT emoji/star icons |
|
|
87
|
+
| `selectionStyles.ts` | Focus ring + cell selected pattern (all scale radios) |
|
|
88
|
+
| `labelStyles.ts` | Hint / column / tick label item colors |
|
|
70
89
|
|
|
71
90
|
Store matrix values as column **`id`** — `matrixColumnStoredValue(col)` from SDK.
|
|
72
91
|
|
|
73
|
-
## Answer logic (when survey has gated options / rows / columns)
|
|
74
|
-
|
|
75
|
-
- [ ] MCQ: filter options with `getVisibleMcqOptionsForAnswers(question, answers, allQuestions, customFieldValues)`
|
|
76
|
-
- [ ] Matrix (CSAT/CFM/RATING/SLIDER): filter rows (and CSAT/CFM columns) with `getVisibleMatrixItemsForAnswers(question, answers, allQuestions, customFieldValues)`
|
|
77
|
-
- [ ] Pass `customFieldValues` from `SurveyPage` → `Question` when survey logic references `CUSTOM_FIELD` entities
|
|
78
|
-
- [ ] Wire `onAction({ type: 'CHANGE' })` so answer logic re-evaluates when prior answers change
|
|
79
|
-
|
|
80
|
-
See [`answer-logic-and-navigation.md`](answer-logic-and-navigation.md) and [`custom-field-logic-and-navigation.md`](custom-field-logic-and-navigation.md).
|
|
81
|
-
|
|
82
92
|
## Step 3: Verify Before Build
|
|
83
93
|
|
|
84
|
-
- [ ] Every type in
|
|
85
|
-
- [ ]
|
|
86
|
-
- [ ]
|
|
87
|
-
- [ ]
|
|
88
|
-
- [ ]
|
|
89
|
-
- [ ]
|
|
90
|
-
- [ ]
|
|
94
|
+
- [ ] Every type in survey inventory has matching component file(s)
|
|
95
|
+
- [ ] **`src/lib/customFieldValues.ts`** when survey logic references `_c_…` ids — keys from **fetch**, wire hook + Question ([`placeholders-and-custom-fields-wiring.md`](00-integration/placeholders-and-custom-fields-wiring.md))
|
|
96
|
+
- [ ] **`SURVEY_PLACEHOLDERS`** keys discovered from fetched `{{TOKEN}}` text — not mockup
|
|
97
|
+
- [ ] `CUSTOM_FIELD_VALUES` wired in `SurveyPage` hook options **and** `Question` prop
|
|
98
|
+
- [ ] Matrix row + column/anchor labels visible (see canonical fixtures)
|
|
99
|
+
- [ ] Slider has header + track (see canonical fixtures)
|
|
100
|
+
- [ ] `Question.tsx` has `questionNumber` prefix and all 11 type branches
|
|
101
|
+
- [ ] `react-icons` in package.json when CSAT/RATING/NPS emoji modes present
|
|
102
|
+
- [ ] Grep: `not yet implemented` → zero matches
|
|
91
103
|
|
|
92
104
|
```bash
|
|
93
|
-
|
|
105
|
+
bash templates/verify-agent-build.sh
|
|
106
|
+
# or from SDK package root: node_modules/@explorer02/cfm-survey-sdk/templates/docs/templates/verify-agent-build.sh
|
|
94
107
|
```
|
|
108
|
+
|
|
109
|
+
## Step 4: Wizard-ready build (Phase 5 — mandatory)
|
|
110
|
+
|
|
111
|
+
Read: [`agent-execution-flow.md`](agent-execution-flow.md), [`wizard-preview-build-guide.md`](wizard-preview-build-guide.md), [`wizard-question-type-styling.md`](wizard-question-type-styling.md)
|
|
112
|
+
|
|
113
|
+
- [ ] `src/styles/survey-theme.css` with full `--cfm-*` set (copy from `templates/survey-theme.css`)
|
|
114
|
+
- [ ] `selectionStyles.ts` + `labelStyles.ts` in `src/lib/surveyUi/`
|
|
115
|
+
- [ ] Draft `./survey-ui-config.json` synced with mockup branding
|
|
116
|
+
- [ ] `previewBridge.ts` + `PreviewBridgeInit` in root layout
|
|
117
|
+
- [ ] Header/Footer/ProgressBar/SurveyPage use `var(--cfm-*)` — no hardcoded brand hex for wizard-controlled tokens
|
|
118
|
+
- [ ] `data-cfm-logo` / `data-cfm-logo-text`, `data-cfm-company`, `data-cfm-survey-title`, `data-cfm-btn-next`, `data-cfm-btn-back`, `data-cfm-thank-you` on chrome
|
|
119
|
+
- [ ] **Layout toggles:** `data-cfm-progress`, `[data-cfm-question-number]`, `[data-cfm-required]`, `.cfm-footer` — see `wizard-troubleshooting.md` §3
|
|
120
|
+
- [ ] Per-type scale vars per `wizard-question-type-styling.md` for **all 11 types** (wizard exports all; survey inventory may be smaller)
|
|
121
|
+
- [ ] Selection pattern: focus ring = outer border + inner dot; cell selected = annulus fill
|
|
122
|
+
- [ ] `npx cfm-sdk export-previews` succeeds from project root (when previews needed for AWS wizard)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Critical Constraints
|
|
2
2
|
|
|
3
|
-
> Non-negotiable rules. Violating any of these breaks the build or survey UX.
|
|
3
|
+
> Non-negotiable rules. Violating any of these breaks the build or survey UX.
|
|
4
|
+
> Agent enforcement: [`agent-operating-contract.md`](agent-operating-contract.md) §4 hallucination blocklist.
|
|
4
5
|
|
|
5
6
|
## 1. Top-Level Imports Only
|
|
6
7
|
|
|
@@ -26,11 +27,19 @@ Every question card **must** have `id={question.id}` on its outermost element:
|
|
|
26
27
|
|
|
27
28
|
Required for scroll-to-error when validation fails.
|
|
28
29
|
|
|
29
|
-
## 4.
|
|
30
|
+
## 4. Logo (wizard-compatible)
|
|
30
31
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
Choose **one** pattern in `Header.tsx` — see [`wizard-preview-build-guide.md`](wizard-preview-build-guide.md) and [`10-header-footer.md`](../01-components/10-header-footer.md):
|
|
33
|
+
|
|
34
|
+
| Mode | Rules |
|
|
35
|
+
|------|--------|
|
|
36
|
+
| **Text / CSS-only** | Build logo with HTML + CSS; use `<span data-cfm-logo-text>`. No `public/` logo file required. |
|
|
37
|
+
| **Local image** | Put asset in `public/`; reference with `<img data-cfm-logo src="/your-logo.svg" />` for local dev. For **AWS static export**, use `src="./your-logo.svg"` (relative — required under `/sites/{surveyId}/{deployId}/`). **Never** use external URLs (`https://…`) or wizard `data:` URLs in the built survey. |
|
|
38
|
+
|
|
39
|
+
- Do **not** drop unrelated `public/logo_*` files during agent build — CLI seeds from `Header.tsx`, not newest `logo_*`.
|
|
40
|
+
- After wizard upload, `survey-ui-config.json` `global.logo.fileName` is authoritative on re-open.
|
|
41
|
+
- Wizard preview shows logo from **browser memory**; CloudFront serves only files in the **deploy bundle** (`out/` → S3 `sites/{surveyId}/{deployId}/`). See [`aws-deploy.md`](aws-deploy.md) § Logos & local assets.
|
|
42
|
+
- After EC2 wizard complete, poll/final JSON includes `global.logo.url` (CloudFront `/assets/` URL) — agent downloads to `public/` via `confirm-ui-config`; still use `./{fileName}` in `Header.tsx`, not the assets URL.
|
|
34
43
|
|
|
35
44
|
## 5. Client Components
|
|
36
45
|
|