koneck 2.56.0 → 2.58.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/browser.d.ts +7 -0
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +13 -0
- package/dist/browser.js.map +1 -1
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +14 -0
- package/dist/engine.js.map +1 -1
- package/dist/handoff.d.ts +76 -0
- package/dist/handoff.d.ts.map +1 -0
- package/dist/handoff.js +152 -0
- package/dist/handoff.js.map +1 -0
- package/dist/ink-chat.d.ts.map +1 -1
- package/dist/ink-chat.js +2 -0
- package/dist/ink-chat.js.map +1 -1
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +10 -1
- package/dist/tools.js.map +1 -1
- package/dist/types.d.ts +7 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/web/api.d.ts.map +1 -1
- package/dist/web/api.js +58 -0
- package/dist/web/api.js.map +1 -1
- package/dist/web/jobs.d.ts.map +1 -1
- package/dist/web/jobs.js +13 -2
- package/dist/web/jobs.js.map +1 -1
- package/dist/web/sessions.d.ts +4 -0
- package/dist/web/sessions.d.ts.map +1 -1
- package/dist/web/sessions.js +15 -0
- package/dist/web/sessions.js.map +1 -1
- package/dist/web/ui-client.d.ts.map +1 -1
- package/dist/web/ui-client.js +333 -84
- package/dist/web/ui-client.js.map +1 -1
- package/dist/web/ui-css.d.ts.map +1 -1
- package/dist/web/ui-css.js +69 -28
- package/dist/web/ui-css.js.map +1 -1
- package/dist/web/ui.d.ts.map +1 -1
- package/dist/web/ui.js +28 -14
- package/dist/web/ui.js.map +1 -1
- package/img/konect terminal.jpeg +0 -0
- package/package.json +2 -1
package/dist/web/ui-client.js
CHANGED
|
@@ -168,7 +168,14 @@ function setView(name) {
|
|
|
168
168
|
if (name === 'changes') loadChanges();
|
|
169
169
|
if (name === 'timing') loadTiming();
|
|
170
170
|
if (name === 'files') loadTree('');
|
|
171
|
-
if (name === 'terminal') {
|
|
171
|
+
if (name === 'terminal') {
|
|
172
|
+
// Built on first sight and kept, so a pane's scrollback survives leaving the tab and coming
|
|
173
|
+
// back — a terminal that forgets what it printed when you look away is not a terminal.
|
|
174
|
+
if (term.panes.length === 0 || !term.panes[0].el) buildTerminal();
|
|
175
|
+
watchTerminal();
|
|
176
|
+
const here = term.panes[term.active];
|
|
177
|
+
if (here && here.el) here.el.input.focus();
|
|
178
|
+
}
|
|
172
179
|
if (name === 'search') $('q').focus();
|
|
173
180
|
if (name === 'review') loadReview();
|
|
174
181
|
if (name === 'refactor') loadRefactor();
|
|
@@ -2620,8 +2627,17 @@ addEventListener('keydown', (ev) => {
|
|
|
2620
2627
|
*/
|
|
2621
2628
|
function ansiToHtml(text) {
|
|
2622
2629
|
const escChar = String.fromCharCode(27);
|
|
2630
|
+
/*
|
|
2631
|
+
* Colour is kept; everything else a terminal emits is swallowed.
|
|
2632
|
+
*
|
|
2633
|
+
* The last alternative is the one that was missing: an escape followed by a single character —
|
|
2634
|
+
* ESC = for keypad mode, ESC > , ESC 7 to save the cursor — has no bracket, so the CSI pattern
|
|
2635
|
+
* never matched it and it reached the page as a control glyph. That is what appeared at the top
|
|
2636
|
+
* of a pane running git.
|
|
2637
|
+
*/
|
|
2623
2638
|
const pattern = new RegExp(escChar + '\\[([0-9;]*)m|' + escChar + '\\[[0-9;?]*[A-Za-z]|'
|
|
2624
|
-
+ escChar + '\\][^\\u0007]
|
|
2639
|
+
+ escChar + '\\][^\\u0007]*(?:\\u0007|' + escChar + '\\\\)|'
|
|
2640
|
+
+ escChar + '[=>78MDEHcZ]|[\\u0000-\\u0008\\u000b\\u000c\\u000e-\\u001f]', 'g');
|
|
2625
2641
|
let out = '';
|
|
2626
2642
|
let open = 0;
|
|
2627
2643
|
let last = 0;
|
|
@@ -2659,96 +2675,303 @@ function ansiToHtml(text) {
|
|
|
2659
2675
|
* matters is not a setting but a fact about the command: a test run finishes and a dev server
|
|
2660
2676
|
* does not, and a runner that waits for the second one looks broken.
|
|
2661
2677
|
*/
|
|
2662
|
-
|
|
2678
|
+
/*
|
|
2679
|
+
* A terminal, not a form with an output box.
|
|
2680
|
+
*
|
|
2681
|
+
* What was here was a job list beside a pane of text: you typed into a field at the top, picked a
|
|
2682
|
+
* row, and read the result — which arrived in whole-buffer snapshots a few times a second, because
|
|
2683
|
+
* the view polled while the runner had been emitting a line-by-line event all along. Everything
|
|
2684
|
+
* about it said "web page".
|
|
2685
|
+
*
|
|
2686
|
+
* This is a scrollback: the command you typed stays above what it printed, the cursor waits at the
|
|
2687
|
+
* bottom, and the next thing you type continues the same column of text. Up to three panes, each
|
|
2688
|
+
* its own shell with its own history, because two is the common case — watch the server, run the
|
|
2689
|
+
* tests — and four on a laptop is four things too narrow to read.
|
|
2690
|
+
*/
|
|
2691
|
+
const term = {
|
|
2692
|
+
panes: [],
|
|
2693
|
+
/** Which pane the keyboard belongs to. */
|
|
2694
|
+
active: 0,
|
|
2695
|
+
stream: null,
|
|
2696
|
+
/** Pane index by job id, so a line can be routed to the pane that asked for it. */
|
|
2697
|
+
ownerOf: {},
|
|
2698
|
+
fontPx: 12.5,
|
|
2699
|
+
};
|
|
2663
2700
|
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2701
|
+
function newPane() {
|
|
2702
|
+
return { job: null, history: [], at: -1, lines: [], running: false, el: null,
|
|
2703
|
+
/** Where this command's output begins, so a catch-up can replace exactly that. */
|
|
2704
|
+
outputStart: 0,
|
|
2705
|
+
/** How many output lines have arrived on the stream, for the same reason. */
|
|
2706
|
+
received: 0 };
|
|
2707
|
+
}
|
|
2708
|
+
|
|
2709
|
+
/** The pane a job's output belongs to, or null when nothing here started it. */
|
|
2710
|
+
function paneForJob(id) {
|
|
2711
|
+
const idx = term.ownerOf[id];
|
|
2712
|
+
return idx === undefined ? null : term.panes[idx] || null;
|
|
2713
|
+
}
|
|
2714
|
+
|
|
2715
|
+
function buildTerminal() {
|
|
2716
|
+
if (term.panes.length === 0) term.panes.push(newPane());
|
|
2717
|
+
const host = $('termpanes');
|
|
2668
2718
|
host.innerHTML = '';
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
if (j.state === 'running') anyRunning = true;
|
|
2676
|
-
const row = el('div', 'jrow' + (j.id === pick ? ' on' : ''));
|
|
2677
|
-
row.appendChild(el('div', 'jc', j.command));
|
|
2678
|
-
const meta = el('div', 'jm');
|
|
2679
|
-
meta.appendChild(el('span', 'js ' + j.state, j.state
|
|
2680
|
-
+ (j.exitCode !== null && j.state !== 'running' ? ' ' + j.exitCode : '')));
|
|
2681
|
-
// Who ran it is a column, not a separate screen.
|
|
2682
|
-
if (j.by === 'agent') meta.appendChild(el('span', null, 'by the agent'));
|
|
2683
|
-
if (j.background) meta.appendChild(el('span', null, 'background'));
|
|
2684
|
-
if (j.pty) meta.appendChild(el('span', null, 'tty'));
|
|
2685
|
-
meta.appendChild(el('span', null, j.lines + (j.lines === 1 ? ' line' : ' lines')));
|
|
2686
|
-
if (j.state === 'running' && j.by !== 'agent') {
|
|
2687
|
-
const stop = el('button', 'jk', 'kill');
|
|
2688
|
-
stop.onclick = async (ev) => {
|
|
2689
|
-
ev.stopPropagation();
|
|
2690
|
-
try { await api('/api/kill', { method: 'POST', body: JSON.stringify({ id: j.id }) }); }
|
|
2691
|
-
catch (e) {}
|
|
2692
|
-
loadJobs(j.id);
|
|
2693
|
-
};
|
|
2694
|
-
meta.appendChild(stop);
|
|
2719
|
+
term.panes.forEach((pane, index) => {
|
|
2720
|
+
if (index > 0) {
|
|
2721
|
+
// A draggable divider, so a pane can be made wide enough for the thing being read.
|
|
2722
|
+
const grip = el('div', 'termgrip');
|
|
2723
|
+
grip.onmousedown = (ev) => startPaneDrag(ev, index);
|
|
2724
|
+
host.appendChild(grip);
|
|
2695
2725
|
}
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2726
|
+
const box = el('div', 'termpane' + (index === term.active ? ' on' : ''));
|
|
2727
|
+
box.style.flex = String(pane.flex || 1);
|
|
2728
|
+
box.onmousedown = () => { term.active = index; markActivePane(); };
|
|
2729
|
+
|
|
2730
|
+
const scroll = el('div', 'termscroll');
|
|
2731
|
+
const body = el('pre', 'termbody');
|
|
2732
|
+
scroll.appendChild(body);
|
|
2733
|
+
|
|
2734
|
+
const row = el('div', 'termrow');
|
|
2735
|
+
row.appendChild(el('span', 'termps', '$'));
|
|
2736
|
+
const input = document.createElement('input');
|
|
2737
|
+
input.className = 'termin';
|
|
2738
|
+
input.spellcheck = false;
|
|
2739
|
+
input.autocomplete = 'off';
|
|
2740
|
+
input.placeholder = index === 0 ? 'npm test, git status, npm run dev…' : '';
|
|
2741
|
+
input.onkeydown = (ev) => paneKey(ev, index);
|
|
2742
|
+
input.onfocus = () => { term.active = index; markActivePane(); };
|
|
2743
|
+
row.appendChild(input);
|
|
2744
|
+
const stop = el('button', 'termstop', 'stop');
|
|
2745
|
+
stop.title = 'Kill what is running in this pane';
|
|
2746
|
+
stop.onclick = () => void killPane(index);
|
|
2747
|
+
row.appendChild(stop);
|
|
2748
|
+
|
|
2749
|
+
box.appendChild(scroll);
|
|
2750
|
+
box.appendChild(row);
|
|
2751
|
+
host.appendChild(box);
|
|
2752
|
+
pane.el = { box: box, scroll: scroll, body: body, input: input, stop: stop };
|
|
2753
|
+
paintPane(index);
|
|
2754
|
+
});
|
|
2755
|
+
applyTerminalLook();
|
|
2756
|
+
markActivePane();
|
|
2757
|
+
const here = term.panes[term.active];
|
|
2758
|
+
if (here && here.el) here.el.input.focus();
|
|
2711
2759
|
}
|
|
2712
2760
|
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
const
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2761
|
+
function markActivePane() {
|
|
2762
|
+
term.panes.forEach((pane, i) => {
|
|
2763
|
+
if (pane.el) pane.el.box.className = 'termpane' + (i === term.active ? ' on' : '');
|
|
2764
|
+
});
|
|
2765
|
+
}
|
|
2766
|
+
|
|
2767
|
+
/** Everything this pane has printed, as one column of text. */
|
|
2768
|
+
function paintPane(index) {
|
|
2769
|
+
const pane = term.panes[index];
|
|
2770
|
+
if (!pane || !pane.el) return;
|
|
2771
|
+
const atEnd = pane.el.scroll.scrollHeight - pane.el.scroll.scrollTop
|
|
2772
|
+
- pane.el.scroll.clientHeight < 60;
|
|
2773
|
+
pane.el.body.innerHTML = ansiToHtml(pane.lines.join('\n'));
|
|
2774
|
+
pane.el.stop.hidden = !pane.running;
|
|
2775
|
+
if (atEnd) pane.el.scroll.scrollTop = pane.el.scroll.scrollHeight;
|
|
2776
|
+
}
|
|
2777
|
+
|
|
2778
|
+
function pushPane(index, line, redraw) {
|
|
2779
|
+
const pane = term.panes[index];
|
|
2780
|
+
if (!pane) return;
|
|
2781
|
+
if (redraw && pane.lines.length > 0) pane.lines[pane.lines.length - 1] = line;
|
|
2782
|
+
else pane.lines.push(line);
|
|
2783
|
+
while (pane.lines.length > 4000) pane.lines.shift();
|
|
2784
|
+
paintPane(index);
|
|
2785
|
+
}
|
|
2786
|
+
|
|
2787
|
+
async function paneKey(ev, index) {
|
|
2788
|
+
const pane = term.panes[index];
|
|
2789
|
+
if (!pane || !pane.el) return;
|
|
2790
|
+
const input = pane.el.input;
|
|
2791
|
+
if (ev.key === 'Enter') {
|
|
2792
|
+
const command = input.value.trim();
|
|
2793
|
+
input.value = '';
|
|
2794
|
+
if (command === '') { pushPane(index, '$ '); return; }
|
|
2795
|
+
if (command === 'clear') { pane.lines = []; paintPane(index); return; }
|
|
2796
|
+
pane.history.push(command);
|
|
2797
|
+
pane.at = pane.history.length;
|
|
2798
|
+
// Echoed above its own output, which is the whole difference from a form.
|
|
2799
|
+
pushPane(index, '$ ' + command);
|
|
2800
|
+
pane.outputStart = pane.lines.length;
|
|
2801
|
+
pane.received = 0;
|
|
2802
|
+
await runInPane(index, command);
|
|
2803
|
+
return;
|
|
2729
2804
|
}
|
|
2730
|
-
|
|
2805
|
+
// A history nobody has to think about: up and down, as everywhere else.
|
|
2806
|
+
if (ev.key === 'ArrowUp') {
|
|
2807
|
+
ev.preventDefault();
|
|
2808
|
+
if (pane.at > 0) pane.at--;
|
|
2809
|
+
input.value = pane.history[pane.at] || '';
|
|
2810
|
+
return;
|
|
2811
|
+
}
|
|
2812
|
+
if (ev.key === 'ArrowDown') {
|
|
2813
|
+
ev.preventDefault();
|
|
2814
|
+
if (pane.at < pane.history.length) pane.at++;
|
|
2815
|
+
input.value = pane.history[pane.at] || '';
|
|
2816
|
+
return;
|
|
2817
|
+
}
|
|
2818
|
+
if (ev.key === 'c' && ev.ctrlKey) { void killPane(index); }
|
|
2731
2819
|
}
|
|
2732
2820
|
|
|
2733
|
-
async function
|
|
2734
|
-
const
|
|
2735
|
-
if (!
|
|
2821
|
+
async function runInPane(index, command) {
|
|
2822
|
+
const pane = term.panes[index];
|
|
2823
|
+
if (!pane) return;
|
|
2824
|
+
// Anything that does not exit on its own is a background job; a runner that waits for a dev
|
|
2825
|
+
// server looks broken, and the fact is about the command rather than a box somebody ticked.
|
|
2826
|
+
const looksLikeServer = /\b(dev|serve|start|watch|nodemon|vite|next\s+dev)\b/.test(command);
|
|
2736
2827
|
let out;
|
|
2737
2828
|
try {
|
|
2738
|
-
out = await api('/api/run', { method: 'POST',
|
|
2739
|
-
command: command, background:
|
|
2829
|
+
out = await api('/api/run', { method: 'POST',
|
|
2830
|
+
body: JSON.stringify({ command: command, background: looksLikeServer }) });
|
|
2740
2831
|
} catch (e) {
|
|
2741
|
-
|
|
2832
|
+
pushPane(index, e.message);
|
|
2742
2833
|
return;
|
|
2743
2834
|
}
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2835
|
+
pane.job = out.id;
|
|
2836
|
+
pane.running = true;
|
|
2837
|
+
term.ownerOf[out.id] = index;
|
|
2838
|
+
paintPane(index);
|
|
2839
|
+
|
|
2840
|
+
/*
|
|
2841
|
+
* One catch-up read, because a command can outrun its own stream.
|
|
2842
|
+
*
|
|
2843
|
+
* The event stream is opened when the tab is first shown and takes a moment to establish. A
|
|
2844
|
+
* command typed inside that moment printed its first lines before anything was listening, and
|
|
2845
|
+
* they were gone: the pane showed the echoed command and nothing under it. Measured — the stream
|
|
2846
|
+
* was still in readyState 0 when the lines were emitted.
|
|
2847
|
+
*
|
|
2848
|
+
* So the runner is asked once, shortly after, what the job has actually produced, and anything
|
|
2849
|
+
* the stream missed is filled in. Counted rather than merged, so a line never appears twice.
|
|
2850
|
+
*/
|
|
2851
|
+
setTimeout(() => { void catchUpPane(index, out.id); }, 400);
|
|
2747
2852
|
}
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2853
|
+
|
|
2854
|
+
async function catchUpPane(index, jobId) {
|
|
2855
|
+
const pane = term.panes[index];
|
|
2856
|
+
if (!pane || pane.job !== jobId) return;
|
|
2857
|
+
let job;
|
|
2858
|
+
try { job = await api('/api/jobs?id=' + encodeURIComponent(jobId)); } catch (e) { return; }
|
|
2859
|
+
const produced = (job.lines || []).length;
|
|
2860
|
+
if (produced <= pane.received) return;
|
|
2861
|
+
pane.lines = pane.lines.slice(0, pane.outputStart).concat(job.lines || []);
|
|
2862
|
+
pane.received = produced;
|
|
2863
|
+
if (job.state && job.state !== 'running') pane.running = false;
|
|
2864
|
+
paintPane(index);
|
|
2865
|
+
}
|
|
2866
|
+
|
|
2867
|
+
async function killPane(index) {
|
|
2868
|
+
const pane = term.panes[index];
|
|
2869
|
+
if (!pane || !pane.job || !pane.running) return;
|
|
2870
|
+
try { await api('/api/kill', { method: 'POST', body: JSON.stringify({ id: pane.job }) }); }
|
|
2871
|
+
catch (e) { pushPane(index, e.message); }
|
|
2872
|
+
}
|
|
2873
|
+
|
|
2874
|
+
/*
|
|
2875
|
+
* Live, from the runner's own event stream.
|
|
2876
|
+
*
|
|
2877
|
+
* Its own stream rather than the session's: a command belongs to the workspace, not to whichever
|
|
2878
|
+
* conversation was open when it was typed.
|
|
2879
|
+
*/
|
|
2880
|
+
function watchTerminal() {
|
|
2881
|
+
if (term.stream) return;
|
|
2882
|
+
const url = '/api/terminal/events' + (state.token ? '?token=' + encodeURIComponent(state.token) : '');
|
|
2883
|
+
const source = new EventSource(url);
|
|
2884
|
+
term.stream = source;
|
|
2885
|
+
source.onmessage = (ev) => {
|
|
2886
|
+
let e;
|
|
2887
|
+
try { e = JSON.parse(ev.data); } catch (err) { return; }
|
|
2888
|
+
if (e.t === 'job-line') {
|
|
2889
|
+
const idx = term.ownerOf[e.id];
|
|
2890
|
+
if (idx === undefined) return;
|
|
2891
|
+
const pane = term.panes[idx];
|
|
2892
|
+
if (pane && !e.redraw) pane.received++;
|
|
2893
|
+
pushPane(idx, e.line, e.redraw === true);
|
|
2894
|
+
noticeServedUrl(e.line);
|
|
2895
|
+
return;
|
|
2896
|
+
}
|
|
2897
|
+
if (e.t === 'job' && e.job) {
|
|
2898
|
+
const idx = term.ownerOf[e.job.id];
|
|
2899
|
+
if (idx === undefined) return;
|
|
2900
|
+
const pane = term.panes[idx];
|
|
2901
|
+
if (!pane) return;
|
|
2902
|
+
if (e.job.state !== 'running') {
|
|
2903
|
+
pane.running = false;
|
|
2904
|
+
// Said the way a shell says it, rather than as a status badge.
|
|
2905
|
+
pushPane(idx, e.job.exitCode === 0 || e.job.exitCode === null
|
|
2906
|
+
? ''
|
|
2907
|
+
: '[' + e.job.state + ' ' + e.job.exitCode + ']');
|
|
2908
|
+
}
|
|
2909
|
+
paintPane(idx);
|
|
2910
|
+
}
|
|
2911
|
+
};
|
|
2912
|
+
source.onerror = () => { /* the browser reconnects on its own */ };
|
|
2913
|
+
}
|
|
2914
|
+
|
|
2915
|
+
/** Font size and backdrop, applied to every pane at once. */
|
|
2916
|
+
function applyTerminalLook() {
|
|
2917
|
+
const host = $('termpanes');
|
|
2918
|
+
host.style.setProperty('--term-font', term.fontPx + 'px');
|
|
2919
|
+
const on = $('tbgimg').checked;
|
|
2920
|
+
const strength = Number($('tbgop').value) / 100;
|
|
2921
|
+
host.classList.toggle('backdrop', on);
|
|
2922
|
+
host.style.setProperty('--term-bg-strength', on ? String(strength) : '0');
|
|
2923
|
+
if (on && !host.style.getPropertyValue('--term-bg-image')) {
|
|
2924
|
+
const url = '/api/terminal/background'
|
|
2925
|
+
+ (state.token ? '?token=' + encodeURIComponent(state.token) : '');
|
|
2926
|
+
host.style.setProperty('--term-bg-image', 'url("' + url + '")');
|
|
2927
|
+
}
|
|
2928
|
+
}
|
|
2929
|
+
|
|
2930
|
+
function startPaneDrag(ev, dividerIndex) {
|
|
2931
|
+
ev.preventDefault();
|
|
2932
|
+
const left = term.panes[dividerIndex - 1];
|
|
2933
|
+
const right = term.panes[dividerIndex];
|
|
2934
|
+
if (!left || !right || !left.el || !right.el) return;
|
|
2935
|
+
const startX = ev.clientX;
|
|
2936
|
+
const leftWas = left.el.box.getBoundingClientRect().width;
|
|
2937
|
+
const rightWas = right.el.box.getBoundingClientRect().width;
|
|
2938
|
+
const total = leftWas + rightWas;
|
|
2939
|
+
const move = (m) => {
|
|
2940
|
+
const wanted = Math.min(Math.max(leftWas + (m.clientX - startX), 120), total - 120);
|
|
2941
|
+
left.flex = wanted / total;
|
|
2942
|
+
right.flex = (total - wanted) / total;
|
|
2943
|
+
left.el.box.style.flex = String(left.flex);
|
|
2944
|
+
right.el.box.style.flex = String(right.flex);
|
|
2945
|
+
};
|
|
2946
|
+
const up = () => {
|
|
2947
|
+
window.removeEventListener('mousemove', move);
|
|
2948
|
+
window.removeEventListener('mouseup', up);
|
|
2949
|
+
};
|
|
2950
|
+
window.addEventListener('mousemove', move);
|
|
2951
|
+
window.addEventListener('mouseup', up);
|
|
2952
|
+
}
|
|
2953
|
+
|
|
2954
|
+
$('tsplit').onclick = () => {
|
|
2955
|
+
// Three, deliberately. Four on a laptop is four things too narrow to read.
|
|
2956
|
+
if (term.panes.length >= 3) return;
|
|
2957
|
+
term.panes.push(newPane());
|
|
2958
|
+
term.active = term.panes.length - 1;
|
|
2959
|
+
buildTerminal();
|
|
2960
|
+
};
|
|
2961
|
+
|
|
2962
|
+
$('tunsplit').onclick = () => {
|
|
2963
|
+
if (term.panes.length <= 1) return;
|
|
2964
|
+
const gone = term.panes.pop();
|
|
2965
|
+
if (gone && gone.job) delete term.ownerOf[gone.job];
|
|
2966
|
+
term.active = Math.min(term.active, term.panes.length - 1);
|
|
2967
|
+
buildTerminal();
|
|
2968
|
+
};
|
|
2969
|
+
|
|
2970
|
+
$('tbgimg').onchange = applyTerminalLook;
|
|
2971
|
+
$('tbgop').oninput = applyTerminalLook;
|
|
2972
|
+
$('tfontup').onclick = () => { term.fontPx = Math.min(20, term.fontPx + 1); applyTerminalLook(); };
|
|
2973
|
+
$('tfontdown').onclick = () => { term.fontPx = Math.max(9, term.fontPx - 1); applyTerminalLook(); };
|
|
2974
|
+
|
|
2752
2975
|
|
|
2753
2976
|
/* ── the page, as it really renders ───────────────────────────────────────────────────────── */
|
|
2754
2977
|
|
|
@@ -2762,6 +2985,16 @@ $('tcmd').addEventListener('keydown', (ev) => {
|
|
|
2762
2985
|
*/
|
|
2763
2986
|
const preview = { shot: null, width: 0 };
|
|
2764
2987
|
|
|
2988
|
+
/** Where in the page a pointer event landed, scaled back from however wide the picture is drawn. */
|
|
2989
|
+
function pageCoords(img, ev) {
|
|
2990
|
+
const box = img.getBoundingClientRect();
|
|
2991
|
+
const scale = img.naturalWidth / box.width;
|
|
2992
|
+
return {
|
|
2993
|
+
x: Math.round((ev.clientX - box.left) * scale),
|
|
2994
|
+
y: Math.round((ev.clientY - box.top) * scale),
|
|
2995
|
+
};
|
|
2996
|
+
}
|
|
2997
|
+
|
|
2765
2998
|
function drawPreview(data) {
|
|
2766
2999
|
const host = $('pvbody');
|
|
2767
3000
|
host.innerHTML = '';
|
|
@@ -2785,15 +3018,31 @@ function drawPreview(data) {
|
|
|
2785
3018
|
img.className = 'pvshot';
|
|
2786
3019
|
img.src = data.shot;
|
|
2787
3020
|
img.alt = data.title || 'the page';
|
|
3021
|
+
/*
|
|
3022
|
+
* The cursor answers the question a browser answers: is there something here to click?
|
|
3023
|
+
*
|
|
3024
|
+
* It was a crosshair over the whole page, which is the language of a screenshot tool. The
|
|
3025
|
+
* controls carry their boxes, so hovering one shows a hand and its label, and everywhere else
|
|
3026
|
+
* shows an arrow — the same two states a real page has, from information the panel already had
|
|
3027
|
+
* and was discarding.
|
|
3028
|
+
*/
|
|
3029
|
+
const controls = (data.controls || []).filter((c) => c.box);
|
|
3030
|
+
img.onmousemove = (ev) => {
|
|
3031
|
+
const at = pageCoords(img, ev);
|
|
3032
|
+
const over = controls.find((c) =>
|
|
3033
|
+
at.x >= c.box.x && at.x <= c.box.x + c.box.w &&
|
|
3034
|
+
at.y >= c.box.y && at.y <= c.box.y + c.box.h);
|
|
3035
|
+
img.style.cursor = over ? 'pointer' : 'default';
|
|
3036
|
+
img.title = over ? (over.label || over.tag) : '';
|
|
3037
|
+
};
|
|
3038
|
+
img.onmouseleave = () => { img.style.cursor = 'default'; img.title = ''; };
|
|
3039
|
+
|
|
2788
3040
|
// The picture is 1280 wide whatever it is displayed at, so a click has to be scaled back into
|
|
2789
3041
|
// page coordinates or it lands somewhere else entirely.
|
|
2790
3042
|
img.onclick = async (ev) => {
|
|
2791
|
-
const
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
const y = Math.round((ev.clientY - box.top) * scale);
|
|
2795
|
-
$('pvinfo').textContent = 'clicking ' + x + ',' + y + '…';
|
|
2796
|
-
await browserDo({ action: 'click', x: x, y: y });
|
|
3043
|
+
const at = pageCoords(img, ev);
|
|
3044
|
+
$('pvinfo').textContent = 'clicking ' + at.x + ',' + at.y + '…';
|
|
3045
|
+
await browserDo({ action: 'click', x: at.x, y: at.y });
|
|
2797
3046
|
};
|
|
2798
3047
|
host.appendChild(img);
|
|
2799
3048
|
const hint = el('div', 'pvhint',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui-client.js","sourceRoot":"","sources":["../../src/web/ui-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,YAAY;IAC1B,OAAO,MAAM,CAAC,GAAG,CAAA
|
|
1
|
+
{"version":3,"file":"ui-client.js","sourceRoot":"","sources":["../../src/web/ui-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,YAAY;IAC1B,OAAO,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6jIlB,CAAC;AACF,CAAC"}
|
package/dist/web/ui-css.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui-css.d.ts","sourceRoot":"","sources":["../../src/web/ui-css.ts"],"names":[],"mappings":"AA8CA,wBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"ui-css.d.ts","sourceRoot":"","sources":["../../src/web/ui-css.ts"],"names":[],"mappings":"AA8CA,wBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAi9B3C"}
|
package/dist/web/ui-css.js
CHANGED
|
@@ -789,34 +789,67 @@ body[data-tint="high"]{filter:contrast(1.14)}
|
|
|
789
789
|
body[data-tint="soft"]{filter:contrast(.92) brightness(1.04)}
|
|
790
790
|
|
|
791
791
|
/* ── a terminal ───────────────────────────────────────────────────────────────────────────── */
|
|
792
|
-
|
|
793
|
-
.
|
|
792
|
+
/*
|
|
793
|
+
* A terminal that reads as one.
|
|
794
|
+
*
|
|
795
|
+
* The difference from the box that was here is not decoration. A terminal is a single column of
|
|
796
|
+
* monospaced text where the command you typed stays above what it printed and the cursor waits at
|
|
797
|
+
* the bottom of it. So: no card around the output, no border between the prompt and the scrollback,
|
|
798
|
+
* one background, and the input line styled as the last line of the text rather than as a form
|
|
799
|
+
* field sitting under it.
|
|
800
|
+
*/
|
|
801
|
+
/*
|
|
802
|
+
* The terminal view fills what it is given.
|
|
803
|
+
*
|
|
804
|
+
* A view scrolls its own overflow, which is right for a document and wrong for a terminal: the
|
|
805
|
+
* panes ended a third of the way down the window with dead space under them, because nothing told
|
|
806
|
+
* them how tall they were allowed to be.
|
|
807
|
+
*/
|
|
808
|
+
#terminalview{display:flex;flex-direction:column;overflow:hidden}
|
|
809
|
+
.termtop{display:flex;gap:8px;align-items:center;padding:9px 14px;background:var(--panel);
|
|
794
810
|
border-bottom:1px solid var(--line);flex:0 0 auto}
|
|
795
|
-
.
|
|
796
|
-
.
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
.
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
.
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
.
|
|
808
|
-
|
|
809
|
-
.
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
.
|
|
819
|
-
|
|
811
|
+
.termttl{font-size:12px;color:var(--muted);letter-spacing:.02em}
|
|
812
|
+
.termgap{flex:0 0 10px}
|
|
813
|
+
.termbtn{padding:4px 10px;border-radius:7px;border:1px solid var(--line-2);color:var(--muted);
|
|
814
|
+
background:transparent;cursor:pointer;font-size:11.5px}
|
|
815
|
+
.termbtn:hover{border-color:var(--cyan);color:var(--cyan)}
|
|
816
|
+
.termchk{display:flex;gap:5px;align-items:center;font-size:11.5px;color:var(--muted);cursor:pointer}
|
|
817
|
+
.termchk input{accent-color:var(--cyan);cursor:pointer}
|
|
818
|
+
#tbgop{width:88px;accent-color:var(--cyan)}
|
|
819
|
+
|
|
820
|
+
.termpanes{--term-font:12.5px;--term-bg-strength:0;--term-bg-image:none;
|
|
821
|
+
flex:1;display:flex;min-height:0;background:var(--bg)}
|
|
822
|
+
.termgrip{flex:0 0 5px;cursor:col-resize;background:var(--line);opacity:.6}
|
|
823
|
+
.termgrip:hover{background:var(--cyan);opacity:1}
|
|
824
|
+
|
|
825
|
+
.termpane{position:relative;display:flex;flex-direction:column;min-width:0;min-height:0;
|
|
826
|
+
border-left:1px solid transparent}
|
|
827
|
+
.termpane.on{border-left-color:var(--cyan)}
|
|
828
|
+
/*
|
|
829
|
+
* The backdrop sits behind the text at a weight the reader chooses, and never on top of it.
|
|
830
|
+
*
|
|
831
|
+
* Its own layer rather than a background on the pane: an image behind live text needs to be dimmed
|
|
832
|
+
* without dimming the text, and an opacity on the pane itself would take the characters with it.
|
|
833
|
+
*/
|
|
834
|
+
.termpane::before{content:'';position:absolute;inset:0;pointer-events:none;
|
|
835
|
+
background-image:var(--term-bg-image);background-size:cover;background-position:center;
|
|
836
|
+
opacity:var(--term-bg-strength);transition:opacity .18s ease}
|
|
837
|
+
.termscroll{position:relative;flex:1;min-height:0;overflow:auto;padding:12px 14px 4px}
|
|
838
|
+
.termbody{margin:0;font-family:var(--mono);font-size:var(--term-font);line-height:1.55;
|
|
839
|
+
white-space:pre-wrap;word-break:break-word;color:var(--ink)}
|
|
840
|
+
.termrow{position:relative;display:flex;gap:8px;align-items:center;padding:2px 14px 12px}
|
|
841
|
+
.termps{font-family:var(--mono);font-size:var(--term-font);color:var(--cyan);flex:0 0 auto}
|
|
842
|
+
/*
|
|
843
|
+
* The input is the last line of the scrollback, not a control under it: no border, no background,
|
|
844
|
+
* the same font and size as the text above, and a caret that looks like a terminal's.
|
|
845
|
+
*/
|
|
846
|
+
.termin{flex:1;min-width:0;border:0;outline:0;background:transparent;color:var(--ink);
|
|
847
|
+
font-family:var(--mono);font-size:var(--term-font);line-height:1.55;caret-color:var(--cyan);
|
|
848
|
+
padding:0}
|
|
849
|
+
.termin::placeholder{color:var(--dim)}
|
|
850
|
+
.termstop{flex:0 0 auto;padding:2px 9px;border-radius:6px;border:1px solid var(--red);
|
|
851
|
+
color:var(--red);background:transparent;cursor:pointer;font-size:10.5px}
|
|
852
|
+
.termpanes .oe{color:var(--red)}
|
|
820
853
|
|
|
821
854
|
/* ── the page, as it really renders ───────────────────────────────────────────────────────── */
|
|
822
855
|
.pvbar{display:flex;gap:8px;align-items:center;padding:11px 14px;background:var(--panel);
|
|
@@ -838,7 +871,15 @@ body[data-tint="soft"]{filter:contrast(.92) brightness(1.04)}
|
|
|
838
871
|
.pvbody{flex:1;overflow:auto;min-height:0;display:flex;flex-direction:column;
|
|
839
872
|
align-items:center;padding:12px;background:var(--panel-2)}
|
|
840
873
|
/* The screenshot is the page. Clicking it clicks the page at the same point. */
|
|
841
|
-
|
|
874
|
+
/*
|
|
875
|
+
* A page behaves like a page: an arrow over it, a hand over what can be clicked.
|
|
876
|
+
*
|
|
877
|
+
* It was a crosshair everywhere, which is the language of a screenshot tool — "pick a coordinate" —
|
|
878
|
+
* and the panel is not a screenshot tool. The controls already carry their boxes, so the client
|
|
879
|
+
* switches between the two the way a browser does, and clicking still lands as a real mouse event
|
|
880
|
+
* at the same point.
|
|
881
|
+
*/
|
|
882
|
+
.pvshot{max-width:100%;border:1px solid var(--line);border-radius:8px;cursor:default;
|
|
842
883
|
background:#fff;box-shadow:var(--shadow)}
|
|
843
884
|
.pvhint{margin-top:11px;font-size:11.5px;color:var(--dim);text-align:center;line-height:1.6}
|
|
844
885
|
/* The same numbered elements the agent is given, so a person can drive the flow it is stuck on. */
|
package/dist/web/ui-css.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui-css.js","sourceRoot":"","sources":["../../src/web/ui-css.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH;;;;;;;;;;;;GAYG;AACH,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;;CAkBZ,CAAC;AAEF,MAAM,UAAU,GAAG,CAAC,OAAe;IACjC,OAAO;;;;;;;;;;;;;;;;;gBAiBO,OAAO;;;oCAGa,IAAI;;2BAEb,IAAI
|
|
1
|
+
{"version":3,"file":"ui-css.js","sourceRoot":"","sources":["../../src/web/ui-css.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH;;;;;;;;;;;;GAYG;AACH,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;;CAkBZ,CAAC;AAEF,MAAM,UAAU,GAAG,CAAC,OAAe;IACjC,OAAO;;;;;;;;;;;;;;;;;gBAiBO,OAAO;;;oCAGa,IAAI;;2BAEb,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAy7B9B,CAAC;AACF,CAAC"}
|
package/dist/web/ui.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../src/web/ui.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,wBAAgB,IAAI,IAAI,MAAM,
|
|
1
|
+
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../src/web/ui.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,wBAAgB,IAAI,IAAI,MAAM,CAiX7B"}
|