clay-server 2.36.2-beta.3 → 2.36.2-beta.4

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.
@@ -289,79 +289,84 @@ export function hideConfirm() {
289
289
  }
290
290
 
291
291
  export function showForceChangePinOverlay() {
292
+ // Inject the same .pin-digit / .pin-wrap CSS the login page uses, so this
293
+ // overlay behaves identically: visible focus ring, filled state, etc.
294
+ // The login page (lib/pages.js) loads this CSS inline; the main app
295
+ // doesn't, so we add it once here.
296
+ if (!document.getElementById("fcp-style")) {
297
+ var st = document.createElement("style");
298
+ st.id = "fcp-style";
299
+ st.textContent =
300
+ "#force-change-pin-overlay .pin-wrap{display:flex;gap:8px;justify-content:center;margin-bottom:16px}" +
301
+ "#force-change-pin-overlay .pin-digit{width:44px;height:56px;background:var(--input-bg);border:1.5px solid var(--border);border-radius:8px;color:var(--text);font-family:'Courier New',Courier,'Roboto Mono',monospace;font-size:28px;font-weight:700;text-align:center;line-height:56px;outline:none;caret-color:transparent;transition:border-color 0.15s,box-shadow 0.15s}" +
302
+ "#force-change-pin-overlay .pin-digit:focus{border-color:var(--accent);box-shadow:0 0 0 2px var(--accent-20,rgba(124,58,237,0.25))}" +
303
+ "#force-change-pin-overlay .pin-digit.filled{color:var(--text)}";
304
+ document.head.appendChild(st);
305
+ }
306
+
292
307
  var ov = document.createElement("div");
293
308
  ov.id = "force-change-pin-overlay";
294
309
  ov.style.cssText = "position:fixed;inset:0;background:var(--bg,#0e0e10);z-index:99999;display:flex;align-items:center;justify-content:center;flex-direction:column";
295
310
  ov.innerHTML = '<div style="width:100%;max-width:380px;padding:24px;text-align:center">' +
296
311
  '<h2 style="margin:0 0 8px;color:var(--text,#fff);font-size:22px">Set your new PIN</h2>' +
297
312
  '<p style="margin:0 0 24px;color:var(--text-secondary,#aaa);font-size:14px">Your temporary PIN has expired. Please set a new 6-digit PIN to continue.</p>' +
298
- '<div style="display:flex;gap:8px;justify-content:center;margin-bottom:16px" id="fcp-boxes">' +
299
- '<input class="fcp-digit" type="password" maxlength="1" inputmode="numeric" pattern="[0-9]*" autocomplete="one-time-code" style="width:44px;height:52px;text-align:center;font-size:22px;font-weight:600;border:2px solid var(--border,#333);border-radius:10px;background:var(--bg-alt,#f5f5f5);color:var(--text,#fff);outline:none;caret-color:var(--accent,#7c3aed)">' +
300
- '<input class="fcp-digit" type="password" maxlength="1" inputmode="numeric" pattern="[0-9]*" autocomplete="one-time-code" style="width:44px;height:52px;text-align:center;font-size:22px;font-weight:600;border:2px solid var(--border,#333);border-radius:10px;background:var(--bg-alt,#f5f5f5);color:var(--text,#fff);outline:none;caret-color:var(--accent,#7c3aed)">' +
301
- '<input class="fcp-digit" type="password" maxlength="1" inputmode="numeric" pattern="[0-9]*" autocomplete="one-time-code" style="width:44px;height:52px;text-align:center;font-size:22px;font-weight:600;border:2px solid var(--border,#333);border-radius:10px;background:var(--bg-alt,#f5f5f5);color:var(--text,#fff);outline:none;caret-color:var(--accent,#7c3aed)">' +
302
- '<input class="fcp-digit" type="password" maxlength="1" inputmode="numeric" pattern="[0-9]*" autocomplete="one-time-code" style="width:44px;height:52px;text-align:center;font-size:22px;font-weight:600;border:2px solid var(--border,#333);border-radius:10px;background:var(--bg-alt,#f5f5f5);color:var(--text,#fff);outline:none;caret-color:var(--accent,#7c3aed)">' +
303
- '<input class="fcp-digit" type="password" maxlength="1" inputmode="numeric" pattern="[0-9]*" autocomplete="one-time-code" style="width:44px;height:52px;text-align:center;font-size:22px;font-weight:600;border:2px solid var(--border,#333);border-radius:10px;background:var(--bg-alt,#f5f5f5);color:var(--text,#fff);outline:none;caret-color:var(--accent,#7c3aed)">' +
304
- '<input class="fcp-digit" type="password" maxlength="1" inputmode="numeric" pattern="[0-9]*" autocomplete="one-time-code" style="width:44px;height:52px;text-align:center;font-size:22px;font-weight:600;border:2px solid var(--border,#333);border-radius:10px;background:var(--bg-alt,#f5f5f5);color:var(--text,#fff);outline:none;caret-color:var(--accent,#7c3aed)">' +
313
+ '<div class="pin-wrap" id="fcp-boxes">' +
314
+ '<input class="pin-digit" type="tel" maxlength="1" inputmode="numeric" autocomplete="off">' +
315
+ '<input class="pin-digit" type="tel" maxlength="1" inputmode="numeric" autocomplete="off">' +
316
+ '<input class="pin-digit" type="tel" maxlength="1" inputmode="numeric" autocomplete="off">' +
317
+ '<input class="pin-digit" type="tel" maxlength="1" inputmode="numeric" autocomplete="off">' +
318
+ '<input class="pin-digit" type="tel" maxlength="1" inputmode="numeric" autocomplete="off">' +
319
+ '<input class="pin-digit" type="tel" maxlength="1" inputmode="numeric" autocomplete="off">' +
305
320
  '</div>' +
306
- '<button id="fcp-save" disabled style="width:100%;padding:12px;border:none;border-radius:10px;background:var(--accent,#7c3aed);color:#fff;font-size:15px;font-weight:600;cursor:pointer;opacity:0.5">Save PIN</button>' +
307
- '<div id="fcp-err" style="margin-top:12px;color:#ef4444;font-size:13px"></div>' +
321
+ '<button id="fcp-save" disabled style="width:100%;padding:12px;border:none;border-radius:10px;background:var(--accent);color:#fff;font-size:15px;font-weight:600;cursor:pointer;opacity:0.5;transition:opacity 0.15s">Save PIN</button>' +
322
+ '<div id="fcp-err" style="margin-top:12px;color:var(--error,#ef4444);font-size:13px;min-height:1.3em"></div>' +
308
323
  '</div>';
309
324
  document.body.appendChild(ov);
310
325
 
311
- var boxes = ov.querySelectorAll(".fcp-digit");
326
+ var boxes = ov.querySelectorAll(".pin-digit");
312
327
  var saveBtn = ov.querySelector("#fcp-save");
313
328
  var errEl = ov.querySelector("#fcp-err");
314
-
315
- // Inject focus styling. Without this the inputs use outline:none with no
316
- // replacement, so users cannot tell which box is focused. Caret is also
317
- // forced via caret-color on the input style.
318
- if (!document.getElementById("fcp-style")) {
319
- var st = document.createElement("style");
320
- st.id = "fcp-style";
321
- st.textContent =
322
- ".fcp-digit:focus{border-color:var(--accent,#7c3aed)!important;box-shadow:0 0 0 3px rgba(124,58,237,0.25)}" +
323
- ".fcp-digit.filled{border-color:var(--accent,#7c3aed)}";
324
- document.head.appendChild(st);
329
+ // Mirror the login screen's pattern (lib/pages.js pinBoxScript): keep an
330
+ // explicit digits[] array as the source of truth, render bullets visually,
331
+ // enable the button when length === 6.
332
+ var digits = ["", "", "", "", "", ""];
333
+
334
+ function setDigit(idx, v) {
335
+ digits[idx] = v;
336
+ boxes[idx].value = v ? "\u2022" : "";
337
+ boxes[idx].classList.toggle("filled", v.length > 0);
325
338
  }
326
339
 
327
340
  function getPin() {
328
- var pin = "";
329
- for (var i = 0; i < boxes.length; i++) pin += boxes[i].value;
330
- return pin;
341
+ return digits.join("");
331
342
  }
332
343
 
333
344
  function updateBtn() {
334
- var pin = getPin();
335
- var ready = pin.length === 6 && /^[0-9]{6}$/.test(pin);
345
+ var ready = getPin().length === 6;
336
346
  saveBtn.disabled = !ready;
337
347
  saveBtn.style.opacity = ready ? "1" : "0.5";
338
348
  }
339
349
 
340
- function refreshFilled(idx) {
341
- boxes[idx].classList.toggle("filled", boxes[idx].value.length > 0);
342
- }
343
-
344
350
  for (var i = 0; i < boxes.length; i++) {
345
351
  (function (idx) {
346
352
  boxes[idx].addEventListener("input", function () {
347
- // Coerce to a single digit. If user types non-numeric, drop it.
348
353
  var raw = this.value.replace(/[^0-9]/g, "");
349
- this.value = raw.length > 0 ? raw.charAt(raw.length - 1) : "";
350
- refreshFilled(idx);
351
- if (this.value && idx < 5) boxes[idx + 1].focus();
354
+ if (!raw) { setDigit(idx, ""); updateBtn(); return; }
355
+ var v = raw.charAt(raw.length - 1);
356
+ setDigit(idx, v);
357
+ if (v && idx < 5) boxes[idx + 1].focus();
352
358
  updateBtn();
353
359
  });
354
360
  boxes[idx].addEventListener("keydown", function (e) {
355
361
  if (e.key === "Backspace") {
356
- if (!boxes[idx].value && idx > 0) {
357
- boxes[idx - 1].value = "";
358
- refreshFilled(idx - 1);
362
+ if (!digits[idx] && idx > 0) {
363
+ setDigit(idx - 1, "");
359
364
  boxes[idx - 1].focus();
360
365
  } else {
361
- boxes[idx].value = "";
362
- refreshFilled(idx);
366
+ setDigit(idx, "");
363
367
  }
364
368
  updateBtn();
369
+ return;
365
370
  }
366
371
  if (e.key === "ArrowLeft" && idx > 0) boxes[idx - 1].focus();
367
372
  if (e.key === "ArrowRight" && idx < 5) boxes[idx + 1].focus();
@@ -372,10 +377,9 @@ export function showForceChangePinOverlay() {
372
377
  boxes[idx].addEventListener("keypress", function (e) { e.stopPropagation(); });
373
378
  boxes[idx].addEventListener("paste", function (e) {
374
379
  e.preventDefault();
375
- var text = (e.clipboardData || window.clipboardData).getData("text").replace(/[^0-9]/g, "").substring(0, 6);
380
+ var text = (e.clipboardData || window.clipboardData).getData("text").replace(/[^0-9]/g, "").slice(0, 6);
376
381
  for (var j = 0; j < text.length && (idx + j) < 6; j++) {
377
- boxes[idx + j].value = text.charAt(j);
378
- refreshFilled(idx + j);
382
+ setDigit(idx + j, text.charAt(j));
379
383
  }
380
384
  if (text.length > 0) {
381
385
  var focusIdx = Math.min(idx + text.length, 5);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clay-server",
3
- "version": "2.36.2-beta.3",
3
+ "version": "2.36.2-beta.4",
4
4
  "description": "Self-hosted team workspace for Claude Code and Codex. Multi-user, browser-based, with persistent AI mates.",
5
5
  "bin": {
6
6
  "clay-server": "./bin/cli.js",