@phenx-inc/ctlsurf 0.6.0 → 0.7.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.
Files changed (26) hide show
  1. package/out/headless/index.mjs +1 -1
  2. package/out/headless/index.mjs.map +1 -1
  3. package/out/renderer/assets/{cssMode-DbMmcl1h.js → cssMode-eTXVdAkZ.js} +3 -3
  4. package/out/renderer/assets/{freemarker2-CvaHiy92.js → freemarker2-B5BKaiK4.js} +1 -1
  5. package/out/renderer/assets/{handlebars-D58lUIOu.js → handlebars-BIdLd2wU.js} +1 -1
  6. package/out/renderer/assets/{html-D1h1aJbM.js → html-BXL4cnLS.js} +1 -1
  7. package/out/renderer/assets/{htmlMode-BdkAp9qr.js → htmlMode-46N3XG2c.js} +3 -3
  8. package/out/renderer/assets/{index-DJFYmHjz.css → index-Cf-RsxoC.css} +74 -0
  9. package/out/renderer/assets/{index-B60JU1yI.js → index-dRvutfbl.js} +180 -27
  10. package/out/renderer/assets/{javascript-CXqZcnvb.js → javascript-n_iZZzDX.js} +2 -2
  11. package/out/renderer/assets/{jsonMode-BuVr-eSl.js → jsonMode-DXDczSNu.js} +3 -3
  12. package/out/renderer/assets/{liquid-LKu0Wd0B.js → liquid-B1QweUh7.js} +1 -1
  13. package/out/renderer/assets/{lspLanguageFeatures-Cjr_4HGs.js → lspLanguageFeatures-DqzMqkRk.js} +1 -1
  14. package/out/renderer/assets/{mdx-Bl84ILla.js → mdx-BCv8lm5e.js} +1 -1
  15. package/out/renderer/assets/{python-0sFd9G1k.js → python-BLNzYwDv.js} +1 -1
  16. package/out/renderer/assets/{razor-Cqcu1rLJ.js → razor-CvAww8bG.js} +1 -1
  17. package/out/renderer/assets/{tsMode-CYd3NUkW.js → tsMode-C7m6Kr5E.js} +1 -1
  18. package/out/renderer/assets/{typescript-rkc9lhpi.js → typescript-DhPw4VVg.js} +1 -1
  19. package/out/renderer/assets/{xml-EsHEUps1.js → xml-B0WLFJ2U.js} +1 -1
  20. package/out/renderer/assets/{yaml-B9-nQ_s2.js → yaml-BWyn9Wd7.js} +1 -1
  21. package/out/renderer/index.html +2 -2
  22. package/package.json +1 -1
  23. package/src/renderer/App.tsx +34 -6
  24. package/src/renderer/components/FloatingMic.tsx +128 -0
  25. package/src/renderer/components/VoiceInput.tsx +11 -3
  26. package/src/renderer/styles.css +74 -0
@@ -1,6 +1,6 @@
1
- import { c as createWebWorker, l as languages } from "./index-B60JU1yI.js";
2
- import { C as CompletionAdapter, H as HoverAdapter, D as DocumentHighlightAdapter, a as DefinitionAdapter, R as ReferenceAdapter, b as DocumentSymbolAdapter, c as RenameAdapter, d as DocumentColorAdapter, F as FoldingRangeAdapter, e as DiagnosticsAdapter, S as SelectionRangeAdapter, f as DocumentFormattingEditProvider, g as DocumentRangeFormattingEditProvider } from "./lspLanguageFeatures-Cjr_4HGs.js";
3
- import { h, i, j, t, k } from "./lspLanguageFeatures-Cjr_4HGs.js";
1
+ import { c as createWebWorker, l as languages } from "./index-dRvutfbl.js";
2
+ import { C as CompletionAdapter, H as HoverAdapter, D as DocumentHighlightAdapter, a as DefinitionAdapter, R as ReferenceAdapter, b as DocumentSymbolAdapter, c as RenameAdapter, d as DocumentColorAdapter, F as FoldingRangeAdapter, e as DiagnosticsAdapter, S as SelectionRangeAdapter, f as DocumentFormattingEditProvider, g as DocumentRangeFormattingEditProvider } from "./lspLanguageFeatures-DqzMqkRk.js";
3
+ import { h, i, j, t, k } from "./lspLanguageFeatures-DqzMqkRk.js";
4
4
  const STOP_WHEN_IDLE_FOR = 2 * 60 * 1e3;
