@explorer02/cfm-survey-sdk 0.0.4 → 0.0.7
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 +0 -32
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/init.d.ts +51 -0
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +152 -43
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/questionnaire/questions.d.ts.map +1 -1
- package/dist/cli/questionnaire/questions.js +10 -0
- package/dist/cli/questionnaire/questions.js.map +1 -1
- package/dist/cli/questionnaire/runner.d.ts.map +1 -1
- package/dist/cli/questionnaire/runner.js +123 -64
- package/dist/cli/questionnaire/runner.js.map +1 -1
- package/dist/cli/questionnaire/server.d.ts +11 -0
- package/dist/cli/questionnaire/server.d.ts.map +1 -0
- package/dist/cli/questionnaire/server.js +80 -0
- package/dist/cli/questionnaire/server.js.map +1 -0
- package/dist/cli/questionnaire/types.d.ts +1 -0
- package/dist/cli/questionnaire/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/postinstall.js +8 -15
- package/templates/AGENT.md +27 -28
- package/templates/wizard.html +1139 -0
|
@@ -22,81 +22,140 @@ exports.runQuestionnaire = runQuestionnaire;
|
|
|
22
22
|
const child_process_1 = require("child_process");
|
|
23
23
|
const path_1 = __importDefault(require("path"));
|
|
24
24
|
const const_1 = require("../const");
|
|
25
|
+
const server_1 = require("./server");
|
|
25
26
|
const c = const_1.colors;
|
|
26
27
|
const TIMEOUT_MS = 15 * 60 * 1000; // 15-minute timeout
|
|
27
|
-
function runQuestionnaire() {
|
|
28
|
-
// Fork the compiled CLI entry point (dist/cli/index.js) with the
|
|
29
|
-
// 'questionnaire-run' command. The child inherits stdin/stdout/stderr so
|
|
30
|
-
// questions appear in the same visible terminal the agent opened, while
|
|
31
|
-
// structured answers flow back through the built-in IPC channel.
|
|
28
|
+
async function runQuestionnaire() {
|
|
32
29
|
const cliEntry = path_1.default.join(__dirname, '..', 'index.js');
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
30
|
+
const isInteractive = !!process.stdin.isTTY;
|
|
31
|
+
if (isInteractive) {
|
|
32
|
+
// Standard inline TTY execution
|
|
33
|
+
return new Promise((resolve, reject) => {
|
|
34
|
+
let child;
|
|
35
|
+
try {
|
|
36
|
+
child = (0, child_process_1.fork)(cliEntry, ['questionnaire-run'], {
|
|
37
|
+
stdio: [0, 1, 2, 'ipc'],
|
|
38
|
+
env: { ...process.env },
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
43
|
+
return reject(new Error(`Failed to start questionnaire process: ${msg}`));
|
|
44
|
+
}
|
|
45
|
+
let settled = false;
|
|
46
|
+
function settle(fn) {
|
|
47
|
+
if (!settled) {
|
|
48
|
+
settled = true;
|
|
49
|
+
clearTimeout(timer);
|
|
50
|
+
fn();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
child.on('message', (raw) => {
|
|
54
|
+
const msg = raw;
|
|
55
|
+
switch (msg.type) {
|
|
56
|
+
case 'questionnaireComplete':
|
|
57
|
+
settle(() => resolve(msg.payload));
|
|
58
|
+
break;
|
|
59
|
+
case 'questionnaireCancelled':
|
|
60
|
+
settle(() => resolve({}));
|
|
61
|
+
break;
|
|
62
|
+
case 'questionnaireError':
|
|
63
|
+
settle(() => reject(new Error(msg.payload.message)));
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
41
66
|
});
|
|
67
|
+
child.on('exit', (code) => {
|
|
68
|
+
settle(() => {
|
|
69
|
+
if (code !== 0) {
|
|
70
|
+
reject(new Error(`Questionnaire process terminated before completion (exit code ${code})`));
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
resolve({});
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
child.on('error', (err) => {
|
|
78
|
+
settle(() => reject(new Error(`Questionnaire process error: ${err.message}`)));
|
|
79
|
+
});
|
|
80
|
+
const timer = setTimeout(() => {
|
|
81
|
+
settle(() => {
|
|
82
|
+
console.error(`\n${c.red}⏱ Questionnaire timed out after 15 minutes — using default values.${c.reset}\n`);
|
|
83
|
+
try {
|
|
84
|
+
child.kill();
|
|
85
|
+
}
|
|
86
|
+
catch { /* ignore */ }
|
|
87
|
+
resolve({});
|
|
88
|
+
});
|
|
89
|
+
}, TIMEOUT_MS);
|
|
90
|
+
if (timer.unref)
|
|
91
|
+
timer.unref();
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
// Non-interactive execution (e.g. executed inside Cursor/VS Code agent chat)
|
|
96
|
+
console.log(`\n${c.yellow}⚠️ Non-interactive terminal detected. Opening a new interactive terminal window to run the questionnaire...${c.reset}\n`);
|
|
97
|
+
let serverHandle;
|
|
98
|
+
try {
|
|
99
|
+
serverHandle = await (0, server_1.createIPCServer)();
|
|
42
100
|
}
|
|
43
101
|
catch (err) {
|
|
44
|
-
|
|
45
|
-
return
|
|
102
|
+
console.error(`\n${c.red}❌ Failed to start IPC server: ${err.message || err}${c.reset}`);
|
|
103
|
+
return {};
|
|
46
104
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
105
|
+
const port = serverHandle.port;
|
|
106
|
+
const cwd = process.cwd();
|
|
107
|
+
const runCmd = `node "${cliEntry}" questionnaire-run --port ${port}`;
|
|
108
|
+
let launchCmd = '';
|
|
109
|
+
if (process.platform === 'darwin') {
|
|
110
|
+
const escCwd = cwd.replace(/"/g, '\\"');
|
|
111
|
+
const escRunCmd = runCmd.replace(/"/g, '\\"');
|
|
112
|
+
const appleScript = `tell application "Terminal"
|
|
113
|
+
activate
|
|
114
|
+
do script "cd \\"${escCwd}\\" && ${escRunCmd}"
|
|
115
|
+
end tell`;
|
|
116
|
+
launchCmd = `osascript -e '${appleScript.replace(/'/g, "'\\''")}'`;
|
|
54
117
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
});
|
|
70
|
-
// ── Child process exits ──────────────────────────────────────────────────
|
|
71
|
-
child.on('exit', (code) => {
|
|
72
|
-
settle(() => {
|
|
73
|
-
if (code !== 0) {
|
|
74
|
-
reject(new Error(`Questionnaire process terminated before completion (exit code ${code})`));
|
|
118
|
+
else if (process.platform === 'win32') {
|
|
119
|
+
launchCmd = `start "CFM Survey SDK Setup" cmd.exe /k "cd /d \\"${cwd}\\" && ${runCmd}"`;
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
launchCmd = `xterm -title "CFM Survey SDK Setup" -e "cd \\"${cwd}\\" && ${runCmd}"`;
|
|
123
|
+
}
|
|
124
|
+
return new Promise((resolve, reject) => {
|
|
125
|
+
let settled = false;
|
|
126
|
+
function settle(fn) {
|
|
127
|
+
if (!settled) {
|
|
128
|
+
settled = true;
|
|
129
|
+
clearTimeout(timer);
|
|
130
|
+
serverHandle.close();
|
|
131
|
+
fn();
|
|
75
132
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
133
|
+
}
|
|
134
|
+
// Launch the terminal window asynchronously
|
|
135
|
+
(0, child_process_1.exec)(launchCmd, (err) => {
|
|
136
|
+
if (err) {
|
|
137
|
+
console.error(`\n${c.red}❌ Failed to automatically launch a new terminal window: ${err.message}${c.reset}`);
|
|
138
|
+
console.log(`${c.yellow}👉 Please open a new terminal window manually and run:${c.reset}`);
|
|
139
|
+
console.log(` ${c.bold}cd "${cwd}" && ${runCmd}${c.reset}\n`);
|
|
79
140
|
}
|
|
80
141
|
});
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
settle(() => {
|
|
89
|
-
console.error(`\n${c.red}⏱ Questionnaire timed out after 15 minutes — using default values.${c.reset}\n`);
|
|
90
|
-
try {
|
|
91
|
-
child.kill();
|
|
92
|
-
}
|
|
93
|
-
catch { /* ignore */ }
|
|
94
|
-
resolve({}); // fall back to all defaults
|
|
142
|
+
// Await answers or error via TCP server
|
|
143
|
+
serverHandle.waitForAnswers()
|
|
144
|
+
.then((answers) => {
|
|
145
|
+
settle(() => resolve(answers));
|
|
146
|
+
})
|
|
147
|
+
.catch((err) => {
|
|
148
|
+
settle(() => reject(err));
|
|
95
149
|
});
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
150
|
+
const timer = setTimeout(() => {
|
|
151
|
+
settle(() => {
|
|
152
|
+
console.error(`\n${c.red}⏱ Questionnaire timed out after 15 minutes — using default values.${c.reset}\n`);
|
|
153
|
+
resolve({});
|
|
154
|
+
});
|
|
155
|
+
}, TIMEOUT_MS);
|
|
156
|
+
if (timer.unref)
|
|
157
|
+
timer.unref();
|
|
158
|
+
});
|
|
159
|
+
}
|
|
101
160
|
}
|
|
102
161
|
//# sourceMappingURL=runner.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../../src/cli/questionnaire/runner.ts"],"names":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../../src/cli/questionnaire/runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Answers } from './types';
|
|
2
|
+
export interface IPCServerHandle {
|
|
3
|
+
/** The port the server is listening on */
|
|
4
|
+
port: number;
|
|
5
|
+
/** Resolves when the client sends answers; rejects on error/disconnect */
|
|
6
|
+
waitForAnswers(): Promise<Answers>;
|
|
7
|
+
/** Shut down the server early */
|
|
8
|
+
close(): void;
|
|
9
|
+
}
|
|
10
|
+
export declare function createIPCServer(): Promise<IPCServerHandle>;
|
|
11
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/cli/questionnaire/server.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,MAAM,WAAW,eAAe;IAC9B,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACnC,iCAAiC;IACjC,KAAK,IAAI,IAAI,CAAC;CACf;AAED,wBAAgB,eAAe,IAAI,OAAO,CAAC,eAAe,CAAC,CA8E1D"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createIPCServer = createIPCServer;
|
|
7
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
8
|
+
// TCP IPC Server
|
|
9
|
+
// Lightweight newline-delimited JSON server using Node's built-in `net` module.
|
|
10
|
+
// No external dependencies. Receives questionnaire answers from the client
|
|
11
|
+
// process running in the new interactive terminal.
|
|
12
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
13
|
+
const net_1 = __importDefault(require("net"));
|
|
14
|
+
function createIPCServer() {
|
|
15
|
+
return new Promise((resolve, reject) => {
|
|
16
|
+
const server = net_1.default.createServer();
|
|
17
|
+
server.once('error', reject);
|
|
18
|
+
server.listen(0, '127.0.0.1', () => {
|
|
19
|
+
const { port } = server.address();
|
|
20
|
+
let resolveAnswers;
|
|
21
|
+
let rejectAnswers;
|
|
22
|
+
let settled = false;
|
|
23
|
+
const answersPromise = new Promise((res, rej) => {
|
|
24
|
+
resolveAnswers = res;
|
|
25
|
+
rejectAnswers = rej;
|
|
26
|
+
});
|
|
27
|
+
function settle(fn) {
|
|
28
|
+
if (!settled) {
|
|
29
|
+
settled = true;
|
|
30
|
+
fn();
|
|
31
|
+
server.close();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
server.on('connection', (socket) => {
|
|
35
|
+
let buf = '';
|
|
36
|
+
socket.on('data', (chunk) => {
|
|
37
|
+
buf += chunk.toString();
|
|
38
|
+
const lines = buf.split('\n');
|
|
39
|
+
buf = lines.pop() ?? '';
|
|
40
|
+
for (const line of lines) {
|
|
41
|
+
const trimmed = line.trim();
|
|
42
|
+
if (!trimmed)
|
|
43
|
+
continue;
|
|
44
|
+
try {
|
|
45
|
+
const msg = JSON.parse(trimmed);
|
|
46
|
+
if (msg.type === 'complete') {
|
|
47
|
+
settle(() => resolveAnswers(msg.answers ?? {}));
|
|
48
|
+
}
|
|
49
|
+
else if (msg.type === 'cancelled') {
|
|
50
|
+
settle(() => resolveAnswers({}));
|
|
51
|
+
}
|
|
52
|
+
else if (msg.type === 'error') {
|
|
53
|
+
settle(() => rejectAnswers(new Error(msg.message ?? 'Unknown error')));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
catch { /* ignore malformed JSON */ }
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
socket.on('close', () => {
|
|
60
|
+
// Connection closed without a result → treat as unexpected termination
|
|
61
|
+
settle(() => rejectAnswers(new Error('Questionnaire terminal was closed before answers were submitted')));
|
|
62
|
+
});
|
|
63
|
+
socket.on('error', (err) => {
|
|
64
|
+
settle(() => rejectAnswers(err));
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
resolve({
|
|
68
|
+
port,
|
|
69
|
+
waitForAnswers: () => answersPromise,
|
|
70
|
+
close: () => {
|
|
71
|
+
if (!settled) {
|
|
72
|
+
settled = true;
|
|
73
|
+
server.close();
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/cli/questionnaire/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -67,6 +67,7 @@ export interface SurveyConfig {
|
|
|
67
67
|
showFooter: boolean;
|
|
68
68
|
showProgressBar: boolean;
|
|
69
69
|
showLanguageSwitcher: boolean;
|
|
70
|
+
showNextButton: boolean;
|
|
70
71
|
showBackButton: boolean;
|
|
71
72
|
width: 'narrow' | 'standard' | 'wide';
|
|
72
73
|
borderStyle: 'sharp' | 'rounded' | 'pill';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/cli/questionnaire/types.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/cli/questionnaire/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/postinstall.js
CHANGED
|
@@ -29,23 +29,16 @@ You are STRICTLY PROHIBITED from scanning, reading, or referencing any existing
|
|
|
29
29
|
in this project (components, configs, styles, or any code) to derive decisions.
|
|
30
30
|
Your ONLY references are: ./AGENT.md and ./survey-config.json (after init runs).
|
|
31
31
|
|
|
32
|
-
RULE 1 —
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
RULE 1 — RUN THE LOCAL SETUP WIZARD FIRST:
|
|
33
|
+
You must run "npx cfm-sdk init" in a terminal panel. Tell the client:
|
|
34
|
+
"I am launching a premium interactive setup page in your browser. Please customize your survey preferences and logo there, then click Complete Setup."
|
|
35
|
+
Wait silently. Do NOT ask the client questions in chat or write survey-config.json manually.
|
|
35
36
|
|
|
36
|
-
RULE 2 —
|
|
37
|
-
|
|
38
|
-
(Ctrl+\` or click the + icon in the Terminal panel).
|
|
39
|
-
Step B: In that new terminal, run:
|
|
40
|
-
npx cfm-sdk init
|
|
41
|
-
Step C: The wizard will prompt the client with questions directly in that terminal.
|
|
42
|
-
Wait silently. Do NOT type anything in the chat while the wizard runs.
|
|
43
|
-
Step D: When npx cfm-sdk init exits and the terminal shows a prompt again,
|
|
44
|
-
read ./survey-config.json immediately and continue to RULE 3.
|
|
37
|
+
RULE 2 — WAIT AND READ CONFIG FILE:
|
|
38
|
+
Wait for "npx cfm-sdk init" to finish execution (it will exit cleanly once the client clicks Complete Setup). Once it exits, immediately read the generated "./survey-config.json" from the root directory.
|
|
45
39
|
|
|
46
|
-
RULE 3 — CONTINUE AUTOMATICALLY
|
|
47
|
-
|
|
48
|
-
Continue automatically: read ./survey-config.json → read ./AGENT.md Phase 3 → build survey.
|
|
40
|
+
RULE 3 — CONTINUE AUTOMATICALLY:
|
|
41
|
+
As soon as the setup wizard exits and you read "./survey-config.json", proceed immediately to Phase 3 in ./AGENT.md to scaffold the Next.js app and build the survey. Do NOT stop, wait, or ask the client to re-invoke you.
|
|
49
42
|
|
|
50
43
|
RULE 4 — FOLLOW AGENT.MD STRICTLY:
|
|
51
44
|
Open ./AGENT.md and follow every phase in order. Do not skip, reorder, or improvise.
|
package/templates/AGENT.md
CHANGED
|
@@ -62,7 +62,7 @@ npx -y create-next-app@latest ./ --ts --tailwind --eslint --app --src-dir --impo
|
|
|
62
62
|
npm install @explorer02/cfm-survey-sdk @tanstack/react-query
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
-
### Phase 2: Configuration Handshake — Run the
|
|
65
|
+
### Phase 2: Configuration Handshake — Run the Local Setup Wizard
|
|
66
66
|
|
|
67
67
|
> 🚨 **CRITICAL — READ CAREFULLY:**
|
|
68
68
|
> 1. Open a **new terminal panel** in the IDE (Ctrl+` or click the + icon in the Terminal panel).
|
|
@@ -70,15 +70,11 @@ npm install @explorer02/cfm-survey-sdk @tanstack/react-query
|
|
|
70
70
|
> ```bash
|
|
71
71
|
> npx cfm-sdk init
|
|
72
72
|
> ```
|
|
73
|
-
> 3.
|
|
74
|
-
> 4.
|
|
75
|
-
> 5.
|
|
73
|
+
> 3. Tell the client in chat: *"I am launching a premium interactive setup page in your browser. Please customize your survey preferences and logo there, then click Complete Setup."*
|
|
74
|
+
> 4. The wizard will open in the browser. The client will answer the questions and upload their logo there. **You do not need to do anything while the wizard is running — just wait.**
|
|
75
|
+
> 5. When `npx cfm-sdk init` exits (the terminal returns to a prompt), **immediately** read `./survey-config.json` and proceed to Phase 3.
|
|
76
|
+
> 6. **Do NOT ask the client to invoke you again.** Continue automatically.
|
|
76
77
|
|
|
77
|
-
The wizard asks about:
|
|
78
|
-
- UI mockup availability, survey title, company name, browser tab title, thank-you message
|
|
79
|
-
- Logo file, layout options, button labels (conditional: back label only asked if back button is enabled)
|
|
80
|
-
- Color theme (mockup extraction / logo derivation / custom hex / automatic)
|
|
81
|
-
- Placeholder values for personalised questions, debug mode, Vercel deployment preference
|
|
82
78
|
|
|
83
79
|
### Phase 3: Configuration Setup
|
|
84
80
|
|
|
@@ -101,6 +97,7 @@ Immediately open and read `./survey-config.json`. This is the single source of t
|
|
|
101
97
|
| `layout.showFooter` | boolean | Build a `<Footer>` component if `true`, omit entirely if `false`. |
|
|
102
98
|
| `layout.showProgressBar` | boolean | Render `<ProgressBar>` if `true`. |
|
|
103
99
|
| `layout.showLanguageSwitcher` | boolean | Render `<LanguageSelector>` if `true`. |
|
|
100
|
+
| `layout.showNextButton` | boolean | Show a Next button navigating to the next page if `true`. |
|
|
104
101
|
| `layout.showBackButton` | boolean | Show a Back button navigating to the previous page if `true`. |
|
|
105
102
|
| `layout.width` | `narrow`/`standard`/`wide` | Map to Tailwind: `max-w-xl` / `max-w-3xl` / `max-w-5xl` on the survey container. |
|
|
106
103
|
| `layout.borderStyle` | `sharp`/`rounded`/`pill` | Map to Tailwind: `rounded-none` / `rounded-lg` / `rounded-full` on cards and inputs. |
|
|
@@ -546,8 +543,8 @@ export default function SurveyPage() {
|
|
|
546
543
|
|
|
547
544
|
{/* Navigation Buttons */}
|
|
548
545
|
<nav>
|
|
549
|
-
{/* Back Button — only show if not on the first page */}
|
|
550
|
-
{state.currentPageIndex > 0 && (
|
|
546
|
+
{/* Back Button — only show if enabled and not on the first page */}
|
|
547
|
+
{state.currentPageIndex > 0 && surveyConfig.layout.showBackButton && (
|
|
551
548
|
<button
|
|
552
549
|
type="button"
|
|
553
550
|
onClick={() => onAction({ type: 'PREVIOUS' })}
|
|
@@ -559,19 +556,21 @@ export default function SurveyPage() {
|
|
|
559
556
|
)}
|
|
560
557
|
|
|
561
558
|
{/* Next / Submit Button */}
|
|
562
|
-
<
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
559
|
+
{(state.currentPageIndex < survey.pages.length - 1 ? surveyConfig.layout.showNextButton : true) && (
|
|
560
|
+
<button
|
|
561
|
+
type="button"
|
|
562
|
+
onClick={() => onAction({ type: 'NEXT' })}
|
|
563
|
+
disabled={submitSurveyResults.isLoading}
|
|
564
|
+
/* STYLE: Design a primary action button matching the mockup.
|
|
565
|
+
Must have disabled state styling for when submission is in progress. */
|
|
566
|
+
>
|
|
567
|
+
{submitSurveyResults.isLoading
|
|
568
|
+
? 'Submitting...'
|
|
569
|
+
: state.currentPageIndex < survey.pages.length - 1
|
|
570
|
+
? 'Next'
|
|
571
|
+
: 'Submit'}
|
|
572
|
+
</button>
|
|
573
|
+
)}
|
|
575
574
|
</nav>
|
|
576
575
|
|
|
577
576
|
{/* Footer — pass links/data as needed */}
|
|
@@ -1034,10 +1033,10 @@ This creates a neutral, professional design that works for any brand. The agent
|
|
|
1034
1033
|
|
|
1035
1034
|
### 6e. Logo Handling
|
|
1036
1035
|
|
|
1037
|
-
|
|
1038
|
-
1.
|
|
1039
|
-
2.
|
|
1040
|
-
3.
|
|
1036
|
+
When a logo is provided (either `logo.fileName` or `logo.defaultUrl`):
|
|
1037
|
+
1. Render it in the header as an industry-standard practice.
|
|
1038
|
+
2. Apply styling to ensure it is displayed in a standard size. Regardless of its original pixel size or resolution, it MUST NOT exceed standard dimensions. Specifically, set its maximum height to 40px, preserve aspect ratio, and handle overflow. Do NOT hardcode large width/height dimensions that might break the layout. For example, use `style={{ maxHeight: '40px', width: 'auto', objectFit: 'contain', display: 'block' }}` or equivalent Tailwind classes.
|
|
1039
|
+
3. If using Next.js `<Image>`, do NOT let the width/height attributes override standard constraints. Always constrain the containing element or the image itself to `max-height: 40px` and `width: auto`.
|
|
1041
1040
|
|
|
1042
1041
|
---
|
|
1043
1042
|
|