@dex-ai/coding-agent 0.1.92
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/bin/dex.ts +402 -0
- package/package.json +45 -0
- package/src/__tests__/command-validation.test.ts +205 -0
- package/src/__tests__/history.test.ts +183 -0
- package/src/cli-extension.ts +153 -0
- package/src/commands/extension-loader.ts +399 -0
- package/src/commands/extension.ts +924 -0
- package/src/commands/update.ts +419 -0
- package/src/env.d.ts +5 -0
- package/src/extensions/cli-tui-components/ActivityPanel.vue +24 -0
- package/src/extensions/cli-tui-components/ActivityPanel.vue.compiled.ts +96 -0
- package/src/extensions/cli-tui-components/App.vue +127 -0
- package/src/extensions/cli-tui-components/App.vue.compiled.ts +374 -0
- package/src/extensions/cli-tui-components/ApprovalPrompt.vue +30 -0
- package/src/extensions/cli-tui-components/ApprovalPrompt.vue.compiled.ts +72 -0
- package/src/extensions/cli-tui-components/AskPanel.vue +228 -0
- package/src/extensions/cli-tui-components/AskPanel.vue.compiled.ts +419 -0
- package/src/extensions/cli-tui-components/CommandPalette.vue +19 -0
- package/src/extensions/cli-tui-components/CommandPalette.vue.compiled.ts +65 -0
- package/src/extensions/cli-tui-components/ConfirmModal.vue +29 -0
- package/src/extensions/cli-tui-components/ConfirmModal.vue.compiled.ts +72 -0
- package/src/extensions/cli-tui-components/DiffView.vue +139 -0
- package/src/extensions/cli-tui-components/DiffView.vue.compiled.ts +274 -0
- package/src/extensions/cli-tui-components/FormModal.vue +58 -0
- package/src/extensions/cli-tui-components/FormModal.vue.compiled.ts +156 -0
- package/src/extensions/cli-tui-components/Header.vue +13 -0
- package/src/extensions/cli-tui-components/Header.vue.compiled.ts +42 -0
- package/src/extensions/cli-tui-components/InputArea.vue +202 -0
- package/src/extensions/cli-tui-components/InputArea.vue.compiled.ts +243 -0
- package/src/extensions/cli-tui-components/InteractivePanel.vue +32 -0
- package/src/extensions/cli-tui-components/InteractivePanel.vue.compiled.ts +103 -0
- package/src/extensions/cli-tui-components/ListModal.vue +58 -0
- package/src/extensions/cli-tui-components/ListModal.vue.compiled.ts +130 -0
- package/src/extensions/cli-tui-components/MarkdownContent.ts +54 -0
- package/src/extensions/cli-tui-components/Messages.vue +68 -0
- package/src/extensions/cli-tui-components/Messages.vue.compiled.ts +253 -0
- package/src/extensions/cli-tui-components/Modal.vue +56 -0
- package/src/extensions/cli-tui-components/Modal.vue.compiled.ts +61 -0
- package/src/extensions/cli-tui-components/SettingsPanel.vue +178 -0
- package/src/extensions/cli-tui-components/SettingsPanel.vue.compiled.ts +359 -0
- package/src/extensions/cli-tui-components/Spinner.vue +19 -0
- package/src/extensions/cli-tui-components/Spinner.vue.compiled.ts +42 -0
- package/src/extensions/cli-tui-components/StatusBar.vue +45 -0
- package/src/extensions/cli-tui-components/StatusBar.vue.compiled.ts +106 -0
- package/src/extensions/cli-tui-components/SteeringPreview.vue +11 -0
- package/src/extensions/cli-tui-components/SteeringPreview.vue.compiled.ts +38 -0
- package/src/extensions/cli-tui-components/ThinkingBlock.vue +40 -0
- package/src/extensions/cli-tui-components/ThinkingBlock.vue.compiled.ts +82 -0
- package/src/extensions/cli-tui-components/ToolCall.vue +114 -0
- package/src/extensions/cli-tui-components/ToolCall.vue.compiled.ts +319 -0
- package/src/extensions/cli-tui-components/UserMessage.vue +40 -0
- package/src/extensions/cli-tui-components/UserMessage.vue.compiled.ts +148 -0
- package/src/extensions/cli-tui-components/ask-panel-controller.ts +573 -0
- package/src/extensions/cli-tui-components/settings-panel-controller.ts +958 -0
- package/src/extensions/cli-tui.ts +2349 -0
- package/src/extensions/debug.ts +46 -0
- package/src/extensions/headless.ts +55 -0
- package/src/extensions/modal-system.ts +719 -0
- package/src/host.ts +505 -0
- package/src/index.ts +9 -0
- package/src/input/history.ts +233 -0
- package/src/input/index.ts +6 -0
- package/src/panels/dynamic-panel.ts +5 -0
- package/src/panels/index.ts +43 -0
- package/src/panels/state.ts +73 -0
- package/src/panels/types.ts +79 -0
- package/src/panels/widget.ts +25 -0
- package/src/provider-registry.ts +44 -0
- package/src/stderr-capture.ts +248 -0
- package/src/types.ts +20 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<stack v-if="hunks.length > 0">
|
|
3
|
+
<line>
|
|
4
|
+
<text color="subtle" :style="{ paddingLeft: 2 }">└ {{ summary }}</text>
|
|
5
|
+
</line>
|
|
6
|
+
<template v-for="(hunk, hi) in hunks" :key="hi">
|
|
7
|
+
<line v-if="hi > 0">
|
|
8
|
+
<text color="subtle" :style="{ paddingLeft: 4 }">...</text>
|
|
9
|
+
</line>
|
|
10
|
+
<template v-for="(line, li) in hunk.lines" :key="`${hi}-${li}`">
|
|
11
|
+
<line>
|
|
12
|
+
<text
|
|
13
|
+
:color="line.type === 'add' ? 'diff-add' : line.type === 'del' ? 'diff-del' : 'subtle'"
|
|
14
|
+
dim
|
|
15
|
+
:style="{ paddingLeft: 4, paddingRight: 1 }"
|
|
16
|
+
>{{ line.lineNo }}</text>
|
|
17
|
+
<text
|
|
18
|
+
v-if="line.type === 'add' || line.type === 'del'"
|
|
19
|
+
:color="line.type === 'add' ? 'diff-add' : 'diff-del'"
|
|
20
|
+
:bg="line.type === 'add' ? 'bg-diff-add' : 'bg-diff-del'"
|
|
21
|
+
>{{ line.text }}</text>
|
|
22
|
+
<text
|
|
23
|
+
v-else
|
|
24
|
+
color="subtle"
|
|
25
|
+
>{{ line.text }}</text>
|
|
26
|
+
</line>
|
|
27
|
+
</template>
|
|
28
|
+
</template>
|
|
29
|
+
</stack>
|
|
30
|
+
</template>
|
|
31
|
+
|
|
32
|
+
<script setup lang="ts">
|
|
33
|
+
import { computed } from "@vue/runtime-core";
|
|
34
|
+
|
|
35
|
+
interface DisplayLine {
|
|
36
|
+
type: "add" | "del" | "ctx";
|
|
37
|
+
lineNo: string;
|
|
38
|
+
text: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
interface DisplayHunk {
|
|
42
|
+
lines: DisplayLine[];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const props = defineProps<{
|
|
46
|
+
diff: string;
|
|
47
|
+
}>();
|
|
48
|
+
|
|
49
|
+
const hunks = computed((): DisplayHunk[] => {
|
|
50
|
+
if (!props.diff) return [];
|
|
51
|
+
|
|
52
|
+
const result: DisplayHunk[] = [];
|
|
53
|
+
let currentHunk: DisplayLine[] = [];
|
|
54
|
+
let oldLine = 0;
|
|
55
|
+
let newLine = 0;
|
|
56
|
+
let maxLineNo = 0;
|
|
57
|
+
|
|
58
|
+
// First pass: find max line number for padding
|
|
59
|
+
for (const raw of props.diff.split("\n")) {
|
|
60
|
+
if (raw.startsWith("@@")) {
|
|
61
|
+
const match = raw.match(/@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/);
|
|
62
|
+
if (match) {
|
|
63
|
+
const oldStart = parseInt(match[1]!, 10);
|
|
64
|
+
const oldCount = parseInt(match[2] ?? "1", 10);
|
|
65
|
+
const newStart = parseInt(match[3]!, 10);
|
|
66
|
+
const newCount = parseInt(match[4] ?? "1", 10);
|
|
67
|
+
maxLineNo = Math.max(maxLineNo, oldStart + oldCount, newStart + newCount);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const pad = Math.max(String(maxLineNo).length, 2);
|
|
72
|
+
|
|
73
|
+
// Second pass: build display lines
|
|
74
|
+
for (const raw of props.diff.split("\n")) {
|
|
75
|
+
if (raw.startsWith("@@")) {
|
|
76
|
+
// Save previous hunk if non-empty
|
|
77
|
+
if (currentHunk.length > 0) {
|
|
78
|
+
result.push({ lines: currentHunk });
|
|
79
|
+
currentHunk = [];
|
|
80
|
+
}
|
|
81
|
+
const match = raw.match(/@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/);
|
|
82
|
+
if (match) {
|
|
83
|
+
oldLine = parseInt(match[1]!, 10);
|
|
84
|
+
newLine = parseInt(match[2]!, 10);
|
|
85
|
+
}
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (raw.startsWith("--- ") || raw.startsWith("+++ ")) continue;
|
|
89
|
+
|
|
90
|
+
if (raw.startsWith("+")) {
|
|
91
|
+
currentHunk.push({
|
|
92
|
+
type: "add",
|
|
93
|
+
lineNo: String(newLine).padStart(pad) + "+",
|
|
94
|
+
text: raw.slice(1).replace(/\t/g, " "),
|
|
95
|
+
});
|
|
96
|
+
newLine++;
|
|
97
|
+
} else if (raw.startsWith("-")) {
|
|
98
|
+
currentHunk.push({
|
|
99
|
+
type: "del",
|
|
100
|
+
lineNo: String(oldLine).padStart(pad) + "-",
|
|
101
|
+
text: raw.slice(1).replace(/\t/g, " "),
|
|
102
|
+
});
|
|
103
|
+
oldLine++;
|
|
104
|
+
} else {
|
|
105
|
+
// Context line (starts with space or is empty)
|
|
106
|
+
const text = (raw.startsWith(" ") ? raw.slice(1) : raw).replace(/\t/g, " ");
|
|
107
|
+
currentHunk.push({
|
|
108
|
+
type: "ctx",
|
|
109
|
+
lineNo: String(newLine).padStart(pad) + " ",
|
|
110
|
+
text,
|
|
111
|
+
});
|
|
112
|
+
oldLine++;
|
|
113
|
+
newLine++;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Push final hunk
|
|
118
|
+
if (currentHunk.length > 0) {
|
|
119
|
+
result.push({ lines: currentHunk });
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return result;
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
const summary = computed(() => {
|
|
126
|
+
let additions = 0;
|
|
127
|
+
let deletions = 0;
|
|
128
|
+
for (const hunk of hunks.value) {
|
|
129
|
+
for (const line of hunk.lines) {
|
|
130
|
+
if (line.type === "add") additions++;
|
|
131
|
+
else if (line.type === "del") deletions++;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
const parts: string[] = [];
|
|
135
|
+
if (additions > 0) parts.push(`Added ${additions} line${additions !== 1 ? "s" : ""}`);
|
|
136
|
+
if (deletions > 0) parts.push(`removed ${deletions} line${deletions !== 1 ? "s" : ""}`);
|
|
137
|
+
return parts.join(", ");
|
|
138
|
+
});
|
|
139
|
+
</script>
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import * as _Vue from "@vue/runtime-core";
|
|
2
|
+
const {
|
|
3
|
+
h: _h,
|
|
4
|
+
toDisplayString: _toDisplayString,
|
|
5
|
+
openBlock: _openBlock,
|
|
6
|
+
createElementBlock: _createElementBlock,
|
|
7
|
+
createElementVNode: _createElementVNode,
|
|
8
|
+
createVNode: _createVNode,
|
|
9
|
+
createBlock: _createBlock,
|
|
10
|
+
createCommentVNode: _createCommentVNode,
|
|
11
|
+
Fragment: _Fragment,
|
|
12
|
+
renderList: _renderList,
|
|
13
|
+
withCtx: _withCtx,
|
|
14
|
+
createTextVNode: _createTextVNode,
|
|
15
|
+
resolveComponent: _resolveComponent,
|
|
16
|
+
normalizeStyle: _normalizeStyle,
|
|
17
|
+
normalizeClass: _normalizeClass,
|
|
18
|
+
normalizeProps: _normalizeProps,
|
|
19
|
+
guardReactiveProps: _guardReactiveProps,
|
|
20
|
+
mergeProps: _mergeProps,
|
|
21
|
+
withDirectives: _withDirectives,
|
|
22
|
+
resolveDynamicComponent: _resolveDynamicComponent,
|
|
23
|
+
} = _Vue;
|
|
24
|
+
|
|
25
|
+
import { defineComponent as _defineComponent } from "@vue/runtime-core";
|
|
26
|
+
import { computed } from "@vue/runtime-core";
|
|
27
|
+
|
|
28
|
+
interface DisplayLine {
|
|
29
|
+
type: "add" | "del" | "ctx";
|
|
30
|
+
lineNo: string;
|
|
31
|
+
marker: string;
|
|
32
|
+
text: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
interface DisplayHunk {
|
|
36
|
+
lines: DisplayLine[];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const __sfc_main = /*@__PURE__*/ _defineComponent({
|
|
40
|
+
__name: "DiffView",
|
|
41
|
+
props: {
|
|
42
|
+
diff: { type: String, required: true },
|
|
43
|
+
},
|
|
44
|
+
setup(__props: any, { expose: __expose }) {
|
|
45
|
+
__expose();
|
|
46
|
+
|
|
47
|
+
const props = __props;
|
|
48
|
+
|
|
49
|
+
const hunks = computed((): DisplayHunk[] => {
|
|
50
|
+
if (!props.diff) return [];
|
|
51
|
+
|
|
52
|
+
const result: DisplayHunk[] = [];
|
|
53
|
+
let currentHunk: DisplayLine[] = [];
|
|
54
|
+
let oldLine = 0;
|
|
55
|
+
let newLine = 0;
|
|
56
|
+
let maxLineNo = 0;
|
|
57
|
+
|
|
58
|
+
// First pass: find max line number for padding
|
|
59
|
+
for (const raw of props.diff.split("\n")) {
|
|
60
|
+
if (raw.startsWith("@@")) {
|
|
61
|
+
const match = raw.match(/@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/);
|
|
62
|
+
if (match) {
|
|
63
|
+
const oldStart = parseInt(match[1]!, 10);
|
|
64
|
+
const oldCount = parseInt(match[2] ?? "1", 10);
|
|
65
|
+
const newStart = parseInt(match[3]!, 10);
|
|
66
|
+
const newCount = parseInt(match[4] ?? "1", 10);
|
|
67
|
+
maxLineNo = Math.max(
|
|
68
|
+
maxLineNo,
|
|
69
|
+
oldStart + oldCount,
|
|
70
|
+
newStart + newCount,
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const pad = Math.max(String(maxLineNo).length, 3);
|
|
76
|
+
|
|
77
|
+
// Second pass: build display lines
|
|
78
|
+
for (const raw of props.diff.split("\n")) {
|
|
79
|
+
if (raw.startsWith("@@")) {
|
|
80
|
+
// Save previous hunk if non-empty
|
|
81
|
+
if (currentHunk.length > 0) {
|
|
82
|
+
result.push({ lines: currentHunk });
|
|
83
|
+
currentHunk = [];
|
|
84
|
+
}
|
|
85
|
+
const match = raw.match(/@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/);
|
|
86
|
+
if (match) {
|
|
87
|
+
oldLine = parseInt(match[1]!, 10);
|
|
88
|
+
newLine = parseInt(match[2]!, 10);
|
|
89
|
+
}
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (raw.startsWith("--- ") || raw.startsWith("+++ ")) continue;
|
|
93
|
+
|
|
94
|
+
if (raw.startsWith("+")) {
|
|
95
|
+
currentHunk.push({
|
|
96
|
+
type: "add",
|
|
97
|
+
lineNo: String(newLine).padStart(pad) + " +",
|
|
98
|
+
marker: "",
|
|
99
|
+
text: raw.slice(1),
|
|
100
|
+
});
|
|
101
|
+
newLine++;
|
|
102
|
+
} else if (raw.startsWith("-")) {
|
|
103
|
+
currentHunk.push({
|
|
104
|
+
type: "del",
|
|
105
|
+
lineNo: String(oldLine).padStart(pad) + " -",
|
|
106
|
+
marker: "",
|
|
107
|
+
text: raw.slice(1),
|
|
108
|
+
});
|
|
109
|
+
oldLine++;
|
|
110
|
+
} else {
|
|
111
|
+
// Context line (starts with space or is empty)
|
|
112
|
+
const text = raw.startsWith(" ") ? raw.slice(1) : raw;
|
|
113
|
+
currentHunk.push({
|
|
114
|
+
type: "ctx",
|
|
115
|
+
lineNo: String(newLine).padStart(pad) + " ",
|
|
116
|
+
marker: "",
|
|
117
|
+
text,
|
|
118
|
+
});
|
|
119
|
+
oldLine++;
|
|
120
|
+
newLine++;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Push final hunk
|
|
125
|
+
if (currentHunk.length > 0) {
|
|
126
|
+
result.push({ lines: currentHunk });
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return result;
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
const summary = computed(() => {
|
|
133
|
+
let additions = 0;
|
|
134
|
+
let deletions = 0;
|
|
135
|
+
for (const hunk of hunks.value) {
|
|
136
|
+
for (const line of hunk.lines) {
|
|
137
|
+
if (line.type === "add") additions++;
|
|
138
|
+
else if (line.type === "del") deletions++;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
const parts: string[] = [];
|
|
142
|
+
if (additions > 0)
|
|
143
|
+
parts.push(`Added ${additions} line${additions !== 1 ? "s" : ""}`);
|
|
144
|
+
if (deletions > 0)
|
|
145
|
+
parts.push(`removed ${deletions} line${deletions !== 1 ? "s" : ""}`);
|
|
146
|
+
return parts.join(", ");
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
const __returned__ = { props, hunks, summary };
|
|
150
|
+
Object.defineProperty(__returned__, "__isScriptSetup", {
|
|
151
|
+
enumerable: false,
|
|
152
|
+
value: true,
|
|
153
|
+
});
|
|
154
|
+
return __returned__;
|
|
155
|
+
},
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
const _hoisted_1 = { key: 0 };
|
|
159
|
+
|
|
160
|
+
const render = (
|
|
161
|
+
_ctx: any,
|
|
162
|
+
_cache: any,
|
|
163
|
+
$props: any,
|
|
164
|
+
$setup: any,
|
|
165
|
+
$data: any,
|
|
166
|
+
$options: any,
|
|
167
|
+
) =>
|
|
168
|
+
$setup.hunks.length > 0
|
|
169
|
+
? (_openBlock(),
|
|
170
|
+
_createElementBlock("stack", _hoisted_1, [
|
|
171
|
+
_createElementVNode("line", null, [
|
|
172
|
+
_createElementVNode(
|
|
173
|
+
"text",
|
|
174
|
+
{
|
|
175
|
+
color: "subtle",
|
|
176
|
+
style: { paddingLeft: 2 },
|
|
177
|
+
},
|
|
178
|
+
_toDisplayString("└ " + $setup.summary),
|
|
179
|
+
1 /* TEXT */,
|
|
180
|
+
),
|
|
181
|
+
]),
|
|
182
|
+
(_openBlock(true),
|
|
183
|
+
_createElementBlock(
|
|
184
|
+
_Fragment,
|
|
185
|
+
null,
|
|
186
|
+
_renderList($setup.hunks, (hunk: any, hi: number) => {
|
|
187
|
+
return (
|
|
188
|
+
_openBlock(),
|
|
189
|
+
_createElementBlock(
|
|
190
|
+
_Fragment,
|
|
191
|
+
{ key: hi },
|
|
192
|
+
[
|
|
193
|
+
hi > 0
|
|
194
|
+
? (_openBlock(),
|
|
195
|
+
_createElementBlock("line", { key: 0 }, [
|
|
196
|
+
_createElementVNode(
|
|
197
|
+
"text",
|
|
198
|
+
{
|
|
199
|
+
color: "subtle",
|
|
200
|
+
style: { paddingLeft: 4 },
|
|
201
|
+
},
|
|
202
|
+
"...",
|
|
203
|
+
),
|
|
204
|
+
]))
|
|
205
|
+
: _createCommentVNode("v-if", true),
|
|
206
|
+
(_openBlock(true),
|
|
207
|
+
_createElementBlock(
|
|
208
|
+
_Fragment,
|
|
209
|
+
null,
|
|
210
|
+
_renderList(hunk.lines, (line: any, li: number) => {
|
|
211
|
+
return (
|
|
212
|
+
_openBlock(),
|
|
213
|
+
_createElementBlock("line", { key: `${hi}-${li}` }, [
|
|
214
|
+
_createElementVNode(
|
|
215
|
+
"text",
|
|
216
|
+
{
|
|
217
|
+
color:
|
|
218
|
+
line.type === "add"
|
|
219
|
+
? "diff-add"
|
|
220
|
+
: line.type === "del"
|
|
221
|
+
? "diff-del"
|
|
222
|
+
: "subtle",
|
|
223
|
+
dim: "",
|
|
224
|
+
style: { paddingLeft: 4, paddingRight: 1 },
|
|
225
|
+
},
|
|
226
|
+
_toDisplayString(line.lineNo),
|
|
227
|
+
9 /* TEXT, PROPS */,
|
|
228
|
+
),
|
|
229
|
+
line.type === "add" || line.type === "del"
|
|
230
|
+
? (_openBlock(),
|
|
231
|
+
_createElementBlock(
|
|
232
|
+
"text",
|
|
233
|
+
{
|
|
234
|
+
key: 0,
|
|
235
|
+
color:
|
|
236
|
+
line.type === "add"
|
|
237
|
+
? "diff-add"
|
|
238
|
+
: "diff-del",
|
|
239
|
+
bg:
|
|
240
|
+
line.type === "add"
|
|
241
|
+
? "bg-diff-add"
|
|
242
|
+
: "bg-diff-del",
|
|
243
|
+
},
|
|
244
|
+
_toDisplayString(line.text),
|
|
245
|
+
9 /* TEXT, PROPS */,
|
|
246
|
+
))
|
|
247
|
+
: (_openBlock(),
|
|
248
|
+
_createElementBlock(
|
|
249
|
+
"text",
|
|
250
|
+
{
|
|
251
|
+
key: 1,
|
|
252
|
+
color: "subtle",
|
|
253
|
+
},
|
|
254
|
+
_toDisplayString(line.text),
|
|
255
|
+
1 /* TEXT */,
|
|
256
|
+
)),
|
|
257
|
+
])
|
|
258
|
+
);
|
|
259
|
+
}),
|
|
260
|
+
128 /* KEYED_FRAGMENT */,
|
|
261
|
+
)),
|
|
262
|
+
],
|
|
263
|
+
64 /* STABLE_FRAGMENT */,
|
|
264
|
+
)
|
|
265
|
+
);
|
|
266
|
+
}),
|
|
267
|
+
128 /* KEYED_FRAGMENT */,
|
|
268
|
+
)),
|
|
269
|
+
]))
|
|
270
|
+
: _createCommentVNode("v-if", true);
|
|
271
|
+
|
|
272
|
+
__sfc_main.render = render;
|
|
273
|
+
|
|
274
|
+
export default __sfc_main;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<stack>
|
|
3
|
+
<line borderTop="solid" :style="{ borderTopColor: 'accent' }">
|
|
4
|
+
<text bold color="accent"> {{ title }} </text>
|
|
5
|
+
</line>
|
|
6
|
+
<line v-for="(field, i) in fields" :key="field.key">
|
|
7
|
+
<text :color="i === focusedIndex ? 'accent' : 'muted'" :style="{ paddingLeft: 1, fontWeight: i === focusedIndex ? 'bold' : 'normal' }">{{ i === focusedIndex ? '❯' : ' ' }}</text>
|
|
8
|
+
<text :style="{ paddingLeft: 1 }" :color="i === focusedIndex ? 'text' : 'muted'">{{ field.label }}</text>
|
|
9
|
+
<text v-if="field.required && !field.readonly && !values[field.key]" color="warn" :style="{ paddingLeft: 1 }">*</text>
|
|
10
|
+
<text muted :style="{ paddingLeft: 1 }">│</text>
|
|
11
|
+
<text v-if="field.readonly && values[field.key]" dim :style="{ paddingLeft: 1 }">{{ values[field.key] }}</text>
|
|
12
|
+
<text v-else-if="field.readonly" dim :style="{ paddingLeft: 1 }">—</text>
|
|
13
|
+
<text v-else-if="i === focusedIndex && editing" color="accent" :style="{ paddingLeft: 1 }">{{ editBuffer }}▏</text>
|
|
14
|
+
<text v-else-if="field.type === 'password' && values[field.key]" :style="{ paddingLeft: 1 }">{{ maskValue(values[field.key]!) }}</text>
|
|
15
|
+
<text v-else-if="values[field.key]" :style="{ paddingLeft: 1 }">{{ values[field.key] }}</text>
|
|
16
|
+
<text v-else-if="field.placeholder" dim :style="{ paddingLeft: 1 }">{{ field.placeholder }}</text>
|
|
17
|
+
</line>
|
|
18
|
+
<line v-if="error">
|
|
19
|
+
<text color="error" :style="{ paddingLeft: 2 }">⚠ {{ error }}</text>
|
|
20
|
+
</line>
|
|
21
|
+
<line borderBottom="solid" :style="{ borderBottomColor: 'subtle' }">
|
|
22
|
+
<text muted>{{ editing ? 'enter/tab confirm · esc revert' : hasEditableFields ? 'tab/enter edit · ↑↓ fields · ctrl+s save · esc cancel' : '↑↓ navigate · esc close' }}</text>
|
|
23
|
+
</line>
|
|
24
|
+
</stack>
|
|
25
|
+
</template>
|
|
26
|
+
|
|
27
|
+
<script setup lang="ts">
|
|
28
|
+
import { computed } from "@vue/runtime-core";
|
|
29
|
+
|
|
30
|
+
export interface FormFieldDef {
|
|
31
|
+
key: string;
|
|
32
|
+
label: string;
|
|
33
|
+
type: 'text' | 'password' | 'select';
|
|
34
|
+
value?: string;
|
|
35
|
+
placeholder?: string;
|
|
36
|
+
hint?: string;
|
|
37
|
+
required?: boolean;
|
|
38
|
+
readonly?: boolean;
|
|
39
|
+
options?: string[];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const props = defineProps<{
|
|
43
|
+
title: string;
|
|
44
|
+
fields: FormFieldDef[];
|
|
45
|
+
values: Record<string, string>;
|
|
46
|
+
focusedIndex: number;
|
|
47
|
+
editing: boolean;
|
|
48
|
+
editBuffer: string;
|
|
49
|
+
error: string;
|
|
50
|
+
}>();
|
|
51
|
+
|
|
52
|
+
const hasEditableFields = computed(() => props.fields.some(f => !f.readonly));
|
|
53
|
+
|
|
54
|
+
function maskValue(val: string): string {
|
|
55
|
+
if (val.length <= 4) return '••••';
|
|
56
|
+
return '••••••••' + val.slice(-4);
|
|
57
|
+
}
|
|
58
|
+
</script>
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import * as _Vue from "@vue/runtime-core";
|
|
2
|
+
const { h: _h, toDisplayString: _toDisplayString, openBlock: _openBlock, createElementBlock: _createElementBlock, createElementVNode: _createElementVNode, createVNode: _createVNode, createBlock: _createBlock, createCommentVNode: _createCommentVNode, Fragment: _Fragment, renderList: _renderList, withCtx: _withCtx, createTextVNode: _createTextVNode, resolveComponent: _resolveComponent, normalizeStyle: _normalizeStyle, normalizeClass: _normalizeClass, normalizeProps: _normalizeProps, guardReactiveProps: _guardReactiveProps, mergeProps: _mergeProps, withDirectives: _withDirectives, resolveDynamicComponent: _resolveDynamicComponent } = _Vue;
|
|
3
|
+
|
|
4
|
+
import { defineComponent as _defineComponent } from "@vue/runtime-core"
|
|
5
|
+
import { computed } from "@vue/runtime-core";
|
|
6
|
+
|
|
7
|
+
export interface FormFieldDef {
|
|
8
|
+
key: string;
|
|
9
|
+
label: string;
|
|
10
|
+
type: 'text' | 'password' | 'select';
|
|
11
|
+
value?: string;
|
|
12
|
+
placeholder?: string;
|
|
13
|
+
hint?: string;
|
|
14
|
+
required?: boolean;
|
|
15
|
+
readonly?: boolean;
|
|
16
|
+
options?: string[];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
const __sfc_main = /*@__PURE__*/_defineComponent({
|
|
21
|
+
__name: 'FormModal',
|
|
22
|
+
props: {
|
|
23
|
+
title: { type: String, required: true },
|
|
24
|
+
fields: { type: Array, required: true },
|
|
25
|
+
values: { type: Object, required: true },
|
|
26
|
+
focusedIndex: { type: Number, required: true },
|
|
27
|
+
editing: { type: Boolean, required: true },
|
|
28
|
+
editBuffer: { type: String, required: true },
|
|
29
|
+
error: { type: String, required: true }
|
|
30
|
+
},
|
|
31
|
+
setup(__props: any, { expose: __expose }) {
|
|
32
|
+
__expose();
|
|
33
|
+
|
|
34
|
+
const props = __props;
|
|
35
|
+
|
|
36
|
+
const hasEditableFields = computed(() => props.fields.some(f => !f.readonly));
|
|
37
|
+
|
|
38
|
+
function maskValue(val: string): string {
|
|
39
|
+
if (val.length <= 4) return '••••';
|
|
40
|
+
return '••••••••' + val.slice(-4);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const __returned__ = { props, hasEditableFields, maskValue }
|
|
44
|
+
Object.defineProperty(__returned__, '__isScriptSetup', { enumerable: false, value: true })
|
|
45
|
+
return __returned__
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
const _hoisted_1 = {
|
|
51
|
+
borderTop: "solid",
|
|
52
|
+
style: { borderTopColor: 'accent' }
|
|
53
|
+
}
|
|
54
|
+
const _hoisted_2 = {
|
|
55
|
+
bold: "",
|
|
56
|
+
color: "accent"
|
|
57
|
+
}
|
|
58
|
+
const _hoisted_3 = ["color"]
|
|
59
|
+
const _hoisted_4 = ["color"]
|
|
60
|
+
const _hoisted_5 = {
|
|
61
|
+
key: 0,
|
|
62
|
+
color: "warn",
|
|
63
|
+
style: { paddingLeft: 1 }
|
|
64
|
+
}
|
|
65
|
+
const _hoisted_6 = {
|
|
66
|
+
key: 1,
|
|
67
|
+
dim: "",
|
|
68
|
+
style: { paddingLeft: 1 }
|
|
69
|
+
}
|
|
70
|
+
const _hoisted_7 = {
|
|
71
|
+
key: 2,
|
|
72
|
+
dim: "",
|
|
73
|
+
style: { paddingLeft: 1 }
|
|
74
|
+
}
|
|
75
|
+
const _hoisted_8 = {
|
|
76
|
+
key: 3,
|
|
77
|
+
color: "accent",
|
|
78
|
+
style: { paddingLeft: 1 }
|
|
79
|
+
}
|
|
80
|
+
const _hoisted_9 = {
|
|
81
|
+
key: 4,
|
|
82
|
+
style: { paddingLeft: 1 }
|
|
83
|
+
}
|
|
84
|
+
const _hoisted_10 = {
|
|
85
|
+
key: 5,
|
|
86
|
+
style: { paddingLeft: 1 }
|
|
87
|
+
}
|
|
88
|
+
const _hoisted_11 = {
|
|
89
|
+
key: 6,
|
|
90
|
+
dim: "",
|
|
91
|
+
style: { paddingLeft: 1 }
|
|
92
|
+
}
|
|
93
|
+
const _hoisted_12 = { key: 0 }
|
|
94
|
+
const _hoisted_13 = {
|
|
95
|
+
color: "error",
|
|
96
|
+
style: { paddingLeft: 2 }
|
|
97
|
+
}
|
|
98
|
+
const _hoisted_14 = {
|
|
99
|
+
borderBottom: "solid",
|
|
100
|
+
style: { borderBottomColor: 'subtle' }
|
|
101
|
+
}
|
|
102
|
+
const _hoisted_15 = { muted: "" }
|
|
103
|
+
|
|
104
|
+
const render = function(_ctx, _cache, $props, $setup, $data, $options) {
|
|
105
|
+
return (_openBlock(), _createElementBlock("stack", null, [
|
|
106
|
+
_createElementVNode("line", _hoisted_1, [
|
|
107
|
+
_createElementVNode("text", _hoisted_2, _toDisplayString($props.title), 1 /* TEXT */)
|
|
108
|
+
]),
|
|
109
|
+
(_openBlock(true), _createElementBlock(_Fragment, null, _renderList($props.fields, (field, i) => {
|
|
110
|
+
return (_openBlock(), _createElementBlock("line", {
|
|
111
|
+
key: field.key
|
|
112
|
+
}, [
|
|
113
|
+
_createElementVNode("text", {
|
|
114
|
+
color: i === $props.focusedIndex ? 'accent' : 'muted',
|
|
115
|
+
style: _normalizeStyle({ paddingLeft: 1, fontWeight: i === $props.focusedIndex ? 'bold' : 'normal' })
|
|
116
|
+
}, _toDisplayString(i === $props.focusedIndex ? '❯' : ' '), 13 /* TEXT, STYLE, PROPS */, _hoisted_3),
|
|
117
|
+
_createElementVNode("text", {
|
|
118
|
+
style: { paddingLeft: 1 },
|
|
119
|
+
color: i === $props.focusedIndex ? 'text' : 'muted'
|
|
120
|
+
}, _toDisplayString(field.label), 9 /* TEXT, PROPS */, _hoisted_4),
|
|
121
|
+
(field.required && !field.readonly && !$props.values[field.key])
|
|
122
|
+
? (_openBlock(), _createElementBlock("text", _hoisted_5, "*"))
|
|
123
|
+
: _createCommentVNode("v-if", true),
|
|
124
|
+
_cache[0] || (_cache[0] = _createElementVNode("text", {
|
|
125
|
+
muted: "",
|
|
126
|
+
style: { paddingLeft: 1 }
|
|
127
|
+
}, "│", -1 /* CACHED */)),
|
|
128
|
+
(field.readonly && $props.values[field.key])
|
|
129
|
+
? (_openBlock(), _createElementBlock("text", _hoisted_6, _toDisplayString($props.values[field.key]), 1 /* TEXT */))
|
|
130
|
+
: (field.readonly)
|
|
131
|
+
? (_openBlock(), _createElementBlock("text", _hoisted_7, "—"))
|
|
132
|
+
: (i === $props.focusedIndex && $props.editing)
|
|
133
|
+
? (_openBlock(), _createElementBlock("text", _hoisted_8, _toDisplayString($props.editBuffer) + "▏", 1 /* TEXT */))
|
|
134
|
+
: (field.type === 'password' && $props.values[field.key])
|
|
135
|
+
? (_openBlock(), _createElementBlock("text", _hoisted_9, _toDisplayString($setup.maskValue($props.values[field.key]!)), 1 /* TEXT */))
|
|
136
|
+
: ($props.values[field.key])
|
|
137
|
+
? (_openBlock(), _createElementBlock("text", _hoisted_10, _toDisplayString($props.values[field.key]), 1 /* TEXT */))
|
|
138
|
+
: (field.placeholder)
|
|
139
|
+
? (_openBlock(), _createElementBlock("text", _hoisted_11, _toDisplayString(field.placeholder), 1 /* TEXT */))
|
|
140
|
+
: _createCommentVNode("v-if", true)
|
|
141
|
+
]))
|
|
142
|
+
}), 128 /* KEYED_FRAGMENT */)),
|
|
143
|
+
($props.error)
|
|
144
|
+
? (_openBlock(), _createElementBlock("line", _hoisted_12, [
|
|
145
|
+
_createElementVNode("text", _hoisted_13, "⚠ " + _toDisplayString($props.error), 1 /* TEXT */)
|
|
146
|
+
]))
|
|
147
|
+
: _createCommentVNode("v-if", true),
|
|
148
|
+
_createElementVNode("line", _hoisted_14, [
|
|
149
|
+
_createElementVNode("text", _hoisted_15, _toDisplayString($props.editing ? 'enter confirm · esc revert' : $setup.hasEditableFields ? '↑↓ fields · enter edit · ctrl+s save · esc cancel' : '↑↓ navigate · esc close'), 1 /* TEXT */)
|
|
150
|
+
])
|
|
151
|
+
]))
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
__sfc_main.render = render;
|
|
155
|
+
|
|
156
|
+
export default __sfc_main;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<line>
|
|
3
|
+
<text color="accent" bold>{{ title }}</text>
|
|
4
|
+
<text dim :style="{ paddingLeft: 1 }">{{ subtitle }}</text>
|
|
5
|
+
</line>
|
|
6
|
+
</template>
|
|
7
|
+
|
|
8
|
+
<script setup lang="ts">
|
|
9
|
+
defineProps<{
|
|
10
|
+
title: string;
|
|
11
|
+
subtitle: string;
|
|
12
|
+
}>();
|
|
13
|
+
</script>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import * as _Vue from "@vue/runtime-core";
|
|
2
|
+
const { h: _h, toDisplayString: _toDisplayString, openBlock: _openBlock, createElementBlock: _createElementBlock, createElementVNode: _createElementVNode, createVNode: _createVNode, createBlock: _createBlock, createCommentVNode: _createCommentVNode, Fragment: _Fragment, renderList: _renderList, withCtx: _withCtx, createTextVNode: _createTextVNode, resolveComponent: _resolveComponent, normalizeStyle: _normalizeStyle, normalizeClass: _normalizeClass, normalizeProps: _normalizeProps, guardReactiveProps: _guardReactiveProps, mergeProps: _mergeProps, withDirectives: _withDirectives, resolveDynamicComponent: _resolveDynamicComponent } = _Vue;
|
|
3
|
+
|
|
4
|
+
import { defineComponent as _defineComponent } from "@vue/runtime-core"
|
|
5
|
+
|
|
6
|
+
const __sfc_main = /*@__PURE__*/_defineComponent({
|
|
7
|
+
__name: 'Header',
|
|
8
|
+
props: {
|
|
9
|
+
title: { type: String, required: true },
|
|
10
|
+
subtitle: { type: String, required: true }
|
|
11
|
+
},
|
|
12
|
+
setup(__props: any, { expose: __expose }) {
|
|
13
|
+
__expose();
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
const __returned__ = { }
|
|
18
|
+
Object.defineProperty(__returned__, '__isScriptSetup', { enumerable: false, value: true })
|
|
19
|
+
return __returned__
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
const _hoisted_1 = {
|
|
25
|
+
color: "accent",
|
|
26
|
+
bold: ""
|
|
27
|
+
}
|
|
28
|
+
const _hoisted_2 = {
|
|
29
|
+
dim: "",
|
|
30
|
+
style: { paddingLeft: 1 }
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const render = function(_ctx, _cache, $props, $setup, $data, $options) {
|
|
34
|
+
return (_openBlock(), _createElementBlock("line", null, [
|
|
35
|
+
_createElementVNode("text", _hoisted_1, _toDisplayString($props.title), 1 /* TEXT */),
|
|
36
|
+
_createElementVNode("text", _hoisted_2, _toDisplayString($props.subtitle), 1 /* TEXT */)
|
|
37
|
+
]))
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
__sfc_main.render = render;
|
|
41
|
+
|
|
42
|
+
export default __sfc_main;
|