@adea-ai/ui 0.142.4 → 0.144.0
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/components/composites/accent-picker/accent-picker.d.ts +28 -0
- package/dist/components/composites/accent-picker/accent-picker.d.ts.map +1 -0
- package/dist/components/composites/accent-picker/accent-picker.js +107 -0
- package/dist/components/composites/accent-picker/accent-picker.js.map +1 -0
- package/dist/components/composites/accent-picker/index.d.ts +2 -0
- package/dist/components/composites/accent-picker/index.d.ts.map +1 -0
- package/dist/components/composites/accent-picker/index.js +2 -0
- package/dist/components/composites/icon-picker/icon-picker.d.ts +52 -0
- package/dist/components/composites/icon-picker/icon-picker.d.ts.map +1 -0
- package/dist/components/composites/icon-picker/icon-picker.js +265 -0
- package/dist/components/composites/icon-picker/icon-picker.js.map +1 -0
- package/dist/components/composites/icon-picker/image-data-url.d.ts +42 -0
- package/dist/components/composites/icon-picker/image-data-url.d.ts.map +1 -0
- package/dist/components/composites/icon-picker/image-data-url.js +90 -0
- package/dist/components/composites/icon-picker/image-data-url.js.map +1 -0
- package/dist/components/composites/icon-picker/index.d.ts +4 -0
- package/dist/components/composites/icon-picker/index.d.ts.map +1 -0
- package/dist/components/composites/icon-picker/index.js +4 -0
- package/dist/components/composites/icon-picker/shell-icons.d.ts +264 -0
- package/dist/components/composites/icon-picker/shell-icons.d.ts.map +1 -0
- package/dist/components/composites/icon-picker/shell-icons.js +334 -0
- package/dist/components/composites/icon-picker/shell-icons.js.map +1 -0
- package/dist/components/composites/settings/settings-navigation.js +1 -1
- package/dist/components/composites/settings/settings-navigation.js.map +1 -1
- package/dist/components/composites/settings/settings.d.ts +8 -14
- package/dist/components/composites/settings/settings.d.ts.map +1 -1
- package/dist/components/composites/settings/settings.js +88 -37
- package/dist/components/composites/settings/settings.js.map +1 -1
- package/dist/components/composites/terminal/terminal.js +2 -2
- package/dist/components/composites/terminal/terminal.js.map +1 -1
- package/dist/components/composites/tree/tree.d.ts +6 -0
- package/dist/components/composites/tree/tree.d.ts.map +1 -1
- package/dist/components/composites/tree/tree.js +35 -14
- package/dist/components/composites/tree/tree.js.map +1 -1
- package/dist/components/composites/workspace-switcher/index.d.ts +2 -0
- package/dist/components/composites/workspace-switcher/index.d.ts.map +1 -0
- package/dist/components/composites/workspace-switcher/index.js +2 -0
- package/dist/components/composites/workspace-switcher/workspace-switcher.d.ts +44 -0
- package/dist/components/composites/workspace-switcher/workspace-switcher.d.ts.map +1 -0
- package/dist/components/composites/workspace-switcher/workspace-switcher.js +157 -0
- package/dist/components/composites/workspace-switcher/workspace-switcher.js.map +1 -0
- package/dist/components/layout/shell-rail/index.d.ts +2 -0
- package/dist/components/layout/shell-rail/index.d.ts.map +1 -0
- package/dist/components/layout/shell-rail/index.js +2 -0
- package/dist/components/layout/shell-rail/shell-rail.d.ts +36 -0
- package/dist/components/layout/shell-rail/shell-rail.d.ts.map +1 -0
- package/dist/components/layout/shell-rail/shell-rail.js +124 -0
- package/dist/components/layout/shell-rail/shell-rail.js.map +1 -0
- package/dist/components/layout/shell-top-bar/index.d.ts +2 -0
- package/dist/components/layout/shell-top-bar/index.d.ts.map +1 -0
- package/dist/components/layout/shell-top-bar/index.js +2 -0
- package/dist/components/layout/shell-top-bar/shell-top-bar.d.ts +68 -0
- package/dist/components/layout/shell-top-bar/shell-top-bar.d.ts.map +1 -0
- package/dist/components/layout/shell-top-bar/shell-top-bar.js +135 -0
- package/dist/components/layout/shell-top-bar/shell-top-bar.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -1
- package/dist/r/accent-picker.json +25 -0
- package/dist/r/icon-picker.json +37 -0
- package/dist/r/registry.json +141 -1
- package/dist/r/settings.json +3 -1
- package/dist/r/shell-rail.json +27 -0
- package/dist/r/shell-top-bar.json +23 -0
- package/dist/r/src/components/composites/accent-picker/accent-picker.tsx +106 -0
- package/dist/r/src/components/composites/accent-picker/index.ts +1 -0
- package/dist/r/src/components/composites/icon-picker/icon-picker.tsx +246 -0
- package/dist/r/src/components/composites/icon-picker/image-data-url.ts +107 -0
- package/dist/r/src/components/composites/icon-picker/index.ts +25 -0
- package/dist/r/src/components/composites/icon-picker/shell-icons.ts +166 -0
- package/dist/r/src/components/composites/settings/settings-navigation.tsx +1 -1
- package/dist/r/src/components/composites/settings/settings.tsx +40 -5
- package/dist/r/src/components/composites/tree/tree.tsx +25 -0
- package/dist/r/src/components/composites/workspace-switcher/index.ts +5 -0
- package/dist/r/src/components/composites/workspace-switcher/workspace-switcher.tsx +128 -0
- package/dist/r/src/components/layout/shell-rail/index.ts +1 -0
- package/dist/r/src/components/layout/shell-rail/shell-rail.tsx +120 -0
- package/dist/r/src/components/layout/shell-top-bar/index.ts +1 -0
- package/dist/r/src/components/layout/shell-top-bar/shell-top-bar.tsx +185 -0
- package/dist/r/workspace-switcher.json +26 -0
- package/package.json +1 -1
- package/registry.json +141 -1
- package/src/components/composites/accent-picker/accent-picker.tsx +106 -0
- package/src/components/composites/accent-picker/index.ts +1 -0
- package/src/components/composites/icon-picker/icon-picker.tsx +246 -0
- package/src/components/composites/icon-picker/image-data-url.ts +107 -0
- package/src/components/composites/icon-picker/index.ts +25 -0
- package/src/components/composites/icon-picker/shell-icons.ts +166 -0
- package/src/components/composites/settings/settings-navigation.tsx +1 -1
- package/src/components/composites/settings/settings.tsx +40 -5
- package/src/components/composites/tree/tree.tsx +25 -0
- package/src/components/composites/workspace-switcher/index.ts +5 -0
- package/src/components/composites/workspace-switcher/workspace-switcher.tsx +128 -0
- package/src/components/layout/shell-rail/index.ts +1 -0
- package/src/components/layout/shell-rail/shell-rail.tsx +120 -0
- package/src/components/layout/shell-top-bar/index.ts +1 -0
- package/src/components/layout/shell-top-bar/shell-top-bar.tsx +185 -0
- package/src/index.ts +5 -0
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { cn } from "../../../lib/utils.js";
|
|
2
2
|
import { Heading } from "../../ui/typography/typography.js";
|
|
3
3
|
import { FormFieldContext, createFormFieldContext } from "../../../lib/form-field.js";
|
|
4
|
+
import { Tooltip, TooltipContent, TooltipTrigger } from "../../ui/tooltip/tooltip.js";
|
|
4
5
|
import { className, createComponent, effect, insert, mergeProps, setAttribute, spread, template } from "solid-js/web";
|
|
6
|
+
import { CircleHelp } from "lucide-solid";
|
|
5
7
|
import { Show, createUniqueId, splitProps } from "solid-js";
|
|
6
8
|
//#region src/components/composites/settings/settings.tsx
|
|
7
9
|
var _tmpl$ = /*#__PURE__*/ template(`<p class="max-w-prose text-sm text-muted-foreground text-pretty">`);
|
|
8
10
|
var _tmpl$2 = /*#__PURE__*/ template(`<div class="flex shrink-0 items-center gap-2">`);
|
|
9
|
-
var _tmpl$3 = /*#__PURE__*/ template(`<section data-slot=settings-section><div class="flex items-start justify-between gap-4"><div class="flex min-w-0 flex-col gap-0.5"></div></div><div data-slot=settings-section-body>`);
|
|
10
|
-
var _tmpl$4 = /*#__PURE__*/ template(`<div data-slot=settings-row><div class="flex min-w-0 flex-col gap-0.5"><div data-slot=settings-row-label class="text-sm font-medium"></div></div><div data-slot=settings-row-control>`);
|
|
11
|
+
var _tmpl$3 = /*#__PURE__*/ template(`<section data-slot=settings-section><div class="flex items-start justify-between gap-4"><div class="flex min-w-0 flex-col gap-0.5"><div class="flex items-center gap-1.5"></div></div></div><div data-slot=settings-section-body>`);
|
|
12
|
+
var _tmpl$4 = /*#__PURE__*/ template(`<div data-slot=settings-row><div class="flex min-w-0 flex-col gap-0.5"><div class="flex items-center gap-1.5"><div data-slot=settings-row-label class="text-sm font-medium"></div></div></div><div data-slot=settings-row-control>`);
|
|
11
13
|
var _tmpl$5 = /*#__PURE__*/ template(`<div data-slot=settings-field><div class="flex flex-col gap-0.5"><label class="text-sm font-medium"></label></div><div>`);
|
|
12
14
|
var _tmpl$6 = /*#__PURE__*/ template(`<div data-slot=settings-page>`);
|
|
13
15
|
/**
|
|
@@ -24,35 +26,70 @@ var _tmpl$6 = /*#__PURE__*/ template(`<div data-slot=settings-page>`);
|
|
|
24
26
|
* the first control inside it. `SettingsField` is the visual stacked layout;
|
|
25
27
|
* use `FormField` when the control needs label, help, or validation wiring.
|
|
26
28
|
*/
|
|
29
|
+
function HelpTip(props) {
|
|
30
|
+
return createComponent(Tooltip, { get children() {
|
|
31
|
+
return [createComponent(TooltipTrigger, {
|
|
32
|
+
as: "button",
|
|
33
|
+
type: "button",
|
|
34
|
+
"data-slot": "settings-row-help",
|
|
35
|
+
get ["aria-label"]() {
|
|
36
|
+
return `About ${props.label}`;
|
|
37
|
+
},
|
|
38
|
+
"class": "inline-flex size-4 items-center justify-center rounded-full text-muted-foreground hover:text-foreground focus-visible:ring-3 focus-visible:ring-ring/50 focus-visible:outline-none",
|
|
39
|
+
get children() {
|
|
40
|
+
return createComponent(CircleHelp, {
|
|
41
|
+
"class": "size-3.5",
|
|
42
|
+
"aria-hidden": "true"
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}), createComponent(TooltipContent, { get children() {
|
|
46
|
+
return props.help;
|
|
47
|
+
} })];
|
|
48
|
+
} });
|
|
49
|
+
}
|
|
27
50
|
function SettingsSection(props) {
|
|
28
51
|
const [local, rest] = splitProps(props, [
|
|
29
52
|
"class",
|
|
30
53
|
"title",
|
|
31
54
|
"description",
|
|
55
|
+
"help",
|
|
32
56
|
"action",
|
|
33
57
|
"bodyLayout",
|
|
34
58
|
"children"
|
|
35
59
|
]);
|
|
36
60
|
return (() => {
|
|
37
|
-
var _el$ = _tmpl$3(), _el$2 = _el$.firstChild, _el$3 = _el$2.firstChild, _el$
|
|
61
|
+
var _el$ = _tmpl$3(), _el$2 = _el$.firstChild, _el$3 = _el$2.firstChild, _el$4 = _el$3.firstChild, _el$7 = _el$2.nextSibling;
|
|
38
62
|
spread(_el$, mergeProps({ get ["class"]() {
|
|
39
63
|
return cn("flex flex-col gap-4 px-5 py-5", local.class);
|
|
40
64
|
} }, rest), false, true);
|
|
41
|
-
insert(_el$
|
|
65
|
+
insert(_el$4, createComponent(Heading, {
|
|
42
66
|
as: "h2",
|
|
43
67
|
size: "card",
|
|
44
68
|
get children() {
|
|
45
69
|
return local.title;
|
|
46
70
|
}
|
|
47
71
|
}), null);
|
|
72
|
+
insert(_el$4, createComponent(Show, {
|
|
73
|
+
get when() {
|
|
74
|
+
return local.help;
|
|
75
|
+
},
|
|
76
|
+
children: (help) => createComponent(HelpTip, {
|
|
77
|
+
get label() {
|
|
78
|
+
return local.title;
|
|
79
|
+
},
|
|
80
|
+
get help() {
|
|
81
|
+
return help();
|
|
82
|
+
}
|
|
83
|
+
})
|
|
84
|
+
}), null);
|
|
48
85
|
insert(_el$3, createComponent(Show, {
|
|
49
86
|
get when() {
|
|
50
87
|
return local.description;
|
|
51
88
|
},
|
|
52
89
|
get children() {
|
|
53
|
-
var _el$
|
|
54
|
-
insert(_el$
|
|
55
|
-
return _el$
|
|
90
|
+
var _el$5 = _tmpl$();
|
|
91
|
+
insert(_el$5, () => local.description);
|
|
92
|
+
return _el$5;
|
|
56
93
|
}
|
|
57
94
|
}), null);
|
|
58
95
|
insert(_el$2, createComponent(Show, {
|
|
@@ -60,13 +97,13 @@ function SettingsSection(props) {
|
|
|
60
97
|
return local.action;
|
|
61
98
|
},
|
|
62
99
|
get children() {
|
|
63
|
-
var _el$
|
|
64
|
-
insert(_el$
|
|
65
|
-
return _el$
|
|
100
|
+
var _el$6 = _tmpl$2();
|
|
101
|
+
insert(_el$6, () => local.action);
|
|
102
|
+
return _el$6;
|
|
66
103
|
}
|
|
67
104
|
}), null);
|
|
68
|
-
insert(_el$
|
|
69
|
-
effect(() => className(_el$
|
|
105
|
+
insert(_el$7, () => local.children);
|
|
106
|
+
effect(() => className(_el$7, cn(local.bodyLayout === "content" ? "flex flex-col gap-4" : "divide-y divide-border rounded-xl border border-border [&>[data-slot=empty-description]]:p-4")));
|
|
70
107
|
return _el$;
|
|
71
108
|
})();
|
|
72
109
|
}
|
|
@@ -83,6 +120,7 @@ function SettingsRow(props) {
|
|
|
83
120
|
"class",
|
|
84
121
|
"label",
|
|
85
122
|
"description",
|
|
123
|
+
"help",
|
|
86
124
|
"orientation",
|
|
87
125
|
"bare",
|
|
88
126
|
"flush",
|
|
@@ -102,26 +140,39 @@ function SettingsRow(props) {
|
|
|
102
140
|
return createComponent(FormFieldContext.Provider, {
|
|
103
141
|
value: field,
|
|
104
142
|
get children() {
|
|
105
|
-
var _el$
|
|
106
|
-
spread(_el$
|
|
143
|
+
var _el$8 = _tmpl$4(), _el$9 = _el$8.firstChild, _el$0 = _el$9.firstChild, _el$1 = _el$0.firstChild, _el$11 = _el$9.nextSibling;
|
|
144
|
+
spread(_el$8, mergeProps({ get ["class"]() {
|
|
107
145
|
return cn("flex gap-4", local.flush ? "p-0" : "p-4", local.orientation === "vertical" ? "flex-col" : "flex-col sm:flex-row sm:items-center sm:justify-between", local.class);
|
|
108
146
|
} }, rest), false, true);
|
|
109
|
-
setAttribute(_el$
|
|
110
|
-
insert(_el$
|
|
111
|
-
insert(_el$
|
|
147
|
+
setAttribute(_el$1, "id", labelId);
|
|
148
|
+
insert(_el$1, () => local.label);
|
|
149
|
+
insert(_el$0, createComponent(Show, {
|
|
150
|
+
get when() {
|
|
151
|
+
return local.help;
|
|
152
|
+
},
|
|
153
|
+
children: (help) => createComponent(HelpTip, {
|
|
154
|
+
get label() {
|
|
155
|
+
return local.label;
|
|
156
|
+
},
|
|
157
|
+
get help() {
|
|
158
|
+
return help();
|
|
159
|
+
}
|
|
160
|
+
})
|
|
161
|
+
}), null);
|
|
162
|
+
insert(_el$9, createComponent(Show, {
|
|
112
163
|
get when() {
|
|
113
164
|
return local.description;
|
|
114
165
|
},
|
|
115
166
|
get children() {
|
|
116
|
-
var _el$
|
|
117
|
-
setAttribute(_el$
|
|
118
|
-
insert(_el$
|
|
119
|
-
return _el$
|
|
167
|
+
var _el$10 = _tmpl$();
|
|
168
|
+
setAttribute(_el$10, "id", descriptionId);
|
|
169
|
+
insert(_el$10, () => local.description);
|
|
170
|
+
return _el$10;
|
|
120
171
|
}
|
|
121
172
|
}), null);
|
|
122
|
-
insert(_el$
|
|
123
|
-
effect(() => className(_el$
|
|
124
|
-
return _el$
|
|
173
|
+
insert(_el$11, () => local.children);
|
|
174
|
+
effect(() => className(_el$11, cn("shrink-0", local.orientation === "vertical" && "w-full")));
|
|
175
|
+
return _el$8;
|
|
125
176
|
}
|
|
126
177
|
});
|
|
127
178
|
}
|
|
@@ -135,35 +186,35 @@ function SettingsField(props) {
|
|
|
135
186
|
"children"
|
|
136
187
|
]);
|
|
137
188
|
return (() => {
|
|
138
|
-
var _el$
|
|
139
|
-
spread(_el$
|
|
189
|
+
var _el$12 = _tmpl$5(), _el$13 = _el$12.firstChild, _el$14 = _el$13.firstChild, _el$16 = _el$13.nextSibling;
|
|
190
|
+
spread(_el$12, mergeProps({ get ["class"]() {
|
|
140
191
|
return cn("flex flex-col gap-2 p-4", local.class);
|
|
141
192
|
} }, rest), false, true);
|
|
142
|
-
insert(_el$
|
|
143
|
-
insert(_el$
|
|
193
|
+
insert(_el$14, () => local.label);
|
|
194
|
+
insert(_el$13, createComponent(Show, {
|
|
144
195
|
get when() {
|
|
145
196
|
return local.description;
|
|
146
197
|
},
|
|
147
198
|
get children() {
|
|
148
|
-
var _el$
|
|
149
|
-
insert(_el$
|
|
150
|
-
return _el$
|
|
199
|
+
var _el$15 = _tmpl$();
|
|
200
|
+
insert(_el$15, () => local.description);
|
|
201
|
+
return _el$15;
|
|
151
202
|
}
|
|
152
203
|
}), null);
|
|
153
|
-
insert(_el$
|
|
154
|
-
effect(() => setAttribute(_el$
|
|
155
|
-
return _el$
|
|
204
|
+
insert(_el$16, () => local.children);
|
|
205
|
+
effect(() => setAttribute(_el$14, "for", local.htmlFor));
|
|
206
|
+
return _el$12;
|
|
156
207
|
})();
|
|
157
208
|
}
|
|
158
209
|
/** A settings page's scrolling body, with the header sticky at the top. */
|
|
159
210
|
function SettingsPage(props) {
|
|
160
211
|
const [local, rest] = splitProps(props, ["class"]);
|
|
161
212
|
return (() => {
|
|
162
|
-
var _el$
|
|
163
|
-
spread(_el$
|
|
213
|
+
var _el$17 = _tmpl$6();
|
|
214
|
+
spread(_el$17, mergeProps({ get ["class"]() {
|
|
164
215
|
return cn("flex min-h-0 flex-1 flex-col overflow-y-auto", local.class);
|
|
165
216
|
} }, rest), false, false);
|
|
166
|
-
return _el$
|
|
217
|
+
return _el$17;
|
|
167
218
|
})();
|
|
168
219
|
}
|
|
169
220
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings.js","names":["ComponentProps","JSX","createUniqueId","Show","splitProps","createFormFieldContext","FormFieldContext","cn","Heading","SettingsSection","props","title","description","action","Element","bodyLayout","local","rest","_el$","_tmpl$3","_el$2","firstChild","_el$3","_el$6","nextSibling","_$spread","_$mergeProps","class","_$insert","_$createComponent","as","size","children","when","_el$4","_tmpl$","_el$5","_tmpl$2","_$effect","_$className","SettingsRow","label","orientation","bare","flush","rowId","labelId","descriptionId","field","defaultControlId","hint","error","undefined","group","Provider","value","_el$7","_tmpl$4","_el$8","_el$9","_el$1","_$setAttribute","_el$0","SettingsField","htmlFor","_el$10","_tmpl$5","_el$11","_el$12","_el$14","_el$13","SettingsPage","_el$15","_tmpl$6","_$mergeProps","_$createComponent","_$className","_$setAttribute"],"sources":["../../../../src/components/composites/settings/settings.tsx"],"sourcesContent":["import type { ComponentProps, JSX } from 'solid-js'\nimport { createUniqueId, Show, splitProps } from 'solid-js'\nimport { createFormFieldContext, FormFieldContext } from '#lib/form-field'\nimport { cn } from '#lib/utils'\nimport { Heading } from '../../ui/typography'\n\n/**\n * SettingsSection and SettingsRow.\n *\n * A settings page is the most repetitive surface in any application, and the\n * one where drift is most visible: label sizes, control widths and description\n * placement all wander unless something fixes them.\n *\n * The row puts the label and description at the start and the control at the\n * end (stacked on a narrow window), so controls line up down the page's end\n * edge regardless of how long the labels are. `SettingsRow` also\n * exposes its label and description through the shared form-field context to\n * the first control inside it. `SettingsField` is the visual stacked layout;\n * use `FormField` when the control needs label, help, or validation wiring.\n */\nexport function SettingsSection(\n props: ComponentProps<'section'> & {\n title: string\n description?: string\n /** A control for the section as a whole, e.g. a master toggle. */\n action?: JSX.Element\n /** Use a spaced content stack for fields, alerts, and cards instead of divided rows. */\n bodyLayout?: 'rows' | 'content'\n }\n) {\n const [local, rest] = splitProps(props, [\n 'class',\n 'title',\n 'description',\n 'action',\n 'bodyLayout',\n 'children',\n ])\n\n return (\n <section\n data-slot=\"settings-section\"\n class={cn('flex flex-col gap-4 px-5 py-5', local.class)}\n {...rest}\n >\n <div class=\"flex items-start justify-between gap-4\">\n <div class=\"flex min-w-0 flex-col gap-0.5\">\n <Heading as=\"h2\" size=\"card\">\n {local.title}\n </Heading>\n <Show when={local.description}>\n <p class=\"max-w-prose text-sm text-muted-foreground text-pretty\">{local.description}</p>\n </Show>\n </div>\n <Show when={local.action}>\n <div class=\"flex shrink-0 items-center gap-2\">{local.action}</div>\n </Show>\n </div>\n <div\n data-slot=\"settings-section-body\"\n class={cn(\n local.bodyLayout === 'content'\n ? 'flex flex-col gap-4'\n : 'divide-y divide-border rounded-xl border border-border [&>[data-slot=empty-description]]:p-4'\n )}\n >\n {local.children}\n </div>\n </section>\n )\n}\n\n/**\n * One setting: a label and description on the leading side, a control on the\n * trailing side.\n *\n * The label and description are linked to a shared control through field\n * context. An explicit `aria-label` or `aria-labelledby` on the control keeps\n * precedence; otherwise the visible row label names it.\n */\nexport function SettingsRow(\n props: ComponentProps<'div'> & {\n label: string\n description?: string\n /** Render a vertical stack when the control needs the full width. */\n orientation?: 'horizontal' | 'vertical'\n /** Hide the divider this row would otherwise contribute. */\n bare?: boolean\n /**\n * Drop the row's own 16px padding so its label and control sit on the same\n * edges as the fields around it. For a row placed loose in a\n * `bodyLayout=\"content\"` section, where nothing encloses it and the section's\n * gap already spaces it from its neighbours. Leave it off inside a divided\n * rows body or a `Card`, whose edge the padding is there to clear.\n */\n flush?: boolean\n }\n) {\n const [local, rest] = splitProps(props, [\n 'class',\n 'label',\n 'description',\n 'orientation',\n 'bare',\n 'flush',\n 'children',\n ])\n const rowId = createUniqueId()\n const labelId = `${rowId}-label`\n const descriptionId = `${rowId}-description`\n const field = createFormFieldContext({\n defaultControlId: rowId,\n labelId,\n descriptionId,\n hint: () => local.description,\n error: () => undefined,\n group: () => false,\n })\n\n return (\n <FormFieldContext.Provider value={field}>\n <div\n data-slot=\"settings-row\"\n class={cn(\n 'flex gap-4',\n local.flush ? 'p-0' : 'p-4',\n local.orientation === 'vertical'\n ? 'flex-col'\n : 'flex-col sm:flex-row sm:items-center sm:justify-between',\n local.class\n )}\n {...rest}\n >\n <div class=\"flex min-w-0 flex-col gap-0.5\">\n <div id={labelId} data-slot=\"settings-row-label\" class=\"text-sm font-medium\">\n {local.label}\n </div>\n <Show when={local.description}>\n <p id={descriptionId} class=\"max-w-prose text-sm text-muted-foreground text-pretty\">\n {local.description}\n </p>\n </Show>\n </div>\n <div\n data-slot=\"settings-row-control\"\n class={cn('shrink-0', local.orientation === 'vertical' && 'w-full')}\n >\n {local.children}\n </div>\n </div>\n </FormFieldContext.Provider>\n )\n}\n\n/** A stacked label-and-control pair, for a control too wide for a row. */\nexport function SettingsField(\n props: ComponentProps<'div'> & { label: string; description?: string; htmlFor?: string }\n) {\n const [local, rest] = splitProps(props, ['class', 'label', 'description', 'htmlFor', 'children'])\n\n return (\n <div data-slot=\"settings-field\" class={cn('flex flex-col gap-2 p-4', local.class)} {...rest}>\n <div class=\"flex flex-col gap-0.5\">\n <label for={local.htmlFor} class=\"text-sm font-medium\">\n {local.label}\n </label>\n <Show when={local.description}>\n <p class=\"max-w-prose text-sm text-muted-foreground text-pretty\">{local.description}</p>\n </Show>\n </div>\n <div>{local.children}</div>\n </div>\n )\n}\n\n/** A settings page's scrolling body, with the header sticky at the top. */\nexport function SettingsPage(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"settings-page\"\n class={cn('flex min-h-0 flex-1 flex-col overflow-y-auto', local.class)}\n {...rest}\n />\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"settings.js","names":["CircleHelp","ComponentProps","JSX","createUniqueId","Show","splitProps","createFormFieldContext","FormFieldContext","cn","Tooltip","TooltipContent","TooltipTrigger","Heading","HelpTip","props","label","help","_$createComponent","children","as","type","aria-label","SettingsSection","title","description","action","Element","bodyLayout","local","rest","_el$","_tmpl$3","_el$2","firstChild","_el$3","_el$4","_el$7","nextSibling","_$spread","_$mergeProps","class","_$insert","size","when","_el$5","_tmpl$","_el$6","_tmpl$2","_$effect","_$className","SettingsRow","orientation","bare","flush","rowId","labelId","descriptionId","field","defaultControlId","hint","error","undefined","group","Provider","value","_el$8","_tmpl$4","_el$9","_el$0","_el$1","_el$11","_$setAttribute","_el$10","SettingsField","htmlFor","_el$12","_tmpl$5","_el$13","_el$14","_el$16","_el$15","SettingsPage","_el$17","_tmpl$6","_$createComponent","_$mergeProps","_$className","_$setAttribute"],"sources":["../../../../src/components/composites/settings/settings.tsx"],"sourcesContent":["import { CircleHelp } from 'lucide-solid'\nimport type { ComponentProps, JSX } from 'solid-js'\nimport { createUniqueId, Show, splitProps } from 'solid-js'\nimport { createFormFieldContext, FormFieldContext } from '#lib/form-field'\nimport { cn } from '#lib/utils'\nimport { Tooltip, TooltipContent, TooltipTrigger } from '../../ui/tooltip'\nimport { Heading } from '../../ui/typography'\n\n/**\n * SettingsSection and SettingsRow.\n *\n * A settings page is the most repetitive surface in any application, and the\n * one where drift is most visible: label sizes, control widths and description\n * placement all wander unless something fixes them.\n *\n * The row puts the label and description at the start and the control at the\n * end (stacked on a narrow window), so controls line up down the page's end\n * edge regardless of how long the labels are. `SettingsRow` also\n * exposes its label and description through the shared form-field context to\n * the first control inside it. `SettingsField` is the visual stacked layout;\n * use `FormField` when the control needs label, help, or validation wiring.\n */\nfunction HelpTip(props: { label: string; help: string }) {\n return (\n <Tooltip>\n <TooltipTrigger\n as=\"button\"\n type=\"button\"\n data-slot=\"settings-row-help\"\n aria-label={`About ${props.label}`}\n class=\"inline-flex size-4 items-center justify-center rounded-full text-muted-foreground hover:text-foreground focus-visible:ring-3 focus-visible:ring-ring/50 focus-visible:outline-none\"\n >\n <CircleHelp class=\"size-3.5\" aria-hidden=\"true\" />\n </TooltipTrigger>\n <TooltipContent>{props.help}</TooltipContent>\n </Tooltip>\n )\n}\n\nexport function SettingsSection(\n props: ComponentProps<'section'> & {\n title: string\n description?: string\n /** A short explanation behind a help icon beside the title; prefer it to a long description. */\n help?: string\n /** A control for the section as a whole, e.g. a master toggle. */\n action?: JSX.Element\n /** Use a spaced content stack for fields, alerts, and cards instead of divided rows. */\n bodyLayout?: 'rows' | 'content'\n }\n) {\n const [local, rest] = splitProps(props, [\n 'class',\n 'title',\n 'description',\n 'help',\n 'action',\n 'bodyLayout',\n 'children',\n ])\n\n return (\n <section\n data-slot=\"settings-section\"\n class={cn('flex flex-col gap-4 px-5 py-5', local.class)}\n {...rest}\n >\n <div class=\"flex items-start justify-between gap-4\">\n <div class=\"flex min-w-0 flex-col gap-0.5\">\n <div class=\"flex items-center gap-1.5\">\n <Heading as=\"h2\" size=\"card\">\n {local.title}\n </Heading>\n <Show when={local.help}>{(help) => <HelpTip label={local.title} help={help()} />}</Show>\n </div>\n <Show when={local.description}>\n <p class=\"max-w-prose text-sm text-muted-foreground text-pretty\">{local.description}</p>\n </Show>\n </div>\n <Show when={local.action}>\n <div class=\"flex shrink-0 items-center gap-2\">{local.action}</div>\n </Show>\n </div>\n <div\n data-slot=\"settings-section-body\"\n class={cn(\n local.bodyLayout === 'content'\n ? 'flex flex-col gap-4'\n : 'divide-y divide-border rounded-xl border border-border [&>[data-slot=empty-description]]:p-4'\n )}\n >\n {local.children}\n </div>\n </section>\n )\n}\n\n/**\n * One setting: a label and description on the leading side, a control on the\n * trailing side.\n *\n * The label and description are linked to a shared control through field\n * context. An explicit `aria-label` or `aria-labelledby` on the control keeps\n * precedence; otherwise the visible row label names it.\n */\nexport function SettingsRow(\n props: ComponentProps<'div'> & {\n label: string\n description?: string\n /**\n * A short explanation behind a help icon beside the label. Prefer it to a\n * long description: the row stays quiet and the explanation is one hover or\n * focus away.\n */\n help?: string\n /** Render a vertical stack when the control needs the full width. */\n orientation?: 'horizontal' | 'vertical'\n /** Hide the divider this row would otherwise contribute. */\n bare?: boolean\n /**\n * Drop the row's own 16px padding so its label and control sit on the same\n * edges as the fields around it. For a row placed loose in a\n * `bodyLayout=\"content\"` section, where nothing encloses it and the section's\n * gap already spaces it from its neighbours. Leave it off inside a divided\n * rows body or a `Card`, whose edge the padding is there to clear.\n */\n flush?: boolean\n }\n) {\n const [local, rest] = splitProps(props, [\n 'class',\n 'label',\n 'description',\n 'help',\n 'orientation',\n 'bare',\n 'flush',\n 'children',\n ])\n const rowId = createUniqueId()\n const labelId = `${rowId}-label`\n const descriptionId = `${rowId}-description`\n const field = createFormFieldContext({\n defaultControlId: rowId,\n labelId,\n descriptionId,\n hint: () => local.description,\n error: () => undefined,\n group: () => false,\n })\n\n return (\n <FormFieldContext.Provider value={field}>\n <div\n data-slot=\"settings-row\"\n class={cn(\n 'flex gap-4',\n local.flush ? 'p-0' : 'p-4',\n local.orientation === 'vertical'\n ? 'flex-col'\n : 'flex-col sm:flex-row sm:items-center sm:justify-between',\n local.class\n )}\n {...rest}\n >\n <div class=\"flex min-w-0 flex-col gap-0.5\">\n <div class=\"flex items-center gap-1.5\">\n <div id={labelId} data-slot=\"settings-row-label\" class=\"text-sm font-medium\">\n {local.label}\n </div>\n <Show when={local.help}>{(help) => <HelpTip label={local.label} help={help()} />}</Show>\n </div>\n <Show when={local.description}>\n <p id={descriptionId} class=\"max-w-prose text-sm text-muted-foreground text-pretty\">\n {local.description}\n </p>\n </Show>\n </div>\n <div\n data-slot=\"settings-row-control\"\n class={cn('shrink-0', local.orientation === 'vertical' && 'w-full')}\n >\n {local.children}\n </div>\n </div>\n </FormFieldContext.Provider>\n )\n}\n\n/** A stacked label-and-control pair, for a control too wide for a row. */\nexport function SettingsField(\n props: ComponentProps<'div'> & { label: string; description?: string; htmlFor?: string }\n) {\n const [local, rest] = splitProps(props, ['class', 'label', 'description', 'htmlFor', 'children'])\n\n return (\n <div data-slot=\"settings-field\" class={cn('flex flex-col gap-2 p-4', local.class)} {...rest}>\n <div class=\"flex flex-col gap-0.5\">\n <label for={local.htmlFor} class=\"text-sm font-medium\">\n {local.label}\n </label>\n <Show when={local.description}>\n <p class=\"max-w-prose text-sm text-muted-foreground text-pretty\">{local.description}</p>\n </Show>\n </div>\n <div>{local.children}</div>\n </div>\n )\n}\n\n/** A settings page's scrolling body, with the header sticky at the top. */\nexport function SettingsPage(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"settings-page\"\n class={cn('flex min-h-0 flex-1 flex-col overflow-y-auto', local.class)}\n {...rest}\n />\n )\n}\n"],"mappings":"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"}
|
|
@@ -155,7 +155,7 @@ function StatusReadout(props) {
|
|
|
155
155
|
return _el$8;
|
|
156
156
|
})();
|
|
157
157
|
}
|
|
158
|
-
function Terminal(props) {
|
|
158
|
+
function Terminal$1(props) {
|
|
159
159
|
const [local, rest] = splitProps(props, [
|
|
160
160
|
"output",
|
|
161
161
|
"command",
|
|
@@ -495,6 +495,6 @@ function Terminal(props) {
|
|
|
495
495
|
})();
|
|
496
496
|
}
|
|
497
497
|
//#endregion
|
|
498
|
-
export { TERMINAL_MAX_LINES, Terminal };
|
|
498
|
+
export { TERMINAL_MAX_LINES, Terminal$1 as Terminal };
|
|
499
499
|
|
|
500
500
|
//# sourceMappingURL=terminal.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"terminal.js","names":["ArrowDown","Check","CircleAlert","CircleSlash","Copy","Eraser","LoaderCircle","createEffect","createMemo","createSignal","For","on","Show","splitProps","ComponentProps","writeClipboardText","cn","Button","createAnsiParser","isPlainStyle","resolveColors","AnsiLine","AnsiStyle","isAtBottom","isFailedExit","revealEarlier","terminalStatusLabel","terminalWindow","TerminalStatus","TerminalProps","Omit","output","command","status","maxLines","retainLines","maxHeight","wrap","size","onClear","copyLabel","copiedLabel","clearLabel","onCopy","ok","TERMINAL_MAX_LINES","FG_CLASS","const","BG_CLASS","segmentClass","style","fg","bg","bold","dim","italic","underline","strike","LineView","props","line","_el$","_tmpl$2","_$insert","_$createComponent","each","segments","children","segment","text","_el$7","_tmpl$3","_$effect","_$className","when","truncated","_el$2","_tmpl$","_el$3","firstChild","_el$6","nextSibling","_el$5","toLocaleString","sameAnsiLine","left","right","length","every","index","StatusReadout","_el$8","_tmpl$5","state","_el$9","_tmpl$4","fallback","_p$","_v$","_v$2","e","_$setAttribute","t","undefined","Terminal","local","rest","small","pageSize","Math","max","floor","newParser","parser","consumed","epoch","revision","next","startsWith","write","slice","equals","limit","setLimit","defer","empty","outputRows","rows","lines","open","openLine","push","parked","setParked","end","total","droppedLines","anchorEnd","current","position","lineWindow","visibleRows","start","retainedIndex","changedParkedLine","newerRows","later","scroller","HTMLDivElement","following","onScroll","atEnd","scrollHeight","scrollTop","clientHeight","currentEpoch","jumpToLatest","focus","copied","setCopied","copyFailed","setCopyFailed","copy","setTimeout","regionLabel","_el$0","_tmpl$0","_el$1","_el$13","_el$16","_el$17","_$spread","_$mergeProps","data-size","aria-busy","class","_tmpl$1","_el$10","_tmpl$6","_el$11","_el$12","_$memo","variant","aria-label","onClick","title","hidden","evicted","_el$14","_tmpl$7","_el$15","lost","revealable","min","addEventListener","_$use","element","_el$26","_tmpl$10","_el$27","_el$18","_tmpl$8","_el$19","_tmpl$9","_el$20","_el$23","_el$21","_el$24","_el$22","_v$3","_v$4","_v$5","a","_$setStyleProperty","_$createComponent","_$className","_$setAttribute","_$mergeProps","_$memo","_$setStyleProperty"],"sources":["../../../../src/components/composites/terminal/terminal.tsx"],"sourcesContent":["import {\n ArrowDown,\n Check,\n CircleAlert,\n CircleSlash,\n Copy,\n Eraser,\n LoaderCircle,\n} from 'lucide-solid'\nimport {\n createEffect,\n createMemo,\n createSignal,\n For,\n on,\n Show,\n splitProps,\n type ComponentProps,\n} from 'solid-js'\nimport { writeClipboardText } from '#lib/clipboard'\nimport { cn } from '#lib/utils'\nimport { Button } from '../../ui/button'\nimport {\n createAnsiParser,\n isPlainStyle,\n resolveColors,\n type AnsiLine,\n type AnsiStyle,\n} from './ansi'\nimport {\n isAtBottom,\n isFailedExit,\n revealEarlier,\n terminalStatusLabel,\n terminalWindow,\n type TerminalStatus,\n} from './terminal-model'\n\n/**\n * Terminal.\n *\n * A command and its output, as it arrives. It is the thing to put inside an\n * agent's \"ran a command\" line (a `TraceLine`, with `size=\"sm\"`) when the output\n * is the evidence; reach for `CodeBlock` instead when the text is source or a\n * finished log that needs no live behaviour, and for `TestResults` when the\n * output is a test run the host can structure.\n *\n * It does not wrap `CodeBlock`. A block's `highlight` seam re-renders the whole\n * body whenever the code changes, which is exactly wrong for output that grows a\n * line at a time, and a terminal has to own its scroller to follow the tail. It\n * keeps the block's header and surface vocabulary so the two read as one family.\n *\n * ## What the output is allowed to do\n *\n * Output is untrusted bytes. It is parsed by `createAnsiParser` into plain text\n * and a fixed set of styles — sixteen theme colours, bold, dim, italic,\n * underline, strike-through, reverse — and everything else (cursor movement,\n * title and clipboard sequences, anything malformed) is dropped, never echoed.\n * Colours come from the theme's `--terminal-ansi-*` tokens, painted on the\n * theme's own terminal background, so a program's colours keep the contrast the\n * theme measured for them. Nothing is rendered as markup.\n *\n * ## Streaming\n *\n * `output` is the whole string so far. When the new value begins with the old\n * one, only the appended text is parsed, so a chunk costs the size of the chunk\n * and not of the transcript. Finished lines are keyed by identity and are never\n * re-rendered; only the line still being written changes, which is what makes a\n * `\\r` progress bar redraw in place. Batch appends per frame — the host sees a\n * prefix check proportional to the output on every change.\n *\n * Only the last `maxLines` finished lines are mounted. The rest are counted in\n * an explicit note with a control to show them a page at a time, because tens of\n * thousands of row elements are a frozen page, not a transcript. Copy still\n * writes `output` exactly as given — not the rendered lines, not the visible tail.\n *\n * ## Following the tail\n *\n * The terminal scrolls inside its own bounded box and follows new output only\n * while the reader is at the bottom of that box. Scrolling up *parks* the view:\n * the lines mounted are the ones that were there when they left, however much\n * output arrives, and \"Jump to latest\" is the only way back to the tail (reaching\n * the bottom of a parked view with nothing newer resumes it, because nothing was\n * missed). If retention discards the lines they were reading the note says how\n * many, and when none are left the oldest retained lines are shown. The page\n * itself is never scrolled. Scrolling is instant, so there is no animation to\n * reduce.\n *\n * ## Status is a claim\n *\n * `status` is drawn only when the host passes it, in words as well as an icon,\n * and only a non-zero exit is toned as a failure: this component does not decide\n * that a command \"passed\". Without a status the header says nothing about whether\n * the command is still running. `onClear` adds a clear button; without it the\n * output is the host's record and nothing here offers to erase it.\n */\nexport type TerminalProps = Omit<ComponentProps<'div'>, 'children'> & {\n /** Everything the command has printed so far, exactly as received. */\n output: string\n /** The command line. Shown as text; the prompt glyph is decoration. */\n command?: string\n status?: TerminalStatus\n /** Finished lines mounted at once; earlier ones are counted and revealed a page at a time. */\n maxLines?: number\n /** Finished lines kept at all; older ones are discarded and counted. Default 200 000. */\n retainLines?: number\n /** Height of the output box, which scrolls past it. A number is pixels. Default `20rem`. */\n maxHeight?: number | string\n /** Soft-wrap long lines instead of scrolling sideways. Off: terminal columns keep their alignment. */\n wrap?: boolean\n /** `sm` is the compact chrome for output nested inside a Trace line. */\n size?: 'default' | 'sm'\n /** Show a clear button. The host empties `output`; the terminal erases nothing itself. */\n onClear?: () => void\n copyLabel?: string\n copiedLabel?: string\n clearLabel?: string\n /** Called after each copy attempt with whether the clipboard accepted it. */\n onCopy?: (ok: boolean) => void\n}\n\n/** Finished lines mounted by default. */\nexport const TERMINAL_MAX_LINES = 1000\n\n// One literal class per colour, written out in full so the stylesheet generator\n// can see each of them; a class assembled from an index would never be emitted.\nconst FG_CLASS = [\n 'text-(color:--terminal-ansi-black)',\n 'text-(color:--terminal-ansi-red)',\n 'text-(color:--terminal-ansi-green)',\n 'text-(color:--terminal-ansi-yellow)',\n 'text-(color:--terminal-ansi-blue)',\n 'text-(color:--terminal-ansi-magenta)',\n 'text-(color:--terminal-ansi-cyan)',\n 'text-(color:--terminal-ansi-white)',\n 'text-(color:--terminal-ansi-bright-black)',\n 'text-(color:--terminal-ansi-bright-red)',\n 'text-(color:--terminal-ansi-bright-green)',\n 'text-(color:--terminal-ansi-bright-yellow)',\n 'text-(color:--terminal-ansi-bright-blue)',\n 'text-(color:--terminal-ansi-bright-magenta)',\n 'text-(color:--terminal-ansi-bright-cyan)',\n 'text-(color:--terminal-ansi-bright-white)',\n] as const\nconst BG_CLASS = [\n 'bg-(--terminal-ansi-black)',\n 'bg-(--terminal-ansi-red)',\n 'bg-(--terminal-ansi-green)',\n 'bg-(--terminal-ansi-yellow)',\n 'bg-(--terminal-ansi-blue)',\n 'bg-(--terminal-ansi-magenta)',\n 'bg-(--terminal-ansi-cyan)',\n 'bg-(--terminal-ansi-white)',\n 'bg-(--terminal-ansi-bright-black)',\n 'bg-(--terminal-ansi-bright-red)',\n 'bg-(--terminal-ansi-bright-green)',\n 'bg-(--terminal-ansi-bright-yellow)',\n 'bg-(--terminal-ansi-bright-blue)',\n 'bg-(--terminal-ansi-bright-magenta)',\n 'bg-(--terminal-ansi-bright-cyan)',\n 'bg-(--terminal-ansi-bright-white)',\n] as const\n\nfunction segmentClass(style: AnsiStyle): string {\n const { fg, bg } = resolveColors(style)\n return cn(\n {\n 'font-bold': style.bold,\n 'opacity-70': style.dim,\n italic: style.italic,\n underline: style.underline && !style.strike,\n 'line-through': style.strike && !style.underline,\n '[text-decoration-line:underline_line-through]': style.underline && style.strike,\n 'text-(color:--terminal-background)': fg === 'default-bg',\n 'bg-(--terminal-foreground)': bg === 'default-fg',\n },\n typeof fg === 'number' && FG_CLASS[fg],\n typeof bg === 'number' && BG_CLASS[bg]\n )\n}\n\nfunction LineView(props: { line: AnsiLine; wrap: boolean }) {\n return (\n // `min-h-lh` keeps an empty line one line tall; a block with no text would\n // collapse and the transcript would lose its blank lines.\n <div\n class={cn('min-h-lh', {\n 'whitespace-pre-wrap [overflow-wrap:anywhere]': props.wrap,\n 'w-max min-w-full': !props.wrap,\n })}\n >\n <For each={props.line.segments}>\n {(segment) =>\n isPlainStyle(segment.style) ? (\n segment.text\n ) : (\n <span class={segmentClass(segment.style)}>{segment.text}</span>\n )\n }\n </For>\n <Show when={props.line.truncated > 0}>\n <span class=\"opacity-70 select-none\">\n {' '}\n … {props.line.truncated.toLocaleString()} more characters not shown\n </span>\n </Show>\n </div>\n )\n}\n\nfunction sameAnsiLine(left: AnsiLine, right: AnsiLine): boolean {\n return (\n left.truncated === right.truncated &&\n left.segments.length === right.segments.length &&\n left.segments.every(\n (segment, index) =>\n segment.text === right.segments[index]?.text &&\n segment.style === right.segments[index]?.style\n )\n )\n}\n\nfunction StatusReadout(props: { status: TerminalStatus }) {\n return (\n // A live region, so a command that finishes while the reader is elsewhere is\n // announced once, in words.\n <span\n role=\"status\"\n data-slot=\"terminal-status\"\n data-state={props.status.state}\n class={cn('flex shrink-0 items-center gap-1 text-xs', {\n 'text-destructive': isFailedExit(props.status),\n 'text-info': props.status.state === 'running',\n 'text-muted-foreground': props.status.state !== 'running' && !isFailedExit(props.status),\n })}\n >\n {/* A zero exit gets no glyph: a tick would be this component deciding the\n command succeeded, and some tools exit non-zero on purpose or zero on\n failure. The words carry the fact; only a non-zero code is toned. */}\n <Show when={props.status.state !== 'exited' || isFailedExit(props.status)}>\n <span aria-hidden=\"true\" class=\"grid size-3.5 place-items-center [&_svg]:size-3.5\">\n <Show\n when={props.status.state === 'running'}\n fallback={\n <Show when={props.status.state === 'cancelled'} fallback={<CircleAlert />}>\n <CircleSlash />\n </Show>\n }\n >\n <LoaderCircle class=\"motion-safe:animate-spin\" />\n </Show>\n </span>\n </Show>\n {terminalStatusLabel(props.status)}\n </span>\n )\n}\n\nexport function Terminal(props: TerminalProps) {\n const [local, rest] = splitProps(props, [\n 'output',\n 'command',\n 'status',\n 'maxLines',\n 'retainLines',\n 'maxHeight',\n 'wrap',\n 'size',\n 'onClear',\n 'copyLabel',\n 'copiedLabel',\n 'clearLabel',\n 'onCopy',\n 'class',\n ])\n\n const small = () => local.size === 'sm'\n const pageSize = () => Math.max(1, Math.floor(local.maxLines ?? TERMINAL_MAX_LINES))\n const maxHeight = () =>\n typeof local.maxHeight === 'number' ? `${local.maxHeight}px` : (local.maxHeight ?? '20rem')\n\n // The parser outlives renders: it holds the half-read escape sequence, the\n // current style and the open line. A new `output` that extends the old one is\n // fed only its tail; anything else (a clear, a different command) starts over.\n const newParser = () => createAnsiParser({ retainLines: local.retainLines })\n let parser = newParser()\n let consumed = ''\n // Bumped when the output restarts, so a parked position from the old output\n // is never applied to the new one.\n let epoch = 0\n const revision = createMemo(\n () => {\n const next = local.output\n if (next.length >= consumed.length && next.startsWith(consumed)) {\n parser.write(next.slice(consumed.length))\n } else {\n parser = newParser()\n parser.write(next)\n epoch += 1\n }\n consumed = next\n return epoch\n },\n undefined,\n { equals: false }\n )\n\n const [limit, setLimit] = createSignal(pageSize())\n createEffect(on(pageSize, (size) => setLimit(size), { defer: true }))\n // A cleared terminal is a fresh one: the next command starts at the page size.\n createEffect(\n on(\n () => local.output === '',\n (empty) => {\n if (empty) setLimit(pageSize())\n },\n { defer: true }\n )\n )\n\n const outputRows = createMemo(\n () => {\n revision()\n const rows = parser.lines.slice()\n const open = parser.openLine()\n if (open) rows.push(open)\n return rows\n },\n [],\n { equals: false }\n )\n // Where the reader parked, as a count of lines since the output began. An open\n // line is a row too: freeze its snapshot so streamed characters and CR redraws\n // do not rewrite the text under a parked reader.\n const [parked, setParked] = createSignal<{ epoch: number; end: number; open?: AnsiLine }>()\n const total = () => parser.droppedLines + outputRows().length\n const anchorEnd = () => {\n const current = revision()\n const position = parked()\n return position && position.epoch === current ? position.end : undefined\n }\n const lineWindow = createMemo(() => {\n revision()\n return terminalWindow(outputRows().length, parser.droppedLines, limit(), anchorEnd())\n })\n // Finished rows keep their parser identity. If an open row existed when the\n // reader parked, substitute its immutable snapshot until they jump to latest.\n const visibleRows = createMemo(\n () => {\n revision()\n const start = lineWindow().start\n const end = lineWindow().end\n const rows = outputRows().slice(start, end)\n const position = parked()\n if (position?.epoch === revision() && position.open) {\n const retainedIndex = position.end - 1 - parser.droppedLines\n if (retainedIndex >= start && retainedIndex < end) {\n rows[retainedIndex - start] = position.open\n }\n }\n return rows\n },\n [],\n { equals: false }\n )\n const changedParkedLine = () => {\n const position = parked()\n if (position?.epoch !== revision() || !position.open) return false\n const retainedIndex = position.end - 1 - parser.droppedLines\n const current = outputRows()[retainedIndex]\n return current !== undefined && !sameAnsiLine(position.open, current)\n }\n const newerRows = () => lineWindow().later + (changedParkedLine() ? 1 : 0)\n\n let scroller: HTMLDivElement | undefined\n const following = () => anchorEnd() === undefined\n\n const onScroll = () => {\n if (!scroller) return\n const atEnd = isAtBottom(scroller.scrollHeight, scroller.scrollTop, scroller.clientHeight)\n const position = anchorEnd()\n if (!atEnd) {\n if (position === undefined) {\n const currentEpoch = revision()\n setParked({ epoch: currentEpoch, end: total(), open: parser.openLine() })\n }\n } else if (position !== undefined && position >= total() && !changedParkedLine()) {\n // Back at the end of a view with nothing newer: nothing was missed.\n setParked(undefined)\n }\n }\n createEffect(\n on(revision, () => {\n if (scroller && following()) scroller.scrollTop = scroller.scrollHeight\n })\n )\n const jumpToLatest = () => {\n if (!scroller) return\n setParked(undefined)\n scroller.scrollTop = scroller.scrollHeight\n // The button is about to disappear; leave focus somewhere real.\n scroller.focus()\n }\n\n const [copied, setCopied] = createSignal(false)\n const [copyFailed, setCopyFailed] = createSignal(false)\n const copy = async () => {\n let ok = true\n try {\n await writeClipboardText(local.output)\n } catch {\n ok = false\n }\n setCopied(ok)\n setCopyFailed(!ok)\n local.onCopy?.(ok)\n if (ok) setTimeout(() => setCopied(false), 1500)\n }\n\n const empty = () => local.output === ''\n const regionLabel = () =>\n local.command ? `Output of ${local.command.slice(0, 120)}` : 'Terminal output'\n\n return (\n <div\n data-slot=\"terminal\"\n data-size={local.size ?? 'default'}\n aria-busy={local.status?.state === 'running' || undefined}\n class={cn(\n 'group/terminal overflow-hidden border border-border bg-card',\n small() ? 'rounded-lg' : 'rounded-xl',\n local.class\n )}\n {...rest}\n >\n <div class={cn('flex items-center gap-2', small() ? 'px-2 py-0.5' : 'px-3 py-1')}>\n <Show\n when={local.command !== undefined}\n fallback={<span class=\"flex-1 text-xs text-muted-foreground\">Terminal</span>}\n >\n <span class=\"flex min-w-0 flex-1 items-baseline gap-2\">\n <span\n aria-hidden=\"true\"\n class=\"shrink-0 font-code text-code text-muted-foreground select-none\"\n >\n $\n </span>\n <code\n title={local.command}\n class=\"line-clamp-2 min-w-0 font-code text-code text-foreground [overflow-wrap:anywhere]\"\n >\n {local.command}\n </code>\n </span>\n </Show>\n <Show when={local.status}>{(status) => <StatusReadout status={status()} />}</Show>\n {/* Hidden until the terminal is hovered or holds focus, never removed:\n a control that only exists under the pointer is unreachable by\n keyboard, and a touch screen has no hover, so it always shows there. */}\n <div class=\"flex items-center gap-1 opacity-0 transition-opacity group-focus-within/terminal:opacity-100 group-hover/terminal:opacity-100 [@media(hover:none)]:opacity-100\">\n <Show when={local.onClear !== undefined && !empty()}>\n <Button\n variant=\"ghost\"\n size=\"icon-2xs\"\n aria-label={local.clearLabel ?? 'Clear output'}\n onClick={() => local.onClear?.()}\n >\n <Eraser aria-hidden=\"true\" />\n </Button>\n </Show>\n <Show when={!empty()}>\n <Button\n variant=\"ghost\"\n size=\"icon-2xs\"\n aria-label={\n copied() ? (local.copiedLabel ?? 'Copied') : (local.copyLabel ?? 'Copy output')\n }\n title={copyFailed() ? 'Copying is unavailable in this context' : undefined}\n onClick={() => void copy()}\n >\n <Show when={copied()} fallback={<Copy aria-hidden=\"true\" />}>\n <Check aria-hidden=\"true\" />\n </Show>\n </Button>\n </Show>\n </div>\n </div>\n\n <Show when={lineWindow().hidden > 0 || lineWindow().evicted > 0}>\n <div\n data-slot=\"terminal-hidden-note\"\n class=\"flex items-center gap-2 border-t border-border px-3 py-1 text-xs text-muted-foreground\"\n >\n <span>\n <Show when={lineWindow().hidden > 0}>\n {lineWindow().hidden.toLocaleString()} earlier{' '}\n {lineWindow().hidden === 1 ? 'line' : 'lines'} hidden\n <Show when={parser.droppedLines > 0}>\n {' '}\n ({parser.droppedLines.toLocaleString()} only in the copy)\n </Show>\n .\n </Show>\n <Show when={lineWindow().evicted > 0}>\n {' '}\n {lineWindow().lost\n ? `The lines you were reading were discarded to keep memory bounded; showing the oldest ${lineWindow().end.toLocaleString()} still kept.`\n : `${lineWindow().evicted.toLocaleString()} of the lines you were reading were discarded to keep memory bounded.`}\n </Show>\n </span>\n <Show when={lineWindow().revealable > 0}>\n <Button\n variant=\"ghost\"\n size=\"2xs\"\n onClick={() => setLimit(revealEarlier(limit(), pageSize(), outputRows().length))}\n >\n Show {Math.min(pageSize(), lineWindow().revealable).toLocaleString()} earlier\n </Button>\n </Show>\n </div>\n </Show>\n\n <div class=\"relative\">\n <div\n ref={(element) => (scroller = element)}\n data-slot=\"terminal-body\"\n // A region that scrolls must be focusable, and a tab stop needs a name.\n role=\"region\"\n tabindex=\"0\"\n aria-label={regionLabel()}\n onScroll={onScroll}\n style={{ 'max-height': maxHeight() }}\n class=\"scroll-fade overflow-auto border-t border-border bg-(--terminal-background) text-(color:--terminal-foreground)\"\n >\n <Show\n when={!empty()}\n fallback={\n <p class={cn('m-0 opacity-70', small() ? 'px-2 py-1.5' : 'px-3 py-2')}>\n <span class=\"font-code text-code\">\n {local.status?.state === 'running' ? 'Waiting for output…' : 'No output'}\n </span>\n </p>\n }\n >\n <pre\n class={cn(\n 'm-0 font-code text-code leading-normal',\n small() ? 'px-2 py-1.5' : 'px-3 py-2'\n )}\n >\n <For each={visibleRows()}>\n {(line) => <LineView line={line} wrap={local.wrap === true} />}\n </For>\n </pre>\n </Show>\n </div>\n <Show when={newerRows() > 0}>\n <Button\n variant=\"secondary\"\n size=\"2xs\"\n class=\"absolute end-3 bottom-2 shadow-sm\"\n onClick={jumpToLatest}\n >\n <ArrowDown aria-hidden=\"true\" />\n Jump to latest\n <span class=\"text-muted-foreground tabular-nums\">\n ({newerRows().toLocaleString()} newer {newerRows() === 1 ? 'line' : 'lines'})\n </span>\n </Button>\n </Show>\n </div>\n </div>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"terminal.js","names":["ArrowDown","Check","CircleAlert","CircleSlash","Copy","Eraser","LoaderCircle","createEffect","createMemo","createSignal","For","on","Show","splitProps","ComponentProps","writeClipboardText","cn","Button","createAnsiParser","isPlainStyle","resolveColors","AnsiLine","AnsiStyle","isAtBottom","isFailedExit","revealEarlier","terminalStatusLabel","terminalWindow","TerminalStatus","TerminalProps","Omit","output","command","status","maxLines","retainLines","maxHeight","wrap","size","onClear","copyLabel","copiedLabel","clearLabel","onCopy","ok","TERMINAL_MAX_LINES","FG_CLASS","const","BG_CLASS","segmentClass","style","fg","bg","bold","dim","italic","underline","strike","LineView","props","line","_el$","_tmpl$2","_$insert","_$createComponent","each","segments","children","segment","text","_el$7","_tmpl$3","_$effect","_$className","when","truncated","_el$2","_tmpl$","_el$3","firstChild","_el$6","nextSibling","_el$5","toLocaleString","sameAnsiLine","left","right","length","every","index","StatusReadout","_el$8","_tmpl$5","state","_el$9","_tmpl$4","fallback","_p$","_v$","_v$2","e","_$setAttribute","t","undefined","Terminal","local","rest","small","pageSize","Math","max","floor","newParser","parser","consumed","epoch","revision","next","startsWith","write","slice","equals","limit","setLimit","defer","empty","outputRows","rows","lines","open","openLine","push","parked","setParked","end","total","droppedLines","anchorEnd","current","position","lineWindow","visibleRows","start","retainedIndex","changedParkedLine","newerRows","later","scroller","HTMLDivElement","following","onScroll","atEnd","scrollHeight","scrollTop","clientHeight","currentEpoch","jumpToLatest","focus","copied","setCopied","copyFailed","setCopyFailed","copy","setTimeout","regionLabel","_el$0","_tmpl$0","_el$1","_el$13","_el$16","_el$17","_$spread","_$mergeProps","data-size","aria-busy","class","_tmpl$1","_el$10","_tmpl$6","_el$11","_el$12","_$memo","variant","aria-label","onClick","title","hidden","evicted","_el$14","_tmpl$7","_el$15","lost","revealable","min","addEventListener","_$use","element","_el$26","_tmpl$10","_el$27","_el$18","_tmpl$8","_el$19","_tmpl$9","_el$20","_el$23","_el$21","_el$24","_el$22","_v$3","_v$4","_v$5","a","_$setStyleProperty","_$createComponent","_$className","_$setAttribute","Terminal","_$mergeProps","_$memo","_$setStyleProperty"],"sources":["../../../../src/components/composites/terminal/terminal.tsx"],"sourcesContent":["import {\n ArrowDown,\n Check,\n CircleAlert,\n CircleSlash,\n Copy,\n Eraser,\n LoaderCircle,\n} from 'lucide-solid'\nimport {\n createEffect,\n createMemo,\n createSignal,\n For,\n on,\n Show,\n splitProps,\n type ComponentProps,\n} from 'solid-js'\nimport { writeClipboardText } from '#lib/clipboard'\nimport { cn } from '#lib/utils'\nimport { Button } from '../../ui/button'\nimport {\n createAnsiParser,\n isPlainStyle,\n resolveColors,\n type AnsiLine,\n type AnsiStyle,\n} from './ansi'\nimport {\n isAtBottom,\n isFailedExit,\n revealEarlier,\n terminalStatusLabel,\n terminalWindow,\n type TerminalStatus,\n} from './terminal-model'\n\n/**\n * Terminal.\n *\n * A command and its output, as it arrives. It is the thing to put inside an\n * agent's \"ran a command\" line (a `TraceLine`, with `size=\"sm\"`) when the output\n * is the evidence; reach for `CodeBlock` instead when the text is source or a\n * finished log that needs no live behaviour, and for `TestResults` when the\n * output is a test run the host can structure.\n *\n * It does not wrap `CodeBlock`. A block's `highlight` seam re-renders the whole\n * body whenever the code changes, which is exactly wrong for output that grows a\n * line at a time, and a terminal has to own its scroller to follow the tail. It\n * keeps the block's header and surface vocabulary so the two read as one family.\n *\n * ## What the output is allowed to do\n *\n * Output is untrusted bytes. It is parsed by `createAnsiParser` into plain text\n * and a fixed set of styles — sixteen theme colours, bold, dim, italic,\n * underline, strike-through, reverse — and everything else (cursor movement,\n * title and clipboard sequences, anything malformed) is dropped, never echoed.\n * Colours come from the theme's `--terminal-ansi-*` tokens, painted on the\n * theme's own terminal background, so a program's colours keep the contrast the\n * theme measured for them. Nothing is rendered as markup.\n *\n * ## Streaming\n *\n * `output` is the whole string so far. When the new value begins with the old\n * one, only the appended text is parsed, so a chunk costs the size of the chunk\n * and not of the transcript. Finished lines are keyed by identity and are never\n * re-rendered; only the line still being written changes, which is what makes a\n * `\\r` progress bar redraw in place. Batch appends per frame — the host sees a\n * prefix check proportional to the output on every change.\n *\n * Only the last `maxLines` finished lines are mounted. The rest are counted in\n * an explicit note with a control to show them a page at a time, because tens of\n * thousands of row elements are a frozen page, not a transcript. Copy still\n * writes `output` exactly as given — not the rendered lines, not the visible tail.\n *\n * ## Following the tail\n *\n * The terminal scrolls inside its own bounded box and follows new output only\n * while the reader is at the bottom of that box. Scrolling up *parks* the view:\n * the lines mounted are the ones that were there when they left, however much\n * output arrives, and \"Jump to latest\" is the only way back to the tail (reaching\n * the bottom of a parked view with nothing newer resumes it, because nothing was\n * missed). If retention discards the lines they were reading the note says how\n * many, and when none are left the oldest retained lines are shown. The page\n * itself is never scrolled. Scrolling is instant, so there is no animation to\n * reduce.\n *\n * ## Status is a claim\n *\n * `status` is drawn only when the host passes it, in words as well as an icon,\n * and only a non-zero exit is toned as a failure: this component does not decide\n * that a command \"passed\". Without a status the header says nothing about whether\n * the command is still running. `onClear` adds a clear button; without it the\n * output is the host's record and nothing here offers to erase it.\n */\nexport type TerminalProps = Omit<ComponentProps<'div'>, 'children'> & {\n /** Everything the command has printed so far, exactly as received. */\n output: string\n /** The command line. Shown as text; the prompt glyph is decoration. */\n command?: string\n status?: TerminalStatus\n /** Finished lines mounted at once; earlier ones are counted and revealed a page at a time. */\n maxLines?: number\n /** Finished lines kept at all; older ones are discarded and counted. Default 200 000. */\n retainLines?: number\n /** Height of the output box, which scrolls past it. A number is pixels. Default `20rem`. */\n maxHeight?: number | string\n /** Soft-wrap long lines instead of scrolling sideways. Off: terminal columns keep their alignment. */\n wrap?: boolean\n /** `sm` is the compact chrome for output nested inside a Trace line. */\n size?: 'default' | 'sm'\n /** Show a clear button. The host empties `output`; the terminal erases nothing itself. */\n onClear?: () => void\n copyLabel?: string\n copiedLabel?: string\n clearLabel?: string\n /** Called after each copy attempt with whether the clipboard accepted it. */\n onCopy?: (ok: boolean) => void\n}\n\n/** Finished lines mounted by default. */\nexport const TERMINAL_MAX_LINES = 1000\n\n// One literal class per colour, written out in full so the stylesheet generator\n// can see each of them; a class assembled from an index would never be emitted.\nconst FG_CLASS = [\n 'text-(color:--terminal-ansi-black)',\n 'text-(color:--terminal-ansi-red)',\n 'text-(color:--terminal-ansi-green)',\n 'text-(color:--terminal-ansi-yellow)',\n 'text-(color:--terminal-ansi-blue)',\n 'text-(color:--terminal-ansi-magenta)',\n 'text-(color:--terminal-ansi-cyan)',\n 'text-(color:--terminal-ansi-white)',\n 'text-(color:--terminal-ansi-bright-black)',\n 'text-(color:--terminal-ansi-bright-red)',\n 'text-(color:--terminal-ansi-bright-green)',\n 'text-(color:--terminal-ansi-bright-yellow)',\n 'text-(color:--terminal-ansi-bright-blue)',\n 'text-(color:--terminal-ansi-bright-magenta)',\n 'text-(color:--terminal-ansi-bright-cyan)',\n 'text-(color:--terminal-ansi-bright-white)',\n] as const\nconst BG_CLASS = [\n 'bg-(--terminal-ansi-black)',\n 'bg-(--terminal-ansi-red)',\n 'bg-(--terminal-ansi-green)',\n 'bg-(--terminal-ansi-yellow)',\n 'bg-(--terminal-ansi-blue)',\n 'bg-(--terminal-ansi-magenta)',\n 'bg-(--terminal-ansi-cyan)',\n 'bg-(--terminal-ansi-white)',\n 'bg-(--terminal-ansi-bright-black)',\n 'bg-(--terminal-ansi-bright-red)',\n 'bg-(--terminal-ansi-bright-green)',\n 'bg-(--terminal-ansi-bright-yellow)',\n 'bg-(--terminal-ansi-bright-blue)',\n 'bg-(--terminal-ansi-bright-magenta)',\n 'bg-(--terminal-ansi-bright-cyan)',\n 'bg-(--terminal-ansi-bright-white)',\n] as const\n\nfunction segmentClass(style: AnsiStyle): string {\n const { fg, bg } = resolveColors(style)\n return cn(\n {\n 'font-bold': style.bold,\n 'opacity-70': style.dim,\n italic: style.italic,\n underline: style.underline && !style.strike,\n 'line-through': style.strike && !style.underline,\n '[text-decoration-line:underline_line-through]': style.underline && style.strike,\n 'text-(color:--terminal-background)': fg === 'default-bg',\n 'bg-(--terminal-foreground)': bg === 'default-fg',\n },\n typeof fg === 'number' && FG_CLASS[fg],\n typeof bg === 'number' && BG_CLASS[bg]\n )\n}\n\nfunction LineView(props: { line: AnsiLine; wrap: boolean }) {\n return (\n // `min-h-lh` keeps an empty line one line tall; a block with no text would\n // collapse and the transcript would lose its blank lines.\n <div\n class={cn('min-h-lh', {\n 'whitespace-pre-wrap [overflow-wrap:anywhere]': props.wrap,\n 'w-max min-w-full': !props.wrap,\n })}\n >\n <For each={props.line.segments}>\n {(segment) =>\n isPlainStyle(segment.style) ? (\n segment.text\n ) : (\n <span class={segmentClass(segment.style)}>{segment.text}</span>\n )\n }\n </For>\n <Show when={props.line.truncated > 0}>\n <span class=\"opacity-70 select-none\">\n {' '}\n … {props.line.truncated.toLocaleString()} more characters not shown\n </span>\n </Show>\n </div>\n )\n}\n\nfunction sameAnsiLine(left: AnsiLine, right: AnsiLine): boolean {\n return (\n left.truncated === right.truncated &&\n left.segments.length === right.segments.length &&\n left.segments.every(\n (segment, index) =>\n segment.text === right.segments[index]?.text &&\n segment.style === right.segments[index]?.style\n )\n )\n}\n\nfunction StatusReadout(props: { status: TerminalStatus }) {\n return (\n // A live region, so a command that finishes while the reader is elsewhere is\n // announced once, in words.\n <span\n role=\"status\"\n data-slot=\"terminal-status\"\n data-state={props.status.state}\n class={cn('flex shrink-0 items-center gap-1 text-xs', {\n 'text-destructive': isFailedExit(props.status),\n 'text-info': props.status.state === 'running',\n 'text-muted-foreground': props.status.state !== 'running' && !isFailedExit(props.status),\n })}\n >\n {/* A zero exit gets no glyph: a tick would be this component deciding the\n command succeeded, and some tools exit non-zero on purpose or zero on\n failure. The words carry the fact; only a non-zero code is toned. */}\n <Show when={props.status.state !== 'exited' || isFailedExit(props.status)}>\n <span aria-hidden=\"true\" class=\"grid size-3.5 place-items-center [&_svg]:size-3.5\">\n <Show\n when={props.status.state === 'running'}\n fallback={\n <Show when={props.status.state === 'cancelled'} fallback={<CircleAlert />}>\n <CircleSlash />\n </Show>\n }\n >\n <LoaderCircle class=\"motion-safe:animate-spin\" />\n </Show>\n </span>\n </Show>\n {terminalStatusLabel(props.status)}\n </span>\n )\n}\n\nexport function Terminal(props: TerminalProps) {\n const [local, rest] = splitProps(props, [\n 'output',\n 'command',\n 'status',\n 'maxLines',\n 'retainLines',\n 'maxHeight',\n 'wrap',\n 'size',\n 'onClear',\n 'copyLabel',\n 'copiedLabel',\n 'clearLabel',\n 'onCopy',\n 'class',\n ])\n\n const small = () => local.size === 'sm'\n const pageSize = () => Math.max(1, Math.floor(local.maxLines ?? TERMINAL_MAX_LINES))\n const maxHeight = () =>\n typeof local.maxHeight === 'number' ? `${local.maxHeight}px` : (local.maxHeight ?? '20rem')\n\n // The parser outlives renders: it holds the half-read escape sequence, the\n // current style and the open line. A new `output` that extends the old one is\n // fed only its tail; anything else (a clear, a different command) starts over.\n const newParser = () => createAnsiParser({ retainLines: local.retainLines })\n let parser = newParser()\n let consumed = ''\n // Bumped when the output restarts, so a parked position from the old output\n // is never applied to the new one.\n let epoch = 0\n const revision = createMemo(\n () => {\n const next = local.output\n if (next.length >= consumed.length && next.startsWith(consumed)) {\n parser.write(next.slice(consumed.length))\n } else {\n parser = newParser()\n parser.write(next)\n epoch += 1\n }\n consumed = next\n return epoch\n },\n undefined,\n { equals: false }\n )\n\n const [limit, setLimit] = createSignal(pageSize())\n createEffect(on(pageSize, (size) => setLimit(size), { defer: true }))\n // A cleared terminal is a fresh one: the next command starts at the page size.\n createEffect(\n on(\n () => local.output === '',\n (empty) => {\n if (empty) setLimit(pageSize())\n },\n { defer: true }\n )\n )\n\n const outputRows = createMemo(\n () => {\n revision()\n const rows = parser.lines.slice()\n const open = parser.openLine()\n if (open) rows.push(open)\n return rows\n },\n [],\n { equals: false }\n )\n // Where the reader parked, as a count of lines since the output began. An open\n // line is a row too: freeze its snapshot so streamed characters and CR redraws\n // do not rewrite the text under a parked reader.\n const [parked, setParked] = createSignal<{ epoch: number; end: number; open?: AnsiLine }>()\n const total = () => parser.droppedLines + outputRows().length\n const anchorEnd = () => {\n const current = revision()\n const position = parked()\n return position && position.epoch === current ? position.end : undefined\n }\n const lineWindow = createMemo(() => {\n revision()\n return terminalWindow(outputRows().length, parser.droppedLines, limit(), anchorEnd())\n })\n // Finished rows keep their parser identity. If an open row existed when the\n // reader parked, substitute its immutable snapshot until they jump to latest.\n const visibleRows = createMemo(\n () => {\n revision()\n const start = lineWindow().start\n const end = lineWindow().end\n const rows = outputRows().slice(start, end)\n const position = parked()\n if (position?.epoch === revision() && position.open) {\n const retainedIndex = position.end - 1 - parser.droppedLines\n if (retainedIndex >= start && retainedIndex < end) {\n rows[retainedIndex - start] = position.open\n }\n }\n return rows\n },\n [],\n { equals: false }\n )\n const changedParkedLine = () => {\n const position = parked()\n if (position?.epoch !== revision() || !position.open) return false\n const retainedIndex = position.end - 1 - parser.droppedLines\n const current = outputRows()[retainedIndex]\n return current !== undefined && !sameAnsiLine(position.open, current)\n }\n const newerRows = () => lineWindow().later + (changedParkedLine() ? 1 : 0)\n\n let scroller: HTMLDivElement | undefined\n const following = () => anchorEnd() === undefined\n\n const onScroll = () => {\n if (!scroller) return\n const atEnd = isAtBottom(scroller.scrollHeight, scroller.scrollTop, scroller.clientHeight)\n const position = anchorEnd()\n if (!atEnd) {\n if (position === undefined) {\n const currentEpoch = revision()\n setParked({ epoch: currentEpoch, end: total(), open: parser.openLine() })\n }\n } else if (position !== undefined && position >= total() && !changedParkedLine()) {\n // Back at the end of a view with nothing newer: nothing was missed.\n setParked(undefined)\n }\n }\n createEffect(\n on(revision, () => {\n if (scroller && following()) scroller.scrollTop = scroller.scrollHeight\n })\n )\n const jumpToLatest = () => {\n if (!scroller) return\n setParked(undefined)\n scroller.scrollTop = scroller.scrollHeight\n // The button is about to disappear; leave focus somewhere real.\n scroller.focus()\n }\n\n const [copied, setCopied] = createSignal(false)\n const [copyFailed, setCopyFailed] = createSignal(false)\n const copy = async () => {\n let ok = true\n try {\n await writeClipboardText(local.output)\n } catch {\n ok = false\n }\n setCopied(ok)\n setCopyFailed(!ok)\n local.onCopy?.(ok)\n if (ok) setTimeout(() => setCopied(false), 1500)\n }\n\n const empty = () => local.output === ''\n const regionLabel = () =>\n local.command ? `Output of ${local.command.slice(0, 120)}` : 'Terminal output'\n\n return (\n <div\n data-slot=\"terminal\"\n data-size={local.size ?? 'default'}\n aria-busy={local.status?.state === 'running' || undefined}\n class={cn(\n 'group/terminal overflow-hidden border border-border bg-card',\n small() ? 'rounded-lg' : 'rounded-xl',\n local.class\n )}\n {...rest}\n >\n <div class={cn('flex items-center gap-2', small() ? 'px-2 py-0.5' : 'px-3 py-1')}>\n <Show\n when={local.command !== undefined}\n fallback={<span class=\"flex-1 text-xs text-muted-foreground\">Terminal</span>}\n >\n <span class=\"flex min-w-0 flex-1 items-baseline gap-2\">\n <span\n aria-hidden=\"true\"\n class=\"shrink-0 font-code text-code text-muted-foreground select-none\"\n >\n $\n </span>\n <code\n title={local.command}\n class=\"line-clamp-2 min-w-0 font-code text-code text-foreground [overflow-wrap:anywhere]\"\n >\n {local.command}\n </code>\n </span>\n </Show>\n <Show when={local.status}>{(status) => <StatusReadout status={status()} />}</Show>\n {/* Hidden until the terminal is hovered or holds focus, never removed:\n a control that only exists under the pointer is unreachable by\n keyboard, and a touch screen has no hover, so it always shows there. */}\n <div class=\"flex items-center gap-1 opacity-0 transition-opacity group-focus-within/terminal:opacity-100 group-hover/terminal:opacity-100 [@media(hover:none)]:opacity-100\">\n <Show when={local.onClear !== undefined && !empty()}>\n <Button\n variant=\"ghost\"\n size=\"icon-2xs\"\n aria-label={local.clearLabel ?? 'Clear output'}\n onClick={() => local.onClear?.()}\n >\n <Eraser aria-hidden=\"true\" />\n </Button>\n </Show>\n <Show when={!empty()}>\n <Button\n variant=\"ghost\"\n size=\"icon-2xs\"\n aria-label={\n copied() ? (local.copiedLabel ?? 'Copied') : (local.copyLabel ?? 'Copy output')\n }\n title={copyFailed() ? 'Copying is unavailable in this context' : undefined}\n onClick={() => void copy()}\n >\n <Show when={copied()} fallback={<Copy aria-hidden=\"true\" />}>\n <Check aria-hidden=\"true\" />\n </Show>\n </Button>\n </Show>\n </div>\n </div>\n\n <Show when={lineWindow().hidden > 0 || lineWindow().evicted > 0}>\n <div\n data-slot=\"terminal-hidden-note\"\n class=\"flex items-center gap-2 border-t border-border px-3 py-1 text-xs text-muted-foreground\"\n >\n <span>\n <Show when={lineWindow().hidden > 0}>\n {lineWindow().hidden.toLocaleString()} earlier{' '}\n {lineWindow().hidden === 1 ? 'line' : 'lines'} hidden\n <Show when={parser.droppedLines > 0}>\n {' '}\n ({parser.droppedLines.toLocaleString()} only in the copy)\n </Show>\n .\n </Show>\n <Show when={lineWindow().evicted > 0}>\n {' '}\n {lineWindow().lost\n ? `The lines you were reading were discarded to keep memory bounded; showing the oldest ${lineWindow().end.toLocaleString()} still kept.`\n : `${lineWindow().evicted.toLocaleString()} of the lines you were reading were discarded to keep memory bounded.`}\n </Show>\n </span>\n <Show when={lineWindow().revealable > 0}>\n <Button\n variant=\"ghost\"\n size=\"2xs\"\n onClick={() => setLimit(revealEarlier(limit(), pageSize(), outputRows().length))}\n >\n Show {Math.min(pageSize(), lineWindow().revealable).toLocaleString()} earlier\n </Button>\n </Show>\n </div>\n </Show>\n\n <div class=\"relative\">\n <div\n ref={(element) => (scroller = element)}\n data-slot=\"terminal-body\"\n // A region that scrolls must be focusable, and a tab stop needs a name.\n role=\"region\"\n tabindex=\"0\"\n aria-label={regionLabel()}\n onScroll={onScroll}\n style={{ 'max-height': maxHeight() }}\n class=\"scroll-fade overflow-auto border-t border-border bg-(--terminal-background) text-(color:--terminal-foreground)\"\n >\n <Show\n when={!empty()}\n fallback={\n <p class={cn('m-0 opacity-70', small() ? 'px-2 py-1.5' : 'px-3 py-2')}>\n <span class=\"font-code text-code\">\n {local.status?.state === 'running' ? 'Waiting for output…' : 'No output'}\n </span>\n </p>\n }\n >\n <pre\n class={cn(\n 'm-0 font-code text-code leading-normal',\n small() ? 'px-2 py-1.5' : 'px-3 py-2'\n )}\n >\n <For each={visibleRows()}>\n {(line) => <LineView line={line} wrap={local.wrap === true} />}\n </For>\n </pre>\n </Show>\n </div>\n <Show when={newerRows() > 0}>\n <Button\n variant=\"secondary\"\n size=\"2xs\"\n class=\"absolute end-3 bottom-2 shadow-sm\"\n onClick={jumpToLatest}\n >\n <ArrowDown aria-hidden=\"true\" />\n Jump to latest\n <span class=\"text-muted-foreground tabular-nums\">\n ({newerRows().toLocaleString()} newer {newerRows() === 1 ? 'line' : 'lines'})\n </span>\n </Button>\n </Show>\n </div>\n </div>\n )\n}\n"],"mappings":"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"}
|
|
@@ -37,6 +37,12 @@ export type TreeProps = Omit<ComponentProps<'div'>, 'children' | 'role' | 'tabIn
|
|
|
37
37
|
* Keyboard behaviour is identical in both modes: Left/Right expand and collapse.
|
|
38
38
|
*/
|
|
39
39
|
disclosure?: TreeDisclosure;
|
|
40
|
+
/**
|
|
41
|
+
* Draw a vertical guide line down each ancestor level of a nested row, so a
|
|
42
|
+
* group of children reads as belonging to its parent. Off by default: a flat
|
|
43
|
+
* list or a dense file explorer carries its own rhythm.
|
|
44
|
+
*/
|
|
45
|
+
guides?: boolean;
|
|
40
46
|
/** Called for Enter or pointer activation. Domain action stays host-owned. */
|
|
41
47
|
onActivate?: (id: string, event: Event) => void;
|
|
42
48
|
/** Called for Space selection. Selection state stays host-owned. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tree.d.ts","sourceRoot":"","sources":["../../../../src/components/composites/tree/tree.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"tree.d.ts","sourceRoot":"","sources":["../../../../src/components/composites/tree/tree.tsx"],"names":[],"mappings":"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"}
|