@crvouga/mockingbird-service-mailosaur 1.5.1 → 1.6.1
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/CHANGELOG.md +14 -4
- package/dist/{chunk-AZIUWKU3.js → chunk-K4JQOFF4.js} +89 -10
- package/dist/chunk-K4JQOFF4.js.map +7 -0
- package/dist/{chunk-EBT7YC5E.js → chunk-ZJPTRVWG.js} +3 -2
- package/dist/chunk-ZJPTRVWG.js.map +7 -0
- package/dist/cli.js +2 -2
- package/dist/index.js +1 -1
- package/dist/server.d.ts +11 -9
- package/dist/server.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-AZIUWKU3.js.map +0 -7
- package/dist/chunk-EBT7YC5E.js.map +0 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
# Changelog — @crvouga/mockingbird-service-mailosaur
|
|
2
2
|
|
|
3
|
-
## 1.
|
|
3
|
+
## 1.6.1 (2026-09-30)
|
|
4
4
|
|
|
5
5
|
### Fixes and improvements
|
|
6
6
|
|
|
7
|
-
- keep
|
|
7
|
+
- keep admin buttons pressed until the action finishes ([0aabfcb](https://github.com/crvouga/mockingbird/commit/0aabfcb5f392aa51e193f9c3f817d5877d92bc6a))
|
|
8
|
+
- size admin select fields like the text inputs beside them ([0fb3ef2](https://github.com/crvouga/mockingbird/commit/0fb3ef2ddbf43376c93a2ae6d87c6c9bf890dafc))
|
|
9
|
+
- keep admin section tabs wired when boot is renamed ([4eda25e](https://github.com/crvouga/mockingbird/commit/4eda25eacd59da048d196f7cc8369d7a02b47bfc))
|
|
10
|
+
|
|
11
|
+
## 1.6.0 (2026-09-29)
|
|
12
|
+
|
|
13
|
+
### Features
|
|
8
14
|
|
|
9
|
-
|
|
15
|
+
- boot Bolt over Socket Mode ([01322df](https://github.com/crvouga/mockingbird/commit/01322df315c66b1f2f5b53094cbbeeeef6d3ae6c))
|
|
10
16
|
|
|
11
|
-
|
|
17
|
+
## 1.5.1 (2026-09-29)
|
|
18
|
+
|
|
19
|
+
### Fixes and improvements
|
|
20
|
+
|
|
21
|
+
- keep hosted pages inside narrow hosts and popups ([6512323](https://github.com/crvouga/mockingbird/commit/6512323198cb00b99005f3d2cfa5b9f1e6e321a7))
|
|
12
22
|
|
|
13
23
|
## 1.5.0 (2026-09-29)
|
|
14
24
|
|
|
@@ -2387,6 +2387,50 @@ function bootAdmin(config) {
|
|
|
2387
2387
|
if (render)
|
|
2388
2388
|
await render();
|
|
2389
2389
|
}
|
|
2390
|
+
const delay = (ms) => new Promise((resolve) => {
|
|
2391
|
+
window.setTimeout(resolve, ms);
|
|
2392
|
+
});
|
|
2393
|
+
const confirmAction = async (button, pending, done, work) => {
|
|
2394
|
+
if (button.dataset.pending === "1")
|
|
2395
|
+
return;
|
|
2396
|
+
const label = button.textContent ?? "";
|
|
2397
|
+
const width = button.offsetWidth;
|
|
2398
|
+
button.dataset.pending = "1";
|
|
2399
|
+
button.classList.add("pressed");
|
|
2400
|
+
button.setAttribute("aria-busy", "true");
|
|
2401
|
+
button.style.minWidth = `${width}px`;
|
|
2402
|
+
button.textContent = pending;
|
|
2403
|
+
try {
|
|
2404
|
+
await work();
|
|
2405
|
+
button.textContent = done;
|
|
2406
|
+
await delay(1e3);
|
|
2407
|
+
} catch (error) {
|
|
2408
|
+
showError(error);
|
|
2409
|
+
} finally {
|
|
2410
|
+
button.textContent = label;
|
|
2411
|
+
button.style.minWidth = "";
|
|
2412
|
+
button.classList.remove("pressed");
|
|
2413
|
+
button.removeAttribute("aria-busy");
|
|
2414
|
+
delete button.dataset.pending;
|
|
2415
|
+
}
|
|
2416
|
+
};
|
|
2417
|
+
document.addEventListener("click", (event) => {
|
|
2418
|
+
const target = event.target;
|
|
2419
|
+
if (!(target instanceof Element))
|
|
2420
|
+
return;
|
|
2421
|
+
const button = target.closest("button");
|
|
2422
|
+
if (!(button instanceof HTMLButtonElement) || button.dataset.pending === "1")
|
|
2423
|
+
return;
|
|
2424
|
+
button.classList.add("pressed");
|
|
2425
|
+
const token = String(Date.now());
|
|
2426
|
+
button.dataset.press = token;
|
|
2427
|
+
window.setTimeout(() => {
|
|
2428
|
+
if (button.dataset.press !== token || button.dataset.pending === "1")
|
|
2429
|
+
return;
|
|
2430
|
+
button.classList.remove("pressed");
|
|
2431
|
+
delete button.dataset.press;
|
|
2432
|
+
}, 450);
|
|
2433
|
+
});
|
|
2390
2434
|
el("namespace", HTMLSelectElement).addEventListener("change", () => {
|
|
2391
2435
|
state.namespace = el("namespace", HTMLSelectElement).value;
|
|
2392
2436
|
refresh().catch(showError);
|
|
@@ -2397,7 +2441,7 @@ function bootAdmin(config) {
|
|
|
2397
2441
|
refresh().catch(showError);
|
|
2398
2442
|
});
|
|
2399
2443
|
el("refresh", HTMLButtonElement).addEventListener("click", () => {
|
|
2400
|
-
refresh().catch(showError);
|
|
2444
|
+
confirmAction(el("refresh", HTMLButtonElement), "Refreshing...", "Updated", () => refresh()).catch(showError);
|
|
2401
2445
|
});
|
|
2402
2446
|
el("collections", HTMLElement).addEventListener("click", (event) => {
|
|
2403
2447
|
const target = event.target;
|
|
@@ -2520,10 +2564,10 @@ function bootAdmin(config) {
|
|
|
2520
2564
|
}).then(() => renderFaults()).catch(showError);
|
|
2521
2565
|
});
|
|
2522
2566
|
el("fault-clear", HTMLButtonElement).addEventListener("click", () => {
|
|
2523
|
-
api("DELETE", "/faults").then(() => renderFaults()).catch(showError);
|
|
2567
|
+
confirmAction(el("fault-clear", HTMLButtonElement), "Clearing...", "Cleared", () => api("DELETE", "/faults").then(() => renderFaults())).catch(showError);
|
|
2524
2568
|
});
|
|
2525
2569
|
el("journal-clear", HTMLButtonElement).addEventListener("click", () => {
|
|
2526
|
-
api("DELETE", "/requests").then(() => renderJournal()).catch(showError);
|
|
2570
|
+
confirmAction(el("journal-clear", HTMLButtonElement), "Clearing...", "Cleared", () => api("DELETE", "/requests").then(() => renderJournal())).catch(showError);
|
|
2527
2571
|
});
|
|
2528
2572
|
el("route-list", HTMLElement).addEventListener("click", (event) => {
|
|
2529
2573
|
const target = event.target;
|
|
@@ -2638,9 +2682,13 @@ function bootAdmin(config) {
|
|
|
2638
2682
|
var clientPrelude = [isRecord2, mountAdminBrand, startAdminBrand, faultPresetList, bootAdmin].map((fn) => fn.toString()).join("\n");
|
|
2639
2683
|
var adminClientSource = (config) => {
|
|
2640
2684
|
const payload = JSON.stringify(config).replace(/</g, "\\u003c");
|
|
2685
|
+
const entry = bootAdmin.name;
|
|
2686
|
+
if (!/^[A-Za-z_$][\w$]*$/.test(entry)) {
|
|
2687
|
+
throw new Error("admin client cannot call its boot function");
|
|
2688
|
+
}
|
|
2641
2689
|
return `<script>
|
|
2642
2690
|
${clientPrelude}
|
|
2643
|
-
|
|
2691
|
+
${entry}(${payload});
|
|
2644
2692
|
</script>`;
|
|
2645
2693
|
};
|
|
2646
2694
|
|
|
@@ -2854,9 +2902,24 @@ var renderAdminDocument = (service) => {
|
|
|
2854
2902
|
.controls { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
|
|
2855
2903
|
label.field { display: flex; flex-direction: column; gap: 2px; font-size: 11px; color: var(--faint); }
|
|
2856
2904
|
label.field input, label.field select, .controls input[type="password"] {
|
|
2857
|
-
background: var(--bg-inset); border: 1px solid var(--line); border-radius: 8px;
|
|
2858
|
-
padding: 7px 8px; min-height: 36px;
|
|
2859
|
-
}
|
|
2905
|
+
background-color: var(--bg-inset); border: 1px solid var(--line); border-radius: 8px;
|
|
2906
|
+
padding: 7px 8px; min-height: 36px; line-height: 1.2;
|
|
2907
|
+
}
|
|
2908
|
+
/* A native menu ignores min-height, so Preset rendered about half as tall as
|
|
2909
|
+
the text fields in the same form. Paint it like those fields. */
|
|
2910
|
+
label.field select {
|
|
2911
|
+
-webkit-appearance: none; appearance: none;
|
|
2912
|
+
padding-right: 28px;
|
|
2913
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='none' stroke='%2371717a' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' d='M2.5 4.5 6 8l3.5-3.5'/%3E%3C/svg%3E");
|
|
2914
|
+
background-repeat: no-repeat; background-position: right 10px center; background-size: 12px 12px;
|
|
2915
|
+
}
|
|
2916
|
+
.stack > .field > input,
|
|
2917
|
+
.stack > .field > select,
|
|
2918
|
+
.stack > .field > textarea,
|
|
2919
|
+
dialog .field > input,
|
|
2920
|
+
dialog .field > select,
|
|
2921
|
+
dialog .field > textarea { width: 100%; }
|
|
2922
|
+
.icon-btn, .btn, .btn-primary, .btn-quiet, .btn-danger, nav.side button { cursor: pointer; }
|
|
2860
2923
|
.icon-btn, .btn, .btn-primary, .btn-quiet, .btn-danger {
|
|
2861
2924
|
border-radius: 9px; min-height: 36px; padding: 0 12px; border: 1px solid var(--line);
|
|
2862
2925
|
background: var(--bg-elev);
|
|
@@ -2864,6 +2927,14 @@ var renderAdminDocument = (service) => {
|
|
|
2864
2927
|
.btn-primary { background: var(--accent); color: var(--accent-ink); border-color: transparent; }
|
|
2865
2928
|
.btn-quiet { background: transparent; }
|
|
2866
2929
|
.btn-danger { color: var(--err); }
|
|
2930
|
+
/* Held after mouseup. Clearing an empty journal changes nothing on screen,
|
|
2931
|
+
so the press itself has to stay visible. */
|
|
2932
|
+
.icon-btn:active, .btn:active, .btn-quiet:active, .btn-danger:active, nav.side button:active,
|
|
2933
|
+
.icon-btn.pressed, .btn.pressed, .btn-quiet.pressed, .btn-danger.pressed, nav.side button.pressed {
|
|
2934
|
+
background: var(--bg-inset); border-color: var(--line-strong); color: var(--ink);
|
|
2935
|
+
}
|
|
2936
|
+
.btn-danger:active, .btn-danger.pressed { background: var(--err-soft); color: var(--err); }
|
|
2937
|
+
.btn-primary:active, .btn-primary.pressed { filter: brightness(0.88); color: var(--accent-ink); }
|
|
2867
2938
|
/* minmax(0, 1fr): a 1fr column will not shrink below its content, so a long
|
|
2868
2939
|
record or the full nav row would widen the page past the viewport. */
|
|
2869
2940
|
.layout {
|
|
@@ -2952,8 +3023,16 @@ var renderAdminDocument = (service) => {
|
|
|
2952
3023
|
input, select, textarea { font-size: 16px; }
|
|
2953
3024
|
.brand, .vendor, .controls { width: 100%; }
|
|
2954
3025
|
label.field, label.field select, label.field input { flex: 1; min-width: 0; }
|
|
2955
|
-
|
|
3026
|
+
/* The layout fills the screen. A single-column grid stretches every auto
|
|
3027
|
+
row, so the tab bar grew with the leftover height and the buttons floated
|
|
3028
|
+
in the middle of it. The bar stays one row; the page below takes the rest. */
|
|
3029
|
+
.layout {
|
|
3030
|
+
grid-template-columns: minmax(0, 1fr);
|
|
3031
|
+
grid-template-rows: auto minmax(0, 1fr);
|
|
3032
|
+
align-content: start;
|
|
3033
|
+
}
|
|
2956
3034
|
nav.side {
|
|
3035
|
+
align-self: start; height: auto;
|
|
2957
3036
|
flex-direction: row; align-items: center; overflow-x: auto; min-width: 0;
|
|
2958
3037
|
border-right: 0; border-bottom: 1px solid var(--line);
|
|
2959
3038
|
padding: 8px;
|
|
@@ -3821,7 +3900,7 @@ var stateAdminRoutes = (routes) => {
|
|
|
3821
3900
|
};
|
|
3822
3901
|
|
|
3823
3902
|
// ../core/dist/version.js
|
|
3824
|
-
var PACKAGE_VERSION = true ? "1.
|
|
3903
|
+
var PACKAGE_VERSION = true ? "1.6.1" : UNRELEASED_VERSION;
|
|
3825
3904
|
|
|
3826
3905
|
// ../core/dist/signing.js
|
|
3827
3906
|
var encoder = new TextEncoder();
|
|
@@ -5145,4 +5224,4 @@ export {
|
|
|
5145
5224
|
matchesCriteria,
|
|
5146
5225
|
MailosaurAPI
|
|
5147
5226
|
};
|
|
5148
|
-
//# sourceMappingURL=chunk-
|
|
5227
|
+
//# sourceMappingURL=chunk-K4JQOFF4.js.map
|