@volter-ai-dev/supercode-ui 0.1.41 → 0.1.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -4
- package/components.d.ts +1 -0
- package/components.mjs +139 -22
- package/composer.mjs +22 -1
- package/embed.mjs +138 -22
- package/index.d.ts +19 -1
- package/messenger.mjs +138 -22
- package/package.json +1 -1
- package/react/components.mjs +139 -22
- package/react/composer.mjs +22 -1
- package/react/index.d.ts +8 -1
- package/react/messenger.mjs +138 -22
- package/react/settings.d.ts +2 -2
- package/react/settings.mjs +74 -0
- package/settings.d.ts +2 -2
- package/settings.mjs +74 -0
- package/styles.css +6 -1
package/react/messenger.mjs
CHANGED
|
@@ -1280,7 +1280,7 @@ function ContinuationBar({ state, adapter, labels = DEFAULT_LABELS }) {
|
|
|
1280
1280
|
] })
|
|
1281
1281
|
] });
|
|
1282
1282
|
}
|
|
1283
|
-
function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.attached?.key || `${state.harness}:${state.workspace}`, pendingStatus = null, restoreDraft = null, contextCandidates = [], components = {}, onPending, onDraftRestored }) {
|
|
1283
|
+
function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.attached?.key || `${state.harness}:${state.workspace}`, pendingStatus = null, restoreDraft = null, command = null, contextCandidates = [], components = {}, onPending, onDraftRestored }) {
|
|
1284
1284
|
const remembered = composerMemory.get(memoryKey) ?? { draft: state.savedDraft, context: [], images: [], queue: [] };
|
|
1285
1285
|
const [draft, setDraft] = useState2(remembered.draft);
|
|
1286
1286
|
const [context, setContext] = useState2(remembered.context ?? []);
|
|
@@ -1292,6 +1292,7 @@ function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.a
|
|
|
1292
1292
|
const [dragging, setDragging] = useState2(false);
|
|
1293
1293
|
const [pickerError, setPickerError] = useState2(null);
|
|
1294
1294
|
const textarea = useRef2(null);
|
|
1295
|
+
const lastCommand = useRef2(null);
|
|
1295
1296
|
useAutosizeTextarea(textarea, draft);
|
|
1296
1297
|
const remember = (nextDraft, nextContext, nextImages, nextQueue) => boundedSet(composerMemory, memoryKey, { draft: nextDraft, context: nextContext, images: nextImages, queue: nextQueue });
|
|
1297
1298
|
useEffect2(() => {
|
|
@@ -1333,6 +1334,26 @@ function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.a
|
|
|
1333
1334
|
textarea.current?.focus({ preventScroll: true });
|
|
1334
1335
|
onDraftRestored?.(restoreDraft.id);
|
|
1335
1336
|
}, [onDraftRestored, restoreDraft?.id]);
|
|
1337
|
+
useEffect2(() => {
|
|
1338
|
+
if (!command || command.id === lastCommand.current) return;
|
|
1339
|
+
lastCommand.current = command.id;
|
|
1340
|
+
if (command.action === "attach") {
|
|
1341
|
+
try {
|
|
1342
|
+
const attachments = partitionAttachments(command.attachments);
|
|
1343
|
+
if (context.length + attachments.context.length > MAX_CONTEXT_ITEMS) throw new Error(`Attach at most ${MAX_CONTEXT_ITEMS} text items.`);
|
|
1344
|
+
if (images.length + attachments.images.length > MAX_IMAGE_ITEMS) throw new Error(`Attach at most ${MAX_IMAGE_ITEMS} images.`);
|
|
1345
|
+
const nextContext = mergeContext(context, attachments.context);
|
|
1346
|
+
const nextImages = mergeImages(images, attachments.images);
|
|
1347
|
+
setContext(nextContext);
|
|
1348
|
+
setImages(nextImages);
|
|
1349
|
+
setPickerError(null);
|
|
1350
|
+
remember(draft, nextContext, nextImages, queue);
|
|
1351
|
+
} catch (error) {
|
|
1352
|
+
setPickerError(error instanceof Error ? error.message : "Could not attach context.");
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
textarea.current?.focus({ preventScroll: true });
|
|
1356
|
+
}, [command?.id]);
|
|
1336
1357
|
useEffect2(() => {
|
|
1337
1358
|
const timer = setTimeout(() => adapter.onIntent({ action: "draft", text: draft }), 250);
|
|
1338
1359
|
return () => clearTimeout(timer);
|
|
@@ -2394,6 +2415,79 @@ function HarnessReadiness({ harnesses, adapter }) {
|
|
|
2394
2415
|
] }, item.id)) })
|
|
2395
2416
|
] });
|
|
2396
2417
|
}
|
|
2418
|
+
function HarnessPicker({ harnesses, value, disabled = false, adapter, onChange, logo: Logo = HarnessLogo }) {
|
|
2419
|
+
const [open, setOpen] = useState5(false);
|
|
2420
|
+
const menuId = useId2();
|
|
2421
|
+
const root = useRef6(null);
|
|
2422
|
+
const trigger = useRef6(null);
|
|
2423
|
+
const panel = useRef6(null);
|
|
2424
|
+
const available = harnesses.filter((item) => item.startable);
|
|
2425
|
+
const unavailable = harnesses.filter((item) => !item.startable);
|
|
2426
|
+
const selected = available.find((item) => item.id === value) ?? available[0] ?? null;
|
|
2427
|
+
const close = () => {
|
|
2428
|
+
setOpen(false);
|
|
2429
|
+
trigger.current?.focus({ preventScroll: true });
|
|
2430
|
+
};
|
|
2431
|
+
useEffect7(() => {
|
|
2432
|
+
if (!open) return;
|
|
2433
|
+
panel.current?.querySelector('[aria-selected="true"], [role="option"]')?.focus({ preventScroll: true });
|
|
2434
|
+
const dismiss = (event) => {
|
|
2435
|
+
if (event.type === "keydown" && event.key === "Escape") {
|
|
2436
|
+
event.preventDefault();
|
|
2437
|
+
close();
|
|
2438
|
+
} else if (event.type === "pointerdown" && !root.current?.contains(event.target)) {
|
|
2439
|
+
setOpen(false);
|
|
2440
|
+
}
|
|
2441
|
+
};
|
|
2442
|
+
document.addEventListener("keydown", dismiss);
|
|
2443
|
+
document.addEventListener("pointerdown", dismiss, true);
|
|
2444
|
+
return () => {
|
|
2445
|
+
document.removeEventListener("keydown", dismiss);
|
|
2446
|
+
document.removeEventListener("pointerdown", dismiss, true);
|
|
2447
|
+
};
|
|
2448
|
+
}, [open]);
|
|
2449
|
+
const navigate = (event) => {
|
|
2450
|
+
if (!["ArrowDown", "ArrowUp", "Home", "End"].includes(event.key)) return;
|
|
2451
|
+
const items = [...panel.current.querySelectorAll('[role="option"]')];
|
|
2452
|
+
if (!items.length) return;
|
|
2453
|
+
event.preventDefault();
|
|
2454
|
+
const current = items.indexOf(document.activeElement);
|
|
2455
|
+
const index = event.key === "Home" ? 0 : event.key === "End" ? items.length - 1 : event.key === "ArrowDown" ? (current + 1) % items.length : (current <= 0 ? items.length : current) - 1;
|
|
2456
|
+
items[index].focus({ preventScroll: true });
|
|
2457
|
+
};
|
|
2458
|
+
const select = (id) => {
|
|
2459
|
+
onChange(id);
|
|
2460
|
+
close();
|
|
2461
|
+
};
|
|
2462
|
+
return /* @__PURE__ */ jsxs7("div", { className: "scui-harness-menu", ref: root, onBlur: (event) => {
|
|
2463
|
+
if (event.relatedTarget && !event.currentTarget.contains(event.relatedTarget)) setOpen(false);
|
|
2464
|
+
}, children: [
|
|
2465
|
+
/* @__PURE__ */ jsxs7("button", { ref: trigger, className: "scui-harness-trigger", type: "button", disabled: disabled || !selected, "aria-label": selected ? `Coding harness: ${selected.label}` : "No coding harness available", "aria-haspopup": "dialog", "aria-expanded": open, "aria-controls": open ? menuId : void 0, onClick: () => setOpen((current) => !current), children: [
|
|
2466
|
+
selected ? /* @__PURE__ */ jsx8(Logo, { id: selected.id, size: 20 }) : null,
|
|
2467
|
+
/* @__PURE__ */ jsx8("strong", { children: selected?.label ?? "No harness available" }),
|
|
2468
|
+
/* @__PURE__ */ jsx8(UiIcon, { name: "chevron", size: 13 })
|
|
2469
|
+
] }),
|
|
2470
|
+
open ? /* @__PURE__ */ jsxs7("div", { ref: panel, id: menuId, className: "scui-harness-popover", role: "dialog", "aria-label": "Choose coding harness", onKeyDown: navigate, children: [
|
|
2471
|
+
/* @__PURE__ */ jsx8("strong", { className: "scui-harness-popover-title", children: "Choose coding harness" }),
|
|
2472
|
+
/* @__PURE__ */ jsx8("div", { className: "scui-harness-options", role: "listbox", "aria-label": "Available coding harnesses", children: available.map((item) => /* @__PURE__ */ jsxs7("button", { type: "button", role: "option", "aria-selected": item.id === selected?.id, onClick: () => select(item.id), children: [
|
|
2473
|
+
/* @__PURE__ */ jsx8(Logo, { id: item.id, size: 24 }),
|
|
2474
|
+
/* @__PURE__ */ jsx8("strong", { children: item.label }),
|
|
2475
|
+
/* @__PURE__ */ jsx8("span", { children: item.id === selected?.id ? /* @__PURE__ */ jsx8(UiIcon, { name: "check", size: 15 }) : null })
|
|
2476
|
+
] }, item.id)) }),
|
|
2477
|
+
unavailable.length ? /* @__PURE__ */ jsxs7("details", { className: "scui-harness-manage", children: [
|
|
2478
|
+
/* @__PURE__ */ jsx8("summary", { children: "Manage additional harnesses" }),
|
|
2479
|
+
/* @__PURE__ */ jsx8("div", { children: unavailable.map((item) => /* @__PURE__ */ jsxs7("section", { children: [
|
|
2480
|
+
/* @__PURE__ */ jsx8(Logo, { id: item.id, size: 24 }),
|
|
2481
|
+
/* @__PURE__ */ jsxs7("span", { children: [
|
|
2482
|
+
/* @__PURE__ */ jsx8("strong", { children: item.label }),
|
|
2483
|
+
/* @__PURE__ */ jsx8("small", { children: item.reason || (item.auth === "required" ? "Authentication required" : "Unavailable") })
|
|
2484
|
+
] }),
|
|
2485
|
+
item.repair ? /* @__PURE__ */ jsx8("button", { type: "button", onClick: () => adapter?.copyText?.(item.repair), children: "Copy fix" }) : null
|
|
2486
|
+
] }, item.id)) })
|
|
2487
|
+
] }) : null
|
|
2488
|
+
] }) : null
|
|
2489
|
+
] });
|
|
2490
|
+
}
|
|
2397
2491
|
|
|
2398
2492
|
// src/messenger.jsx
|
|
2399
2493
|
import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
@@ -2540,7 +2634,7 @@ function ChatHeader({ state, adapter, pendingStatus, actionPending, onBack, onNe
|
|
|
2540
2634
|
onClose ? /* @__PURE__ */ jsx9("button", { type: "button", "aria-label": "Close", onClick: onClose, children: /* @__PURE__ */ jsx9(UiIcon, { name: "close", size: 18 }) }) : null
|
|
2541
2635
|
] });
|
|
2542
2636
|
}
|
|
2543
|
-
function Chat({ state, adapter, onBack, onNew, onClose, components, slots, labels, contextCandidates, navigation }) {
|
|
2637
|
+
function Chat({ state, adapter, onBack, onNew, onClose, components, slots, labels, contextCandidates, navigation, composerCommand }) {
|
|
2544
2638
|
const Header = slots.header;
|
|
2545
2639
|
const HeaderActions = slots.headerActions;
|
|
2546
2640
|
const memoryKey = state.attached?.key || `${state.harness}:${state.workspace}`;
|
|
@@ -2667,11 +2761,11 @@ function Chat({ state, adapter, onBack, onNew, onClose, components, slots, label
|
|
|
2667
2761
|
/* @__PURE__ */ jsx9(Conversation, { state: actionState, adapter: trackedAdapter, components, slots, memoryKey, pending: pendingMessage, unreadAfterMessages }, memoryKey),
|
|
2668
2762
|
/* @__PURE__ */ jsx9(ContinuationBar, { state: actionState, adapter: trackedAdapter, labels }),
|
|
2669
2763
|
/* @__PURE__ */ jsx9(Advisory, { state: actionState, adapter: trackedAdapter, value: state.interopSettings?.advisories[0] ?? null, onReview: (recommendedChange) => setSettings({ recommendedChange }) }),
|
|
2670
|
-
state.mode !== "mirror" || state.canSend ? /* @__PURE__ */ jsx9(Composer, { state: actionState, adapter: trackedAdapter, labels, memoryKey, pendingStatus: pending?.status ?? null, restoreDraft, contextCandidates, components, onDraftRestored: (id) => setRestoreDraft((value) => value?.id === id ? null : value), onPending: beginPending }, memoryKey) : null,
|
|
2764
|
+
state.mode !== "mirror" || state.canSend ? /* @__PURE__ */ jsx9(Composer, { state: actionState, adapter: trackedAdapter, labels, memoryKey, pendingStatus: pending?.status ?? null, restoreDraft, command: composerCommand, contextCandidates, components, onDraftRestored: (id) => setRestoreDraft((value) => value?.id === id ? null : value), onPending: beginPending }, memoryKey) : null,
|
|
2671
2765
|
settings ? /* @__PURE__ */ jsx9(SettingsPanel, { state: actionState, adapter: trackedAdapter, value: state.interopSettings, recommendedChange: settings.recommendedChange, onClose: () => setSettings(null) }) : null
|
|
2672
2766
|
] });
|
|
2673
2767
|
}
|
|
2674
|
-
function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey, headerActions: HeaderActions, contextCandidates, components, navigation }) {
|
|
2768
|
+
function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey, headerActions: HeaderActions, contextCandidates, components, navigation, composerCommand }) {
|
|
2675
2769
|
const startable = state.harnesses.filter((item) => item.startable);
|
|
2676
2770
|
const startableKey = startable.map((item) => `${item.id}:${item.launchModes?.join(",")}:${item.preferredLaunchMode ?? ""}`).join("\0");
|
|
2677
2771
|
const remembered = newChatMemory.get(memoryKey) ?? { harness: startable[0]?.id ?? "", draft: "", context: [], images: [], modes: {} };
|
|
@@ -2685,8 +2779,10 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
2685
2779
|
const [dragging, setDragging] = useState6(false);
|
|
2686
2780
|
const [pickerError, setPickerError] = useState6(null);
|
|
2687
2781
|
const startSequence = useRef7(0);
|
|
2782
|
+
const lastComposerCommand = useRef7(null);
|
|
2688
2783
|
const textarea = useRef7(null);
|
|
2689
2784
|
const selectedHarness = startable.find((item) => item.id === harness) ?? null;
|
|
2785
|
+
const Picker = components.HarnessPicker ?? HarnessPicker;
|
|
2690
2786
|
const Readiness = components.HarnessReadiness ?? HarnessReadiness;
|
|
2691
2787
|
const launchModes = selectedHarness?.launchModes?.length ? selectedHarness.launchModes : ["headless"];
|
|
2692
2788
|
const rememberedMode = modes[harness];
|
|
@@ -2727,6 +2823,32 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
2727
2823
|
remember({ harness: nextHarness, draft: nextDraft, context: nextContext, images: nextImages });
|
|
2728
2824
|
textarea.current?.focus({ preventScroll: true });
|
|
2729
2825
|
}, [navigation?.id]);
|
|
2826
|
+
useEffect8(() => {
|
|
2827
|
+
if (!composerCommand || composerCommand.id === lastComposerCommand.current) return;
|
|
2828
|
+
lastComposerCommand.current = composerCommand.id;
|
|
2829
|
+
if (composerCommand.action === "attach") {
|
|
2830
|
+
if (mode === "terminal" && !launchModes.includes("headless")) {
|
|
2831
|
+
setPickerError("Terminal starts currently accept text only. Choose Chat to attach context or images.");
|
|
2832
|
+
} else {
|
|
2833
|
+
try {
|
|
2834
|
+
const attachments = partitionAttachments(composerCommand.attachments);
|
|
2835
|
+
if (context.length + attachments.context.length > MAX_CONTEXT_ITEMS) throw new Error(`Attach at most ${MAX_CONTEXT_ITEMS} text items.`);
|
|
2836
|
+
if (images.length + attachments.images.length > MAX_IMAGE_ITEMS) throw new Error(`Attach at most ${MAX_IMAGE_ITEMS} images.`);
|
|
2837
|
+
const nextContext = mergeContext(context, attachments.context);
|
|
2838
|
+
const nextImages = mergeImages(images, attachments.images);
|
|
2839
|
+
const nextModes = mode === "terminal" ? { ...modes, [harness]: "headless" } : modes;
|
|
2840
|
+
if (nextModes !== modes) setModes(nextModes);
|
|
2841
|
+
setContext(nextContext);
|
|
2842
|
+
setImages(nextImages);
|
|
2843
|
+
setPickerError(null);
|
|
2844
|
+
remember({ context: nextContext, images: nextImages, modes: nextModes });
|
|
2845
|
+
} catch (error) {
|
|
2846
|
+
setPickerError(error instanceof Error ? error.message : "Could not attach context.");
|
|
2847
|
+
}
|
|
2848
|
+
}
|
|
2849
|
+
}
|
|
2850
|
+
textarea.current?.focus({ preventScroll: true });
|
|
2851
|
+
}, [composerCommand?.id]);
|
|
2730
2852
|
const pickContext = () => {
|
|
2731
2853
|
if (mode === "terminal" || !adapter.pickContext || picking || context.length >= MAX_CONTEXT_ITEMS && images.length >= MAX_IMAGE_ITEMS) return;
|
|
2732
2854
|
setPicking(true);
|
|
@@ -2824,18 +2946,6 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
2824
2946
|
/* @__PURE__ */ jsx9("small", { children: "Choose a coding harness and send the first message." })
|
|
2825
2947
|
] }),
|
|
2826
2948
|
/* @__PURE__ */ jsxs8("div", { className: "scui-compose", children: [
|
|
2827
|
-
/* @__PURE__ */ jsxs8("label", { className: "scui-harness-picker", children: [
|
|
2828
|
-
/* @__PURE__ */ jsx9(HarnessLogo, { id: harness, size: 24 }),
|
|
2829
|
-
/* @__PURE__ */ jsx9("span", { children: "Coding harness" }),
|
|
2830
|
-
/* @__PURE__ */ jsx9("select", { value: harness, disabled: Boolean(starting), onChange: (event) => {
|
|
2831
|
-
const value = event.currentTarget.value;
|
|
2832
|
-
setHarness(value);
|
|
2833
|
-
remember({ harness: value });
|
|
2834
|
-
}, children: state.harnesses.map((item) => /* @__PURE__ */ jsxs8("option", { value: item.id, disabled: !item.startable, children: [
|
|
2835
|
-
item.label,
|
|
2836
|
-
item.startable ? "" : " \xB7 unavailable"
|
|
2837
|
-
] }, item.id)) })
|
|
2838
|
-
] }),
|
|
2839
2949
|
/* @__PURE__ */ jsx9(Readiness, { harnesses: state.harnesses, state, adapter }),
|
|
2840
2950
|
launchModes.length > 1 ? /* @__PURE__ */ jsxs8("fieldset", { className: "scui-launch-modes", disabled: Boolean(starting), children: [
|
|
2841
2951
|
/* @__PURE__ */ jsx9("legend", { children: "Run as" }),
|
|
@@ -2864,7 +2974,7 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
2864
2974
|
return next;
|
|
2865
2975
|
}) }),
|
|
2866
2976
|
terminalAttachments ? /* @__PURE__ */ jsx9("small", { className: "scui-context-error", role: "alert", children: "Terminal starts currently accept text only. Remove attachments or choose Chat." }) : pickerError ? /* @__PURE__ */ jsx9("small", { className: "scui-context-error", role: "alert", children: pickerError }) : null,
|
|
2867
|
-
/* @__PURE__ */ jsxs8("div", { className: `scui-envelope${dragging ? " scui-drop-target" : ""}`, onDragEnter: (event) => {
|
|
2977
|
+
/* @__PURE__ */ jsxs8("div", { className: `scui-envelope scui-new-envelope${dragging ? " scui-drop-target" : ""}`, onDragEnter: (event) => {
|
|
2868
2978
|
if (Array.from(event.dataTransfer?.types ?? []).includes("Files")) {
|
|
2869
2979
|
event.preventDefault();
|
|
2870
2980
|
setDragging(true);
|
|
@@ -2874,7 +2984,6 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
2874
2984
|
}, onDragLeave: (event) => {
|
|
2875
2985
|
if (!event.currentTarget.contains(event.relatedTarget)) setDragging(false);
|
|
2876
2986
|
}, onDrop: dropImages, children: [
|
|
2877
|
-
adapter.pickContext ? /* @__PURE__ */ jsx9("button", { className: "scui-attach", type: "button", "aria-label": "Attach files or images", disabled: mode === "terminal" || picking || context.length >= MAX_CONTEXT_ITEMS && images.length >= MAX_IMAGE_ITEMS || Boolean(starting), onClick: pickContext, children: picking ? /* @__PURE__ */ jsx9("i", { className: "scui-control-spinner" }) : /* @__PURE__ */ jsx9(UiIcon, { name: "attach", size: 17 }) }) : null,
|
|
2878
2987
|
/* @__PURE__ */ jsx9("textarea", { ref: textarea, rows: 3, "aria-label": "Message coding agent", placeholder: startable.length ? "What should the agent do?" : "No coding harness is available", value: draft, disabled: !startable.length || Boolean(starting), onPaste: pasteImages, onInput: (event) => {
|
|
2879
2988
|
const value = event.currentTarget.value;
|
|
2880
2989
|
setDraft(value);
|
|
@@ -2885,12 +2994,19 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
2885
2994
|
send();
|
|
2886
2995
|
}
|
|
2887
2996
|
} }),
|
|
2888
|
-
/* @__PURE__ */
|
|
2997
|
+
/* @__PURE__ */ jsxs8("footer", { className: "scui-new-envelope-controls", children: [
|
|
2998
|
+
adapter.pickContext ? /* @__PURE__ */ jsx9("button", { className: "scui-attach", type: "button", "aria-label": "Attach files or images", disabled: mode === "terminal" || picking || context.length >= MAX_CONTEXT_ITEMS && images.length >= MAX_IMAGE_ITEMS || Boolean(starting), onClick: pickContext, children: picking ? /* @__PURE__ */ jsx9("i", { className: "scui-control-spinner" }) : /* @__PURE__ */ jsx9(UiIcon, { name: "attach", size: 17 }) }) : null,
|
|
2999
|
+
/* @__PURE__ */ jsx9(Picker, { harnesses: state.harnesses, value: harness, disabled: Boolean(starting), adapter, logo: components.HarnessLogo, onChange: (value) => {
|
|
3000
|
+
setHarness(value);
|
|
3001
|
+
remember({ harness: value });
|
|
3002
|
+
} }),
|
|
3003
|
+
/* @__PURE__ */ jsx9("span", { children: /* @__PURE__ */ jsx9("button", { type: "button", className: "scui-send", "aria-label": mode === "terminal" ? "Start terminal session" : "Start chat", disabled: !draft.trim() && !images.length || !harness || Boolean(starting) || terminalAttachments || mode === "terminal" && !draft.trim(), onClick: send, children: starting ? /* @__PURE__ */ jsx9("i", { className: "scui-control-spinner" }) : /* @__PURE__ */ jsx9(UiIcon, { name: "send", size: 17 }) }) })
|
|
3004
|
+
] })
|
|
2889
3005
|
] })
|
|
2890
3006
|
] })
|
|
2891
3007
|
] });
|
|
2892
3008
|
}
|
|
2893
|
-
function SupercodeMessenger({ state: stateInput, adapter, class: className = "", initialView, navigation = null, onViewChange, contextCandidates: candidatesInput = [], labels, components = {}, slots = {} }) {
|
|
3009
|
+
function SupercodeMessenger({ state: stateInput, adapter, class: className = "", initialView, navigation = null, composerCommand = null, onViewChange, contextCandidates: candidatesInput = [], labels, components = {}, slots = {} }) {
|
|
2894
3010
|
const state = useMemo3(() => normalizeUiState(stateInput), [stateInput]);
|
|
2895
3011
|
const contextCandidates = useMemo3(() => normalizeAttachmentCandidates(candidatesInput), [candidatesInput]);
|
|
2896
3012
|
const copy = { ...DEFAULT_LABELS, ...labels };
|
|
@@ -2961,7 +3077,7 @@ function SupercodeMessenger({ state: stateInput, adapter, class: className = "",
|
|
|
2961
3077
|
setNewNavigation(null);
|
|
2962
3078
|
setView("new");
|
|
2963
3079
|
}, onClose: adapter.onClose ? close : void 0, components, labels: copy, memoryKey, slots, headerActions: HeaderActions }) : null,
|
|
2964
|
-
view === "new" ? /* @__PURE__ */ jsx9(NewChat, { state, adapter, onBack: () => setView("list"), onClose: adapter.onClose ? close : void 0, onStarted: (mode) => setView(mode === "terminal" ? "list" : "chat"), labels: copy, memoryKey, headerActions: HeaderActions, contextCandidates, components, navigation: newNavigation }) : null,
|
|
3080
|
+
view === "new" ? /* @__PURE__ */ jsx9(NewChat, { state, adapter, onBack: () => setView("list"), onClose: adapter.onClose ? close : void 0, onStarted: (mode) => setView(mode === "terminal" ? "list" : "chat"), labels: copy, memoryKey, headerActions: HeaderActions, contextCandidates, components, navigation: newNavigation, composerCommand }) : null,
|
|
2965
3081
|
view === "chat" ? /* @__PURE__ */ jsx9(Chat, { state, adapter, onBack: () => {
|
|
2966
3082
|
setListFocus(state.attached?.key ?? listFocus);
|
|
2967
3083
|
setView("list");
|
|
@@ -2970,7 +3086,7 @@ function SupercodeMessenger({ state: stateInput, adapter, class: className = "",
|
|
|
2970
3086
|
setChatNavigation(null);
|
|
2971
3087
|
setNewNavigation(null);
|
|
2972
3088
|
setView("new");
|
|
2973
|
-
}, onClose: adapter.onClose ? close : void 0, components, slots, labels: copy, contextCandidates, navigation: chatNavigation?.sessionKey === state.attached?.key ? chatNavigation : null }) : null,
|
|
3089
|
+
}, onClose: adapter.onClose ? close : void 0, components, slots, labels: copy, contextCandidates, navigation: chatNavigation?.sessionKey === state.attached?.key ? chatNavigation : null, composerCommand }) : null,
|
|
2974
3090
|
opening ? /* @__PURE__ */ jsxs8("div", { className: "scui-opening", role: "status", "aria-busy": "true", children: [
|
|
2975
3091
|
/* @__PURE__ */ jsx9(HarnessLogo, { id: opening.harness, size: 34 }),
|
|
2976
3092
|
/* @__PURE__ */ jsxs8("span", { children: [
|
package/react/settings.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export type { HarnessAdvisoryProps, HarnessSettingsPanelProps } from './index.js';
|
|
2
|
-
export { HarnessAdvisory, HarnessSettingsPanel } from './index.js';
|
|
1
|
+
export type { HarnessAdvisoryProps, HarnessPickerProps, HarnessSettingsPanelProps } from './index.js';
|
|
2
|
+
export { HarnessAdvisory, HarnessPicker, HarnessSettingsPanel } from './index.js';
|
package/react/settings.mjs
CHANGED
|
@@ -307,8 +307,82 @@ function HarnessReadiness({ harnesses, adapter }) {
|
|
|
307
307
|
] }, item.id)) })
|
|
308
308
|
] });
|
|
309
309
|
}
|
|
310
|
+
function HarnessPicker({ harnesses, value, disabled = false, adapter, onChange, logo: Logo = HarnessLogo }) {
|
|
311
|
+
const [open, setOpen] = useState(false);
|
|
312
|
+
const menuId = useId();
|
|
313
|
+
const root = useRef(null);
|
|
314
|
+
const trigger = useRef(null);
|
|
315
|
+
const panel = useRef(null);
|
|
316
|
+
const available = harnesses.filter((item) => item.startable);
|
|
317
|
+
const unavailable = harnesses.filter((item) => !item.startable);
|
|
318
|
+
const selected = available.find((item) => item.id === value) ?? available[0] ?? null;
|
|
319
|
+
const close = () => {
|
|
320
|
+
setOpen(false);
|
|
321
|
+
trigger.current?.focus({ preventScroll: true });
|
|
322
|
+
};
|
|
323
|
+
useEffect2(() => {
|
|
324
|
+
if (!open) return;
|
|
325
|
+
panel.current?.querySelector('[aria-selected="true"], [role="option"]')?.focus({ preventScroll: true });
|
|
326
|
+
const dismiss = (event) => {
|
|
327
|
+
if (event.type === "keydown" && event.key === "Escape") {
|
|
328
|
+
event.preventDefault();
|
|
329
|
+
close();
|
|
330
|
+
} else if (event.type === "pointerdown" && !root.current?.contains(event.target)) {
|
|
331
|
+
setOpen(false);
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
document.addEventListener("keydown", dismiss);
|
|
335
|
+
document.addEventListener("pointerdown", dismiss, true);
|
|
336
|
+
return () => {
|
|
337
|
+
document.removeEventListener("keydown", dismiss);
|
|
338
|
+
document.removeEventListener("pointerdown", dismiss, true);
|
|
339
|
+
};
|
|
340
|
+
}, [open]);
|
|
341
|
+
const navigate = (event) => {
|
|
342
|
+
if (!["ArrowDown", "ArrowUp", "Home", "End"].includes(event.key)) return;
|
|
343
|
+
const items = [...panel.current.querySelectorAll('[role="option"]')];
|
|
344
|
+
if (!items.length) return;
|
|
345
|
+
event.preventDefault();
|
|
346
|
+
const current = items.indexOf(document.activeElement);
|
|
347
|
+
const index = event.key === "Home" ? 0 : event.key === "End" ? items.length - 1 : event.key === "ArrowDown" ? (current + 1) % items.length : (current <= 0 ? items.length : current) - 1;
|
|
348
|
+
items[index].focus({ preventScroll: true });
|
|
349
|
+
};
|
|
350
|
+
const select = (id) => {
|
|
351
|
+
onChange(id);
|
|
352
|
+
close();
|
|
353
|
+
};
|
|
354
|
+
return /* @__PURE__ */ jsxs3("div", { className: "scui-harness-menu", ref: root, onBlur: (event) => {
|
|
355
|
+
if (event.relatedTarget && !event.currentTarget.contains(event.relatedTarget)) setOpen(false);
|
|
356
|
+
}, children: [
|
|
357
|
+
/* @__PURE__ */ jsxs3("button", { ref: trigger, className: "scui-harness-trigger", type: "button", disabled: disabled || !selected, "aria-label": selected ? `Coding harness: ${selected.label}` : "No coding harness available", "aria-haspopup": "dialog", "aria-expanded": open, "aria-controls": open ? menuId : void 0, onClick: () => setOpen((current) => !current), children: [
|
|
358
|
+
selected ? /* @__PURE__ */ jsx3(Logo, { id: selected.id, size: 20 }) : null,
|
|
359
|
+
/* @__PURE__ */ jsx3("strong", { children: selected?.label ?? "No harness available" }),
|
|
360
|
+
/* @__PURE__ */ jsx3(UiIcon, { name: "chevron", size: 13 })
|
|
361
|
+
] }),
|
|
362
|
+
open ? /* @__PURE__ */ jsxs3("div", { ref: panel, id: menuId, className: "scui-harness-popover", role: "dialog", "aria-label": "Choose coding harness", onKeyDown: navigate, children: [
|
|
363
|
+
/* @__PURE__ */ jsx3("strong", { className: "scui-harness-popover-title", children: "Choose coding harness" }),
|
|
364
|
+
/* @__PURE__ */ jsx3("div", { className: "scui-harness-options", role: "listbox", "aria-label": "Available coding harnesses", children: available.map((item) => /* @__PURE__ */ jsxs3("button", { type: "button", role: "option", "aria-selected": item.id === selected?.id, onClick: () => select(item.id), children: [
|
|
365
|
+
/* @__PURE__ */ jsx3(Logo, { id: item.id, size: 24 }),
|
|
366
|
+
/* @__PURE__ */ jsx3("strong", { children: item.label }),
|
|
367
|
+
/* @__PURE__ */ jsx3("span", { children: item.id === selected?.id ? /* @__PURE__ */ jsx3(UiIcon, { name: "check", size: 15 }) : null })
|
|
368
|
+
] }, item.id)) }),
|
|
369
|
+
unavailable.length ? /* @__PURE__ */ jsxs3("details", { className: "scui-harness-manage", children: [
|
|
370
|
+
/* @__PURE__ */ jsx3("summary", { children: "Manage additional harnesses" }),
|
|
371
|
+
/* @__PURE__ */ jsx3("div", { children: unavailable.map((item) => /* @__PURE__ */ jsxs3("section", { children: [
|
|
372
|
+
/* @__PURE__ */ jsx3(Logo, { id: item.id, size: 24 }),
|
|
373
|
+
/* @__PURE__ */ jsxs3("span", { children: [
|
|
374
|
+
/* @__PURE__ */ jsx3("strong", { children: item.label }),
|
|
375
|
+
/* @__PURE__ */ jsx3("small", { children: item.reason || (item.auth === "required" ? "Authentication required" : "Unavailable") })
|
|
376
|
+
] }),
|
|
377
|
+
item.repair ? /* @__PURE__ */ jsx3("button", { type: "button", onClick: () => adapter?.copyText?.(item.repair), children: "Copy fix" }) : null
|
|
378
|
+
] }, item.id)) })
|
|
379
|
+
] }) : null
|
|
380
|
+
] }) : null
|
|
381
|
+
] });
|
|
382
|
+
}
|
|
310
383
|
export {
|
|
311
384
|
HarnessAdvisory,
|
|
385
|
+
HarnessPicker,
|
|
312
386
|
HarnessReadiness,
|
|
313
387
|
HarnessSettingsPanel
|
|
314
388
|
};
|
package/settings.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { HarnessAdvisory, HarnessSettingsPanel } from './index.js';
|
|
2
|
-
export type { HarnessAdvisoryProps, HarnessSettingsPanelProps } from './index.js';
|
|
1
|
+
export { HarnessAdvisory, HarnessPicker, HarnessSettingsPanel } from './index.js';
|
|
2
|
+
export type { HarnessAdvisoryProps, HarnessPickerProps, HarnessSettingsPanelProps } from './index.js';
|
package/settings.mjs
CHANGED
|
@@ -307,8 +307,82 @@ function HarnessReadiness({ harnesses, adapter }) {
|
|
|
307
307
|
] }, item.id)) })
|
|
308
308
|
] });
|
|
309
309
|
}
|
|
310
|
+
function HarnessPicker({ harnesses, value, disabled = false, adapter, onChange, logo: Logo = HarnessLogo }) {
|
|
311
|
+
const [open, setOpen] = useState(false);
|
|
312
|
+
const menuId = useId();
|
|
313
|
+
const root = useRef(null);
|
|
314
|
+
const trigger = useRef(null);
|
|
315
|
+
const panel = useRef(null);
|
|
316
|
+
const available = harnesses.filter((item) => item.startable);
|
|
317
|
+
const unavailable = harnesses.filter((item) => !item.startable);
|
|
318
|
+
const selected = available.find((item) => item.id === value) ?? available[0] ?? null;
|
|
319
|
+
const close = () => {
|
|
320
|
+
setOpen(false);
|
|
321
|
+
trigger.current?.focus({ preventScroll: true });
|
|
322
|
+
};
|
|
323
|
+
useEffect2(() => {
|
|
324
|
+
if (!open) return;
|
|
325
|
+
panel.current?.querySelector('[aria-selected="true"], [role="option"]')?.focus({ preventScroll: true });
|
|
326
|
+
const dismiss = (event) => {
|
|
327
|
+
if (event.type === "keydown" && event.key === "Escape") {
|
|
328
|
+
event.preventDefault();
|
|
329
|
+
close();
|
|
330
|
+
} else if (event.type === "pointerdown" && !root.current?.contains(event.target)) {
|
|
331
|
+
setOpen(false);
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
document.addEventListener("keydown", dismiss);
|
|
335
|
+
document.addEventListener("pointerdown", dismiss, true);
|
|
336
|
+
return () => {
|
|
337
|
+
document.removeEventListener("keydown", dismiss);
|
|
338
|
+
document.removeEventListener("pointerdown", dismiss, true);
|
|
339
|
+
};
|
|
340
|
+
}, [open]);
|
|
341
|
+
const navigate = (event) => {
|
|
342
|
+
if (!["ArrowDown", "ArrowUp", "Home", "End"].includes(event.key)) return;
|
|
343
|
+
const items = [...panel.current.querySelectorAll('[role="option"]')];
|
|
344
|
+
if (!items.length) return;
|
|
345
|
+
event.preventDefault();
|
|
346
|
+
const current = items.indexOf(document.activeElement);
|
|
347
|
+
const index = event.key === "Home" ? 0 : event.key === "End" ? items.length - 1 : event.key === "ArrowDown" ? (current + 1) % items.length : (current <= 0 ? items.length : current) - 1;
|
|
348
|
+
items[index].focus({ preventScroll: true });
|
|
349
|
+
};
|
|
350
|
+
const select = (id) => {
|
|
351
|
+
onChange(id);
|
|
352
|
+
close();
|
|
353
|
+
};
|
|
354
|
+
return /* @__PURE__ */ jsxs3("div", { className: "scui-harness-menu", ref: root, onBlur: (event) => {
|
|
355
|
+
if (event.relatedTarget && !event.currentTarget.contains(event.relatedTarget)) setOpen(false);
|
|
356
|
+
}, children: [
|
|
357
|
+
/* @__PURE__ */ jsxs3("button", { ref: trigger, className: "scui-harness-trigger", type: "button", disabled: disabled || !selected, "aria-label": selected ? `Coding harness: ${selected.label}` : "No coding harness available", "aria-haspopup": "dialog", "aria-expanded": open, "aria-controls": open ? menuId : void 0, onClick: () => setOpen((current) => !current), children: [
|
|
358
|
+
selected ? /* @__PURE__ */ jsx3(Logo, { id: selected.id, size: 20 }) : null,
|
|
359
|
+
/* @__PURE__ */ jsx3("strong", { children: selected?.label ?? "No harness available" }),
|
|
360
|
+
/* @__PURE__ */ jsx3(UiIcon, { name: "chevron", size: 13 })
|
|
361
|
+
] }),
|
|
362
|
+
open ? /* @__PURE__ */ jsxs3("div", { ref: panel, id: menuId, className: "scui-harness-popover", role: "dialog", "aria-label": "Choose coding harness", onKeyDown: navigate, children: [
|
|
363
|
+
/* @__PURE__ */ jsx3("strong", { className: "scui-harness-popover-title", children: "Choose coding harness" }),
|
|
364
|
+
/* @__PURE__ */ jsx3("div", { className: "scui-harness-options", role: "listbox", "aria-label": "Available coding harnesses", children: available.map((item) => /* @__PURE__ */ jsxs3("button", { type: "button", role: "option", "aria-selected": item.id === selected?.id, onClick: () => select(item.id), children: [
|
|
365
|
+
/* @__PURE__ */ jsx3(Logo, { id: item.id, size: 24 }),
|
|
366
|
+
/* @__PURE__ */ jsx3("strong", { children: item.label }),
|
|
367
|
+
/* @__PURE__ */ jsx3("span", { children: item.id === selected?.id ? /* @__PURE__ */ jsx3(UiIcon, { name: "check", size: 15 }) : null })
|
|
368
|
+
] }, item.id)) }),
|
|
369
|
+
unavailable.length ? /* @__PURE__ */ jsxs3("details", { className: "scui-harness-manage", children: [
|
|
370
|
+
/* @__PURE__ */ jsx3("summary", { children: "Manage additional harnesses" }),
|
|
371
|
+
/* @__PURE__ */ jsx3("div", { children: unavailable.map((item) => /* @__PURE__ */ jsxs3("section", { children: [
|
|
372
|
+
/* @__PURE__ */ jsx3(Logo, { id: item.id, size: 24 }),
|
|
373
|
+
/* @__PURE__ */ jsxs3("span", { children: [
|
|
374
|
+
/* @__PURE__ */ jsx3("strong", { children: item.label }),
|
|
375
|
+
/* @__PURE__ */ jsx3("small", { children: item.reason || (item.auth === "required" ? "Authentication required" : "Unavailable") })
|
|
376
|
+
] }),
|
|
377
|
+
item.repair ? /* @__PURE__ */ jsx3("button", { type: "button", onClick: () => adapter?.copyText?.(item.repair), children: "Copy fix" }) : null
|
|
378
|
+
] }, item.id)) })
|
|
379
|
+
] }) : null
|
|
380
|
+
] }) : null
|
|
381
|
+
] });
|
|
382
|
+
}
|
|
310
383
|
export {
|
|
311
384
|
HarnessAdvisory,
|
|
385
|
+
HarnessPicker,
|
|
312
386
|
HarnessReadiness,
|
|
313
387
|
HarnessSettingsPanel
|
|
314
388
|
};
|
package/styles.css
CHANGED
|
@@ -198,7 +198,10 @@
|
|
|
198
198
|
.scui-send,.scui-stop { display:grid; width:29px; height:29px; padding:0; place-items:center; border:0; border-radius:8px; background:var(--scui-accent); color:#fff; cursor:pointer }.scui-stop { background:var(--scui-danger) }.scui-send:disabled,.scui-stop:disabled { opacity:.4; cursor:default }.scui-control-spinner { box-sizing:border-box; width:13px; height:13px; border:1.5px solid currentColor; border-right-color:transparent; border-radius:50%; animation:scui-spin .75s linear infinite }
|
|
199
199
|
.scui-queue-send { display:grid; width:29px; height:29px; padding:0; place-items:center; border:0; border-radius:8px; background:transparent; color:var(--scui-muted); cursor:pointer }.scui-queue-send:hover { background:var(--scui-fill); color:var(--scui-fg) }
|
|
200
200
|
.scui-queue { display:grid; gap:4px; max-height:85px; margin-bottom:6px; overflow:auto; font-size:10.5px }.scui-queue > span { display:flex; gap:6px; padding:4px 6px; border-radius:5px; background:var(--scui-fill) }.scui-queue > span > span { display:grid; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap }.scui-queue small { color:var(--scui-muted) }.scui-queue > span button { margin-left:auto; border:0; background:transparent }
|
|
201
|
-
.scui-
|
|
201
|
+
.scui-new-envelope { display:grid; align-items:stretch; gap:3px; padding:7px }.scui-new-envelope textarea { box-sizing:border-box; width:100%; min-height:54px; padding:2px 3px }.scui-new-envelope-controls { display:flex; min-width:0; align-items:center; gap:3px }.scui-new-envelope-controls > span { display:flex; margin-left:auto }.scui-new-envelope-controls .scui-attach { flex-basis:29px; width:29px; height:29px }
|
|
202
|
+
.scui-harness-menu { position:relative; min-width:0 }.scui-harness-trigger { display:flex; max-width:170px; height:29px; align-items:center; gap:6px; padding:3px 7px 3px 4px; border:0; border-radius:8px; background:transparent; color:var(--scui-fg); cursor:pointer }.scui-harness-trigger:hover:not(:disabled),.scui-harness-trigger:focus-visible,.scui-harness-trigger[aria-expanded="true"] { background:var(--scui-fill) }.scui-harness-trigger:disabled { cursor:default; opacity:.55 }.scui-harness-trigger > strong { min-width:0; overflow:hidden; font-size:10.5px; font-weight:600; text-overflow:ellipsis; white-space:nowrap }.scui-harness-trigger > .scui-icon { flex:none; color:var(--scui-muted); transform:rotate(90deg); transition:transform 120ms }.scui-harness-trigger[aria-expanded="true"] > .scui-icon { transform:rotate(-90deg) }
|
|
203
|
+
.scui-harness-popover { position:absolute; z-index:25; bottom:calc(100% + 7px); left:0; display:grid; box-sizing:border-box; width:min(250px,calc(100vw - 24px)); max-height:min(330px,calc(100dvh - 90px)); overflow:auto; padding:5px; border:1px solid var(--scui-border-strong); border-radius:10px; background:var(--scui-bg-raised); box-shadow:0 12px 34px rgba(0,0,0,.2) }.scui-harness-popover-title { padding:5px 7px; color:var(--scui-muted); font-size:8.5px; font-weight:650; letter-spacing:.055em; text-transform:uppercase }.scui-harness-options { display:grid; gap:1px }.scui-harness-options > button { display:grid; grid-template-columns:auto minmax(0,1fr) 18px; width:100%; min-height:36px; align-items:center; gap:8px; padding:5px 7px; border:0; border-radius:7px; background:transparent; color:var(--scui-fg); text-align:left; cursor:pointer }.scui-harness-options > button:hover,.scui-harness-options > button:focus-visible { background:var(--scui-fill) }.scui-harness-options > button[aria-selected="true"] { background:color-mix(in srgb,var(--scui-accent) 8%,var(--scui-bg-raised)) }.scui-harness-options > button > strong { min-width:0; overflow:hidden; font-size:11px; font-weight:600; text-overflow:ellipsis; white-space:nowrap }.scui-harness-options > button > span { display:grid; color:var(--scui-accent); place-items:center }
|
|
204
|
+
.scui-harness-manage { margin-top:4px; padding-top:4px; border-top:1px solid var(--scui-border) }.scui-harness-manage > summary { padding:6px 7px; color:var(--scui-muted); cursor:pointer; font-size:9.5px }.scui-harness-manage > div { display:grid; gap:1px }.scui-harness-manage section { display:grid; grid-template-columns:auto minmax(0,1fr) auto; min-height:36px; align-items:center; gap:8px; padding:5px 7px }.scui-harness-manage section > span { display:grid; min-width:0 }.scui-harness-manage section strong,.scui-harness-manage section small { overflow:hidden; text-overflow:ellipsis; white-space:nowrap }.scui-harness-manage section strong { font-size:10.5px; font-weight:600 }.scui-harness-manage section small { color:var(--scui-muted); font-size:8.5px }.scui-harness-manage section > button { padding:4px 6px; border:1px solid var(--scui-border); border-radius:6px; background:transparent; color:var(--scui-muted); cursor:pointer; font-size:8.5px }.scui-harness-manage section > button:hover { border-color:var(--scui-border-strong); color:var(--scui-fg) }
|
|
202
205
|
.scui-readiness { margin:0 0 7px; border:1px solid var(--scui-border); border-radius:7px; background:var(--scui-bg) }.scui-readiness > summary { padding:6px 8px; color:var(--scui-muted); cursor:pointer; font-size:10px }.scui-readiness > div { display:grid; border-top:1px solid var(--scui-border) }.scui-readiness section { display:grid; grid-template-columns:auto minmax(0,1fr) auto; align-items:center; gap:7px; padding:7px 8px }.scui-readiness section + section { border-top:1px solid var(--scui-border) }.scui-readiness section > span { display:grid; min-width:0 }.scui-readiness section strong,.scui-readiness section small,.scui-readiness section em { overflow:hidden; text-overflow:ellipsis; white-space:nowrap }.scui-readiness section small { color:var(--scui-muted); font-size:9px }.scui-readiness section em { color:var(--scui-muted); font-size:8px; font-style:normal }.scui-readiness section button { padding:4px 6px; border:1px solid var(--scui-border); border-radius:6px; background:transparent; cursor:pointer; font-size:9px }
|
|
203
206
|
.scui-launch-modes { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:5px; margin:0 0 7px; padding:0; border:0 }.scui-launch-modes legend { position:absolute; overflow:hidden; width:1px; height:1px; clip:rect(0 0 0 0); white-space:nowrap }.scui-launch-modes label { position:relative; min-width:0; cursor:pointer }.scui-launch-modes input { position:absolute; opacity:0; pointer-events:none }.scui-launch-modes label > span { display:flex; min-height:42px; flex-direction:column; justify-content:center; padding:6px 9px; border:1px solid var(--scui-border); border-radius:7px; background:var(--scui-bg); transition:border-color .14s ease,background .14s ease }.scui-launch-modes strong { font-size:11px; font-weight:650 }.scui-launch-modes small { overflow:hidden; color:var(--scui-muted); font-size:9px; text-overflow:ellipsis; white-space:nowrap }.scui-launch-modes input:checked + span { border-color:color-mix(in srgb,var(--scui-accent) 58%,var(--scui-border)); background:color-mix(in srgb,var(--scui-accent) 8%,var(--scui-bg)) }.scui-launch-modes input:focus-visible + span { outline:2px solid var(--scui-accent); outline-offset:1px }.scui-launch-modes:disabled label { cursor:default; opacity:.62 }
|
|
204
207
|
.scui-new { display:grid; justify-items:center; gap:5px; margin:auto; padding:20px; color:var(--scui-muted); text-align:center }.scui-new > span { color:var(--scui-accent); font-size:28px }.scui-new strong { color:var(--scui-fg) }
|
|
@@ -215,6 +218,8 @@
|
|
|
215
218
|
.scui-head { min-height:52px }
|
|
216
219
|
.scui-menu-panel button,.scui-request-actions button,.scui-load { min-height:40px }
|
|
217
220
|
.scui-send,.scui-stop { width:40px; height:40px }
|
|
221
|
+
.scui-new-envelope-controls .scui-attach,.scui-harness-trigger { min-height:40px }
|
|
222
|
+
.scui-harness-options > button,.scui-harness-manage section { min-height:44px }
|
|
218
223
|
.scui-message-meta button,.scui-code-copy { min-width:36px; min-height:36px }
|
|
219
224
|
.scui-latest { min-height:36px; padding-inline:12px }
|
|
220
225
|
}
|