5
5
  class WorkerManager {
6
6
  constructor(defaults) {
@@ -1,4 +1,4 @@
1
- import { l as languages } from "./index-B60JU1yI.js";
1
+ import { l as languages } from "./index-dRvutfbl.js";
2
2
  const EMPTY_ELEMENTS = [
3
3
  "assign",
4
4
  "flush",
@@ -1,4 +1,4 @@
1
- import { l as languages } from "./index-B60JU1yI.js";
1
+ import { l as languages } from "./index-dRvutfbl.js";
2
2
  const EMPTY_ELEMENTS = [
3
3
  "area",
4
4
  "base",
@@ -1,4 +1,4 @@
1
- import { l as languages } from "./index-B60JU1yI.js";
1
+ import { l as languages } from "./index-dRvutfbl.js";
2
2
  const EMPTY_ELEMENTS = [
3
3
  "area",
4
4
  "base",
@@ -1,6 +1,6 @@
1
- import { c as createWebWorker, l as languages } from "./index-B60JU1yI.js";
2
- import { H as HoverAdapter, D as DocumentHighlightAdapter, h as DocumentLinkAdapter, F as FoldingRangeAdapter, b as DocumentSymbolAdapter, S as SelectionRangeAdapter, c as RenameAdapter, f as DocumentFormattingEditProvider, g as DocumentRangeFormattingEditProvider, C as CompletionAdapter } from "./lspLanguageFeatures-Cjr_4HGs.js";
3
- import { a, e, d, R, i, j, t, k } from "./lspLanguageFeatures-Cjr_4HGs.js";
1
+ import { c as createWebWorker, l as languages } from "./index-dRvutfbl.js";
2
+ import { H as HoverAdapter, D as DocumentHighlightAdapter, h as DocumentLinkAdapter, F as FoldingRangeAdapter, b as DocumentSymbolAdapter, S as SelectionRangeAdapter, c as RenameAdapter, f as DocumentFormattingEditProvider, g as DocumentRangeFormattingEditProvider, C as CompletionAdapter } from "./lspLanguageFeatures-DqzMqkRk.js";
3
+ import { a, e, d, R, i, j, t, k } from "./lspLanguageFeatures-DqzMqkRk.js";
4
4
  const STOP_WHEN_IDLE_FOR = 2 * 60 * 1e3;
5
5
  class WorkerManager {
6
6
  constructor(defaults) {
@@ -8045,6 +8045,80 @@ html, body, #root {
8045
8045
  white-space: normal;
8046
8046
  }
8047
8047
 
8048
+ /* Floating push-to-talk mic (draggable, dismissable FAB) */
8049
+ .floating-mic {
8050
+ position: fixed;
8051
+ z-index: 200;
8052
+ display: flex;
8053
+ flex-direction: column;
8054
+ align-items: center;
8055
+ gap: 4px;
8056
+ padding: 4px 4px 6px;
8057
+ background: #16161e;
8058
+ border: 1px solid #3b3d57;
8059
+ border-radius: 12px;
8060
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.45);
8061
+ user-select: none;
8062
+ -webkit-user-select: none;
8063
+ }
8064
+ .floating-mic-handle {
8065
+ display: flex;
8066
+ align-items: center;
8067
+ justify-content: space-between;
8068
+ width: 100%;
8069
+ cursor: grab;
8070
+ touch-action: none;
8071
+ }
8072
+ .floating-mic-handle:active { cursor: grabbing; }
8073
+ .floating-mic-grip {
8074
+ color: #565f89;
8075
+ font-size: 12px;
8076
+ line-height: 1;
8077
+ padding: 0 2px;
8078
+ }
8079
+ .floating-mic-hide {
8080
+ background: transparent;
8081
+ border: none;
8082
+ color: #565f89;
8083
+ font-size: 15px;
8084
+ line-height: 1;
8085
+ cursor: pointer;
8086
+ padding: 0 2px;
8087
+ }
8088
+ .floating-mic-hide:hover { color: #f7768e; }
8089
+
8090
+ .voice-btn-floating {
8091
+ width: 48px;
8092
+ height: 48px;
8093
+ border-radius: 50%;
8094
+ display: inline-flex;
8095
+ align-items: center;
8096
+ justify-content: center;
8097
+ background: #2a2b3d;
8098
+ border: 1px solid #3b3d57;
8099
+ color: #a9b1d6;
8100
+ cursor: pointer;
8101
+ position: relative;
8102
+ transition: all 0.15s;
8103
+ }
8104
+ .voice-btn-floating:hover { border-color: #565f89; }
8105
+ .voice-btn-floating .voice-icon { font-size: 22px; }
8106
+ .voice-btn-floating .voice-dot {
8107
+ position: absolute;
8108
+ top: 5px;
8109
+ right: 5px;
8110
+ }
8111
+ /* Floating chip sits above the round button rather than below it. */
8112
+ .voice-chip-floating {
8113
+ top: auto;
8114
+ bottom: 100%;
8115
+ right: auto;
8116
+ left: 50%;
8117
+ transform: translateX(-50%);
8118
+ margin-top: 0;
8119
+ margin-bottom: 8px;
8120
+ }
8121
+
8048
8122
  /* Editor panel */
8049
8123
  .editor-panel {
8050
8124
  display: flex;
@@ -1,4 +1,4 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./cssMode-DbMmcl1h.js","./lspLanguageFeatures-Cjr_4HGs.js","./htmlMode-BdkAp9qr.js","./jsonMode-BuVr-eSl.js","./javascript-CXqZcnvb.js","./typescript-rkc9lhpi.js"])))=>i.map(i=>d[i]);
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./cssMode-eTXVdAkZ.js","./lspLanguageFeatures-DqzMqkRk.js","./htmlMode-46N3XG2c.js","./jsonMode-DXDczSNu.js","./javascript-n_iZZzDX.js","./typescript-DhPw4VVg.js"])))=>i.map(i=>d[i]);
2
2
  function getDefaultExportFromCjs(x) {
3
3
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
4
4
  }
@@ -19245,7 +19245,7 @@ function describeMicError(err) {
19245
19245
  if (name === "NotFoundError") return "No microphone found";
19246
19246
  return "Could not start microphone";
19247
19247
  }
19248
- function VoiceInput({ onTranscript }) {
19248
+ function VoiceInput({ onTranscript, variant = "titlebar" }) {
19249
19249
  const [engine, setEngine] = reactExports.useState(loadInitialEngine);
19250
19250
  const [phase, setPhase] = reactExports.useState("idle");
19251
19251
  const [interim, setInterim] = reactExports.useState("");
@@ -19441,12 +19441,14 @@ function VoiceInput({ onTranscript }) {
19441
19441
  else if (notice && phase === "idle") chip = { kind: "notice", text: notice };
19442
19442
  else if (listening) chip = { kind: "listening", text: interim || (engine === "local" ? "Recording…" : "Listening…") };
19443
19443
  else if (busy) chip = { kind: "busy", text: modelPct !== null ? `Downloading voice model… ${modelPct}%` : "Transcribing…" };
19444
+ const floating = variant === "floating";
19445
+ const btnClass = floating ? `voice-btn voice-btn-floating ${listening ? "listening" : ""} ${busy ? "busy" : ""}` : `titlebar-btn titlebar-icon-btn voice-btn ${listening ? "listening" : ""} ${busy ? "busy" : ""}`;
19444
19446
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "voice-input-wrap", children: [
19445
19447
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
19446
19448
  "button",
19447
19449
  {
19448
19450
  type: "button",
19449
- className: `titlebar-btn titlebar-icon-btn voice-btn ${listening ? "listening" : ""} ${busy ? "busy" : ""}`,
19451
+ className: btnClass,
19450
19452
  disabled: !ANY_SUPPORTED,
19451
19453
  onPointerDown: handlePointerDown,
19452
19454
  onPointerUp: handlePointerUp,
@@ -19460,7 +19462,109 @@ function VoiceInput({ onTranscript }) {
19460
19462
  ]
19461
19463
  }
19462
19464
  ),
19463
- chip && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: `voice-chip ${chip.kind}`, children: chip.text })
19465
+ chip && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: `voice-chip ${chip.kind} ${floating ? "voice-chip-floating" : ""}`, children: chip.text })
19466
+ ] });
19467
+ }
19468
+ const POS_KEY = "ctlsurf.floatingMicPos";
19469
+ const EDGE = 20;
19470
+ const TOP_MIN = 46;
19471
+ const BOTTOM_GAP = 36;
19472
+ function loadPos() {
19473
+ try {
19474
+ const raw = localStorage.getItem(POS_KEY);
19475
+ if (raw) {
19476
+ const p = JSON.parse(raw);
19477
+ if (typeof p.x === "number" && typeof p.y === "number") return { x: p.x, y: p.y };
19478
+ }
19479
+ } catch {
19480
+ }
19481
+ return null;
19482
+ }
19483
+ function FloatingMic({ onTranscript, onHide }) {
19484
+ const [pos, setPos] = reactExports.useState(loadPos);
19485
+ const elRef = reactExports.useRef(null);
19486
+ const dragRef = reactExports.useRef(null);
19487
+ const clamp2 = reactExports.useCallback((x, y) => {
19488
+ const el = elRef.current;
19489
+ const w = el?.offsetWidth ?? 64;
19490
+ const h2 = el?.offsetHeight ?? 90;
19491
+ return {
19492
+ x: Math.max(EDGE, Math.min(x, window.innerWidth - w - EDGE)),
19493
+ y: Math.max(TOP_MIN, Math.min(y, window.innerHeight - h2 - BOTTOM_GAP))
19494
+ };
19495
+ }, []);
19496
+ reactExports.useEffect(() => {
19497
+ if (pos) return;
19498
+ const el = elRef.current;
19499
+ const w = el?.offsetWidth ?? 64;
19500
+ const h2 = el?.offsetHeight ?? 90;
19501
+ setPos({
19502
+ x: window.innerWidth - w - EDGE,
19503
+ y: window.innerHeight - h2 - BOTTOM_GAP
19504
+ });
19505
+ }, [pos]);
19506
+ reactExports.useEffect(() => {
19507
+ const onResize = () => setPos((p) => p ? clamp2(p.x, p.y) : p);
19508
+ window.addEventListener("resize", onResize);
19509
+ return () => window.removeEventListener("resize", onResize);
19510
+ }, [clamp2]);
19511
+ const onHandleDown = reactExports.useCallback((e) => {
19512
+ const el = elRef.current;
19513
+ if (!el) return;
19514
+ e.preventDefault();
19515
+ const rect = el.getBoundingClientRect();
19516
+ dragRef.current = { dx: e.clientX - rect.left, dy: e.clientY - rect.top };
19517
+ e.currentTarget.setPointerCapture?.(e.pointerId);
19518
+ }, []);
19519
+ const onHandleMove = reactExports.useCallback((e) => {
19520
+ const d = dragRef.current;
19521
+ if (!d) return;
19522
+ setPos(clamp2(e.clientX - d.dx, e.clientY - d.dy));
19523
+ }, [clamp2]);
19524
+ const onHandleUp = reactExports.useCallback((e) => {
19525
+ if (!dragRef.current) return;
19526
+ dragRef.current = null;
19527
+ e.currentTarget.releasePointerCapture?.(e.pointerId);
19528
+ setPos((p) => {
19529
+ if (p) {
19530
+ try {
19531
+ localStorage.setItem(POS_KEY, JSON.stringify(p));
19532
+ } catch {
19533
+ }
19534
+ }
19535
+ return p;
19536
+ });
19537
+ }, []);
19538
+ const style = pos ? { left: pos.x, top: pos.y } : { left: -9999, top: -9999, visibility: "hidden" };
19539
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { ref: elRef, className: "floating-mic", style, children: [
19540
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
19541
+ "div",
19542
+ {
19543
+ className: "floating-mic-handle",
19544
+ onPointerDown: onHandleDown,
19545
+ onPointerMove: onHandleMove,
19546
+ onPointerUp: onHandleUp,
19547
+ onPointerCancel: onHandleUp,
19548
+ title: "Drag to move",
19549
+ "aria-label": "Drag floating mic",
19550
+ children: [
19551
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "floating-mic-grip", "aria-hidden": "true", children: "⠿" }),
19552
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
19553
+ "button",
19554
+ {
19555
+ type: "button",
19556
+ className: "floating-mic-hide",
19557
+ onPointerDown: (e) => e.stopPropagation(),
19558
+ onClick: onHide,
19559
+ title: "Hide floating mic",
19560
+ "aria-label": "Hide floating mic",
19561
+ children: "×"
19562
+ }
19563
+ )
19564
+ ]
19565
+ }
19566
+ ),
19567
+ /* @__PURE__ */ jsxRuntimeExports.jsx(VoiceInput, { variant: "floating", onTranscript })
19464
19568
  ] });
