@north-light/crouter 0.3.191 → 0.3.193
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/api/client.d.ts +31 -10
- package/dist/api/client.js +83 -24
- package/dist/api/dto/bash-jobs.d.ts +22 -0
- package/dist/api/dto/bash-jobs.js +9 -0
- package/dist/api/dto/human.d.ts +3 -4
- package/dist/api/dto/inbox.d.ts +106 -65
- package/dist/api/dto/inbox.js +2 -8
- package/dist/api/index.d.ts +1 -0
- package/dist/api/index.js +1 -0
- package/dist/api/routes.d.ts +7 -0
- package/dist/api/routes.js +7 -0
- package/dist/builtin-memory/internal/storage-tiers.md +1 -1
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/serial/provider-rotation.test.ts +101 -3
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.d.ts +6 -2
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.js +68 -14
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +87 -13
- package/dist/clients/attach/__tests__/chat-view-snapshot-ordering.test.js +2 -2
- package/dist/clients/attach/__tests__/group-activity.test.js +2 -2
- package/dist/clients/attach/chrome/canvas-panels.d.ts +1 -1
- package/dist/clients/attach/chrome/canvas-panels.js +1 -1
- package/dist/clients/attach/input/overlay-owner.js +1 -1
- package/dist/clients/attach/overlays/auth.js +34 -8
- package/dist/clients/attach/overlays/pickers.d.ts +5 -8
- package/dist/clients/attach/overlays/pickers.js +37 -43
- package/dist/clients/attach/viewer.js +643 -620
- package/dist/clients/inbox/__tests__/serial/inbox-controller.test.js +38 -128
- package/dist/clients/inbox/__tests__/serial/mount-panel.test.js +72 -148
- package/dist/clients/inbox/controller.d.ts +2 -3
- package/dist/clients/inbox/controller.js +41 -42
- package/dist/clients/inbox/page-adapter.d.ts +33 -0
- package/dist/clients/inbox/page-adapter.js +54 -0
- package/dist/clients/inbox/resolve.d.ts +2 -2
- package/dist/clients/inbox/resolve.js +1 -1
- package/dist/clients/inbox/review-visibility.d.ts +1 -1
- package/dist/clients/inbox/review-visibility.js +1 -1
- package/dist/clients/inbox/tui/ansi.d.ts +1 -1
- package/dist/clients/inbox/tui/ansi.js +2 -2
- package/dist/clients/inbox/tui/input.d.ts +1 -3
- package/dist/clients/inbox/tui/input.js +242 -553
- package/dist/clients/inbox/tui/panel.d.ts +3 -1
- package/dist/clients/inbox/tui/panel.js +59 -187
- package/dist/clients/inbox/tui/render.d.ts +0 -25
- package/dist/clients/inbox/tui/render.js +165 -416
- package/dist/clients/inbox/tui/slots.d.ts +32 -0
- package/dist/clients/inbox/tui/slots.js +156 -0
- package/dist/clients/inbox/tui/types.d.ts +25 -13
- package/dist/clients/inbox/tui.js +5 -3
- package/dist/commands/attention.js +2 -2
- package/dist/commands/human/doc.js +66 -20
- package/dist/commands/human/prompts.d.ts +3 -3
- package/dist/commands/human/prompts.js +158 -112
- package/dist/commands/human/queue.d.ts +0 -1
- package/dist/commands/human/queue.js +34 -94
- package/dist/commands/human/shared.d.ts +10 -4
- package/dist/commands/human/shared.js +62 -13
- package/dist/commands/human.js +8 -4
- package/dist/commands/memory/read.js +13 -5
- package/dist/commands/node/bash.js +15 -28
- package/dist/commands/surface/node/focus.js +1 -1
- package/dist/core/__tests__/human-deliver.test.js +40 -46
- package/dist/core/__tests__/seam/broker-attach-stream.test.js +7 -1
- package/dist/core/__tests__/serial/human-deliver-e2e.test.js +40 -31
- package/dist/core/__tests__/serial/spawn-root.test.js +3 -1
- package/dist/core/__tests__/spawn-worktree-id-conflict.test.js +3 -1
- package/dist/core/auth-interaction.d.ts +2 -2
- package/dist/core/bash-jobs.d.ts +32 -0
- package/dist/core/bash-jobs.js +72 -1
- package/dist/core/canvas/__tests__/attention.test.js +16 -10
- package/dist/core/canvas/__tests__/render-remote.test.js +9 -3
- package/dist/core/canvas/attention.js +1 -1
- package/dist/core/canvas/browse/app.js +1 -1
- package/dist/core/canvas/nav-model.d.ts +1 -1
- package/dist/core/canvas/nav-model.js +1 -1
- package/dist/core/canvas/remote-canvas-source.js +1 -1
- package/dist/core/config.js +4 -1
- package/dist/core/human/__tests__/page-render.test.d.ts +1 -0
- package/dist/core/human/__tests__/page-render.test.js +49 -0
- package/dist/core/human/__tests__/page-tickets.test.d.ts +1 -0
- package/dist/core/human/__tests__/page-tickets.test.js +112 -0
- package/dist/core/human/__tests__/page.test.d.ts +1 -0
- package/dist/core/human/__tests__/page.test.js +139 -0
- package/dist/core/human/__tests__/serial/inbox-core.test.js +42 -32
- package/dist/core/human/claim.js +2 -2
- package/dist/core/human/convention.d.ts +4 -4
- package/dist/core/human/convention.js +6 -13
- package/dist/core/human/markdown-html.d.ts +8 -0
- package/dist/core/human/markdown-html.js +581 -0
- package/dist/core/human/page-catalog.d.ts +6 -0
- package/dist/core/human/page-catalog.js +43 -0
- package/dist/core/human/page-render.d.ts +3 -0
- package/dist/core/human/page-render.js +131 -0
- package/dist/core/human/page-schema.d.ts +312 -0
- package/dist/core/human/page-schema.js +291 -0
- package/dist/core/human/page-synth.d.ts +9 -0
- package/dist/core/human/page-synth.js +17 -0
- package/dist/core/human/page.d.ts +22 -0
- package/dist/core/human/page.js +427 -0
- package/dist/core/human/review-schema.d.ts +19 -0
- package/dist/core/human/review-schema.js +34 -0
- package/dist/core/human/scan.d.ts +12 -3
- package/dist/core/human/scan.js +69 -26
- package/dist/core/human/summary.d.ts +5 -6
- package/dist/core/human/summary.js +54 -37
- package/dist/core/human/tickets.d.ts +61 -11
- package/dist/core/human/tickets.js +100 -57
- package/dist/core/human/types.d.ts +21 -66
- package/dist/core/human/types.js +1 -5
- package/dist/core/preview-registry.js +0 -1
- package/dist/core/review/ticket-filter.d.ts +1 -1
- package/dist/core/review/ticket-filter.js +2 -8
- package/dist/core/runtime/broker/read-ops.js +3 -0
- package/dist/core/runtime/broker.js +19 -10
- package/dist/core/runtime/package-health.js +1 -1
- package/dist/core/termrender/termrender.d.ts +1 -1
- package/dist/core/termrender/termrender.js +2 -2
- package/dist/core/tui/page-host.d.ts +1 -1
- package/dist/core/tui/page-host.js +2 -2
- package/dist/core/user-settings.d.ts +19 -0
- package/dist/core/user-settings.js +22 -0
- package/dist/daemon/api/handlers/bash-jobs.d.ts +2 -0
- package/dist/daemon/api/handlers/bash-jobs.js +89 -0
- package/dist/daemon/api/handlers/human.js +16 -14
- package/dist/daemon/api/handlers/inbox.js +311 -227
- package/dist/daemon/api/router.d.ts +5 -1
- package/dist/daemon/api/router.js +5 -0
- package/dist/daemon/api/server.js +2 -0
- package/dist/daemon/cron-run.js +23 -10
- package/dist/daemon/human/finish.d.ts +8 -3
- package/dist/daemon/human/finish.js +35 -15
- package/dist/pages/bundle.css +1 -0
- package/dist/pages/bundle.js +1347 -0
- package/dist/pages/comments.d.ts +34 -0
- package/dist/pages/comments.js +72 -0
- package/dist/pages/elements/cards.d.ts +17 -0
- package/dist/pages/elements/cards.js +785 -0
- package/dist/pages/elements/chart.d.ts +1 -0
- package/dist/pages/elements/chart.js +648 -0
- package/dist/pages/elements/options.d.ts +21 -0
- package/dist/pages/elements/options.js +604 -0
- package/dist/pages/elements/pages.d.ts +24 -0
- package/dist/pages/elements/pages.js +355 -0
- package/dist/pages/elements/slot.d.ts +21 -0
- package/dist/pages/elements/slot.js +105 -0
- package/dist/pages/elements/table.d.ts +19 -0
- package/dist/pages/elements/table.js +906 -0
- package/dist/pages/elements/text.d.ts +25 -0
- package/dist/pages/elements/text.js +951 -0
- package/dist/pages/entry.d.ts +8 -0
- package/dist/pages/entry.js +8 -0
- package/dist/pages/host.d.ts +132 -0
- package/dist/pages/host.js +149 -0
- package/dist/pages/register.d.ts +2 -0
- package/dist/pages/register.js +3 -0
- package/dist/pages/slot-config.d.ts +36 -0
- package/dist/pages/slot-config.js +50 -0
- package/dist/pages/types.d.ts +98 -0
- package/dist/pages/types.js +23 -0
- package/dist/pi-extensions/__tests__/canvas-structured-output.test.js +13 -5
- package/dist/pi-extensions/canvas-structured-output.js +7 -3
- package/dist/types.d.ts +4 -0
- package/dist/types.js +2 -0
- package/package.json +8 -8
- package/runtime.lock.json +156 -101
- package/dist/clients/inbox/deck-adapter.d.ts +0 -29
- package/dist/clients/inbox/deck-adapter.js +0 -63
- package/dist/core/human/deck-factories.d.ts +0 -8
- package/dist/core/human/deck-factories.js +0 -15
- package/dist/core/human/deck-schema.d.ts +0 -70
- package/dist/core/human/deck-schema.js +0 -92
|
@@ -1,2 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { PageResponses } from '../../../core/human/page-schema.js';
|
|
2
|
+
import type { MountedPanel, MountedPanelOpts, TuiState } from './types.js';
|
|
3
|
+
export declare function collectResponses(state: TuiState): PageResponses;
|
|
2
4
|
export declare function mountPanel(opts: MountedPanelOpts): MountedPanel;
|
|
@@ -1,125 +1,56 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { assignShortcuts, handleKeypress } from './input.js';
|
|
1
|
+
import { handleKeypress } from './input.js';
|
|
3
2
|
import { clampItemReviewScroll, renderFinal, renderItemReview, renderOverview } from './render.js';
|
|
4
|
-
|
|
5
|
-
function
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
// takes priority — mid-deck progress should not be overwritten by defaults.
|
|
15
|
-
for (const interaction of deck.interactions) {
|
|
16
|
-
const pa = interaction.preAnswered;
|
|
17
|
-
if (pa === undefined)
|
|
3
|
+
import { pageComplete, slotAnswered } from './slots.js';
|
|
4
|
+
function projectProse(projection) {
|
|
5
|
+
const overviewProse = [];
|
|
6
|
+
const slotProse = new Map();
|
|
7
|
+
let pending = [];
|
|
8
|
+
let seenSlot = false;
|
|
9
|
+
for (const block of projection) {
|
|
10
|
+
if (block.kind === 'prose') {
|
|
11
|
+
if (block.markdown.trim() !== '')
|
|
12
|
+
pending.push(block.markdown);
|
|
18
13
|
continue;
|
|
19
|
-
const response = { id: interaction.id };
|
|
20
|
-
if (pa.selectedOptionId !== undefined)
|
|
21
|
-
response.selectedOptionId = pa.selectedOptionId;
|
|
22
|
-
if (pa.selectedOptionIds !== undefined)
|
|
23
|
-
response.selectedOptionIds = [...pa.selectedOptionIds];
|
|
24
|
-
if (pa.freetext !== undefined)
|
|
25
|
-
response.freetext = pa.freetext;
|
|
26
|
-
responses.set(interaction.id, response);
|
|
27
|
-
preAnsweredIds.add(interaction.id);
|
|
28
|
-
}
|
|
29
|
-
// Start cursor on the first unanswered interaction — humans land where they
|
|
30
|
-
// need to act. If every interaction is pre-answered, fall back to index 0.
|
|
31
|
-
const firstUnanswered = deck.interactions.findIndex((i) => !responses.has(i.id));
|
|
32
|
-
return {
|
|
33
|
-
phase: initialPhase,
|
|
34
|
-
currentIndex: firstUnanswered >= 0 ? firstUnanswered : 0,
|
|
35
|
-
interactions: deck.interactions,
|
|
36
|
-
responses,
|
|
37
|
-
preAnsweredIds,
|
|
38
|
-
inputMode: null,
|
|
39
|
-
selectedAction: 0,
|
|
40
|
-
bodyMode: 'question',
|
|
41
|
-
scrollOffset: 0,
|
|
42
|
-
bodyScrollOffsets: { question: 0 },
|
|
43
|
-
hscrollOffset: 0,
|
|
44
|
-
hscrollMax: 0,
|
|
45
|
-
wrapWidth,
|
|
46
|
-
editorAvailable,
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
function collectResponses(state) {
|
|
50
|
-
const out = [];
|
|
51
|
-
for (const interaction of state.interactions) {
|
|
52
|
-
const r = state.responses.get(interaction.id);
|
|
53
|
-
if (r !== undefined)
|
|
54
|
-
out.push(r);
|
|
55
|
-
}
|
|
56
|
-
return out;
|
|
57
|
-
}
|
|
58
|
-
function tryResume(state, progressPath, interactions) {
|
|
59
|
-
try {
|
|
60
|
-
const prior = JSON.parse(readFileSync(progressPath, 'utf8'));
|
|
61
|
-
if (!Array.isArray(prior.responses))
|
|
62
|
-
return;
|
|
63
|
-
const validIds = new Set(interactions.map((i) => i.id));
|
|
64
|
-
for (const r of prior.responses) {
|
|
65
|
-
if (validIds.has(r.id))
|
|
66
|
-
state.responses.set(r.id, r);
|
|
67
14
|
}
|
|
68
|
-
|
|
69
|
-
|
|
15
|
+
if (!seenSlot)
|
|
16
|
+
overviewProse.push(...pending);
|
|
17
|
+
else
|
|
18
|
+
slotProse.set(block.slotIndex, pending);
|
|
19
|
+
pending = [];
|
|
20
|
+
seenSlot = true;
|
|
70
21
|
}
|
|
71
|
-
|
|
72
|
-
|
|
22
|
+
// A page with no slots has no final phase to reach — its prose is the overview.
|
|
23
|
+
if (!seenSlot) {
|
|
24
|
+
overviewProse.push(...pending);
|
|
25
|
+
return { overviewProse, slotProse, finalProse: [] };
|
|
73
26
|
}
|
|
27
|
+
return { overviewProse, slotProse, finalProse: pending };
|
|
74
28
|
}
|
|
75
|
-
function
|
|
76
|
-
const
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
internals.state.persist = () => {
|
|
88
|
-
const responses = collectResponses(internals.state);
|
|
89
|
-
if (internals.progressPath !== undefined)
|
|
90
|
-
atomicWriteProgress(internals.progressPath, responses);
|
|
91
|
-
internals.callbacks.onProgress?.(responses);
|
|
92
|
-
};
|
|
29
|
+
function buildInitialState(manifest, projection, initialResponses, productKinds, editorAvailable, wrapWidth) {
|
|
30
|
+
const prose = projectProse(projection);
|
|
31
|
+
const responses = new Map();
|
|
32
|
+
const validIds = new Set(manifest.slots.flatMap((slot) => slot.id === undefined ? [] : [slot.id]));
|
|
33
|
+
for (const [id, response] of Object.entries(initialResponses ?? {}))
|
|
34
|
+
if (validIds.has(id))
|
|
35
|
+
responses.set(id, response);
|
|
36
|
+
const state = { phase: manifest.slots.length === 1 ? 'item-review' : 'overview', currentIndex: 0, manifest, slots: manifest.slots, ...prose, responses, productKinds, inputMode: null, selectedAction: 0, bodyMode: 'question', scrollOffset: 0, bodyScrollOffsets: { question: 0 }, hscrollOffset: 0, hscrollMax: 0, wrapWidth, editorAvailable };
|
|
37
|
+
const first = manifest.slots.findIndex((slot) => slot.id !== undefined && !slotAnswered(state, slot));
|
|
38
|
+
if (first >= 0)
|
|
39
|
+
state.currentIndex = first;
|
|
40
|
+
return state;
|
|
93
41
|
}
|
|
42
|
+
export function collectResponses(state) { return Object.fromEntries(state.responses); }
|
|
43
|
+
function rebindPersist(internals) { internals.state.persist = () => internals.callbacks.onProgress?.(collectResponses(internals.state)); }
|
|
94
44
|
export function mountPanel(opts) {
|
|
95
|
-
const internals = {
|
|
96
|
-
state: buildInitialState(opts.deck, opts.onEditorRequest !== undefined, opts.cols),
|
|
97
|
-
cols: opts.cols,
|
|
98
|
-
rows: opts.rows,
|
|
99
|
-
mounted: true,
|
|
100
|
-
progressPath: opts.progressPath,
|
|
101
|
-
callbacks: {
|
|
102
|
-
onProgress: opts.onProgress, onComplete: opts.onComplete, onExit: opts.onExit,
|
|
103
|
-
onDirty: opts.onDirty, onEditorRequest: opts.onEditorRequest,
|
|
104
|
-
},
|
|
105
|
-
};
|
|
106
|
-
assignShortcuts(internals.state.interactions);
|
|
45
|
+
const internals = { state: buildInitialState(opts.manifest, opts.projection, opts.initialResponses, opts.productKinds ?? [], opts.onEditorRequest !== undefined, opts.cols), cols: opts.cols, rows: opts.rows, mounted: true, callbacks: { onProgress: opts.onProgress, onComplete: opts.onComplete, onExit: opts.onExit, onDirty: opts.onDirty, onEditorRequest: opts.onEditorRequest } };
|
|
107
46
|
rebindPersist(internals);
|
|
108
|
-
if (internals.progressPath !== undefined) {
|
|
109
|
-
tryResume(internals.state, internals.progressPath, opts.deck.interactions);
|
|
110
|
-
}
|
|
111
47
|
const renderLines = () => {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
// stays pure; running it here covers mount, resize and every keypress.
|
|
119
|
-
clampItemReviewScroll(internals.state, internals.cols, internals.rows);
|
|
120
|
-
return renderItemReview(internals.state, internals.cols, internals.rows);
|
|
121
|
-
case 'final': return renderFinal(internals.state, internals.cols, internals.rows);
|
|
122
|
-
}
|
|
48
|
+
if (internals.state.phase === 'overview')
|
|
49
|
+
return renderOverview(internals.state, internals.cols, internals.rows);
|
|
50
|
+
if (internals.state.phase === 'final')
|
|
51
|
+
return renderFinal(internals.state, internals.cols, internals.rows);
|
|
52
|
+
clampItemReviewScroll(internals.state, internals.cols, internals.rows);
|
|
53
|
+
return renderItemReview(internals.state, internals.cols, internals.rows);
|
|
123
54
|
};
|
|
124
55
|
return {
|
|
125
56
|
handleKey(input, key) {
|
|
@@ -129,89 +60,30 @@ export function mountPanel(opts) {
|
|
|
129
60
|
internals.callbacks.onEditorRequest();
|
|
130
61
|
return;
|
|
131
62
|
}
|
|
132
|
-
|
|
133
|
-
const responses = collectResponses(internals.state);
|
|
134
|
-
if (internals.progressPath !== undefined) {
|
|
135
|
-
try {
|
|
136
|
-
unlinkSync(internals.progressPath);
|
|
137
|
-
}
|
|
138
|
-
catch { /* ignore */ }
|
|
139
|
-
}
|
|
140
|
-
internals.callbacks.onComplete?.(responses);
|
|
141
|
-
};
|
|
142
|
-
handleKeypress(input, key, internals.state, () => { }, () => {
|
|
63
|
+
handleKeypress(input, key, internals.state, () => internals.callbacks.onDirty?.(), (submit) => {
|
|
143
64
|
const responses = collectResponses(internals.state);
|
|
144
|
-
if (
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
else {
|
|
65
|
+
if (submit === true && pageComplete(internals.state))
|
|
66
|
+
internals.callbacks.onComplete?.(responses);
|
|
67
|
+
else
|
|
148
68
|
internals.callbacks.onExit?.();
|
|
149
|
-
}
|
|
150
69
|
});
|
|
70
|
+
internals.callbacks.onDirty?.();
|
|
151
71
|
},
|
|
152
|
-
render()
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
},
|
|
157
|
-
handleResize(cols, rows) {
|
|
158
|
-
internals.cols = cols;
|
|
159
|
-
internals.rows = rows;
|
|
160
|
-
internals.state.wrapWidth = cols;
|
|
161
|
-
return renderLines();
|
|
162
|
-
},
|
|
163
|
-
unmount() {
|
|
164
|
-
if (!internals.mounted)
|
|
165
|
-
return;
|
|
166
|
-
internals.mounted = false;
|
|
167
|
-
internals.state.persist = undefined;
|
|
168
|
-
},
|
|
169
|
-
loadDeck(deck, loadOpts) {
|
|
72
|
+
render: () => internals.mounted ? renderLines() : [],
|
|
73
|
+
handleResize(cols, rows) { internals.cols = cols; internals.rows = rows; internals.state.wrapWidth = cols; return renderLines(); },
|
|
74
|
+
unmount() { internals.mounted = false; internals.state.persist = undefined; },
|
|
75
|
+
loadPage(manifest, projection, loadOpts) {
|
|
170
76
|
if (!internals.mounted)
|
|
171
77
|
return;
|
|
172
78
|
const prior = collectResponses(internals.state);
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
internals.progressPath = loadOpts.progressPath;
|
|
176
|
-
}
|
|
177
|
-
assignShortcuts(internals.state.interactions);
|
|
79
|
+
const merged = { ...(loadOpts?.initialResponses ?? {}), ...prior };
|
|
80
|
+
internals.state = buildInitialState(manifest, projection, merged, loadOpts?.productKinds ?? internals.state.productKinds, internals.callbacks.onEditorRequest !== undefined, internals.cols);
|
|
178
81
|
rebindPersist(internals);
|
|
179
|
-
if (internals.progressPath !== undefined) {
|
|
180
|
-
tryResume(internals.state, internals.progressPath, deck.interactions);
|
|
181
|
-
}
|
|
182
|
-
// A live request replacement is allowed to add/remove questions but not
|
|
183
|
-
// discard answers the human has already made to surviving ids.
|
|
184
|
-
const validIds = new Set(deck.interactions.map((interaction) => interaction.id));
|
|
185
|
-
for (const response of prior) {
|
|
186
|
-
if (validIds.has(response.id))
|
|
187
|
-
internals.state.responses.set(response.id, response);
|
|
188
|
-
}
|
|
189
|
-
const currentId = internals.state.interactions[internals.state.currentIndex]?.id;
|
|
190
|
-
if (currentId === undefined || !validIds.has(currentId)) {
|
|
191
|
-
const firstUnanswered = internals.state.interactions.findIndex((interaction) => !internals.state.responses.has(interaction.id));
|
|
192
|
-
internals.state.currentIndex = firstUnanswered >= 0 ? firstUnanswered : 0;
|
|
193
|
-
}
|
|
194
|
-
},
|
|
195
|
-
canAcceptHostKeys() {
|
|
196
|
-
if (!internals.mounted)
|
|
197
|
-
return false;
|
|
198
|
-
return internals.state.inputMode === null;
|
|
199
|
-
},
|
|
200
|
-
atDeckTop() {
|
|
201
|
-
if (!internals.mounted)
|
|
202
|
-
return true;
|
|
203
|
-
return internals.state.phase === 'overview' && internals.state.inputMode === null;
|
|
204
|
-
},
|
|
205
|
-
getInputBuffer() {
|
|
206
|
-
if (!internals.mounted || internals.state.inputMode === null)
|
|
207
|
-
return undefined;
|
|
208
|
-
return internals.state.inputMode.buffer;
|
|
209
|
-
},
|
|
210
|
-
setInputBuffer(text) {
|
|
211
|
-
if (!internals.mounted || internals.state.inputMode === null)
|
|
212
|
-
return;
|
|
213
|
-
internals.state.inputMode.buffer = text;
|
|
214
|
-
internals.state.inputMode.cursor = [...text].length;
|
|
215
82
|
},
|
|
83
|
+
canAcceptHostKeys: () => internals.mounted && internals.state.inputMode === null,
|
|
84
|
+
atPageTop: () => !internals.mounted || (internals.state.phase === 'overview' && internals.state.inputMode === null),
|
|
85
|
+
getInputBuffer: () => !internals.mounted || internals.state.inputMode === null ? undefined : internals.state.inputMode.buffer,
|
|
86
|
+
setInputBuffer(text) { if (!internals.mounted || internals.state.inputMode === null)
|
|
87
|
+
return; internals.state.inputMode.buffer = text; internals.state.inputMode.cursor = [...text].length; },
|
|
216
88
|
};
|
|
217
89
|
}
|
|
@@ -1,37 +1,12 @@
|
|
|
1
1
|
import type { TuiState } from './types.js';
|
|
2
|
-
import type { Interaction, InteractionResponse } from '../../../core/human/types.js';
|
|
3
2
|
export declare function renderOverview(state: TuiState, cols: number, rows: number): string[];
|
|
4
|
-
/**
|
|
5
|
-
* Render a (possibly multiline) input buffer with a visible cursor at
|
|
6
|
-
* `cursor` (a code-point index). A private-use sentinel is inserted at the
|
|
7
|
-
* cursor position, the result is hard-wrapped (so `\n` and width-wrapping
|
|
8
|
-
* behave exactly as they would without a cursor), then the sentinel is
|
|
9
|
-
* swapped for a reverse-video block on whichever wrapped line it landed on.
|
|
10
|
-
* `stringWidth('\uE000') === 1`, so it occupies exactly one column and never
|
|
11
|
-
* throws off the wrap math.
|
|
12
|
-
*/
|
|
13
3
|
export declare function renderInputBuffer(buffer: string, cursor: number, maxWidth: number): string[];
|
|
14
|
-
/** Code-point bounds of every visual row `renderInputBuffer` paints, mirroring
|
|
15
|
-
* `hardWrap` (character-based, lossless) so a cursor index maps to the row the
|
|
16
|
-
* human actually sees. `end` is exclusive of the row's trailing '\n', if any. */
|
|
17
4
|
export declare function wrappedRowBounds(buffer: string, width: number): {
|
|
18
5
|
start: number;
|
|
19
6
|
end: number;
|
|
20
7
|
}[];
|
|
21
|
-
/** Vertical motion by *visual* row — what up/down mean in a wrapped input box,
|
|
22
|
-
* where one long soft-wrapped paragraph spans many rows. Returns the new
|
|
23
|
-
* code-point cursor, unchanged when there is no row in that direction. */
|
|
24
8
|
export declare function verticalCursor(buffer: string, cursor: number, delta: number, width: number): number;
|
|
25
|
-
/**
|
|
26
|
-
* Clamp state.scrollOffset to the current body's scroll bounds. The host runs
|
|
27
|
-
* this as a pre-render step (from the input path) so `renderItemReview` stays a
|
|
28
|
-
* pure function of state — the clamp keeps u/d scrolling responsive without the
|
|
29
|
-
* renderer mutating state mid-frame.
|
|
30
|
-
*/
|
|
31
9
|
export declare function clampItemReviewScroll(state: TuiState, cols: number, rows: number): void;
|
|
32
|
-
/** Pan the card body horizontally. Clamping happens in the pre-render clamp
|
|
33
|
-
* the host already runs, exactly like vertical over-scroll. */
|
|
34
10
|
export declare function panItemReview(state: TuiState, direction: -1 | 1): void;
|
|
35
11
|
export declare function renderItemReview(state: TuiState, cols: number, rows: number): string[];
|
|
36
12
|
export declare function renderFinal(state: TuiState, cols: number, rows: number): string[];
|
|
37
|
-
export declare function responseSummary(r: InteractionResponse, interaction: Interaction): string;
|