@ai-ecoverse/slicc-spectrum 1.58.3 → 1.60.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/README.md +16 -0
- package/dist/{chunk-TK4ZJ7LA.js → chunk-XI74SELH.js} +140 -27
- package/dist/chunk-XI74SELH.js.map +7 -0
- package/dist/slicc-terminal.js +1 -1
- package/dist/slicc-ui.js +1393 -946
- package/dist/slicc-ui.js.map +4 -4
- package/dist/types/app/app.d.ts +2 -0
- package/dist/types/app/chat.d.ts +1 -0
- package/dist/types/app/panel-command.d.ts +71 -0
- package/dist/types/app/panels.d.ts +4 -3
- package/dist/types/app/settings.d.ts +1 -0
- package/dist/types/app/updates.d.ts +1 -0
- package/dist/types/color-query.d.ts +15 -0
- package/dist/types/model/types.d.ts +1 -1
- package/dist/types/ui.d.ts +2 -0
- package/package.json +1 -1
- package/dist/chunk-TK4ZJ7LA.js.map +0 -7
package/README.md
CHANGED
|
@@ -32,6 +32,8 @@ Web components for SLICC: `<slicc-terminal>`, and SLICC's app UI on [Spectrum We
|
|
|
32
32
|
|
|
33
33
|
Events, all `CustomEvent`s with the payload in `detail`: `ready` `{cols, rows}`, `resize` `{cols, rows}`, `exit` `{status}`, `title` `{title}`, `bell` `{count}`, `error` `{error}`.
|
|
34
34
|
|
|
35
|
+
It answers OSC 10 and OSC 11 color queries (`ESC ] 10 ; ? ST` and `ESC ] 11 ; ? ST`) with the foreground and background it shows at that moment, as `rgb:rrrr/gggg/bbbb`, so command-line tools can tell a light theme from a dark one and follow a theme switch. The answer reaches the backend before replies to anything that comes later in the output.
|
|
36
|
+
|
|
35
37
|
Removing the element closes the session and destroys the screen. Adding it again mounts a fresh screen and opens a new session on the same backend.
|
|
36
38
|
|
|
37
39
|
## Backend interface
|
|
@@ -192,6 +194,20 @@ A sprinkle's frame gets `window.slicc` with `name` and `lick(event)`. When the m
|
|
|
192
194
|
|
|
193
195
|
Paths are the agent's: `/shared/…` and `/home/…`, nothing else. A refusal or a missing file rejects with an `Error`. There is no `exec`: a sprinkle that needs a command asks its cone with `slicc.lick()`. Without `call`, none of the four exist, so guard them (`typeof slicc.readFile === 'function'`) and fall back.
|
|
194
196
|
|
|
197
|
+
### Panel command
|
|
198
|
+
|
|
199
|
+
`panelCommand(app, argv, caller)`, exported from `dist/slicc-ui.js`, runs `panel` for an agent or a terminal, so the agent can arrange the UI. It returns `{ stdout, stderr, code }`. A leading `panel` in `argv` is dropped. `caller` is `{ agentId, cone?, readOnly? }`: `agentId` is the calling cone or scoop, or `null` for the user at a terminal; `cone` is the caller's cone when the agent already knows it (otherwise the `parentId` chain of `agentId` finds it).
|
|
200
|
+
|
|
201
|
+
- `panel list [--json]` lists the panels the caller can reach, open or not, with their state (`active`, `shown`, `open` or `closed`) and why one is busy. `--json` prints `PanelInfo`s: `id`, `title`, `kind` (`surface`, `chat`, `terminal`, `sprinkle`, `file`, `diff`), home `side`, `agent`, `open`, `visible`, `active` and `busy`.
|
|
202
|
+
- `panel open <id> [place] [--section <name>]` shows a panel without moving keyboard focus. `panel focus <id> [place] [--section <name>]` also gives it focus.
|
|
203
|
+
- `panel close <id>`, `panel move <id> <place>` (a closed panel opens there) and `panel reset` (the default layout).
|
|
204
|
+
- A place is `left`, `center` or `right` (a group on that side as the layout is now, with the chats' column as the center, or a new one beside its neighbours), or `--left`, `--right`, `--above`, `--below` or `--within <id>`.
|
|
205
|
+
- Ids are the surface ids (`files`, `changes`, `terminal`, `monitor`, `settings`, …), `chat:<agent>`, `terminal:<id>`, `sprinkle:<id>`, `file:<path>` and `diff:<path>`. `chat` is the caller's cone's chat (without a caller, the selected thread's), `terminal` the active terminal, else the latest open one, else the newest, and a sprinkle can be named by its name alone.
|
|
206
|
+
|
|
207
|
+
Exit codes: 0 done, 1 no such panel, 2 usage (with the help text), 5 refused. 3 and 4 are left to the agent's transport.
|
|
208
|
+
|
|
209
|
+
With an `agentId` or a `cone`, the caller reaches the shared surfaces, the chats of its cone and its scoops, its cone's sprinkles and the built-in ones; anything else is reported as missing. With `readOnly` (a page that only follows), everything but `list` and `--help` is refused. The command refuses (code 5) to close a terminal (its shell would stop), the last chat, or a busy panel, and to move or reset while a panel is busy. A panel element tells it is busy with a `busyReason` string: Settings while signing in or entering a key, Install / Update while a package installs, a chat while a question waits. For an agent, it also refuses to reopen a panel the user closed in the last 60 seconds (or to reset the layout then), and while the user is typing (a key in a text field in the last 3 seconds, or a focused field with text), `focus` only shows the panel. On a phone, `move` changes nothing. `app.panels` (`Panels`) is the controller under the command, with `list()`, `find(id)`, `open(id, { place, section })`, `focus`, `close`, `move(id, place)` and `reset()`, each returning `{ code, message }` and without the agent-only rules. Agent changes are saved with the layout.
|
|
210
|
+
|
|
195
211
|
### Model
|
|
196
212
|
|
|
197
213
|
`SliccModel` (`src/model/types.ts`) has one port per future backend, so adapters can replace the dummy without UI changes. Every port is subscribable with `on(type, listener)`, which returns an unsubscribe function.
|
|
@@ -440,13 +440,13 @@ var GraphicsLayer = class {
|
|
|
440
440
|
if (!canvas)
|
|
441
441
|
continue;
|
|
442
442
|
if (changed || !existingCanvas) {
|
|
443
|
-
let
|
|
443
|
+
let painted2 = false;
|
|
444
444
|
try {
|
|
445
|
-
|
|
445
|
+
painted2 = this.paint(canvas, key, cached.data, placement, viewport, bounds, flowOffsets.get(placement.row) ?? 0);
|
|
446
446
|
} catch {
|
|
447
|
-
|
|
447
|
+
painted2 = false;
|
|
448
448
|
}
|
|
449
|
-
if (!
|
|
449
|
+
if (!painted2) {
|
|
450
450
|
this.removeCanvas(key);
|
|
451
451
|
}
|
|
452
452
|
} else {
|
|
@@ -845,7 +845,7 @@ function textPoint(element, offset) {
|
|
|
845
845
|
var MAX_SELECTION_ROWS = 1e3;
|
|
846
846
|
var MAX_SELECTION_TEXT = 1024 * 1024;
|
|
847
847
|
var WORD_BOUNDARIES = new Set(" '\"\u2502`|:;,()[]{}<>$");
|
|
848
|
-
function selectionRange(core, position,
|
|
848
|
+
function selectionRange(core, position, unit2) {
|
|
849
849
|
const history = core.getScrollbackCount();
|
|
850
850
|
const total = history + core.getRows();
|
|
851
851
|
const cols = core.getCols();
|
|
@@ -893,7 +893,7 @@ function selectionRange(core, position, unit) {
|
|
|
893
893
|
const value = cell(next);
|
|
894
894
|
if (value.width !== 0 && !value.spacerHead) {
|
|
895
895
|
const chars = value.chars ?? String.fromCodePoint(value.char || 32);
|
|
896
|
-
if (
|
|
896
|
+
if (unit2 === "word" && boundary(chars) !== expected)
|
|
897
897
|
return included;
|
|
898
898
|
length += chars.length;
|
|
899
899
|
included = next;
|
|
@@ -1912,10 +1912,10 @@ var Renderer = class {
|
|
|
1912
1912
|
const col = Math.floor((clientX - mounted.element.getBoundingClientRect().left) / charWidth);
|
|
1913
1913
|
return col >= 0 && col < this.cols ? { row: mounted.row, col } : null;
|
|
1914
1914
|
}
|
|
1915
|
-
select(core, position,
|
|
1915
|
+
select(core, position, unit2, beforeSelect) {
|
|
1916
1916
|
if (!this.painted || this.needsSetup)
|
|
1917
1917
|
return false;
|
|
1918
|
-
const range = selectionRange(core, position,
|
|
1918
|
+
const range = selectionRange(core, position, unit2);
|
|
1919
1919
|
if (!range)
|
|
1920
1920
|
return false;
|
|
1921
1921
|
beforeSelect();
|
|
@@ -3923,8 +3923,8 @@ function fold(text, caseSensitive) {
|
|
|
3923
3923
|
folded += char.toLowerCase();
|
|
3924
3924
|
return folded;
|
|
3925
3925
|
}
|
|
3926
|
-
function* scanSearch(core,
|
|
3927
|
-
const needle = fold(
|
|
3926
|
+
function* scanSearch(core, query2, caseSensitive) {
|
|
3927
|
+
const needle = fold(query2, caseSensitive);
|
|
3928
3928
|
if (!needle)
|
|
3929
3929
|
return;
|
|
3930
3930
|
const prefix = new Uint32Array(needle.length);
|
|
@@ -3965,15 +3965,15 @@ function* scanSearch(core, query, caseSensitive) {
|
|
|
3965
3965
|
col,
|
|
3966
3966
|
endCol: Math.min(cols, col + (cell.width ?? 1))
|
|
3967
3967
|
};
|
|
3968
|
-
for (let
|
|
3968
|
+
for (let unit2 = 0; unit2 < text.length; unit2++) {
|
|
3969
3969
|
if (++work >= 256) {
|
|
3970
3970
|
work = 0;
|
|
3971
3971
|
yield null;
|
|
3972
3972
|
}
|
|
3973
3973
|
positions[index++ % needle.length] = position;
|
|
3974
|
-
while (matched > 0 && text[
|
|
3974
|
+
while (matched > 0 && text[unit2] !== needle[matched])
|
|
3975
3975
|
matched = prefix[matched - 1];
|
|
3976
|
-
if (text[
|
|
3976
|
+
if (text[unit2] === needle[matched])
|
|
3977
3977
|
matched++;
|
|
3978
3978
|
if (matched === needle.length) {
|
|
3979
3979
|
const match = {
|
|
@@ -4015,10 +4015,10 @@ var SearchController = class {
|
|
|
4015
4015
|
snapshot() {
|
|
4016
4016
|
return { ...this.state };
|
|
4017
4017
|
}
|
|
4018
|
-
search(
|
|
4019
|
-
if (
|
|
4018
|
+
search(query2, options) {
|
|
4019
|
+
if (query2.length > 1024)
|
|
4020
4020
|
throw new RangeError("Search query exceeds 1,024 UTF-16 code units");
|
|
4021
|
-
this.state.query =
|
|
4021
|
+
this.state.query = query2;
|
|
4022
4022
|
this.state.caseSensitive = options.caseSensitive ?? false;
|
|
4023
4023
|
this.revealFirst = true;
|
|
4024
4024
|
this.invalidate();
|
|
@@ -4484,9 +4484,9 @@ var WTerm = class {
|
|
|
4484
4484
|
this._scheduleRender();
|
|
4485
4485
|
}
|
|
4486
4486
|
drain();
|
|
4487
|
-
for (const
|
|
4487
|
+
for (const query2 of windowSizeQueries) {
|
|
4488
4488
|
try {
|
|
4489
|
-
this.onData?.(this._windowSizeResponse(
|
|
4489
|
+
this.onData?.(this._windowSizeResponse(query2));
|
|
4490
4490
|
} catch (error) {
|
|
4491
4491
|
recordDeliveryError(error);
|
|
4492
4492
|
}
|
|
@@ -4546,10 +4546,10 @@ var WTerm = class {
|
|
|
4546
4546
|
this.onResize(this.cols, this.rows);
|
|
4547
4547
|
}
|
|
4548
4548
|
/** Search retained history and the active screen, using plain text. */
|
|
4549
|
-
search(
|
|
4549
|
+
search(query2, options = {}) {
|
|
4550
4550
|
if (this._destroyed)
|
|
4551
4551
|
return;
|
|
4552
|
-
this._search.search(
|
|
4552
|
+
this._search.search(query2, options);
|
|
4553
4553
|
this._paintSearch();
|
|
4554
4554
|
}
|
|
4555
4555
|
findNext() {
|
|
@@ -4650,10 +4650,10 @@ var WTerm = class {
|
|
|
4650
4650
|
this._historySelection.paintRectangle(this.renderer.searchRows(), this._charWidth);
|
|
4651
4651
|
return true;
|
|
4652
4652
|
}
|
|
4653
|
-
_selectUnit(position,
|
|
4653
|
+
_selectUnit(position, unit2) {
|
|
4654
4654
|
if (this._destroyed || !this.bridge || !this.renderer)
|
|
4655
4655
|
return false;
|
|
4656
|
-
return this.renderer.select(this.bridge, position,
|
|
4656
|
+
return this.renderer.select(this.bridge, position, unit2, () => {
|
|
4657
4657
|
this._rectangleDrag.cancel();
|
|
4658
4658
|
this._historySelection.clear();
|
|
4659
4659
|
const active = this.element.ownerDocument.activeElement;
|
|
@@ -4955,9 +4955,9 @@ var WTerm = class {
|
|
|
4955
4955
|
this._windowSizeQueryState = state;
|
|
4956
4956
|
return queries;
|
|
4957
4957
|
}
|
|
4958
|
-
_windowSizeResponse(
|
|
4958
|
+
_windowSizeResponse(query2) {
|
|
4959
4959
|
const { width, height } = this._pixelSize();
|
|
4960
|
-
if (
|
|
4960
|
+
if (query2 === 14) {
|
|
4961
4961
|
return `\x1B[4;${height};${width}t`;
|
|
4962
4962
|
}
|
|
4963
4963
|
const cellWidth = Math.max(1, Math.round(this._charWidth));
|
|
@@ -5098,6 +5098,101 @@ var controlBytes = {
|
|
|
5098
5098
|
SIGHUP: null
|
|
5099
5099
|
};
|
|
5100
5100
|
|
|
5101
|
+
// src/color-query.ts
|
|
5102
|
+
var query = /\x1b\](1[01])((?:;\?){1,10})(\x07|\x1b\\)/g;
|
|
5103
|
+
var partial = /\x1b(?:\](?:1(?:[01](?:;\?){0,10};?\x1b?)?)?)?$/;
|
|
5104
|
+
var latin1 = new TextDecoder("latin1");
|
|
5105
|
+
var ColorQueries = class {
|
|
5106
|
+
#tail = "";
|
|
5107
|
+
scan(data) {
|
|
5108
|
+
const chunk = typeof data === "string" ? data : latin1.decode(data);
|
|
5109
|
+
if (!this.#tail && !chunk.includes("\x1B")) return [];
|
|
5110
|
+
const carried = this.#tail.length;
|
|
5111
|
+
const text = this.#tail + chunk;
|
|
5112
|
+
const found = [];
|
|
5113
|
+
for (const match of text.matchAll(query)) {
|
|
5114
|
+
const first = Number(match[1]);
|
|
5115
|
+
const codes = Array.from({ length: match[2].length / 2 }, (_, index) => first + index);
|
|
5116
|
+
found.push({
|
|
5117
|
+
at: match.index + match[0].length - carried,
|
|
5118
|
+
codes: codes.filter((code) => code <= 11),
|
|
5119
|
+
end: match[3]
|
|
5120
|
+
});
|
|
5121
|
+
}
|
|
5122
|
+
const last = found.at(-1);
|
|
5123
|
+
const rest = last ? text.slice(last.at + carried) : text;
|
|
5124
|
+
this.#tail = rest.match(partial)?.[0] ?? "";
|
|
5125
|
+
return found;
|
|
5126
|
+
}
|
|
5127
|
+
};
|
|
5128
|
+
var hex = (value) => Math.round(Math.min(255, Math.max(0, value))).toString(16).padStart(2, "0").repeat(2);
|
|
5129
|
+
var unit = (value) => value === void 0 ? 1 : value.endsWith("%") ? Number.parseFloat(value) / 100 : Number(value);
|
|
5130
|
+
function channels(color) {
|
|
5131
|
+
const value = color.trim().toLowerCase();
|
|
5132
|
+
const short = value.match(/^#([0-9a-f])([0-9a-f])([0-9a-f])$/);
|
|
5133
|
+
if (short)
|
|
5134
|
+
return [
|
|
5135
|
+
...[short[1], short[2], short[3]].map((digit) => Number.parseInt(digit.repeat(2), 16)),
|
|
5136
|
+
1
|
|
5137
|
+
];
|
|
5138
|
+
const long = value.match(/^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})?$/);
|
|
5139
|
+
if (long)
|
|
5140
|
+
return [
|
|
5141
|
+
...[long[1], long[2], long[3]].map((pair) => Number.parseInt(pair, 16)),
|
|
5142
|
+
long[4] ? Number.parseInt(long[4], 16) / 255 : 1
|
|
5143
|
+
];
|
|
5144
|
+
const number = String.raw`(-?[\d.]+(?:e-?\d+)?)`;
|
|
5145
|
+
const alpha = String.raw`(?:\s*[/,]\s*(-?[\d.]+(?:e-?\d+)?%?))?\s*\)`;
|
|
5146
|
+
const srgb = value.match(
|
|
5147
|
+
new RegExp(String.raw`^color\(srgb ${number} ${number} ${number}${alpha}`)
|
|
5148
|
+
);
|
|
5149
|
+
if (srgb)
|
|
5150
|
+
return [
|
|
5151
|
+
...[srgb[1], srgb[2], srgb[3]].map((part) => Number(part) * 255),
|
|
5152
|
+
unit(srgb[4])
|
|
5153
|
+
];
|
|
5154
|
+
const rgb = value.match(
|
|
5155
|
+
new RegExp(String.raw`^rgba?\(${number}[ ,]+${number}[ ,]+${number}${alpha}`)
|
|
5156
|
+
);
|
|
5157
|
+
if (rgb) return [...[rgb[1], rgb[2], rgb[3]].map(Number), unit(rgb[4])];
|
|
5158
|
+
return null;
|
|
5159
|
+
}
|
|
5160
|
+
var painter;
|
|
5161
|
+
function painted(color) {
|
|
5162
|
+
painter ??= typeof OffscreenCanvas === "function" ? new OffscreenCanvas(1, 1).getContext("2d", { willReadFrequently: true }) : null;
|
|
5163
|
+
if (!painter) return null;
|
|
5164
|
+
painter.clearRect(0, 0, 1, 1);
|
|
5165
|
+
painter.fillStyle = color;
|
|
5166
|
+
painter.fillRect(0, 0, 1, 1);
|
|
5167
|
+
const [red, green, blue, alpha] = painter.getImageData(0, 0, 1, 1).data;
|
|
5168
|
+
return [red, green, blue, alpha / 255];
|
|
5169
|
+
}
|
|
5170
|
+
function over(top, bottom) {
|
|
5171
|
+
const lower = bottom[3] * (1 - top[3]);
|
|
5172
|
+
const alpha = top[3] + lower;
|
|
5173
|
+
if (!alpha) return [0, 0, 0, 0];
|
|
5174
|
+
return [
|
|
5175
|
+
...[0, 1, 2].map((index) => (top[index] * top[3] + bottom[index] * lower) / alpha),
|
|
5176
|
+
alpha
|
|
5177
|
+
];
|
|
5178
|
+
}
|
|
5179
|
+
var read = (color) => channels(color) ?? painted(color);
|
|
5180
|
+
var parentOf = (node) => node.parentElement ?? node.getRootNode().host ?? null;
|
|
5181
|
+
function themeColors(element) {
|
|
5182
|
+
const style = getComputedStyle(element);
|
|
5183
|
+
let back = [0, 0, 0, 0];
|
|
5184
|
+
for (let node = element; node && back[3] < 1; node = parentOf(node)) {
|
|
5185
|
+
const layer = read(getComputedStyle(node).backgroundColor);
|
|
5186
|
+
if (layer) back = over(back, layer);
|
|
5187
|
+
}
|
|
5188
|
+
back = over(back, style.colorScheme === "dark" ? [18, 18, 18, 1] : [255, 255, 255, 1]);
|
|
5189
|
+
const front = read(style.color);
|
|
5190
|
+
return front ? { 10: over(front, back), 11: back } : { 11: back };
|
|
5191
|
+
}
|
|
5192
|
+
function colorReply(code, rgb, end) {
|
|
5193
|
+
return `\x1B]${code};rgb:${rgb.slice(0, 3).map(hex).join("/")}${end}`;
|
|
5194
|
+
}
|
|
5195
|
+
|
|
5101
5196
|
// node_modules/@wterm/dom/src/terminal.css
|
|
5102
5197
|
var terminal_default = '.wterm {\n /* Application overrides are owned by the renderer; each terminal is isolated. */\n --term-app-fg: initial;\n --term-app-bg: initial;\n --term-app-cursor: initial;\n\n --term-fg: #d4d4d4;\n --term-bg: #1e1e1e;\n --term-cursor: #aeafad;\n\n --term-color-0: #1e1e1e;\n --term-color-1: #f44747;\n --term-color-2: #6a9955;\n --term-color-3: #d7ba7d;\n --term-color-4: #569cd6;\n --term-color-5: #c586c0;\n --term-color-6: #4ec9b0;\n --term-color-7: #d4d4d4;\n --term-color-8: #808080;\n --term-color-9: #f44747;\n --term-color-10: #6a9955;\n --term-color-11: #d7ba7d;\n --term-color-12: #569cd6;\n --term-color-13: #c586c0;\n --term-color-14: #4ec9b0;\n --term-color-15: #ffffff;\n\n --term-font-family:\n "Menlo", "Consolas", "DejaVu Sans Mono", "Courier New", monospace;\n --term-font-size: 14px;\n --term-line-height: 1.2;\n --term-row-height: 17px;\n\n position: relative;\n background: var(--term-app-bg, var(--term-bg));\n color: var(--term-app-fg, var(--term-fg));\n font-family: var(--term-font-family);\n font-size: var(--term-font-size);\n font-kerning: none;\n font-variant-ligatures: none;\n line-height: var(--term-line-height);\n padding: 12px;\n border-radius: 8px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);\n outline: none;\n overflow: hidden;\n overflow-anchor: none;\n}\n\n.wterm:focus,\n.wterm:focus-visible {\n outline: none;\n}\n\n.term-grid {\n display: block;\n position: relative;\n white-space: pre;\n contain: layout paint style;\n will-change: contents;\n}\n\n.term-announcements {\n position: absolute;\n left: 0;\n top: 0;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: pre;\n pointer-events: none;\n user-select: none;\n}\n\n.term-images {\n position: absolute;\n inset: 0;\n pointer-events: none;\n overflow: visible;\n z-index: 1;\n}\n\n.term-search-layer {\n position: absolute;\n inset: 0;\n pointer-events: none;\n user-select: none;\n z-index: 2;\n}\n\n.term-search-match {\n position: absolute;\n background: var(--term-search-match, rgb(255 200 0 / 25%));\n}\n\n.term-search-active {\n background: var(--term-search-active, rgb(255 150 0 / 40%));\n box-shadow: inset 0 0 0 1px var(--term-search-border, #ffb000);\n}\n\n.term-image-flow-spacer {\n display: block;\n height: 0;\n pointer-events: none;\n}\n\n.term-image {\n position: absolute;\n display: block;\n pointer-events: none;\n user-select: none;\n}\n\n.term-row {\n display: block;\n height: var(--term-row-height);\n line-height: var(--term-row-height);\n contain: layout style;\n}\n\n.term-select-all .term-row,\n.term-rectangle-row {\n position: relative;\n}\n\n.term-select-all .term-row::after,\n.term-rectangle-row::after {\n content: "";\n position: absolute;\n inset: 0;\n background: var(--term-selection-bg, rgb(80 140 255 / 30%));\n pointer-events: none;\n user-select: none;\n z-index: 3;\n}\n\n.term-rectangle-row::after {\n left: var(--term-selection-left);\n width: var(--term-selection-width);\n right: auto;\n}\n\n.term-selection-status {\n position: sticky;\n bottom: 0;\n width: fit-content;\n max-width: 100%;\n white-space: normal;\n background: var(--term-app-bg, var(--term-bg));\n color: var(--term-app-fg, var(--term-fg));\n user-select: none;\n pointer-events: none;\n z-index: 4;\n}\n\n.term-selection-status:empty {\n display: none;\n}\n\n.term-scrollback-spacer {\n display: block;\n pointer-events: none;\n}\n\n.term-size-probe {\n position: absolute;\n top: 0;\n left: 0;\n visibility: hidden;\n pointer-events: none;\n white-space: pre;\n width: auto;\n height: var(--term-row-height);\n}\n\n.term-row > span,\n.term-row > .term-link,\n.term-link > span {\n display: inline-block;\n height: var(--term-row-height);\n vertical-align: top;\n}\n\n.term-row > span,\n.term-link > span {\n width: calc(var(--term-span-cols, 1) * var(--term-cell-width, 1ch));\n /* Glyph ink may overhang its advance without moving the following cell. */\n overflow: visible;\n}\n\n.term-link {\n color: inherit;\n cursor: text;\n}\n\n.wterm.link-modifier-active .term-link:hover,\n.term-link:focus-visible {\n cursor: pointer;\n}\n\n.wterm.link-modifier-active .term-link:hover > span,\n.term-link:focus-visible > span {\n text-decoration: underline;\n text-underline-offset: 0.15em;\n}\n\n.term-block {\n width: var(--term-cell-width, 1ch);\n overflow: hidden;\n -webkit-text-fill-color: transparent;\n}\n\n.term-box {\n --term-box-stroke: max(\n 1px,\n round(calc(var(--term-cell-width, 1ch) * 0.18), 1px)\n );\n -webkit-text-fill-color: transparent;\n}\n\n.term-box-heavy,\n.term-box-bold {\n --term-box-stroke: max(\n 2px,\n round(calc(var(--term-cell-width, 1ch) * 0.3), 1px)\n );\n}\n\n.term-box-round {\n position: relative;\n}\n\n.term-box-round::after {\n content: "";\n position: absolute;\n box-sizing: border-box;\n border: 0 solid currentColor;\n pointer-events: none;\n}\n\n.term-box-round-tl::after {\n inset: calc(50% - var(--term-box-stroke) * 0.5) 0 0\n calc(50% - var(--term-box-stroke) * 0.5);\n border-top-width: var(--term-box-stroke);\n border-left-width: var(--term-box-stroke);\n border-top-left-radius: 100%;\n}\n\n.term-box-round-tr::after {\n inset: calc(50% - var(--term-box-stroke) * 0.5)\n calc(50% - var(--term-box-stroke) * 0.5) 0 0;\n border-top-width: var(--term-box-stroke);\n border-right-width: var(--term-box-stroke);\n border-top-right-radius: 100%;\n}\n\n.term-box-round-br::after {\n inset: 0 calc(50% - var(--term-box-stroke) * 0.5)\n calc(50% - var(--term-box-stroke) * 0.5) 0;\n border-bottom-width: var(--term-box-stroke);\n border-right-width: var(--term-box-stroke);\n border-bottom-right-radius: 100%;\n}\n\n.term-box-round-bl::after {\n inset: 0 0 calc(50% - var(--term-box-stroke) * 0.5)\n calc(50% - var(--term-box-stroke) * 0.5);\n border-bottom-width: var(--term-box-stroke);\n border-left-width: var(--term-box-stroke);\n border-bottom-left-radius: 100%;\n}\n\n@media (forced-colors: active), print {\n .term-block {\n background: none !important;\n -webkit-text-fill-color: currentColor;\n }\n\n .term-box {\n background-image: none !important;\n -webkit-text-fill-color: currentColor;\n }\n\n .term-box-round::after {\n display: none;\n }\n}\n\n.term-wide {\n --term-span-cols: 2;\n overflow: visible;\n}\n\n.term-cursor {\n color: var(--term-cell-fg, inherit);\n background: var(--term-cell-bg, transparent);\n outline: 1px solid var(--term-app-cursor, var(--term-cursor));\n outline-offset: -1px;\n}\n\n/* Native text selection can blur the input until click-to-focus runs. Keep\n the cursor active during that press without cancelling the selection. */\n.wterm:is(.focused, :active) .term-cursor {\n background: var(--term-app-cursor, var(--term-cursor));\n color: var(--term-app-bg, var(--term-bg));\n outline: none;\n}\n\n.wterm:is(.focused, :active) .term-grid[data-cursor-shape="bar"] .term-cursor,\n.wterm:is(.focused, :active) .term-grid[data-cursor-shape="underline"] .term-cursor {\n background: var(--term-cell-bg, transparent);\n color: var(--term-cell-fg, inherit);\n box-shadow: var(--term-cursor-shadow);\n --term-cursor-animation: cursor-line-blink;\n}\n\n.term-grid[data-cursor-shape="bar"] .term-cursor {\n --term-cursor-shadow: inset 2px 0 0 var(--term-app-cursor, var(--term-cursor));\n}\n\n.term-grid[data-cursor-shape="underline"] .term-cursor {\n --term-cursor-shadow: inset 0 -2px 0\n var(--term-app-cursor, var(--term-cursor));\n}\n\n.wterm:is(.focused, :active).cursor-blink .term-cursor,\n.wterm:is(.focused, :active):not(.cursor-steady)\n .term-grid[data-cursor-blink="true"]\n .term-cursor {\n animation: var(--term-cursor-animation, cursor-blink) 1s step-end infinite;\n}\n\n@keyframes cursor-blink {\n 0%,\n 100% {\n background: var(--term-app-cursor, var(--term-cursor));\n color: var(--term-app-bg, var(--term-bg));\n }\n 50% {\n background: var(--term-cell-bg, transparent);\n color: var(--term-cell-fg, inherit);\n }\n}\n\n@keyframes cursor-line-blink {\n 0%,\n 100% {\n box-shadow: var(--term-cursor-shadow);\n }\n 50% {\n box-shadow: none;\n }\n}\n\n.wterm.has-scrollback,\n.wterm.has-image-flow {\n overflow-y: auto;\n}\n\n.wterm ::selection {\n background: rgba(86, 156, 214, 0.3);\n}\n\n/* Solarized Dark */\n.wterm.theme-solarized-dark {\n --term-fg: #839496;\n --term-bg: #002b36;\n --term-cursor: #93a1a1;\n --term-color-0: #073642;\n --term-color-1: #dc322f;\n --term-color-2: #859900;\n --term-color-3: #b58900;\n --term-color-4: #268bd2;\n --term-color-5: #d33682;\n --term-color-6: #2aa198;\n --term-color-7: #eee8d5;\n --term-color-8: #586e75;\n --term-color-9: #cb4b16;\n --term-color-10: #586e75;\n --term-color-11: #657b83;\n --term-color-12: #839496;\n --term-color-13: #6c71c4;\n --term-color-14: #93a1a1;\n --term-color-15: #fdf6e3;\n}\n\n/* Monokai */\n.wterm.theme-monokai {\n --term-fg: #f8f8f2;\n --term-bg: #272822;\n --term-cursor: #f8f8f0;\n --term-color-0: #272822;\n --term-color-1: #f92672;\n --term-color-2: #a6e22e;\n --term-color-3: #f4bf75;\n --term-color-4: #66d9ef;\n --term-color-5: #ae81ff;\n --term-color-6: #a1efe4;\n --term-color-7: #f8f8f2;\n --term-color-8: #75715e;\n --term-color-9: #f92672;\n --term-color-10: #a6e22e;\n --term-color-11: #f4bf75;\n --term-color-12: #66d9ef;\n --term-color-13: #ae81ff;\n --term-color-14: #a1efe4;\n --term-color-15: #f9f8f5;\n}\n\n/* Light */\n.wterm.theme-light {\n --term-fg: #383a42;\n --term-bg: #fafafa;\n --term-cursor: #526eff;\n --term-color-0: #383a42;\n --term-color-1: #e45649;\n --term-color-2: #50a14f;\n --term-color-3: #c18401;\n --term-color-4: #4078f2;\n --term-color-5: #a626a4;\n --term-color-6: #0184bc;\n --term-color-7: #fafafa;\n --term-color-8: #a0a1a7;\n --term-color-9: #e45649;\n --term-color-10: #50a14f;\n --term-color-11: #c18401;\n --term-color-12: #4078f2;\n --term-color-13: #a626a4;\n --term-color-14: #0184bc;\n --term-color-15: #ffffff;\n}\n';
|
|
5103
5198
|
|
|
@@ -5140,6 +5235,7 @@ var SliccTerminal = class _SliccTerminal extends HTMLElement {
|
|
|
5140
5235
|
#attempt = 0;
|
|
5141
5236
|
#batching = false;
|
|
5142
5237
|
#pasting = false;
|
|
5238
|
+
#queries = new ColorQueries();
|
|
5143
5239
|
#ready = Promise.withResolvers();
|
|
5144
5240
|
constructor() {
|
|
5145
5241
|
super();
|
|
@@ -5205,7 +5301,7 @@ var SliccTerminal = class _SliccTerminal extends HTMLElement {
|
|
|
5205
5301
|
});
|
|
5206
5302
|
}
|
|
5207
5303
|
write(data) {
|
|
5208
|
-
this.#
|
|
5304
|
+
this.#output(data);
|
|
5209
5305
|
}
|
|
5210
5306
|
send(data) {
|
|
5211
5307
|
const bytes = typeof data === "string" ? encoder.encode(data) : data;
|
|
@@ -5259,6 +5355,7 @@ var SliccTerminal = class _SliccTerminal extends HTMLElement {
|
|
|
5259
5355
|
if (!backend) return this.#announce();
|
|
5260
5356
|
const queue = [];
|
|
5261
5357
|
this.#queue = queue;
|
|
5358
|
+
this.#queries = new ColorQueries();
|
|
5262
5359
|
let ended = false;
|
|
5263
5360
|
const current = () => generation === this.#generation && attempt === this.#attempt;
|
|
5264
5361
|
const live = () => !ended && current();
|
|
@@ -5268,7 +5365,7 @@ var SliccTerminal = class _SliccTerminal extends HTMLElement {
|
|
|
5268
5365
|
session = await backend.open(
|
|
5269
5366
|
{
|
|
5270
5367
|
output: (data) => {
|
|
5271
|
-
if (live()) this.#
|
|
5368
|
+
if (live()) this.#output(data);
|
|
5272
5369
|
},
|
|
5273
5370
|
exit: (status) => {
|
|
5274
5371
|
if (!live()) return;
|
|
@@ -5295,6 +5392,22 @@ var SliccTerminal = class _SliccTerminal extends HTMLElement {
|
|
|
5295
5392
|
for (const bytes of queue) session.write(bytes);
|
|
5296
5393
|
this.#announce();
|
|
5297
5394
|
}
|
|
5395
|
+
#output(data) {
|
|
5396
|
+
const term = this.#term;
|
|
5397
|
+
if (!term) return;
|
|
5398
|
+
const part = (from2, to) => typeof data === "string" ? data.slice(from2, to) : data.subarray(from2, to);
|
|
5399
|
+
let from = 0;
|
|
5400
|
+
for (const { at, codes, end } of this.#queries.scan(data)) {
|
|
5401
|
+
term.write(part(from, at));
|
|
5402
|
+
from = at;
|
|
5403
|
+
const colors = themeColors(term.element);
|
|
5404
|
+
for (const code of codes) {
|
|
5405
|
+
const rgb = colors[code];
|
|
5406
|
+
if (rgb) this.send(colorReply(code, rgb, end));
|
|
5407
|
+
}
|
|
5408
|
+
}
|
|
5409
|
+
if (from < data.length) term.write(from ? part(from) : data);
|
|
5410
|
+
}
|
|
5298
5411
|
#batch(change) {
|
|
5299
5412
|
this.#batching = true;
|
|
5300
5413
|
try {
|
|
@@ -5343,4 +5456,4 @@ export {
|
|
|
5343
5456
|
SliccTerminal,
|
|
5344
5457
|
define
|
|
5345
5458
|
};
|
|
5346
|
-
//# sourceMappingURL=chunk-
|
|
5459
|
+
//# sourceMappingURL=chunk-XI74SELH.js.map
|