19465
19569
  }
19466
19570
  function CtlsurfPanel({ navigate }) {
@@ -207057,7 +207161,7 @@ const lessDefaults = new LanguageServiceDefaultsImpl$3(
207057
207161
  modeConfigurationDefault$2
207058
207162
  );
207059
207163
  function getMode$3() {
207060
- return __vitePreload(() => import("./cssMode-DbMmcl1h.js"), true ? __vite__mapDeps([0,1]) : void 0, import.meta.url);
207164
+ return __vitePreload(() => import("./cssMode-eTXVdAkZ.js"), true ? __vite__mapDeps([0,1]) : void 0, import.meta.url);
207061
207165
  }
207062
207166
  languages.onLanguage("less", () => {
207063
207167
  getMode$3().then((mode2) => mode2.setupMode(lessDefaults));
@@ -207162,7 +207266,7 @@ const razorLanguageService = registerHTMLLanguageService(
207162
207266
  );
207163
207267
  const razorDefaults = razorLanguageService.defaults;
207164
207268
  function getMode$2() {
207165
- return __vitePreload(() => import("./htmlMode-BdkAp9qr.js"), true ? __vite__mapDeps([2,1]) : void 0, import.meta.url);
207269
+ return __vitePreload(() => import("./htmlMode-46N3XG2c.js"), true ? __vite__mapDeps([2,1]) : void 0, import.meta.url);
207166
207270
  }
207167
207271
  function registerHTMLLanguageService(languageId, options = optionsDefault, modeConfiguration = getConfigurationDefault(languageId)) {
207168
207272
  const defaults = new LanguageServiceDefaultsImpl$2(languageId, options, modeConfiguration);
@@ -207246,7 +207350,7 @@ const jsonDefaults = new LanguageServiceDefaultsImpl$1(
207246
207350
  );
207247
207351
  const getWorker$1 = () => getMode$1().then((mode2) => mode2.getWorker());
207248
207352
  function getMode$1() {
207249
- return __vitePreload(() => import("./jsonMode-BuVr-eSl.js"), true ? __vite__mapDeps([3,1]) : void 0, import.meta.url);
207353
+ return __vitePreload(() => import("./jsonMode-DXDczSNu.js"), true ? __vite__mapDeps([3,1]) : void 0, import.meta.url);
207250
207354
  }
207251
207355
  languages.register({
207252
207356
  id: "json",
@@ -207492,7 +207596,7 @@ const getJavaScriptWorker = () => {
207492
207596
  return getMode().then((mode) => mode.getJavaScriptWorker());
207493
207597
  };
207494
207598
  function getMode() {
207495
- return __vitePreload(() => import("./tsMode-CYd3NUkW.js"), true ? [] : void 0, import.meta.url);
207599
+ return __vitePreload(() => import("./tsMode-C7m6Kr5E.js"), true ? [] : void 0, import.meta.url);
207496
207600
  }
207497
207601
  languages.onLanguage("typescript", () => {
207498
207602
  return getMode().then((mode) => mode.setupTypeScript(typescriptDefaults));
@@ -207687,49 +207791,49 @@ registerLanguage({
207687
207791
  extensions: [".ftl", ".ftlh", ".ftlx"],
207688
207792
  aliases: ["FreeMarker2", "Apache FreeMarker2"],
207689
207793
  loader: () => {
207690
- return __vitePreload(() => import("./freemarker2-CvaHiy92.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAutoInterpolationDollar);
207794
+ return __vitePreload(() => import("./freemarker2-B5BKaiK4.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAutoInterpolationDollar);
207691
207795
  }
207692
207796
  });
207693
207797
  registerLanguage({
207694
207798
  id: "freemarker2.tag-angle.interpolation-dollar",
207695
207799
  aliases: ["FreeMarker2 (Angle/Dollar)", "Apache FreeMarker2 (Angle/Dollar)"],
207696
207800
  loader: () => {
207697
- return __vitePreload(() => import("./freemarker2-CvaHiy92.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAngleInterpolationDollar);
207801
+ return __vitePreload(() => import("./freemarker2-B5BKaiK4.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAngleInterpolationDollar);
207698
207802
  }
207699
207803
  });
207700
207804
  registerLanguage({
207701
207805
  id: "freemarker2.tag-bracket.interpolation-dollar",
207702
207806
  aliases: ["FreeMarker2 (Bracket/Dollar)", "Apache FreeMarker2 (Bracket/Dollar)"],
207703
207807
  loader: () => {
207704
- return __vitePreload(() => import("./freemarker2-CvaHiy92.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagBracketInterpolationDollar);
207808
+ return __vitePreload(() => import("./freemarker2-B5BKaiK4.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagBracketInterpolationDollar);
207705
207809
  }
207706
207810
  });
207707
207811
  registerLanguage({
207708
207812
  id: "freemarker2.tag-angle.interpolation-bracket",
207709
207813
  aliases: ["FreeMarker2 (Angle/Bracket)", "Apache FreeMarker2 (Angle/Bracket)"],
207710
207814
  loader: () => {
207711
- return __vitePreload(() => import("./freemarker2-CvaHiy92.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAngleInterpolationBracket);
207815
+ return __vitePreload(() => import("./freemarker2-B5BKaiK4.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAngleInterpolationBracket);
207712
207816
  }
207713
207817
  });
207714
207818
  registerLanguage({
207715
207819
  id: "freemarker2.tag-bracket.interpolation-bracket",
207716
207820
  aliases: ["FreeMarker2 (Bracket/Bracket)", "Apache FreeMarker2 (Bracket/Bracket)"],
207717
207821
  loader: () => {
207718
- return __vitePreload(() => import("./freemarker2-CvaHiy92.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagBracketInterpolationBracket);
207822
+ return __vitePreload(() => import("./freemarker2-B5BKaiK4.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagBracketInterpolationBracket);
207719
207823
  }
207720
207824
  });
207721
207825
  registerLanguage({
207722
207826
  id: "freemarker2.tag-auto.interpolation-dollar",
207723
207827
  aliases: ["FreeMarker2 (Auto/Dollar)", "Apache FreeMarker2 (Auto/Dollar)"],
207724
207828
  loader: () => {
207725
- return __vitePreload(() => import("./freemarker2-CvaHiy92.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAutoInterpolationDollar);
207829
+ return __vitePreload(() => import("./freemarker2-B5BKaiK4.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAutoInterpolationDollar);
207726
207830
  }
207727
207831
  });
207728
207832
  registerLanguage({
207729
207833
  id: "freemarker2.tag-auto.interpolation-bracket",
207730
207834
  aliases: ["FreeMarker2 (Auto/Bracket)", "Apache FreeMarker2 (Auto/Bracket)"],
207731
207835
  loader: () => {
207732
- return __vitePreload(() => import("./freemarker2-CvaHiy92.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAutoInterpolationBracket);
207836
+ return __vitePreload(() => import("./freemarker2-B5BKaiK4.js"), true ? [] : void 0, import.meta.url).then((m) => m.TagAutoInterpolationBracket);
207733
207837
  }
207734
207838
  });
207735
207839
  registerLanguage({
@@ -207750,7 +207854,7 @@ registerLanguage({
207750
207854
  extensions: [".handlebars", ".hbs"],
207751
207855
  aliases: ["Handlebars", "handlebars", "hbs"],
207752
207856
  mimetypes: ["text/x-handlebars-template"],
207753
- loader: () => __vitePreload(() => import("./handlebars-D58lUIOu.js"), true ? [] : void 0, import.meta.url)
207857
+ loader: () => __vitePreload(() => import("./handlebars-BIdLd2wU.js"), true ? [] : void 0, import.meta.url)
207754
207858
  });
207755
207859
  registerLanguage({
207756
207860
  id: "hcl",
@@ -207763,7 +207867,7 @@ registerLanguage({
207763
207867
  extensions: [".html", ".htm", ".shtml", ".xhtml", ".mdoc", ".jsp", ".asp", ".aspx", ".jshtm"],
207764
207868
  aliases: ["HTML", "htm", "html", "xhtml"],
207765
207869
  mimetypes: ["text/html", "text/x-jshtm", "text/template", "text/ng-template"],
207766
- loader: () => __vitePreload(() => import("./html-D1h1aJbM.js"), true ? [] : void 0, import.meta.url)
207870
+ loader: () => __vitePreload(() => import("./html-BXL4cnLS.js"), true ? [] : void 0, import.meta.url)
207767
207871
  });
207768
207872
  registerLanguage({
207769
207873
  id: "ini",
@@ -207786,7 +207890,7 @@ registerLanguage({
207786
207890
  filenames: ["jakefile"],
207787
207891
  aliases: ["JavaScript", "javascript", "js"],
207788
207892
  mimetypes: ["text/javascript"],
207789
- loader: () => __vitePreload(() => import("./javascript-CXqZcnvb.js"), true ? __vite__mapDeps([4,5]) : void 0, import.meta.url)
207893
+ loader: () => __vitePreload(() => import("./javascript-n_iZZzDX.js"), true ? __vite__mapDeps([4,5]) : void 0, import.meta.url)
207790
207894
  });
207791
207895
  registerLanguage({
207792
207896
  id: "julia",
@@ -207825,7 +207929,7 @@ registerLanguage({
207825
207929
  extensions: [".liquid", ".html.liquid"],
207826
207930
  aliases: ["Liquid", "liquid"],
207827
207931
  mimetypes: ["application/liquid"],
207828
- loader: () => __vitePreload(() => import("./liquid-LKu0Wd0B.js"), true ? [] : void 0, import.meta.url)
207932
+ loader: () => __vitePreload(() => import("./liquid-B1QweUh7.js"), true ? [] : void 0, import.meta.url)
207829
207933
  });
207830
207934
  registerLanguage({
207831
207935
  id: "m3",
@@ -207843,7 +207947,7 @@ registerLanguage({
207843
207947
  id: "mdx",
207844
207948
  extensions: [".mdx"],
207845
207949
  aliases: ["MDX", "mdx"],
207846
- loader: () => __vitePreload(() => import("./mdx-Bl84ILla.js"), true ? [] : void 0, import.meta.url)
207950
+ loader: () => __vitePreload(() => import("./mdx-BCv8lm5e.js"), true ? [] : void 0, import.meta.url)
207847
207951
  });
207848
207952
  registerLanguage({
207849
207953
  id: "mips",
@@ -207942,7 +208046,7 @@ registerLanguage({
207942
208046
  extensions: [".py", ".rpy", ".pyw", ".cpy", ".gyp", ".gypi"],
207943
208047
  aliases: ["Python", "py"],
207944
208048
  firstLine: "^#!/.*\\bpython[0-9.-]*\\b",
207945
- loader: () => __vitePreload(() => import("./python-0sFd9G1k.js"), true ? [] : void 0, import.meta.url)
208049
+ loader: () => __vitePreload(() => import("./python-BLNzYwDv.js"), true ? [] : void 0, import.meta.url)
207946
208050
  });
207947
208051
  registerLanguage({
207948
208052
  id: "qsharp",
@@ -207961,7 +208065,7 @@ registerLanguage({
207961
208065
  extensions: [".cshtml"],
207962
208066
  aliases: ["Razor", "razor"],
207963
208067
  mimetypes: ["text/x-cshtml"],
207964
- loader: () => __vitePreload(() => import("./razor-Cqcu1rLJ.js"), true ? [] : void 0, import.meta.url)
208068
+ loader: () => __vitePreload(() => import("./razor-CvAww8bG.js"), true ? [] : void 0, import.meta.url)
207965
208069
  });
207966
208070
  registerLanguage({
207967
208071
  id: "redis",
@@ -208094,7 +208198,7 @@ registerLanguage({
208094
208198
  aliases: ["TypeScript", "ts", "typescript"],
208095
208199
  mimetypes: ["text/typescript"],
208096
208200
  loader: () => {
208097
- return __vitePreload(() => import("./typescript-rkc9lhpi.js"), true ? [] : void 0, import.meta.url);
208201
+ return __vitePreload(() => import("./typescript-DhPw4VVg.js"), true ? [] : void 0, import.meta.url);
208098
208202
  }
208099
208203
  });
208100
208204
  registerLanguage({
@@ -208139,14 +208243,14 @@ registerLanguage({
208139
208243
  firstLine: "(\\<\\?xml.*)|(\\<svg)|(\\<\\!doctype\\s+svg)",
208140
208244
  aliases: ["XML", "xml"],
208141
208245
  mimetypes: ["text/xml", "application/xml", "application/xaml+xml", "application/xml-dtd"],
208142
- loader: () => __vitePreload(() => import("./xml-EsHEUps1.js"), true ? [] : void 0, import.meta.url)
208246
+ loader: () => __vitePreload(() => import("./xml-B0WLFJ2U.js"), true ? [] : void 0, import.meta.url)
208143
208247
  });
208144
208248
  registerLanguage({
208145
208249
  id: "yaml",
208146
208250
  extensions: [".yaml", ".yml"],
208147
208251
  aliases: ["YAML", "yaml", "YML", "yml"],
208148
208252
  mimetypes: ["application/x-yaml", "text/x-yaml"],
208149
- loader: () => __vitePreload(() => import("./yaml-B9-nQ_s2.js"), true ? [] : void 0, import.meta.url)
208253
+ loader: () => __vitePreload(() => import("./yaml-BWyn9Wd7.js"), true ? [] : void 0, import.meta.url)
208150
208254
  });
208151
208255
  var __defProp = Object.defineProperty;
208152
208256
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
@@ -212549,6 +212653,20 @@ function App() {
212549
212653
  const [activeTabId, setActiveTabId] = reactExports.useState(tabs[0].id);
212550
212654
  const [trackingActive, setTrackingActive] = reactExports.useState(false);
212551
212655
  const [showTicketPanel, setShowTicketPanel] = reactExports.useState(false);
212656
+ const [showFloatingMic, setShowFloatingMic] = reactExports.useState(() => {
212657
+ try {
212658
+ return localStorage.getItem("ctlsurf.floatingMicVisible") !== "false";
212659
+ } catch {
212660
+ return true;
212661
+ }
212662
+ });
212663
+ const setFloatingMicVisible = reactExports.useCallback((v2) => {
212664
+ setShowFloatingMic(v2);
212665
+ try {
212666
+ localStorage.setItem("ctlsurf.floatingMicVisible", String(v2));
212667
+ } catch {
212668
+ }
212669
+ }, []);
212552
212670
  const [pickerTargetTabId, setPickerTargetTabId] = reactExports.useState(tabs[0].id);
212553
212671
  const [showAgentPicker, setShowAgentPicker] = reactExports.useState(true);
212554
212672
  const visiblePaneIds = findPaneIds(layout2);
@@ -212619,7 +212737,7 @@ function App() {
212619
212737
  const handleVoiceTranscript = reactExports.useCallback((text2) => {
212620
212738
  const trimmed = text2.trim();
212621
212739
  if (!trimmed) return;
212622
- window.worker.writePty(activeTabId, trimmed);
212740
+ window.worker.writePty(activeTabId, trimmed + "\r");
212623
212741
  focusTerminal(activeTabId);
212624
212742
  }, [activeTabId]);
212625
212743
  const cwdRef = reactExports.useRef(null);
@@ -212883,7 +213001,35 @@ function App() {
212883
213001
  ]
212884
213002
  }
212885
213003
  ),
212886
- /* @__PURE__ */ jsxRuntimeExports.jsx(VoiceInput, { onTranscript: handleVoiceTranscript }),
213004
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
213005
+ "button",
213006
+ {
213007
+ className: `titlebar-btn titlebar-icon-btn ${showFloatingMic ? "active" : ""}`,
213008
+ onClick: () => setFloatingMicVisible(!showFloatingMic),
213009
+ title: showFloatingMic ? "Hide floating mic" : "Show floating mic",
213010
+ "aria-label": "Toggle floating mic",
213011
+ children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
213012
+ "svg",
213013
+ {
213014
+ viewBox: "0 0 24 24",
213015
+ width: "13",
213016
+ height: "13",
213017
+ fill: "none",
213018
+ stroke: "currentColor",
213019
+ strokeWidth: "2",
213020
+ strokeLinecap: "round",
213021
+ strokeLinejoin: "round",
213022
+ "aria-hidden": "true",
213023
+ children: [
213024
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z" }),
213025
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M19 10v2a7 7 0 0 1-14 0v-2" }),
213026
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "12", y1: "19", x2: "12", y2: "23" }),
213027
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "8", y1: "23", x2: "16", y2: "23" })
213028
+ ]
213029
+ }
213030
+ )
213031
+ }
213032
+ ),
212887
213033
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "titlebar-separator" }),
212888
213034
  agents.map((a) => {
212889
213035
  const activeTab = tabs.find((t) => t.id === activeTabId);
@@ -212937,6 +213083,13 @@ function App() {
212937
213083
  }
212938
213084
  }
212939
213085
  }
213086
+ ),
213087
+ showFloatingMic && /* @__PURE__ */ jsxRuntimeExports.jsx(
213088
+ FloatingMic,
213089
+ {
213090
+ onTranscript: handleVoiceTranscript,
213091
+ onHide: () => setFloatingMicVisible(false)
213092
+ }
212940
213093
  )
212941
213094
  ] });
212942
213095
  }
@@ -1,5 +1,5 @@
1
- import { conf as conf$1, language as language$1 } from "./typescript-rkc9lhpi.js";
2
- import "./index-B60JU1yI.js";
1
+ import { conf as conf$1, language as language$1 } from "./typescript-DhPw4VVg.js";
2
+ import "./index-dRvutfbl.js";
3
3
  const conf = conf$1;
4
4
  const language = {
5
5
  // Set defaultToken to invalid to see what you do not tokenize yet
@@ -1,6 +1,6 @@
1
- import { c as createWebWorker, l as languages, e as editor } from "./index-B60JU1yI.js";
2
- import { f as DocumentFormattingEditProvider, g as DocumentRangeFormattingEditProvider, C as CompletionAdapter, H as HoverAdapter, b as DocumentSymbolAdapter, d as DocumentColorAdapter, F as FoldingRangeAdapter, S as SelectionRangeAdapter, e as DiagnosticsAdapter } from "./lspLanguageFeatures-Cjr_4HGs.js";
3
- import { a, D, h, R, c, i, j, t, k } from "./lspLanguageFeatures-Cjr_4HGs.js";
1
+ import { c as createWebWorker, l as languages, e as editor } from "./index-dRvutfbl.js";
2
+ import { f as DocumentFormattingEditProvider, g as DocumentRangeFormattingEditProvider, C as CompletionAdapter, H as HoverAdapter, b as DocumentSymbolAdapter, d as DocumentColorAdapter, F as FoldingRangeAdapter, S as SelectionRangeAdapter, e as DiagnosticsAdapter } from "./lspLanguageFeatures-DqzMqkRk.js";
3
+ import { a, D, h, R, c, i, j, t, k } from "./lspLanguageFeatures-DqzMqkRk.js";
4
4
  const STOP_WHEN_IDLE_FOR = 2 * 60 * 1e3;
5
5
  class WorkerManager {
6
6
  constructor(defaults) {
@@ -1,4 +1,4 @@
1
- import { l as languages } from "./index-B60JU1yI.js";
1
+ import { l as languages } from "./index-dRvutfbl.js";
2
2
  const EMPTY_ELEMENTS = [
3
3
  "area",
4
4
  "base",
@@ -1,4 +1,4 @@
1
- import { R as Range$1, l as languages, e as editor, U as Uri, M as MarkerSeverity } from "./index-B60JU1yI.js";
1
+ import { R as Range$1, l as languages, e as editor, U as Uri, M as MarkerSeverity } from "./index-dRvutfbl.js";
2
2
  var DocumentUri;
3
3
  (function(DocumentUri2) {
4
4
  function is(value) {
@@ -1,4 +1,4 @@
1
- import { l as languages } from "./index-B60JU1yI.js";
1
+ import { l as languages } from "./index-dRvutfbl.js";
2
2
  const conf = {
3
3
  comments: {
4
4
  blockComment: ["{/*", "*/}"]
@@ -1,4 +1,4 @@
1
- import { l as languages } from "./index-B60JU1yI.js";
1
+ import { l as languages } from "./index-dRvutfbl.js";
2
2
  const conf = {
3
3
  comments: {
4
4
  lineComment: "#",
@@ -1,4 +1,4 @@
1
- import { l as languages } from "./index-B60JU1yI.js";
1
+ import { l as languages } from "./index-dRvutfbl.js";
2
2
  const EMPTY_ELEMENTS = [
3
3
  "area",
4
4
  "base",
@@ -1,4 +1,4 @@
1
- import { c as createWebWorker, e as editor, U as Uri, a as MarkerTag, M as MarkerSeverity, l as languages, t as typescriptDefaults, R as Range } from "./index-B60JU1yI.js";
1
+ import { c as createWebWorker, e as editor, U as Uri, a as MarkerTag, M as MarkerSeverity, l as languages, t as typescriptDefaults, R as Range } from "./index-dRvutfbl.js";
2
2
  class WorkerManager {
3
3
  constructor(_modeId, _defaults) {
4
4
  this._modeId = _modeId;
@@ -1,4 +1,4 @@
1
- import { l as languages } from "./index-B60JU1yI.js";
1
+ import { l as languages } from "./index-dRvutfbl.js";
2
2
  const conf = {
3
3
  wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\@\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g,
4
4
  comments: {
@@ -1,4 +1,4 @@
1
- import { l as languages } from "./index-B60JU1yI.js";
1
+ import { l as languages } from "./index-dRvutfbl.js";
2
2
  const conf = {
3
3
  comments: {
4
4
  blockComment: ["<!--", "-->"]
@@ -1,4 +1,4 @@
1
- import { l as languages } from "./index-B60JU1yI.js";
1
+ import { l as languages } from "./index-dRvutfbl.js";
2
2
  const conf = {
3
3
  comments: {
4
4
  lineComment: "#"
@@ -4,8 +4,8 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>ctlsurf-worker</title>
7
- <script type="module" crossorigin src="./assets/index-B60JU1yI.js"></script>
8
- <link rel="stylesheet" crossorigin href="./assets/index-DJFYmHjz.css">
7
+ <script type="module" crossorigin src="./assets/index-dRvutfbl.js"></script>
8
+ <link rel="stylesheet" crossorigin href="./assets/index-Cf-RsxoC.css">
9
9
  </head>
10
10
  <body>
11
11
  <div id="root"></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phenx-inc/ctlsurf",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Agent-agnostic terminal and desktop app for ctlsurf — run Claude Code, Codex, or any coding agent with live session logging and remote control",
5
5
  "main": "out/main/index.js",
6
6
  "bin": {