@explorer02/cfm-survey-sdk 0.2.3 → 0.2.4
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 +140 -33
- package/dist/cli/index.mjs +140 -33
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +8 -1
- package/postinstall.js +8 -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 +281 -0
- package/templates/docs/00-integration/agent-operating-contract.md +260 -0
- package/templates/docs/00-integration/apply-ui-config.md +365 -0
- 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 +88 -62
- package/templates/docs/00-integration/constraints.md +13 -5
- package/templates/docs/00-integration/custom-field-logic-and-navigation.md +56 -0
- 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 +144 -0
- package/templates/docs/00-integration/useSurveySDK.md +35 -1
- package/templates/docs/00-integration/wizard-api.md +134 -0
- package/templates/docs/00-integration/wizard-config-handoff.md +246 -0
- package/templates/docs/00-integration/wizard-preview-build-guide.md +400 -0
- package/templates/docs/00-integration/wizard-question-type-styling.md +195 -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 +162 -6
- package/templates/docs/index.md +116 -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/implementation_plan.md +56 -9
- 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-DgHfrVeb.js +1 -0
- package/templates/wizard-dist/assets/TypePanel-CFVC3Ptn.js +1 -0
- package/templates/wizard-dist/assets/index-BhWM50Yu.css +1 -0
- package/templates/wizard-dist/assets/index-DYK3X1e5.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
|
@@ -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,120 @@
|
|
|
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
|
-
- [ ] `SurveyPage`
|
|
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
|
|
96
|
+
- [ ] `CUSTOM_FIELD_VALUES` wired in `SurveyPage` hook options **and** `Question` prop
|
|
97
|
+
- [ ] Matrix row + column/anchor labels visible (see canonical fixtures)
|
|
98
|
+
- [ ] Slider has header + track (see canonical fixtures)
|
|
99
|
+
- [ ] `Question.tsx` has `questionNumber` prefix and all 11 type branches
|
|
100
|
+
- [ ] `react-icons` in package.json when CSAT/RATING/NPS emoji modes present
|
|
101
|
+
- [ ] Grep: `not yet implemented` → zero matches
|
|
91
102
|
|
|
92
103
|
```bash
|
|
93
|
-
|
|
104
|
+
bash templates/verify-agent-build.sh
|
|
105
|
+
# or from SDK package root: node_modules/@explorer02/cfm-survey-sdk/templates/docs/templates/verify-agent-build.sh
|
|
94
106
|
```
|
|
107
|
+
|
|
108
|
+
## Step 4: Wizard-ready build (Phase 5 — mandatory)
|
|
109
|
+
|
|
110
|
+
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)
|
|
111
|
+
|
|
112
|
+
- [ ] `src/styles/survey-theme.css` with full `--cfm-*` set (copy from `templates/survey-theme.css`)
|
|
113
|
+
- [ ] `selectionStyles.ts` + `labelStyles.ts` in `src/lib/surveyUi/`
|
|
114
|
+
- [ ] Draft `./survey-ui-config.json` synced with mockup branding
|
|
115
|
+
- [ ] `previewBridge.ts` + `PreviewBridgeInit` in root layout
|
|
116
|
+
- [ ] Header/Footer/ProgressBar/SurveyPage use `var(--cfm-*)` — no hardcoded brand hex for wizard-controlled tokens
|
|
117
|
+
- [ ] `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
|
|
118
|
+
- [ ] Per-type scale vars per `wizard-question-type-styling.md` for types in survey inventory
|
|
119
|
+
- [ ] Selection pattern: focus ring = outer border + inner dot; cell selected = annulus fill
|
|
120
|
+
- [ ] `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,18 @@ 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" />`. **Never** use external URLs (`https://…`) 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
|
+
- After wizard complete, poll/final JSON includes `global.logo.url` (public CloudFront URL) for agent handoff; the agent still copies the file to `public/` and uses a local `src` in `Header.tsx`.
|
|
34
42
|
|
|
35
43
|
## 5. Client Components
|
|
36
44
|
|
|
@@ -18,6 +18,61 @@ Survey logic rules may reference **custom fields** instead of survey questions:
|
|
|
18
18
|
|
|
19
19
|
Inspect fetched survey data: any `skipLogics`, `displayLogic`, or `answerLogic` with `entityType: 'CUSTOM_FIELD'` requires client-supplied values.
|
|
20
20
|
|
|
21
|
+
Copy portable template: [`templates/customFieldValues.ts`](../templates/customFieldValues.ts) → `src/lib/customFieldValues.ts`. See [`client-lib-folder.md`](client-lib-folder.md).
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Agent implementation recipe
|
|
26
|
+
|
|
27
|
+
1. **After fetch** — scan `survey.pages` (and `endPages` logic) for `conditionEntity.entityType === 'CUSTOM_FIELD'`. Collect every `conditionEntity.id` (`_c_…`).
|
|
28
|
+
2. **Record** each id in `implementation_plan.md` §3d with `fieldType`, logic kind (skip/display/answer/end), and expected CRM value shape.
|
|
29
|
+
3. **Copy** [`templates/customFieldValues.ts`](../templates/customFieldValues.ts) → `src/lib/customFieldValues.ts`. Populate from CRM/transaction API — **not** inline in `SurveyPage`.
|
|
30
|
+
4. **Wire hook** — import map and pass in stable `useMemo` options:
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
import { CUSTOM_FIELD_VALUES } from '@/lib/customFieldValues';
|
|
34
|
+
|
|
35
|
+
const surveyOptions = useMemo(
|
|
36
|
+
() => ({
|
|
37
|
+
instanceId,
|
|
38
|
+
placeholders: SURVEY_PLACEHOLDERS,
|
|
39
|
+
customFieldValues: CUSTOM_FIELD_VALUES,
|
|
40
|
+
}),
|
|
41
|
+
[instanceId, selectedLanguage]
|
|
42
|
+
);
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
5. **Wire Question** — pass the **same** map as `customFieldValues` prop (template `Question.tsx` already forwards it to `getVisible*ForAnswers`).
|
|
46
|
+
6. **Verify** — trigger a custom-field skip rule on Next; no per-question client evaluator code needed.
|
|
47
|
+
|
|
48
|
+
**Blocking gate:** if any `_c_…` id exists in fetched survey → `src/lib/customFieldValues.ts` must exist before Phase 5 BUILD.
|
|
49
|
+
|
|
50
|
+
### Fixture example (integration-test survey)
|
|
51
|
+
|
|
52
|
+
Page 2 `SLIDER_MATRIX` has a skip rule:
|
|
53
|
+
|
|
54
|
+
```json
|
|
55
|
+
{
|
|
56
|
+
"conditionEntity": {
|
|
57
|
+
"id": "_c_67199096d294be011a2b4773",
|
|
58
|
+
"entityType": "CUSTOM_FIELD",
|
|
59
|
+
"fieldType": "TEXT"
|
|
60
|
+
},
|
|
61
|
+
"field": "CASE_SENSITIVE_TEXT",
|
|
62
|
+
"values": ["abc"]
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Client map:
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
export const CUSTOM_FIELD_VALUES: CustomFieldValueMap = {
|
|
70
|
+
'_c_67199096d294be011a2b4773': 'abc',
|
|
71
|
+
};
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
When this value matches, SDK skip logic runs on Next — values must be in **hook options**, not typed by the respondent.
|
|
75
|
+
|
|
21
76
|
---
|
|
22
77
|
|
|
23
78
|
## Client value map
|
|
@@ -172,3 +227,4 @@ When a question has several `skipLogics[]` entries (including custom-field rules
|
|
|
172
227
|
- [`display-logic-and-navigation.md`](display-logic-and-navigation.md) — question-level gating
|
|
173
228
|
- [`answer-logic-and-navigation.md`](answer-logic-and-navigation.md) — option/row/column gating + visibility helpers
|
|
174
229
|
- [`client-integration-guide.md`](client-integration-guide.md) — full wiring map
|
|
230
|
+
- [`client-lib-folder.md`](client-lib-folder.md) — lib folder layout + portable templates
|
|
@@ -52,10 +52,12 @@ Survey: 4 questions on active path (Q1–Q4 sequential).
|
|
|
52
52
|
|
|
53
53
|
## UI wiring
|
|
54
54
|
|
|
55
|
+
On the **content** phase, render progress inside sticky chrome so it stays visible when scrolling to the last question on a page:
|
|
56
|
+
|
|
55
57
|
```tsx
|
|
56
|
-
<
|
|
58
|
+
<SurveyStickyChrome progressPercentage={state.progressPercentage} />
|
|
57
59
|
```
|
|
58
60
|
|
|
59
|
-
See [`01-components/11-progress-bar.md`](../01-components/11-progress-bar.md) and [`03-ui-specs/12-survey-chrome.md`](../03-ui-specs/12-survey-chrome.md).
|
|
61
|
+
See [`01-components/19-survey-sticky-chrome.md`](../01-components/19-survey-sticky-chrome.md), [`01-components/11-progress-bar.md`](../01-components/11-progress-bar.md), and [`03-ui-specs/12-survey-chrome.md`](../03-ui-specs/12-survey-chrome.md).
|
|
60
62
|
|
|
61
63
|
See also: [`skip-logic-and-navigation.md`](skip-logic-and-navigation.md).
|
|
@@ -132,6 +132,18 @@ else → ask client which React setup to use
|
|
|
132
132
|
|
|
133
133
|
For **existing apps**, read `package.json` and project structure — do not scaffold from scratch unless the client asks.
|
|
134
134
|
|
|
135
|
+
### Recommended `src/lib/` scaffold
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
src/lib/
|
|
139
|
+
├── customFieldValues.ts ← templates/customFieldValues.ts (when CUSTOM_FIELD logic)
|
|
140
|
+
├── surveyUiScaleUtils.ts ← templates/surveyUiScaleUtils.ts
|
|
141
|
+
├── surveyUiIcons.tsx ← templates/surveyUiIcons.tsx (optional co-locate)
|
|
142
|
+
└── heatmapCoords.ts ← templates/heatmapCoords.ts (HEATMAP only)
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
See [`client-lib-folder.md`](client-lib-folder.md).
|
|
146
|
+
|
|
135
147
|
---
|
|
136
148
|
|
|
137
149
|
## Survey-type conditional dependencies
|