koneck 2.92.0 → 2.93.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.
@@ -1 +1 @@
1
- {"version":3,"file":"ui-client.d.ts","sourceRoot":"","sources":["../../src/web/ui-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAk9LrC"}
1
+ {"version":3,"file":"ui-client.d.ts","sourceRoot":"","sources":["../../src/web/ui-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,IAAI,MAAM,CA6qMrC"}
@@ -4446,7 +4446,15 @@ $('tfontdown').onclick = () => { term.fontPx = Math.max(9, term.fontPx - 1); app
4446
4446
  * is dispatched as a real mouse event at the same point, so what happens is what would happen to a
4447
4447
  * person clicking there.
4448
4448
  */
4449
- const preview = { shot: null, width: 0 };
4449
+ /*
4450
+ * Nothing here: this held { shot, width } and was read by nothing at all.
4451
+ *
4452
+ * Left over from a version where the panel kept the picture itself. The name is now the panel's own
4453
+ * elements, a few lines down, and two declarations of it stopped the whole client script from
4454
+ * parsing — which takes every handler on the page with it, so the view menu, the composer and the
4455
+ * panel all stop responding at once. Worth knowing that is the symptom: not one broken control but
4456
+ * all of them.
4457
+ */
4450
4458
 
4451
4459
  /*
4452
4460
  * Typing into the page.
@@ -4487,6 +4495,19 @@ function flushTyping() {
4487
4495
  async function pageKey(ev) {
4488
4496
  // Left alone: the browser's own shortcuts, and anything with a modifier that is not Shift.
4489
4497
  if (ev.metaKey || ev.ctrlKey || ev.altKey) return;
4498
+ /*
4499
+ * Scrolling first, and handled here rather than sent to the page as a keypress.
4500
+ *
4501
+ * Pressing PageDown in the page would work too, but only when something scrollable has focus
4502
+ * there — click a text field first and PageDown moves the caret instead, which is the page
4503
+ * behaving correctly and the panel appearing not to. Scrolling the window is unambiguous.
4504
+ */
4505
+ const scroll = SCROLL_KEYS[ev.key];
4506
+ if (scroll) {
4507
+ ev.preventDefault();
4508
+ scroll();
4509
+ return;
4510
+ }
4490
4511
  const special = SPECIAL_KEYS[ev.key];
4491
4512
  if (special) {
4492
4513
  ev.preventDefault();
@@ -4516,92 +4537,215 @@ function pageCoords(img, ev) {
4516
4537
  };
4517
4538
  }
4518
4539
 
4519
- function drawPreview(data) {
4540
+ /**
4541
+ * The preview's own elements, built once and kept.
4542
+ *
4543
+ * It used to empty the panel and build a fresh <img> on every update — so every scroll, click and
4544
+ * refresh blanked the picture, decoded a new one, and put it back. That is the blinking: not a slow
4545
+ * page but a panel demolishing itself thirty times a minute. Reported as "no smooth scrolling, like
4546
+ * opening sections", which is exactly what a sequence of rebuilt stills looks like.
4547
+ *
4548
+ * Held here rather than found by id each time, because the handlers are wired once and must read
4549
+ * whatever is current rather than closing over one draw's data.
4550
+ */
4551
+ const preview = { stage: null, img: null, cursor: null, hint: null, chips: null,
4552
+ controls: [], swapping: false, next: null };
4553
+
4554
+ /**
4555
+ * The pointer, where something just happened.
4556
+ *
4557
+ * Asked for as "see the mouse pointer like a human when operating" — and it is not decoration: a
4558
+ * click whose target you cannot see is a click you cannot check. It moves to the point, presses,
4559
+ * and fades, so watching the panel tells you where the agent went and whether it hit the thing it
4560
+ * meant to.
4561
+ */
4562
+ function showPointer(pageX, pageY, kind) {
4563
+ const img = preview.img;
4564
+ const cursor = preview.cursor;
4565
+ if (!img || !cursor || !img.naturalWidth) return;
4566
+ const box = img.getBoundingClientRect();
4567
+ const stage = preview.stage.getBoundingClientRect();
4568
+ const scale = box.width / img.naturalWidth;
4569
+ cursor.style.left = Math.round(box.left - stage.left + pageX * scale) + 'px';
4570
+ cursor.style.top = Math.round(box.top - stage.top + pageY * scale) + 'px';
4571
+ cursor.hidden = false;
4572
+ // Restarted rather than added to: a second click during the first animation should look like a
4573
+ // second click, not like nothing.
4574
+ cursor.classList.remove('press', 'move');
4575
+ void cursor.offsetWidth;
4576
+ cursor.classList.add(kind === 'press' ? 'press' : 'move');
4577
+ }
4578
+
4579
+ /** Where a control is on the page, from the last read, so the agent's clicks can be pointed at. */
4580
+ function boxOfControl(want) {
4581
+ const found = (preview.controls || []).find((c) =>
4582
+ (typeof want.ref === 'number' && c.ref === want.ref)
4583
+ || (want.selector && c.selector === want.selector)
4584
+ || (want.label && String(c.label || '').toLowerCase() === String(want.label).toLowerCase()));
4585
+ if (!found || !found.box) return null;
4586
+ return { x: found.box.x + found.box.w / 2, y: found.box.y + found.box.h / 2 };
4587
+ }
4588
+
4589
+ /**
4590
+ * Swaps the picture without a blank frame in between.
4591
+ *
4592
+ * decode() waits for the new image to be ready before it is shown, so the old one stays up until
4593
+ * the new one can replace it in a single paint. Without it the src change clears the element and
4594
+ * the panel flashes white between every frame, which is the whole of the flicker.
4595
+ *
4596
+ * Coalesced, because pictures can arrive faster than they decode: while one is being prepared the
4597
+ * newest arrival is held, and anything older than it is dropped — showing a stale frame after a
4598
+ * fresh one is worse than skipping it.
4599
+ */
4600
+ async function swapShot(src) {
4601
+ if (preview.swapping) { preview.next = src; return; }
4602
+ preview.swapping = true;
4603
+ try {
4604
+ for (let src2 = src; src2; src2 = preview.next, preview.next = null) {
4605
+ const loading = new Image();
4606
+ loading.src = src2;
4607
+ try { if (loading.decode) await loading.decode(); } catch (e) { /* show it regardless */ }
4608
+ if (preview.img) preview.img.src = src2;
4609
+ }
4610
+ } finally {
4611
+ preview.swapping = false;
4612
+ }
4613
+ }
4614
+
4615
+ /** The panel's furniture, wired once. */
4616
+ function previewShell() {
4617
+ if (preview.stage && preview.stage.parentNode) return;
4520
4618
  const host = $('pvbody');
4521
4619
  host.innerHTML = '';
4522
- if (!data || data.running === false) {
4523
- host.appendChild(el('div', 'pvnone', (data && data.note)
4524
- || 'Nothing open yet.'));
4525
- $('pvinfo').textContent = '';
4526
- return;
4527
- }
4528
- $('pvurl').value = data.url || $('pvurl').value;
4529
- $('pvinfo').textContent = data.title || '';
4530
- // Shown as unusable rather than silently doing nothing, which is the difference between a
4531
- // control that is off and one that is broken.
4532
- $('pvback').disabled = !(data.nav && data.nav.back);
4533
- $('pvfwd').disabled = !(data.nav && data.nav.forward);
4534
- if (!data.shot) {
4535
- host.appendChild(el('div', 'pvnone', 'The browser is open but produced no picture.'));
4536
- return;
4537
- }
4620
+
4621
+ const stage = el('div', 'pvstage');
4538
4622
  const img = document.createElement('img');
4539
4623
  img.className = 'pvshot';
4540
- img.src = data.shot;
4541
- img.alt = data.title || 'the page';
4624
+ img.alt = 'the page';
4625
+ /*
4626
+ * Focusable, so the keyboard has somewhere to go.
4627
+ *
4628
+ * An image cannot receive key events without this, which was the mechanical reason typing did
4629
+ * nothing: there was no element for the keys to arrive at.
4630
+ */
4631
+ img.tabIndex = 0;
4632
+ const cursor = el('div', 'pvcursor');
4633
+ cursor.hidden = true;
4634
+ stage.appendChild(img);
4635
+ stage.appendChild(cursor);
4636
+ host.appendChild(stage);
4637
+
4638
+ const hint = el('div', 'pvhint');
4639
+ host.appendChild(hint);
4640
+ const chips = el('div', 'pvctl');
4641
+ host.appendChild(chips);
4642
+
4643
+ /*
4644
+ * Buttons for the same thing the keys do.
4645
+ *
4646
+ * They moved a flat 600 pixels, which is most of a page on a laptop and a third of one on a tall
4647
+ * window — so "scroll down" twice could skip a band of the page or barely move. A page is the
4648
+ * picture's height, whatever that is.
4649
+ */
4650
+ const scroller = el('div', 'pvhint');
4651
+ for (const [label, go] of [['↑ page', () => scrollByPages(-1)], ['↓ page', () => scrollByPages(1)],
4652
+ ['top', () => SCROLL_KEYS.Home()], ['end', () => SCROLL_KEYS.End()]]) {
4653
+ const b = el('button', 'pvbtn', label);
4654
+ b.style.margin = '0 4px';
4655
+ b.onclick = () => { if (preview.img) preview.img.focus(); go(); };
4656
+ scroller.appendChild(b);
4657
+ }
4658
+ scroller.appendChild(el('span', 'dim', ' \u2014 or the wheel, PageUp/PageDown, Home/End'));
4659
+ host.appendChild(scroller);
4660
+
4542
4661
  /*
4543
4662
  * The cursor answers the question a browser answers: is there something here to click?
4544
4663
  *
4545
- * It was a crosshair over the whole page, which is the language of a screenshot tool. The
4546
- * controls carry their boxes, so hovering one shows a hand and its label, and everywhere else
4547
- * shows an arrow — the same two states a real page has, from information the panel already had
4548
- * and was discarding.
4664
+ * A crosshair over the whole page is the language of a screenshot tool. The controls carry their
4665
+ * boxes, so hovering one shows a hand and its label and everywhere else shows an arrow — the same
4666
+ * two states a real page has, from information the panel already had.
4549
4667
  */
4550
- const controls = (data.controls || []).filter((c) => c.box);
4551
4668
  img.onmousemove = (ev) => {
4552
4669
  const at = pageCoords(img, ev);
4553
- const over = controls.find((c) =>
4670
+ const over = (preview.controls || []).filter((c) => c.box).find((c) =>
4554
4671
  at.x >= c.box.x && at.x <= c.box.x + c.box.w &&
4555
4672
  at.y >= c.box.y && at.y <= c.box.y + c.box.h);
4556
4673
  img.style.cursor = over ? 'pointer' : 'default';
4557
4674
  img.title = over ? (over.label || over.tag) : '';
4558
4675
  };
4559
4676
  img.onmouseleave = () => { img.style.cursor = 'default'; img.title = ''; };
4560
- /*
4561
- * Focusable, so the keyboard has somewhere to go.
4562
- *
4563
- * An image cannot receive key events without this, which is the mechanical reason typing did
4564
- * nothing: there was no element for the keys to arrive at. Clicking the page focuses it, so
4565
- * clicking a field and then typing works the way it reads.
4566
- */
4567
- img.tabIndex = 0;
4568
4677
  img.onkeydown = (ev) => { void pageKey(ev); };
4569
4678
  img.onblur = () => { void flushTyping(); };
4570
4679
 
4571
- // The picture is 1280 wide whatever it is displayed at, so a click has to be scaled back into
4572
- // page coordinates or it lands somewhere else entirely.
4680
+ // The picture is 1280 wide whatever it is displayed at, so a click is scaled back into page
4681
+ // coordinates or it lands somewhere else entirely.
4573
4682
  img.onclick = async (ev) => {
4574
4683
  img.focus();
4575
4684
  const at = pageCoords(img, ev);
4685
+ showPointer(at.x, at.y, 'press');
4576
4686
  $('pvinfo').textContent = 'clicking ' + at.x + ',' + at.y + '…';
4577
4687
  await browserDo({ action: 'click', x: at.x, y: at.y });
4578
4688
  };
4579
- host.appendChild(img);
4580
- const hint = el('div', 'pvhint',
4581
- 'Click the page to click it for real, then type. ' + (data.controls || []).length
4582
- + ' interactive elements.');
4583
- host.appendChild(hint);
4584
- // The same numbered elements the agent is given, clickable — so a person can drive the flow the
4585
- // agent is stuck on without hunting for the pixel.
4586
- if ((data.controls || []).length) {
4587
- const row = el('div', 'pvctl');
4588
- for (const c of data.controls.slice(0, 18)) {
4689
+
4690
+ preview.stage = stage;
4691
+ preview.img = img;
4692
+ preview.cursor = cursor;
4693
+ preview.hint = hint;
4694
+ preview.chips = chips;
4695
+ }
4696
+
4697
+ function drawPreview(data) {
4698
+ const host = $('pvbody');
4699
+ if (!data || data.running === false) {
4700
+ host.innerHTML = '';
4701
+ preview.stage = null;
4702
+ host.appendChild(el('div', 'pvnone', (data && data.note) || 'Nothing open yet.'));
4703
+ $('pvinfo').textContent = '';
4704
+ return;
4705
+ }
4706
+ $('pvurl').value = data.url || $('pvurl').value;
4707
+ $('pvinfo').textContent = data.title || '';
4708
+ // Shown as unusable rather than silently doing nothing, which is the difference between a
4709
+ // control that is off and one that is broken.
4710
+ $('pvback').disabled = !(data.nav && data.nav.back);
4711
+ $('pvfwd').disabled = !(data.nav && data.nav.forward);
4712
+ if (!data.shot) {
4713
+ host.innerHTML = '';
4714
+ preview.stage = null;
4715
+ host.appendChild(el('div', 'pvnone', 'The browser is open but produced no picture.'));
4716
+ return;
4717
+ }
4718
+
4719
+ previewShell();
4720
+ preview.controls = data.controls || [];
4721
+ void swapShot(data.shot);
4722
+ preview.hint.textContent = 'Click the page to click it for real, then type. '
4723
+ + preview.controls.length + ' interactive elements.';
4724
+
4725
+ /*
4726
+ * The chips, rebuilt only when they have changed.
4727
+ *
4728
+ * They are the one part that genuinely differs between pages, and rebuilding them on every scroll
4729
+ * — when the controls are identical — was throwing away the element under somebody's pointer
4730
+ * mid-click.
4731
+ */
4732
+ const want = preview.controls.slice(0, 18)
4733
+ .map((c) => c.ref + '. ' + (c.label || c.tag)).join('|');
4734
+ if (preview.chips.dataset.shape !== want) {
4735
+ preview.chips.dataset.shape = want;
4736
+ preview.chips.innerHTML = '';
4737
+ for (const c of preview.controls.slice(0, 18)) {
4589
4738
  const b = el('button', 'pvchip', c.ref + '. ' + (c.label || c.tag));
4590
4739
  b.type = 'button';
4591
4740
  b.title = c.selector;
4592
- b.onclick = () => void browserDo({ action: 'click', ref: c.ref });
4593
- row.appendChild(b);
4741
+ b.onclick = () => {
4742
+ const at = boxOfControl({ ref: c.ref });
4743
+ if (at) showPointer(at.x, at.y, 'press');
4744
+ void browserDo({ action: 'click', ref: c.ref });
4745
+ };
4746
+ preview.chips.appendChild(b);
4594
4747
  }
4595
- host.appendChild(row);
4596
- }
4597
- const row = el('div', 'pvhint');
4598
- for (const [label, by] of [['scroll up', -600], ['scroll down', 600]]) {
4599
- const b = el('button', 'pvbtn', label);
4600
- b.style.margin = '0 4px';
4601
- b.onclick = () => void browserDo({ action: 'scroll', by: by });
4602
- row.appendChild(b);
4603
4748
  }
4604
- host.appendChild(row);
4605
4749
  }
4606
4750
 
4607
4751
  /*
@@ -4622,16 +4766,69 @@ function drawPreview(data) {
4622
4766
  $('pvbody').addEventListener('wheel', (ev) => {
4623
4767
  if (!document.querySelector('#pvbody .pvshot')) return; // nothing open to scroll
4624
4768
  ev.preventDefault();
4625
- scrolling.by += ev.deltaY;
4626
- if (scrolling.timer) return;
4627
- scrolling.timer = setTimeout(() => {
4628
- const by = Math.round(scrolling.by);
4629
- scrolling.by = 0;
4630
- scrolling.timer = null;
4631
- if (by !== 0) void browserDo({ action: 'scroll', by: by });
4632
- }, SCROLL_BATCH_MS);
4769
+ queueScroll(ev.deltaY);
4633
4770
  }, { passive: false });
4634
4771
 
4772
+ /*
4773
+ * A click anywhere in the panel gives the page the keyboard.
4774
+ *
4775
+ * Only the picture is focusable, so Page Down after clicking the space beside it did nothing —
4776
+ * focus was on the document body and the panel's keys never fired. A browser viewport does not work
4777
+ * that way: clicking near the page is clicking the page. Buttons and fields are left alone, or
4778
+ * pressing one would take the focus straight back off it again.
4779
+ */
4780
+ $('pvbody').addEventListener('mousedown', (ev) => {
4781
+ if (!preview.img) return;
4782
+ if (ev.target.closest('button, input, select, textarea, a')) return;
4783
+ preview.img.focus();
4784
+ });
4785
+
4786
+ /** Gathers a burst, sends it as one movement. */
4787
+ function queueScroll(by) {
4788
+ scrolling.by += by;
4789
+ if (scrolling.timer) return;
4790
+ scrolling.timer = setTimeout(flushScroll, SCROLL_BATCH_MS);
4791
+ }
4792
+
4793
+ function flushScroll() {
4794
+ const by = Math.round(scrolling.by);
4795
+ scrolling.by = 0;
4796
+ if (scrolling.timer) clearTimeout(scrolling.timer);
4797
+ scrolling.timer = null;
4798
+ if (by !== 0) void browserDo({ action: 'scroll', by: by });
4799
+ }
4800
+
4801
+ /*
4802
+ * Page Down, and the rest of the keys that move a page rather than a few lines.
4803
+ *
4804
+ * A wheel is for reading something already on screen. Getting to the bottom of a long form with one
4805
+ * is thirty gestures, each costing a screenshot, and the panel is not the place to do that. Page Up
4806
+ * and Page Down move a viewport at a time; Home and End go to the ends, expressed as a scroll far
4807
+ * larger than any page because scrollBy clamps and asking for a million pixels lands at the edge.
4808
+ *
4809
+ * A viewport is the picture's own height: the shot is the viewport and nothing beyond it, so its
4810
+ * natural height is exactly how far a page goes. Less a small overlap, so the line you stopped
4811
+ * reading on is still there after the jump — the reason every document reader does this.
4812
+ *
4813
+ * Sent immediately rather than batched. A held Page Down is a handful of events, not fifty, and
4814
+ * waiting on a deliberate keypress reads as the key not working.
4815
+ */
4816
+ const PAGE_OVERLAP = 60;
4817
+
4818
+ function scrollByPages(pages) {
4819
+ const img = preview.img;
4820
+ const viewport = img && img.naturalHeight ? img.naturalHeight : 720;
4821
+ scrolling.by += pages * Math.max(120, viewport - PAGE_OVERLAP);
4822
+ flushScroll();
4823
+ }
4824
+
4825
+ const SCROLL_KEYS = {
4826
+ PageDown: () => scrollByPages(1),
4827
+ PageUp: () => scrollByPages(-1),
4828
+ Home: () => { scrolling.by -= 1e7; flushScroll(); },
4829
+ End: () => { scrolling.by += 1e7; flushScroll(); },
4830
+ };
4831
+
4635
4832
  async function browserDo(body) {
4636
4833
  $('pvinfo').textContent = 'working…';
4637
4834
  let out;
@@ -5037,6 +5234,28 @@ function watchTool(e, done) {
5037
5234
  if (e.name === 'browser') {
5038
5235
  $('watch').hidden = false;
5039
5236
  if (t.url) $('pvurl').value = t.url;
5237
+ /*
5238
+ * The pointer goes where the agent is acting, before the picture catches up.
5239
+ *
5240
+ * Watching a screenshot change is watching the aftermath; watching the pointer arrive and press
5241
+ * is watching the work. The coordinates come either straight from the call or from the box of
5242
+ * the control it named in the last read, which is how a click by ref or label can be pointed at
5243
+ * rather than merely reported.
5244
+ */
5245
+ if (!done) {
5246
+ let asked = null;
5247
+ try { asked = e.args ? JSON.parse(e.args) : null; } catch (err) { asked = null; }
5248
+ if (asked && /^(click|type|fill)$/.test(String(asked.action ?? ''))) {
5249
+ const at = typeof asked.x === 'number' && typeof asked.y === 'number'
5250
+ ? { x: asked.x, y: asked.y }
5251
+ : boxOfControl({ ref: asked.ref, label: asked.label, selector: asked.selector })
5252
+ // A fill names its fields rather than one target: point at the first it can place.
5253
+ ?? (Array.isArray(asked.fields)
5254
+ ? asked.fields.map((f) => boxOfControl(f)).find(Boolean) ?? null
5255
+ : null);
5256
+ if (at) showPointer(at.x, at.y, asked.action === 'click' ? 'press' : 'move');
5257
+ }
5258
+ }
5040
5259
  watchHead(verb, t.url || 'the page');
5041
5260
  trailPush({ label: t.url ? shortUrl(t.url) : 'page', verb, kind: 'page',
5042
5261
  url: t.url || '', ok: done ? e.ok !== false : undefined });
@@ -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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAg9LlB,CAAC;AACF,CAAC"}
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2qMlB,CAAC;AACF,CAAC"}
@@ -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,CAwzC3C"}
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,CA61C3C"}
@@ -560,6 +560,43 @@ footer{flex:0 0 auto;border-top:1px solid var(--line);background:var(--panel);pa
560
560
  .tobottom:hover{background:var(--panel-2)}
561
561
  .tobottom[hidden]{display:none}
562
562
 
563
+ /*
564
+ * The page, and a pointer over it.
565
+ *
566
+ * The stage exists so the cursor can be positioned against the picture without being inside it —
567
+ * an <img> cannot hold a child, and absolutely positioning against the scrolling panel would put
568
+ * the pointer in the wrong place the moment anything moved.
569
+ */
570
+ .pvstage{position:relative;flex:0 0 auto;line-height:0;max-width:100%}
571
+ /*
572
+ * A pointer you can see, where something just happened.
573
+ *
574
+ * Asked for as "see the mouse pointer like a human when operating", and it is not decoration: a
575
+ * click whose target you cannot see is a click you cannot check. Drawn rather than an image, so it
576
+ * costs nothing to load and takes the theme's own colour.
577
+ */
578
+ .pvcursor{position:absolute;width:15px;height:22px;margin:-2px 0 0 -2px;pointer-events:none;
579
+ z-index:5;opacity:0;
580
+ /* An arrow, in the shape every desktop draws it. */
581
+ background:var(--ink);
582
+ -webkit-clip-path:polygon(0 0,0 72%,26% 55%,44% 96%,62% 88%,44% 48%,74% 44%);
583
+ clip-path:polygon(0 0,0 72%,26% 55%,44% 96%,62% 88%,44% 48%,74% 44%);
584
+ filter:drop-shadow(0 0 1px var(--bg)) drop-shadow(0 1px 2px rgba(0,0,0,.5))}
585
+ .pvcursor[hidden]{display:none}
586
+ /* Arriving somewhere: visible, and settling. */
587
+ .pvcursor.move{animation:pvmove .5s ease-out forwards}
588
+ @keyframes pvmove{0%{opacity:.55;transform:scale(1.25)}100%{opacity:.9;transform:scale(1)}}
589
+ /*
590
+ * Pressing: a ring leaves the point, the way a tap looks on a touchscreen.
591
+ *
592
+ * The ring rather than moving the arrow, because an arrow that jumps on click reads as a glitch
593
+ * while a ring reads as contact.
594
+ */
595
+ .pvcursor.press{animation:pvmove .5s ease-out forwards}
596
+ .pvcursor.press::after{content:'';position:absolute;left:-9px;top:-9px;width:26px;height:26px;
597
+ border-radius:50%;border:2px solid var(--cyan);animation:pvring .55s ease-out forwards}
598
+ @keyframes pvring{0%{transform:scale(.2);opacity:.95}100%{transform:scale(1.6);opacity:0}}
599
+
563
600
  /* A heading inside a settings section: quieter than a section, louder than a row. */
564
601
  .sgroup{margin:18px 0 2px;font-size:calc(var(--ui) * 0.7857);letter-spacing:.09em;text-transform:uppercase;
565
602
  color:var(--muted);font-weight:600}
@@ -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;;;;;;;;;;;;;;;;;;;;;;;;;gBAyBO,OAAO;;;oCAGa,IAAI;;2BAEb,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwxC9B,CAAC;AACF,CAAC"}
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;;;;;;;;;;;;;;;;;;;;;;;;;gBAyBO,OAAO;;;oCAGa,IAAI;;2BAEb,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6zC9B,CAAC;AACF,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "koneck",
3
- "version": "2.92.0",
3
+ "version": "2.93.0",
4
4
  "description": "Kinetically Orchestrated Neural Execution Engine for Code",
5
5
  "type": "module",
6
6
  "bin": {