shadok-ai 0.16.15 → 0.16.16
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/package.json +1 -1
- package/public/index.html +80 -0
package/package.json
CHANGED
package/public/index.html
CHANGED
|
@@ -1221,6 +1221,38 @@
|
|
|
1221
1221
|
padding: 6px 10px; background: var(--bg-inset); border: 1px solid var(--line); border-radius: 8px;
|
|
1222
1222
|
color: var(--text-dim); text-decoration: none; font-family: var(--mono); font-size: 12px; }
|
|
1223
1223
|
.att-file:hover { color: var(--amber); border-color: var(--amber); }
|
|
1224
|
+
/* Any image in the chat (agent file card, user attachment, markdown image)
|
|
1225
|
+
opens full-size in the lightbox on click. */
|
|
1226
|
+
.file-img img, .att-img img, .bubble.md img { cursor: zoom-in; }
|
|
1227
|
+
#lightbox {
|
|
1228
|
+
position: fixed; inset: 0; z-index: 5000;
|
|
1229
|
+
display: flex; align-items: center; justify-content: center;
|
|
1230
|
+
padding: 40px; background: rgba(6, 7, 10, 0.85);
|
|
1231
|
+
-webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
|
|
1232
|
+
}
|
|
1233
|
+
#lightbox[hidden] { display: none; }
|
|
1234
|
+
#lightbox img {
|
|
1235
|
+
max-width: 94vw; max-height: 86vh; object-fit: contain;
|
|
1236
|
+
border-radius: 8px; box-shadow: 0 16px 50px rgba(0, 0, 0, 0.6);
|
|
1237
|
+
cursor: default; background: var(--bg-raised);
|
|
1238
|
+
}
|
|
1239
|
+
#lightboxClose {
|
|
1240
|
+
position: absolute; top: 14px; right: 16px;
|
|
1241
|
+
width: 40px; height: 40px; border-radius: 50%;
|
|
1242
|
+
display: flex; align-items: center; justify-content: center;
|
|
1243
|
+
font-size: 22px; line-height: 1; color: #fff; cursor: pointer;
|
|
1244
|
+
background: rgba(0, 0, 0, 0.45); border: 1px solid rgba(255, 255, 255, 0.3);
|
|
1245
|
+
}
|
|
1246
|
+
#lightboxClose:hover { background: rgba(0, 0, 0, 0.7); }
|
|
1247
|
+
#lightboxBar { position: absolute; left: 50%; bottom: 20px; transform: translateX(-50%); max-width: 90vw; }
|
|
1248
|
+
#lightboxDl {
|
|
1249
|
+
display: inline-block; max-width: 100%; overflow: hidden; text-overflow: ellipsis;
|
|
1250
|
+
white-space: nowrap; color: #fff; text-decoration: none;
|
|
1251
|
+
font-family: var(--mono); font-size: 12px;
|
|
1252
|
+
background: rgba(0, 0, 0, 0.5); border: 1px solid rgba(255, 255, 255, 0.25);
|
|
1253
|
+
border-radius: 8px; padding: 7px 14px;
|
|
1254
|
+
}
|
|
1255
|
+
#lightboxDl:hover { background: rgba(0, 0, 0, 0.75); }
|
|
1224
1256
|
.att-file .att-ic { color: var(--amber); flex: none; }
|
|
1225
1257
|
.att-file .att-nm { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
1226
1258
|
/* Composer attachment strip: the SAME dropped/pasted files, previewed above the
|
|
@@ -3202,6 +3234,13 @@
|
|
|
3202
3234
|
</aside>
|
|
3203
3235
|
</main>
|
|
3204
3236
|
|
|
3237
|
+
<!-- Full-size image viewer: click any chat image to open it here. -->
|
|
3238
|
+
<div id="lightbox" role="dialog" aria-modal="true" aria-label="Image preview" hidden>
|
|
3239
|
+
<button id="lightboxClose" type="button" aria-label="Close image preview">×</button>
|
|
3240
|
+
<img id="lightboxImg" alt="">
|
|
3241
|
+
<div id="lightboxBar"><a id="lightboxDl" download>⭳ Download</a></div>
|
|
3242
|
+
</div>
|
|
3243
|
+
|
|
3205
3244
|
<link rel="stylesheet" href="/vendor/xterm.css">
|
|
3206
3245
|
<script src="/vendor/xterm.js"></script>
|
|
3207
3246
|
<script src="/vendor/addon-fit.js"></script>
|
|
@@ -9077,6 +9116,44 @@
|
|
|
9077
9116
|
sendTo(active, { type: "key", key: b.dataset.key });
|
|
9078
9117
|
})
|
|
9079
9118
|
);
|
|
9119
|
+
// ── Image lightbox: click any chat image to view it full-size ───────────
|
|
9120
|
+
// One viewer for every image in the chat — agent file cards (`.file-img`), the
|
|
9121
|
+
// user's own attachments (`.att-img`, whose <a> would otherwise open a new
|
|
9122
|
+
// tab) and images inside rendered markdown (`.bubble.md img`). A delegated
|
|
9123
|
+
// click on the transcripts container covers every tab with one listener.
|
|
9124
|
+
const lightbox = $("lightbox"), lightboxImg = $("lightboxImg"), lightboxDl = $("lightboxDl");
|
|
9125
|
+
let lightboxReturnFocus = null;
|
|
9126
|
+
function openLightbox(src, name) {
|
|
9127
|
+
if (!src) return;
|
|
9128
|
+
lightboxImg.src = src;
|
|
9129
|
+
lightboxImg.alt = name || "";
|
|
9130
|
+
lightboxDl.href = src;
|
|
9131
|
+
lightboxDl.download = name || "image";
|
|
9132
|
+
lightboxDl.textContent = name ? "⭳ " + name : "⭳ Download";
|
|
9133
|
+
lightboxReturnFocus = document.activeElement;
|
|
9134
|
+
lightbox.hidden = false;
|
|
9135
|
+
$("lightboxClose").focus();
|
|
9136
|
+
}
|
|
9137
|
+
function closeLightbox() {
|
|
9138
|
+
if (lightbox.hidden) return;
|
|
9139
|
+
lightbox.hidden = true;
|
|
9140
|
+
lightboxImg.removeAttribute("src"); // stop the load, drop the decode
|
|
9141
|
+
if (lightboxReturnFocus && lightboxReturnFocus.focus) lightboxReturnFocus.focus();
|
|
9142
|
+
lightboxReturnFocus = null;
|
|
9143
|
+
}
|
|
9144
|
+
transcripts.addEventListener("click", (e) => {
|
|
9145
|
+
const img = e.target.closest("img");
|
|
9146
|
+
if (!img || !img.closest(".file-img, .att-img, .bubble.md")) return;
|
|
9147
|
+
e.preventDefault(); // an .att-img image sits in an <a target="_blank">
|
|
9148
|
+
openLightbox(img.currentSrc || img.src, img.alt || "");
|
|
9149
|
+
});
|
|
9150
|
+
lightbox.addEventListener("click", (e) => {
|
|
9151
|
+
// A click anywhere but the image itself (or the download link) closes it.
|
|
9152
|
+
if (e.target === lightboxImg || e.target.closest("#lightboxDl")) return;
|
|
9153
|
+
closeLightbox();
|
|
9154
|
+
});
|
|
9155
|
+
$("lightboxClose").addEventListener("click", closeLightbox);
|
|
9156
|
+
|
|
9080
9157
|
// The Escape key sends esc to the active session (like the engine room's Esc
|
|
9081
9158
|
// button). Precedence: an open overlay/panel is closed first (Escape does not
|
|
9082
9159
|
// reach down to the session); a pending clickable dialog is left intact;
|
|
@@ -9085,6 +9162,9 @@
|
|
|
9085
9162
|
// The inline edit calls stopPropagation, so this handler never sees it.
|
|
9086
9163
|
document.addEventListener("keydown", (e) => {
|
|
9087
9164
|
if (e.key !== "Escape") return;
|
|
9165
|
+
// The image viewer sits on top of everything, including the terminal, so it
|
|
9166
|
+
// is closed before any other Escape handling.
|
|
9167
|
+
if (!lightbox.hidden) { closeLightbox(); e.preventDefault(); return; }
|
|
9088
9168
|
// In the interactive terminal, xterm owns every key (incl. Esc) — the raw
|
|
9089
9169
|
// keystroke already flows to the pane via term.onData; don't double-handle.
|
|
9090
9170
|
if (active && active.termOn) return;
|