@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
|
@@ -1,78 +1,105 @@
|
|
|
1
1
|
# UI Spec: Slider Matrix (`type: 'SLIDER_MATRIX'`)
|
|
2
2
|
|
|
3
|
-
> **
|
|
3
|
+
> **COPY TEMPLATE FIRST:** [`templates/SliderMatrixScale.tsx`](../templates/SliderMatrixScale.tsx) + [`CustomSliderTrack.tsx`](../templates/CustomSliderTrack.tsx) + [`surveyUiScaleUtils.ts`](../templates/surveyUiScaleUtils.ts)
|
|
4
|
+
>
|
|
5
|
+
> **Anti-pattern:** Do NOT build custom range overlay sliders. Lone pink circle with no track = broken implementation.
|
|
6
|
+
>
|
|
4
7
|
> **SDK type:** `SliderMatrixQuestion` — `fetchSurvey/types/sliderMatrix.ts`
|
|
5
8
|
> **Component blueprint:** `01-components/07-slider-matrix-scale.md`
|
|
6
|
-
> **Shared:** [`shared/custom-slider-track.md`](shared/custom-slider-track.md)
|
|
7
9
|
|
|
8
10
|
## Config Inventory
|
|
9
11
|
|
|
10
12
|
| Field | Implemented | UI impact |
|
|
11
13
|
|-------|-------------|-----------|
|
|
12
|
-
| `
|
|
13
|
-
| `
|
|
14
|
-
| `
|
|
15
|
-
| `
|
|
16
|
-
| `sliderType: 'graphics'` | ✅ | Plain text tick labels; emoji thumb |
|
|
14
|
+
| `statementRows[]` (min/max/step) | ✅ | Per-row slider + **25% statement column** |
|
|
15
|
+
| `scaleAnchorLabels?` | ✅ | Text labels above tick badge row |
|
|
16
|
+
| `ticks.count` + `ticks.marks[]` | ✅ | Colored header badges (`tickPosition`, `tickLabel`) |
|
|
17
|
+
| `sliderStyle: 'graphics'` | ✅ | Plain text tick labels; emoji thumb |
|
|
17
18
|
| `enableInputBox` | ✅ | 80px input + stepper buttons |
|
|
18
19
|
| `displayValues` | ✅ | Passed to CustomSliderTrack |
|
|
19
|
-
| `
|
|
20
|
+
| `hasNotApplicableOption` | ✅ | Checkbox; answer value **`'N/A'`** string |
|
|
20
21
|
|
|
21
22
|
## Layout Anatomy
|
|
22
23
|
|
|
23
24
|
```
|
|
24
|
-
[header:
|
|
25
|
+
[header: scaleAnchorLabels? + colored tick badges from ticks.marks]
|
|
25
26
|
┌─ row band (#f3f4f6, rounded-xl) ─────────────────────────────┐
|
|
26
|
-
│ 25%
|
|
27
|
+
│ 25% statementText │ CustomSliderTrack │ 80px input? │ N/A? │
|
|
27
28
|
└───────────────────────────────────────────────────────────────┘
|
|
28
29
|
```
|
|
29
30
|
|
|
30
|
-
##
|
|
31
|
+
## Statement text (CRITICAL)
|
|
32
|
+
|
|
33
|
+
Every row MUST show `statementRows[].statementText` in the left 25% column:
|
|
34
|
+
|
|
35
|
+
```tsx
|
|
36
|
+
<div style={{ flex: '0 0 25%', paddingRight: '16px' }}>
|
|
37
|
+
{row.statementText && row.statementText !== 'Question' && (
|
|
38
|
+
<span dangerouslySetInnerHTML={{ __html: row.statementText }} />
|
|
39
|
+
)}
|
|
40
|
+
</div>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Agents that hide statement text or merge it into the question title break multi-row sliders.
|
|
44
|
+
|
|
45
|
+
## Header tick badges
|
|
31
46
|
|
|
32
47
|
```typescript
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
48
|
+
tickValues = ticks.marks.map((mark, i) => ({
|
|
49
|
+
value: mark.tickPosition,
|
|
50
|
+
label: mark.tickLabel,
|
|
51
|
+
color: tickColorFromIndex(i, ticks.count),
|
|
52
|
+
}));
|
|
53
|
+
percentage = ((tv.value - min) / (max - min)) * 100;
|
|
54
|
+
htmlStep = ticks.count > 1 ? (max - min) / (ticks.count - 1) : row.step;
|
|
37
55
|
```
|
|
38
56
|
|
|
39
|
-
## CustomSliderTrack per row
|
|
57
|
+
## CustomSliderTrack per row
|
|
40
58
|
|
|
41
59
|
```typescript
|
|
42
60
|
<CustomSliderTrack
|
|
43
61
|
min={row.min}
|
|
44
62
|
max={row.max}
|
|
45
|
-
htmlStep={
|
|
63
|
+
htmlStep={htmlStep}
|
|
46
64
|
value={rowVal as number}
|
|
47
|
-
|
|
48
|
-
|
|
65
|
+
disabled={rowVal === 'N/A'}
|
|
66
|
+
hasSelectedValue={typeof rowVal === 'number'}
|
|
67
|
+
displayValues={displayValues}
|
|
49
68
|
sliderType={question.sliderStyle === 'graphics' ? 'graphics' : undefined}
|
|
69
|
+
ticks={ticks.count}
|
|
50
70
|
onChange={v => updateRow(row.id, v)}
|
|
51
71
|
/>
|
|
52
72
|
```
|
|
53
73
|
|
|
54
|
-
Pass **`scaleColumns[].label`** (or row tick labels) as `tickLabels` — required for correct tooltip text (Day 19 fix).
|
|
55
|
-
|
|
56
74
|
## N/A Behavior
|
|
57
75
|
|
|
58
|
-
- Checked → `rowVal === 'N/A'`; slider disabled
|
|
76
|
+
- Checked → `rowVal === 'N/A'`; slider disabled
|
|
59
77
|
- Unchecked → reset to `defaultValue ?? min`
|
|
60
78
|
|
|
61
|
-
## Input Box
|
|
62
|
-
|
|
63
|
-
- Clamp to row.min / row.max on change
|
|
64
|
-
- Steppers use `htmlStep` increment/decrement
|
|
65
|
-
|
|
66
79
|
## Answer Mutation
|
|
67
80
|
|
|
68
81
|
```typescript
|
|
69
|
-
onSelect(Record<string, number |
|
|
82
|
+
onSelect(Record<string, number | 'N/A'>)
|
|
83
|
+
onAction({ type: 'CHANGE', payload: { questionId, answerValue: MatrixRowAnswers } })
|
|
70
84
|
```
|
|
71
85
|
|
|
72
86
|
## Agent Checklist
|
|
73
87
|
|
|
74
|
-
- [ ]
|
|
75
|
-
- [ ]
|
|
88
|
+
- [ ] Copied portable templates — did not build slider from scratch
|
|
89
|
+
- [ ] Shared header with colored 0–10 badges (even single-row questions)
|
|
90
|
+
- [ ] Gray row bands with **visible** statement text in 25% column
|
|
76
91
|
- [ ] CustomSliderTrack per row with correct htmlStep
|
|
77
|
-
- [ ]
|
|
78
|
-
|
|
92
|
+
- [ ] N/A uses `'N/A'` string, not null
|
|
93
|
+
|
|
94
|
+
## Wizard customization (Phase 5 — required)
|
|
95
|
+
|
|
96
|
+
| Control | CSS vars | Apply in |
|
|
97
|
+
|---------|----------|----------|
|
|
98
|
+
| Tick label items | `--cfm-slider-tick-label-color`, `--cfm-slider-tick-label-bg` | Header badge row — `sliderTickLabelStyle()` |
|
|
99
|
+
| Row band | `--cfm-slider-row-bg` | Gray statement band |
|
|
100
|
+
| Thumb selection | `--cfm-matrix-selected`, `--cfm-input-focus-ring` | `CustomSliderTrack` thumb ring + annulus + dot |
|
|
101
|
+
|
|
102
|
+
### Wizard checklist
|
|
103
|
+
|
|
104
|
+
- [ ] Colored tick badges use `--cfm-number-*` when traffic-light mode applies
|
|
105
|
+
- [ ] `labelStyles.ts` imported for tick label row
|
|
@@ -73,3 +73,14 @@ onAction({ type: 'CHANGE', payload: { questionId, answerValue: UploadedFileAnswe
|
|
|
73
73
|
- [ ] Final answer shape: `UploadedFileAnswer[]` with `id` + `mediaUrl`
|
|
74
74
|
- [ ] Remove clears answer or passes updated array
|
|
75
75
|
- [ ] Matrix row: [`question-type-sdk-matrix.md#file_upload`](../00-integration/question-type-sdk-matrix.md#file_upload)
|
|
76
|
+
|
|
77
|
+
## Wizard customization (Phase 5 — required)
|
|
78
|
+
|
|
79
|
+
| Control | CSS vars | Apply in |
|
|
80
|
+
|---------|----------|----------|
|
|
81
|
+
| Dropzone border | `--cfm-upload-border-color` | Dashed border on upload area |
|
|
82
|
+
| Focus / drag-over | `--cfm-input-focus-ring` | Active dropzone outline |
|
|
83
|
+
|
|
84
|
+
### Wizard checklist
|
|
85
|
+
|
|
86
|
+
- [ ] Dropzone border uses `var(--cfm-upload-border-color)` not hardcoded hex
|
|
@@ -47,3 +47,7 @@ Container-level media (survey chrome) is separate — see `03-ui-specs/12-survey
|
|
|
47
47
|
|
|
48
48
|
- [ ] No CHANGE action — display-only
|
|
49
49
|
- [ ] Matrix row: [`question-type-sdk-matrix.md#text_and_media`](../00-integration/question-type-sdk-matrix.md#text_and_media)
|
|
50
|
+
|
|
51
|
+
## Wizard customization (Phase 5 — required)
|
|
52
|
+
|
|
53
|
+
Display-only — no selection tokens. Media caption may use `--cfm-question-title-color` for consistency.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# UI Spec: Survey Chrome
|
|
2
2
|
|
|
3
|
-
> **Reference:** `SurveyPage.tsx`, `Header.tsx`, `Footer.tsx`, `ProgressBar.tsx`, `LanguageSelector.tsx`, `IntroPage.tsx`, `EndPage.tsx`, `PausedPage.tsx`
|
|
4
|
-
> **Component blueprints:** `01-components/01-survey-page.md`, `10-header-footer.md`, `11-progress-bar.md`, `12-language-selector.md`, `14-intro-page.md`, `15-end-page.md`, `16-paused-page.md`
|
|
3
|
+
> **Reference:** `SurveyPage.tsx`, `SurveyStickyChrome.tsx`, `Header.tsx`, `Footer.tsx`, `ProgressBar.tsx`, `LanguageSelector.tsx`, `IntroPage.tsx`, `EndPage.tsx`, `PausedPage.tsx`
|
|
4
|
+
> **Component blueprints:** `01-components/01-survey-page.md`, `10-header-footer.md`, `11-progress-bar.md`, `19-survey-sticky-chrome.md`, `12-language-selector.md`, `14-intro-page.md`, `15-end-page.md`, `16-paused-page.md`
|
|
5
5
|
|
|
6
6
|
## SurveyPage — Phase Router
|
|
7
7
|
|
|
@@ -21,9 +21,8 @@
|
|
|
21
21
|
## Active Layout
|
|
22
22
|
|
|
23
23
|
```
|
|
24
|
-
Header
|
|
24
|
+
SurveyStickyChrome (sticky top-0 — Header + ProgressBar)
|
|
25
25
|
main (max-w-4xl)
|
|
26
|
-
ProgressBar(progressPercentage)
|
|
27
26
|
LanguageSelector (hidden if ≤1 language)
|
|
28
27
|
Questions (space-y-12)
|
|
29
28
|
Submit error (if any)
|
|
@@ -31,6 +30,25 @@ main (max-w-4xl)
|
|
|
31
30
|
Footer
|
|
32
31
|
```
|
|
33
32
|
|
|
33
|
+
### Sticky chrome (required on content phase)
|
|
34
|
+
|
|
35
|
+
Long pages push the last question below the fold. Wrap **Header + ProgressBar** in one sticky container so progress stays visible while answering.
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
<div className="sticky top-0 z-30 bg-white shadow-[0_2px_8px_rgba(0,0,0,0.06)]">
|
|
39
|
+
<Header embedded />
|
|
40
|
+
<div className="mx-auto w-full max-w-4xl px-4 pb-5 pt-4 sm:px-6 lg:px-8">
|
|
41
|
+
<ProgressBar progressPercentage={state.progressPercentage} />
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**Spacing:** `pt-4` (16px) between logo block and progress track; `pb-5` (20px) below the track before scrollable content. Do not flush the bar against the logo square.
|
|
47
|
+
|
|
48
|
+
See [`01-components/19-survey-sticky-chrome.md`](../01-components/19-survey-sticky-chrome.md). Copy [`templates/SurveyStickyChrome.tsx`](../templates/SurveyStickyChrome.tsx).
|
|
49
|
+
|
|
50
|
+
Use standalone `Header` (no sticky wrapper) on intro, end, paused, loading, and terminal phases.
|
|
51
|
+
|
|
34
52
|
## Navigation Labels
|
|
35
53
|
|
|
36
54
|
German when `survey.language.startsWith('de')`:
|
|
@@ -51,6 +69,14 @@ German when `survey.language.startsWith('de')`:
|
|
|
51
69
|
|
|
52
70
|
Pink fill bar. Bound to `state.progressPercentage` (path-scoped — see `00-integration/progress.md`).
|
|
53
71
|
|
|
72
|
+
Render inside **`SurveyStickyChrome`** (sticky header + progress) on the content phase — not inside scrollable `<main>`. Clamp width to `0–100`.
|
|
73
|
+
|
|
74
|
+
| Token | Value | Role |
|
|
75
|
+
|-------|-------|------|
|
|
76
|
+
| Gap above track | `pt-4` (16px) | Space between logo block and progress bar |
|
|
77
|
+
| Gap below track | `pb-5` (20px) | Breathing room before question content |
|
|
78
|
+
| Track height | `h-3` (12px) | Full-width rounded pill |
|
|
79
|
+
|
|
54
80
|
## LanguageSelector
|
|
55
81
|
|
|
56
82
|
- Hidden when `languages.length <= 1`
|
|
@@ -97,8 +123,31 @@ Disable primary Next/Submit when `submitSurveyResults.isLoading`; label "Submitt
|
|
|
97
123
|
- [ ] `onAction({ type: 'START' })` on intro
|
|
98
124
|
- [ ] `onAction({ type: 'CHANGE' })` wired per question with `allAnswers` / `allQuestions`
|
|
99
125
|
- [ ] Back uses `state.canGoBack`; primary uses `state.primaryButtonType`
|
|
100
|
-
- [ ] ProgressBar receives `state.progressPercentage`
|
|
126
|
+
- [ ] ProgressBar receives `state.progressPercentage` inside sticky chrome (`SurveyStickyChrome`)
|
|
127
|
+
- [ ] Sticky `top-0 z-30` wrapper keeps progress visible on long pages
|
|
128
|
+
- [ ] `pt-4` / `pb-5` spacing between logo, progress track, and question content
|
|
101
129
|
- [ ] Header/Footer on every state branch
|
|
102
130
|
- [ ] `questionNumber` prefix when present on content questions
|
|
103
131
|
- [ ] Intro / Paused / End / terminal phase branches
|
|
104
132
|
- [ ] Submit button disabled while `submitSurveyResults.isLoading`
|
|
133
|
+
|
|
134
|
+
## Wizard customization (Phase 5 — required)
|
|
135
|
+
|
|
136
|
+
> Full chrome contract: [`wizard-preview-build-guide.md`](../00-integration/wizard-preview-build-guide.md).
|
|
137
|
+
|
|
138
|
+
| Element | `data-cfm-*` / CSS vars |
|
|
139
|
+
|---------|-------------------------|
|
|
140
|
+
| Logo | `data-cfm-logo` or `data-cfm-logo-text` |
|
|
141
|
+
| Company | `data-cfm-company` |
|
|
142
|
+
| Survey title | `data-cfm-survey-title` |
|
|
143
|
+
| Thank you | `data-cfm-thank-you` |
|
|
144
|
+
| Next / Back | `data-cfm-btn-next`, `data-cfm-btn-back` |
|
|
145
|
+
| Footer | `data-cfm-copyright`, `data-cfm-footer-links` |
|
|
146
|
+
| Progress | `--cfm-progress-track`, `--cfm-progress-fill` |
|
|
147
|
+
| Header bg | `--cfm-header-bg`, `--cfm-header-text` |
|
|
148
|
+
|
|
149
|
+
### Wizard checklist
|
|
150
|
+
|
|
151
|
+
- [ ] All editable chrome strings use `data-cfm-*` attributes
|
|
152
|
+
- [ ] Buttons and progress use `var(--cfm-*)` — not hardcoded Telekom hex
|
|
153
|
+
- [ ] Logo: text/CSS **or** local `public/` image — never external URL (see `constraints.md` §4)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# UI Spec: Heatmap (`type: 'HEATMAP'`)
|
|
2
2
|
|
|
3
|
-
> **Implement from this spec
|
|
3
|
+
> **Implement from this spec.** Portable template: `docs/templates/HeatmapScale.tsx`
|
|
4
4
|
> **SDK type:** `HeatmapQuestion` — `fetchSurvey/types/heatmap.ts`
|
|
5
5
|
> **Component blueprint:** `01-components/17-heatmap-scale.md`
|
|
6
6
|
|
|
@@ -78,3 +78,14 @@ Copy coord helpers from [`templates/heatmapCoords.ts`](../templates/heatmapCoord
|
|
|
78
78
|
- [ ] Wait for `onLoad` before accepting clicks
|
|
79
79
|
- [ ] Percentage-positioned spots (survives resize)
|
|
80
80
|
- [ ] Do NOT render region overlays on respondent UI
|
|
81
|
+
|
|
82
|
+
## Wizard customization (Phase 5 — required)
|
|
83
|
+
|
|
84
|
+
| Control | CSS vars | Apply in |
|
|
85
|
+
|---------|----------|----------|
|
|
86
|
+
| Spot color | `--cfm-heatmap-spot-color` | Click markers |
|
|
87
|
+
| Spot border | `--cfm-heatmap-spot-border` | Marker outline |
|
|
88
|
+
|
|
89
|
+
### Wizard checklist
|
|
90
|
+
|
|
91
|
+
- [ ] Spot markers use `--cfm-heatmap-spot-*` vars
|
|
@@ -126,3 +126,14 @@ RANK_ORDER operators (ranked as/above/below) — see [`logic-fields-catalog.md`]
|
|
|
126
126
|
- [ ] `option.imageUrl` before `previewImageUrl`
|
|
127
127
|
- [ ] No client-side re-shuffle when `shuffleOptions` is true
|
|
128
128
|
- [ ] No stub placeholder text
|
|
129
|
+
|
|
130
|
+
## Wizard customization (Phase 5 — required)
|
|
131
|
+
|
|
132
|
+
| Control | CSS vars | Apply in |
|
|
133
|
+
|---------|----------|----------|
|
|
134
|
+
| Rank badge | `--cfm-rank-badge-bg`, `--cfm-rank-badge-color` | Drag handle / rank number |
|
|
135
|
+
| Option border | `--cfm-rank-option-border` | List item cards |
|
|
136
|
+
|
|
137
|
+
### Wizard checklist
|
|
138
|
+
|
|
139
|
+
- [ ] Rank badges and option borders use `--cfm-rank-*` vars
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
# UI Specifications — Reference Implementation Guide
|
|
2
2
|
|
|
3
3
|
> **For npm installs:** implement from these specs + [`templates/Question.tsx`](../templates/Question.tsx).
|
|
4
|
-
> **
|
|
4
|
+
> **Shared lib utilities** (NPS colors, custom fields, heatmap coords) live in [`templates/`](../templates/) — see [`client-lib-folder.md`](../00-integration/client-lib-folder.md), not in this ui-specs folder.
|
|
5
5
|
> Read the spec for **each question type present** in the fetched survey before writing React code.
|
|
6
6
|
|
|
7
|
+
> **Wizard customization:** When the client may use the web wizard, hardcoded hex in § Design Tokens below are **defaults only**. Wire `var(--cfm-*)` per [`wizard-question-type-styling.md`](../00-integration/wizard-question-type-styling.md) — especially `--cfm-matrix-selected` (cell annulus) and `--cfm-input-focus-ring` (outer border + inner dot). Portable scale templates in `docs/templates/` are layout/logic baselines; extend with `selectionStyles.ts` + `labelStyles.ts` for live preview.
|
|
8
|
+
|
|
7
9
|
## How to Read a UI Spec
|
|
8
10
|
|
|
9
11
|
Each file in this folder follows the same structure:
|
|
@@ -75,7 +77,7 @@ Use accent colors from SDK options — never invent colors for NPS:
|
|
|
75
77
|
|
|
76
78
|
## When to Read
|
|
77
79
|
|
|
78
|
-
After Phase 3 in [`index.md`](../index.md), for each question in the fetched survey:
|
|
80
|
+
After Phase 3 in [`index.md`](../index.md) and [`agent-execution-flow.md`](../00-integration/agent-execution-flow.md), for each question in the fetched survey:
|
|
79
81
|
|
|
80
82
|
1. Read [`02-reference/question-types/`](../02-reference/question-types/) for data shape
|
|
81
83
|
2. Read matching spec from this folder (see [`MANIFEST.json`](../MANIFEST.json) `questionTypes.{type}.uiSpec`)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# UI Spec: Matrix Dropdown (shared primitive)
|
|
2
2
|
|
|
3
|
-
> **Implement from this spec
|
|
3
|
+
> **Implement from this spec.** Portable template: `docs/templates/MatrixDropdown.tsx`
|
|
4
4
|
> **Used by:** `LikertMatrixScale`, `CsatMatrixScale` vertical list
|
|
5
5
|
|
|
6
6
|
## Modes
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"docsSchemaVersion": "2.
|
|
2
|
+
"docsSchemaVersion": "2.6.0",
|
|
3
3
|
"sdkTypesVersion": "0.2.1",
|
|
4
4
|
"packageNames": {
|
|
5
5
|
"npm": "@explorer02/cfm-survey-sdk",
|
|
@@ -13,8 +13,28 @@
|
|
|
13
13
|
"clientInputs": [
|
|
14
14
|
"initialPrompt",
|
|
15
15
|
"instanceIdJwt",
|
|
16
|
+
"customizationWizardOptional",
|
|
16
17
|
"deployConfirmation"
|
|
17
18
|
],
|
|
19
|
+
"surveyUiConfig": {
|
|
20
|
+
"artifact": "survey-ui-config.json",
|
|
21
|
+
"schema": "templates/survey-ui-config.schema.json",
|
|
22
|
+
"cliCommand": "npx cfm-sdk customize-ui",
|
|
23
|
+
"cliCommands": {
|
|
24
|
+
"aws": "npx cfm-sdk customize-ui",
|
|
25
|
+
"local": "npx cfm-sdk customize",
|
|
26
|
+
"exportPreviews": "npx cfm-sdk export-previews"
|
|
27
|
+
},
|
|
28
|
+
"wizardApiDoc": "00-integration/wizard-api.md",
|
|
29
|
+
"applyDoc": "00-integration/apply-ui-config.md",
|
|
30
|
+
"wizardDoc": "00-integration/ui-customization-wizard.md",
|
|
31
|
+
"previewBuildDoc": "00-integration/wizard-preview-build-guide.md",
|
|
32
|
+
"questionTypeStylingDoc": "00-integration/wizard-question-type-styling.md",
|
|
33
|
+
"agentExecutionFlowDoc": "00-integration/agent-execution-flow.md",
|
|
34
|
+
"agentOperatingContractDoc": "00-integration/agent-operating-contract.md",
|
|
35
|
+
"wizardConfigHandoffDoc": "00-integration/wizard-config-handoff.md",
|
|
36
|
+
"previewBridgeTemplate": "templates/previewBridge.ts"
|
|
37
|
+
},
|
|
18
38
|
"hookContract": {
|
|
19
39
|
"answersField": "state.answers",
|
|
20
40
|
"customFieldValuesField": "options.customFieldValues",
|
|
@@ -44,6 +64,14 @@
|
|
|
44
64
|
]
|
|
45
65
|
},
|
|
46
66
|
"integrationDocs": [
|
|
67
|
+
{
|
|
68
|
+
"path": "00-integration/agent-operating-contract.md",
|
|
69
|
+
"purpose": "Anti-hallucination rules — read-before-write gates, doc routing, forbidden inventions (read FIRST)"
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"path": "00-integration/agent-execution-flow.md",
|
|
73
|
+
"purpose": "Authoritative agent pipeline — client questions, phase order, wizard-ready build (read with index.md)"
|
|
74
|
+
},
|
|
47
75
|
{
|
|
48
76
|
"path": "00-integration/client-integration-guide.md",
|
|
49
77
|
"purpose": "Master wiring map — start here for full client integration"
|
|
@@ -119,6 +147,38 @@
|
|
|
119
147
|
{
|
|
120
148
|
"path": "00-integration/file-upload-aws.md",
|
|
121
149
|
"purpose": "Presigned S3 upload flow for FILE_UPLOAD submit contract"
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
"path": "00-integration/canonical-survey-fixtures.md",
|
|
153
|
+
"purpose": "Page-by-page UI expectations — matrix labels, slider header, template copy list"
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
"path": "00-integration/client-lib-folder.md",
|
|
157
|
+
"purpose": "src/lib layout — customFieldValues + surveyUi portable templates"
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
"path": "00-integration/wizard-preview-build-guide.md",
|
|
161
|
+
"purpose": "Build client components for wizard live preview — --cfm-* vars and data-cfm-* hooks (Phase 5)"
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
"path": "00-integration/wizard-question-type-styling.md",
|
|
165
|
+
"purpose": "Per-type wizard styling — selection colors, label items, all 11 question types (Phase 5)"
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
"path": "00-integration/wizard-config-handoff.md",
|
|
169
|
+
"purpose": "Wait for client submit, review artifacts (.final.json, .diff.md), confirm-ui-config order (Phase 6b→6c)"
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
"path": "00-integration/ui-customization-wizard.md",
|
|
173
|
+
"purpose": "Optional web wizard flow, CLI commands, wizard steps"
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
"path": "00-integration/apply-ui-config.md",
|
|
177
|
+
"purpose": "Apply survey-ui-config.json tokens after wizard (Phase 6c)"
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
"path": "00-integration/wizard-api.md",
|
|
181
|
+
"purpose": "EC2 /wizard/* API for customize-ui and preview hosting"
|
|
122
182
|
}
|
|
123
183
|
],
|
|
124
184
|
"templateScaleFiles": [
|
|
@@ -126,7 +186,15 @@
|
|
|
126
186
|
"templates/MatrixDropdown.tsx",
|
|
127
187
|
"templates/CustomSliderTrack.tsx",
|
|
128
188
|
"templates/surveyUiIcons.tsx",
|
|
129
|
-
"templates/
|
|
189
|
+
"templates/surveyUiScaleUtils.ts",
|
|
190
|
+
"templates/SliderMatrixScale.tsx",
|
|
191
|
+
"templates/RatingScale.tsx",
|
|
192
|
+
"templates/LikertMatrixScale.tsx",
|
|
193
|
+
"templates/CsatMatrixScale.tsx",
|
|
194
|
+
"templates/HeatmapScale.tsx",
|
|
195
|
+
"templates/FileUploadScale.tsx",
|
|
196
|
+
"templates/heatmapCoords.ts",
|
|
197
|
+
"templates/customFieldValues.ts"
|
|
130
198
|
],
|
|
131
199
|
"deployTargets": {
|
|
132
200
|
"aws": {
|
|
@@ -134,6 +202,8 @@
|
|
|
134
202
|
"script": "templates/deploy-to-aws.sh",
|
|
135
203
|
"apiBaseEnv": "CFM_DEPLOY_API_BASE",
|
|
136
204
|
"apiBaseDefault": "http://43.204.26.213:3000",
|
|
205
|
+
"wizardClientUrlPattern": "{CFM_DEPLOY_API_BASE}/wizard-app/index.html?session={sessionId}&secret={sessionSecret}",
|
|
206
|
+
"wizardClientUrlNote": "Printed by customize-ui after component previews upload to S3 — agent copies link and sends to client",
|
|
137
207
|
"instanceIdEnv": "CFM_INSTANCE_ID",
|
|
138
208
|
"outDirEnv": "OUT_DIR",
|
|
139
209
|
"healthPath": "/health",
|
|
@@ -190,7 +260,10 @@
|
|
|
190
260
|
"name": "orient",
|
|
191
261
|
"read": [
|
|
192
262
|
"index.md",
|
|
193
|
-
"../AGENT.md"
|
|
263
|
+
"../AGENT.md",
|
|
264
|
+
"00-integration/agent-operating-contract.md",
|
|
265
|
+
"00-integration/agent-execution-flow.md",
|
|
266
|
+
"MANIFEST.json"
|
|
194
267
|
],
|
|
195
268
|
"actions": [
|
|
196
269
|
"detectFramework",
|
|
@@ -229,6 +302,7 @@
|
|
|
229
302
|
"00-integration/display-logic-and-navigation.md",
|
|
230
303
|
"00-integration/answer-logic-and-navigation.md",
|
|
231
304
|
"00-integration/custom-field-logic-and-navigation.md",
|
|
305
|
+
"00-integration/client-lib-folder.md",
|
|
232
306
|
"00-integration/question-display-variants.md",
|
|
233
307
|
"00-integration/question-numbering.md",
|
|
234
308
|
"00-integration/placeholders-and-tokens.md",
|
|
@@ -244,7 +318,12 @@
|
|
|
244
318
|
"id": 4,
|
|
245
319
|
"name": "planAndIngest",
|
|
246
320
|
"readAlways": [
|
|
321
|
+
"00-integration/agent-operating-contract.md",
|
|
322
|
+
"00-integration/agent-execution-flow.md",
|
|
247
323
|
"00-integration/component-checklist.md",
|
|
324
|
+
"00-integration/canonical-survey-fixtures.md",
|
|
325
|
+
"00-integration/client-lib-folder.md",
|
|
326
|
+
"00-integration/custom-field-logic-and-navigation.md",
|
|
248
327
|
"00-integration/question-type-sdk-matrix.md",
|
|
249
328
|
"00-integration/logic-fields-catalog.md",
|
|
250
329
|
"03-ui-specs/00-question-shell.md",
|
|
@@ -266,7 +345,12 @@
|
|
|
266
345
|
"id": 5,
|
|
267
346
|
"name": "build",
|
|
268
347
|
"read": [
|
|
348
|
+
"00-integration/agent-operating-contract.md",
|
|
349
|
+
"00-integration/agent-execution-flow.md",
|
|
269
350
|
"00-integration/constraints.md",
|
|
351
|
+
"00-integration/component-checklist.md",
|
|
352
|
+
"00-integration/wizard-preview-build-guide.md",
|
|
353
|
+
"00-integration/wizard-question-type-styling.md",
|
|
270
354
|
"02-reference/routing-table.md"
|
|
271
355
|
],
|
|
272
356
|
"onDemand": "02-reference/question-types"
|
|
@@ -275,7 +359,10 @@
|
|
|
275
359
|
"id": 6,
|
|
276
360
|
"name": "verify",
|
|
277
361
|
"read": [
|
|
278
|
-
"00-integration/
|
|
362
|
+
"00-integration/agent-operating-contract.md",
|
|
363
|
+
"00-integration/agent-execution-flow.md",
|
|
364
|
+
"00-integration/constraints.md",
|
|
365
|
+
"00-integration/component-checklist.md"
|
|
279
366
|
],
|
|
280
367
|
"script": "templates/verify-agent-build.sh",
|
|
281
368
|
"checklist": [
|
|
@@ -295,8 +382,76 @@
|
|
|
295
382
|
"outIndexHtmlExists",
|
|
296
383
|
"outFileCountUnder500",
|
|
297
384
|
"rankOrderScaleTemplateCopied",
|
|
385
|
+
"sliderMatrixScaleTemplateCopied",
|
|
386
|
+
"ratingScaleTemplateCopied",
|
|
387
|
+
"matrixScaleTemplatesCopied",
|
|
388
|
+
"heatmapScaleTemplateCopied",
|
|
298
389
|
"dndKitWhenRankOrder",
|
|
299
|
-
"fileUploadPresignedFlowWhenFileUpload"
|
|
390
|
+
"fileUploadPresignedFlowWhenFileUpload",
|
|
391
|
+
"surveyThemeCssPresent",
|
|
392
|
+
"selectionStylesCopied",
|
|
393
|
+
"labelStylesCopied",
|
|
394
|
+
"chromeDataCfmHooksPresent",
|
|
395
|
+
"draftSurveyUiConfigPresent"
|
|
396
|
+
],
|
|
397
|
+
"postVerify": [
|
|
398
|
+
"startDevServer",
|
|
399
|
+
"askCustomizationWizard"
|
|
400
|
+
]
|
|
401
|
+
},
|
|
402
|
+
{
|
|
403
|
+
"id": "6b",
|
|
404
|
+
"name": "optionalUiCustomization",
|
|
405
|
+
"optional": true,
|
|
406
|
+
"requiresClientConfirmation": true,
|
|
407
|
+
"read": [
|
|
408
|
+
"00-integration/wizard-config-handoff.md",
|
|
409
|
+
"00-integration/ui-customization-wizard.md",
|
|
410
|
+
"00-integration/wizard-preview-build-guide.md",
|
|
411
|
+
"00-integration/wizard-question-type-styling.md",
|
|
412
|
+
"00-integration/wizard-api.md"
|
|
413
|
+
],
|
|
414
|
+
"cliCommand": "npx cfm-sdk customize-ui",
|
|
415
|
+
"cliCommandLocal": "npx cfm-sdk customize",
|
|
416
|
+
"cliConfirmCommand": "npx cfm-sdk confirm-ui-config",
|
|
417
|
+
"output": "survey-ui-config.final.json",
|
|
418
|
+
"outputArtifacts": [
|
|
419
|
+
"survey-ui-config.seed.json",
|
|
420
|
+
"survey-ui-config.final.json",
|
|
421
|
+
"survey-ui-config.diff.json",
|
|
422
|
+
"survey-ui-config.diff.md"
|
|
423
|
+
],
|
|
424
|
+
"agentMustWait": true,
|
|
425
|
+
"waitUntil": "cliExit0ConfigurationReady",
|
|
426
|
+
"clientHandoff": "shareDeployedWizardUrlAfterS3Upload",
|
|
427
|
+
"prerequisites": [
|
|
428
|
+
"phase6VerifyPassed",
|
|
429
|
+
"devServerRunning"
|
|
430
|
+
]
|
|
431
|
+
},
|
|
432
|
+
{
|
|
433
|
+
"id": "6c",
|
|
434
|
+
"name": "applyUiConfig",
|
|
435
|
+
"optional": true,
|
|
436
|
+
"when": "wizardUsedOrSurveyUiConfigExists",
|
|
437
|
+
"read": [
|
|
438
|
+
"00-integration/wizard-config-handoff.md",
|
|
439
|
+
"00-integration/apply-ui-config.md",
|
|
440
|
+
"00-integration/wizard-preview-build-guide.md",
|
|
441
|
+
"00-integration/wizard-question-type-styling.md"
|
|
442
|
+
],
|
|
443
|
+
"inputFile": "survey-ui-config.final.json",
|
|
444
|
+
"inputFileLocal": "survey-ui-config.json",
|
|
445
|
+
"actions": [
|
|
446
|
+
"readDiffMdCompletely",
|
|
447
|
+
"validateAgainstSchema",
|
|
448
|
+
"regenerateSurveyThemeCssFromFinal",
|
|
449
|
+
"applyDataCfmContentHooks",
|
|
450
|
+
"applyLayoutToggles",
|
|
451
|
+
"applyQuestionTypesTokens",
|
|
452
|
+
"runConfirmUiConfigAws",
|
|
453
|
+
"crossCheckEveryDiffPath",
|
|
454
|
+
"reRunVerify"
|
|
300
455
|
]
|
|
301
456
|
},
|
|
302
457
|
{
|
|
@@ -305,7 +460,8 @@
|
|
|
305
460
|
"requiresClientConfirmation": true,
|
|
306
461
|
"selectTargetFromPrompt": {
|
|
307
462
|
"awsKeywords": ["aws", "cloudfront", "s3", "ec2", "sprinklr"],
|
|
308
|
-
"default": "vercel"
|
|
463
|
+
"default": "vercel",
|
|
464
|
+
"fallbackFromConfig": "survey-ui-config.json deploy.target"
|
|
309
465
|
},
|
|
310
466
|
"targets": {
|
|
311
467
|
"aws": {
|