lite-questionnaire 1.0.3 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -0
- package/input.ts +33 -4
- package/modules/confirm.ts +16 -7
- package/modules/select.ts +4 -9
- package/package.json +7 -3
- package/render.ts +4 -1
package/README.md
CHANGED
|
@@ -376,5 +376,12 @@ lite-questionnaire/
|
|
|
376
376
|
│ └── rating.ts # 评分滑块 + 表情渲染
|
|
377
377
|
├── design/
|
|
378
378
|
│ └── questionnaire-openapi.yaml
|
|
379
|
+
├── image/
|
|
380
|
+
├── skills/
|
|
381
|
+
│ └── lite-questionnaire/
|
|
382
|
+
│ └── SKILL.md
|
|
383
|
+
├── .gitignore
|
|
384
|
+
├── LICENSE
|
|
385
|
+
├── package.json
|
|
379
386
|
└── README.md
|
|
380
387
|
```
|
package/input.ts
CHANGED
|
@@ -256,20 +256,33 @@ export function createInputHandler(
|
|
|
256
256
|
if (q.type === "confirm") {
|
|
257
257
|
if (matchesKey(data, Key.left)) {
|
|
258
258
|
const state = core.getUIState();
|
|
259
|
-
state.
|
|
259
|
+
state.optionIndex = 0; // 光标移到「是」
|
|
260
260
|
core.saveUIState(state);
|
|
261
261
|
onUpdate();
|
|
262
262
|
return;
|
|
263
263
|
}
|
|
264
264
|
if (matchesKey(data, Key.right)) {
|
|
265
265
|
const state = core.getUIState();
|
|
266
|
-
state.
|
|
266
|
+
state.optionIndex = 1; // 光标移到「否」
|
|
267
|
+
core.saveUIState(state);
|
|
268
|
+
onUpdate();
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
if (matchesKey(data, Key.space)) {
|
|
272
|
+
const state = core.getUIState();
|
|
273
|
+
state.confirmValue = state.optionIndex === 0; // ● 移到光标位置
|
|
267
274
|
core.saveUIState(state);
|
|
268
275
|
onUpdate();
|
|
269
276
|
return;
|
|
270
277
|
}
|
|
271
278
|
if (matchesKey(data, Key.enter)) {
|
|
272
|
-
|
|
279
|
+
const state = core.getUIState();
|
|
280
|
+
state.confirmValue = state.optionIndex === 0; // 确认选中
|
|
281
|
+
core.saveUIState(state);
|
|
282
|
+
core.inputMode = false;
|
|
283
|
+
core.inputQuestionId = null;
|
|
284
|
+
saveFn();
|
|
285
|
+
onUpdate();
|
|
273
286
|
return;
|
|
274
287
|
}
|
|
275
288
|
return;
|
|
@@ -492,7 +505,23 @@ export function createInputHandler(
|
|
|
492
505
|
return;
|
|
493
506
|
}
|
|
494
507
|
|
|
495
|
-
case "confirm":
|
|
508
|
+
case "confirm": {
|
|
509
|
+
if (matchesKey(data, Key.tab)) {
|
|
510
|
+
core.inputMode = true;
|
|
511
|
+
core.inputQuestionId = q.id;
|
|
512
|
+
// 进入选择态时,光标初始位置与当前 ● 一致
|
|
513
|
+
const state = core.getUIState();
|
|
514
|
+
state.optionIndex = state.confirmValue ? 0 : 1;
|
|
515
|
+
core.saveUIState(state);
|
|
516
|
+
onUpdate();
|
|
517
|
+
return;
|
|
518
|
+
}
|
|
519
|
+
if (matchesKey(data, Key.enter)) {
|
|
520
|
+
advance();
|
|
521
|
+
return;
|
|
522
|
+
}
|
|
523
|
+
break;
|
|
524
|
+
}
|
|
496
525
|
case "rating": {
|
|
497
526
|
if (matchesKey(data, Key.tab)) {
|
|
498
527
|
core.inputMode = true;
|
package/modules/confirm.ts
CHANGED
|
@@ -25,18 +25,27 @@ export function renderConfirmQuestion(
|
|
|
25
25
|
const noLabel = q.noLabel || "否";
|
|
26
26
|
const selectedYes = state.confirmValue === true;
|
|
27
27
|
|
|
28
|
-
//
|
|
29
|
-
const
|
|
28
|
+
// 是否处于选择态(Tab 进入的编辑模式)
|
|
29
|
+
const isEditing = core.inputMode && core.inputQuestionId === q.id;
|
|
30
|
+
// 选择态下光标位置:optionIndex=0 表示在「是」,1 表示在「否」
|
|
31
|
+
const cursorOnYes = isEditing && state.optionIndex === 0;
|
|
32
|
+
const cursorOnNo = isEditing && state.optionIndex === 1;
|
|
33
|
+
|
|
34
|
+
// 渲染两个按钮:● 表示已选中(基于 confirmValue),背景高亮表示光标(仅选择态可见)
|
|
35
|
+
const dot = theme.fg("success", "●");
|
|
36
|
+
const blank = " ";
|
|
37
|
+
|
|
38
|
+
const yesBtn = cursorOnYes
|
|
30
39
|
? theme.bg("selectedBg", theme.fg("text", ` [${yesLabel}] `))
|
|
31
40
|
: ` [${yesLabel}] `;
|
|
32
|
-
const noBtn =
|
|
41
|
+
const noBtn = cursorOnNo
|
|
33
42
|
? theme.bg("selectedBg", theme.fg("text", ` [${noLabel}] `))
|
|
34
43
|
: ` [${noLabel}] `;
|
|
35
44
|
|
|
36
|
-
const
|
|
37
|
-
?
|
|
38
|
-
: "
|
|
45
|
+
const row = selectedYes
|
|
46
|
+
? dot + " " + yesBtn + " " + blank + " " + noBtn
|
|
47
|
+
: blank + " " + yesBtn + " " + dot + " " + noBtn;
|
|
39
48
|
|
|
40
|
-
lines.push(truncateToWidth(" " +
|
|
49
|
+
lines.push(truncateToWidth(" " + row, width));
|
|
41
50
|
return lines;
|
|
42
51
|
}
|
package/modules/select.ts
CHANGED
|
@@ -33,15 +33,10 @@ export function renderSelectOptions(
|
|
|
33
33
|
const hasCustomText = opt.isCustom && state.customText !== null;
|
|
34
34
|
const isSelected = state.selectedIndices.includes(i);
|
|
35
35
|
|
|
36
|
-
//
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
} else if (isSelected) {
|
|
41
|
-
prefix = theme.fg("success", "• ");
|
|
42
|
-
} else {
|
|
43
|
-
prefix = " ";
|
|
44
|
-
}
|
|
36
|
+
// 前缀:两列独立 — 列0: >, 列1: ●
|
|
37
|
+
const col0 = isCursor ? theme.fg("accent", ">") : " ";
|
|
38
|
+
const col1 = isSelected ? theme.fg("success", "●") : " ";
|
|
39
|
+
const prefix = col0 + col1 + " ";
|
|
45
40
|
|
|
46
41
|
// 颜色
|
|
47
42
|
const color = isCursor ? "accent" : isSelected ? "success" : "text";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lite-questionnaire",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"description": "轻量级交互式问卷工具 — 单选、多选、文本、确认、评分,带条件子问题和声明式校验",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|
|
@@ -17,8 +17,12 @@
|
|
|
17
17
|
"url": "git+https://github.com/yunwuhai/lite-questionnaire.git"
|
|
18
18
|
},
|
|
19
19
|
"pi": {
|
|
20
|
-
"extensions": [
|
|
21
|
-
|
|
20
|
+
"extensions": [
|
|
21
|
+
"./index.ts"
|
|
22
|
+
],
|
|
23
|
+
"skills": [
|
|
24
|
+
"./skills"
|
|
25
|
+
],
|
|
22
26
|
"image": "https://raw.githubusercontent.com/yunwuhai/lite-questionnaire/main/image/logo.png"
|
|
23
27
|
},
|
|
24
28
|
"peerDependencies": {
|
package/render.ts
CHANGED
|
@@ -143,6 +143,9 @@ export function renderHelpBar(
|
|
|
143
143
|
theme: { fg: (c: string, t: string) => string },
|
|
144
144
|
): string {
|
|
145
145
|
if (inputMode) {
|
|
146
|
+
if (q?.type === "confirm") {
|
|
147
|
+
return theme.fg("dim", " ← → 切换 · Space 选中 · Enter 确认 · Esc 退出");
|
|
148
|
+
}
|
|
146
149
|
return theme.fg("dim", " ← → 调整/移动 · Enter 保存 · Esc 退出编辑");
|
|
147
150
|
}
|
|
148
151
|
|
|
@@ -162,7 +165,7 @@ export function renderHelpBar(
|
|
|
162
165
|
case "text":
|
|
163
166
|
return theme.fg("dim", " Tab 编辑 · Enter 提交 · Esc 取消" + (isMultiQuestion ? " · ← → 切换问题" : ""));
|
|
164
167
|
case "confirm":
|
|
165
|
-
return theme.fg("dim", " Tab
|
|
168
|
+
return theme.fg("dim", " Tab 编辑 · Enter 进入下一栏 · Esc 取消" + (isMultiQuestion ? " · ← → 切换问题" : ""));
|
|
166
169
|
case "rating":
|
|
167
170
|
return theme.fg("dim", " Tab 调整 · Enter 确认 · Esc 取消" + (isMultiQuestion ? " · ← → 切换问题" : ""));
|
|
168
171
|
default:
|