@crvouga/mockingbird-service-twilio 1.6.0 → 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 +9 -1
- package/dist/{chunk-5CN3JESR.js → chunk-JIDPDWLD.js} +2 -2
- package/dist/{chunk-VV4XROZJ.js → chunk-KBYCDOZD.js} +89 -10
- package/dist/chunk-KBYCDOZD.js.map +7 -0
- package/dist/cli.js +2 -2
- package/dist/index.js +1 -1
- package/dist/server.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-VV4XROZJ.js.map +0 -7
- /package/dist/{chunk-5CN3JESR.js.map → chunk-JIDPDWLD.js.map} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
# Changelog — @crvouga/mockingbird-service-twilio
|
|
2
2
|
|
|
3
|
-
## 1.6.
|
|
3
|
+
## 1.6.1 (2026-09-30)
|
|
4
|
+
|
|
5
|
+
### Fixes and improvements
|
|
6
|
+
|
|
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)
|
|
4
12
|
|
|
5
13
|
### Features
|
|
6
14
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createRuntime
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-KBYCDOZD.js";
|
|
4
4
|
|
|
5
5
|
// ../../adapters/node/dist/cli.js
|
|
6
6
|
import { readFile } from "node:fs/promises";
|
|
@@ -389,4 +389,4 @@ export {
|
|
|
389
389
|
createServer2 as createServer,
|
|
390
390
|
serveTarget
|
|
391
391
|
};
|
|
392
|
-
//# sourceMappingURL=chunk-
|
|
392
|
+
//# sourceMappingURL=chunk-JIDPDWLD.js.map
|
|
@@ -2192,6 +2192,50 @@ function bootAdmin(config) {
|
|
|
2192
2192
|
if (render)
|
|
2193
2193
|
await render();
|
|
2194
2194
|
}
|
|
2195
|
+
const delay = (ms) => new Promise((resolve) => {
|
|
2196
|
+
window.setTimeout(resolve, ms);
|
|
2197
|
+
});
|
|
2198
|
+
const confirmAction = async (button, pending, done, work) => {
|
|
2199
|
+
if (button.dataset.pending === "1")
|
|
2200
|
+
return;
|
|
2201
|
+
const label = button.textContent ?? "";
|
|
2202
|
+
const width = button.offsetWidth;
|
|
2203
|
+
button.dataset.pending = "1";
|
|
2204
|
+
button.classList.add("pressed");
|
|
2205
|
+
button.setAttribute("aria-busy", "true");
|
|
2206
|
+
button.style.minWidth = `${width}px`;
|
|
2207
|
+
button.textContent = pending;
|
|
2208
|
+
try {
|
|
2209
|
+
await work();
|
|
2210
|
+
button.textContent = done;
|
|
2211
|
+
await delay(1e3);
|
|
2212
|
+
} catch (error) {
|
|
2213
|
+
showError(error);
|
|
2214
|
+
} finally {
|
|
2215
|
+
button.textContent = label;
|
|
2216
|
+
button.style.minWidth = "";
|
|
2217
|
+
button.classList.remove("pressed");
|
|
2218
|
+
button.removeAttribute("aria-busy");
|
|
2219
|
+
delete button.dataset.pending;
|
|
2220
|
+
}
|
|
2221
|
+
};
|
|
2222
|
+
document.addEventListener("click", (event) => {
|
|
2223
|
+
const target = event.target;
|
|
2224
|
+
if (!(target instanceof Element))
|
|
2225
|
+
return;
|
|
2226
|
+
const button = target.closest("button");
|
|
2227
|
+
if (!(button instanceof HTMLButtonElement) || button.dataset.pending === "1")
|
|
2228
|
+
return;
|
|
2229
|
+
button.classList.add("pressed");
|
|
2230
|
+
const token = String(Date.now());
|
|
2231
|
+
button.dataset.press = token;
|
|
2232
|
+
window.setTimeout(() => {
|
|
2233
|
+
if (button.dataset.press !== token || button.dataset.pending === "1")
|
|
2234
|
+
return;
|
|
2235
|
+
button.classList.remove("pressed");
|
|
2236
|
+
delete button.dataset.press;
|
|
2237
|
+
}, 450);
|
|
2238
|
+
});
|
|
2195
2239
|
el("namespace", HTMLSelectElement).addEventListener("change", () => {
|
|
2196
2240
|
state.namespace = el("namespace", HTMLSelectElement).value;
|
|
2197
2241
|
refresh().catch(showError);
|
|
@@ -2202,7 +2246,7 @@ function bootAdmin(config) {
|
|
|
2202
2246
|
refresh().catch(showError);
|
|
2203
2247
|
});
|
|
2204
2248
|
el("refresh", HTMLButtonElement).addEventListener("click", () => {
|
|
2205
|
-
refresh().catch(showError);
|
|
2249
|
+
confirmAction(el("refresh", HTMLButtonElement), "Refreshing...", "Updated", () => refresh()).catch(showError);
|
|
2206
2250
|
});
|
|
2207
2251
|
el("collections", HTMLElement).addEventListener("click", (event) => {
|
|
2208
2252
|
const target = event.target;
|
|
@@ -2325,10 +2369,10 @@ function bootAdmin(config) {
|
|
|
2325
2369
|
}).then(() => renderFaults()).catch(showError);
|
|
2326
2370
|
});
|
|
2327
2371
|
el("fault-clear", HTMLButtonElement).addEventListener("click", () => {
|
|
2328
|
-
api("DELETE", "/faults").then(() => renderFaults()).catch(showError);
|
|
2372
|
+
confirmAction(el("fault-clear", HTMLButtonElement), "Clearing...", "Cleared", () => api("DELETE", "/faults").then(() => renderFaults())).catch(showError);
|
|
2329
2373
|
});
|
|
2330
2374
|
el("journal-clear", HTMLButtonElement).addEventListener("click", () => {
|
|
2331
|
-
api("DELETE", "/requests").then(() => renderJournal()).catch(showError);
|
|
2375
|
+
confirmAction(el("journal-clear", HTMLButtonElement), "Clearing...", "Cleared", () => api("DELETE", "/requests").then(() => renderJournal())).catch(showError);
|
|
2332
2376
|
});
|
|
2333
2377
|
el("route-list", HTMLElement).addEventListener("click", (event) => {
|
|
2334
2378
|
const target = event.target;
|
|
@@ -2443,9 +2487,13 @@ function bootAdmin(config) {
|
|
|
2443
2487
|
var clientPrelude = [isRecord2, mountAdminBrand, startAdminBrand, faultPresetList, bootAdmin].map((fn) => fn.toString()).join("\n");
|
|
2444
2488
|
var adminClientSource = (config) => {
|
|
2445
2489
|
const payload = JSON.stringify(config).replace(/</g, "\\u003c");
|
|
2490
|
+
const entry = bootAdmin.name;
|
|
2491
|
+
if (!/^[A-Za-z_$][\w$]*$/.test(entry)) {
|
|
2492
|
+
throw new Error("admin client cannot call its boot function");
|
|
2493
|
+
}
|
|
2446
2494
|
return `<script>
|
|
2447
2495
|
${clientPrelude}
|
|
2448
|
-
|
|
2496
|
+
${entry}(${payload});
|
|
2449
2497
|
</script>`;
|
|
2450
2498
|
};
|
|
2451
2499
|
|
|
@@ -2659,9 +2707,24 @@ var renderAdminDocument = (service) => {
|
|
|
2659
2707
|
.controls { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
|
|
2660
2708
|
label.field { display: flex; flex-direction: column; gap: 2px; font-size: 11px; color: var(--faint); }
|
|
2661
2709
|
label.field input, label.field select, .controls input[type="password"] {
|
|
2662
|
-
background: var(--bg-inset); border: 1px solid var(--line); border-radius: 8px;
|
|
2663
|
-
padding: 7px 8px; min-height: 36px;
|
|
2664
|
-
}
|
|
2710
|
+
background-color: var(--bg-inset); border: 1px solid var(--line); border-radius: 8px;
|
|
2711
|
+
padding: 7px 8px; min-height: 36px; line-height: 1.2;
|
|
2712
|
+
}
|
|
2713
|
+
/* A native menu ignores min-height, so Preset rendered about half as tall as
|
|
2714
|
+
the text fields in the same form. Paint it like those fields. */
|
|
2715
|
+
label.field select {
|
|
2716
|
+
-webkit-appearance: none; appearance: none;
|
|
2717
|
+
padding-right: 28px;
|
|
2718
|
+
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");
|
|
2719
|
+
background-repeat: no-repeat; background-position: right 10px center; background-size: 12px 12px;
|
|
2720
|
+
}
|
|
2721
|
+
.stack > .field > input,
|
|
2722
|
+
.stack > .field > select,
|
|
2723
|
+
.stack > .field > textarea,
|
|
2724
|
+
dialog .field > input,
|
|
2725
|
+
dialog .field > select,
|
|
2726
|
+
dialog .field > textarea { width: 100%; }
|
|
2727
|
+
.icon-btn, .btn, .btn-primary, .btn-quiet, .btn-danger, nav.side button { cursor: pointer; }
|
|
2665
2728
|
.icon-btn, .btn, .btn-primary, .btn-quiet, .btn-danger {
|
|
2666
2729
|
border-radius: 9px; min-height: 36px; padding: 0 12px; border: 1px solid var(--line);
|
|
2667
2730
|
background: var(--bg-elev);
|
|
@@ -2669,6 +2732,14 @@ var renderAdminDocument = (service) => {
|
|
|
2669
2732
|
.btn-primary { background: var(--accent); color: var(--accent-ink); border-color: transparent; }
|
|
2670
2733
|
.btn-quiet { background: transparent; }
|
|
2671
2734
|
.btn-danger { color: var(--err); }
|
|
2735
|
+
/* Held after mouseup. Clearing an empty journal changes nothing on screen,
|
|
2736
|
+
so the press itself has to stay visible. */
|
|
2737
|
+
.icon-btn:active, .btn:active, .btn-quiet:active, .btn-danger:active, nav.side button:active,
|
|
2738
|
+
.icon-btn.pressed, .btn.pressed, .btn-quiet.pressed, .btn-danger.pressed, nav.side button.pressed {
|
|
2739
|
+
background: var(--bg-inset); border-color: var(--line-strong); color: var(--ink);
|
|
2740
|
+
}
|
|
2741
|
+
.btn-danger:active, .btn-danger.pressed { background: var(--err-soft); color: var(--err); }
|
|
2742
|
+
.btn-primary:active, .btn-primary.pressed { filter: brightness(0.88); color: var(--accent-ink); }
|
|
2672
2743
|
/* minmax(0, 1fr): a 1fr column will not shrink below its content, so a long
|
|
2673
2744
|
record or the full nav row would widen the page past the viewport. */
|
|
2674
2745
|
.layout {
|
|
@@ -2757,8 +2828,16 @@ var renderAdminDocument = (service) => {
|
|
|
2757
2828
|
input, select, textarea { font-size: 16px; }
|
|
2758
2829
|
.brand, .vendor, .controls { width: 100%; }
|
|
2759
2830
|
label.field, label.field select, label.field input { flex: 1; min-width: 0; }
|
|
2760
|
-
|
|
2831
|
+
/* The layout fills the screen. A single-column grid stretches every auto
|
|
2832
|
+
row, so the tab bar grew with the leftover height and the buttons floated
|
|
2833
|
+
in the middle of it. The bar stays one row; the page below takes the rest. */
|
|
2834
|
+
.layout {
|
|
2835
|
+
grid-template-columns: minmax(0, 1fr);
|
|
2836
|
+
grid-template-rows: auto minmax(0, 1fr);
|
|
2837
|
+
align-content: start;
|
|
2838
|
+
}
|
|
2761
2839
|
nav.side {
|
|
2840
|
+
align-self: start; height: auto;
|
|
2762
2841
|
flex-direction: row; align-items: center; overflow-x: auto; min-width: 0;
|
|
2763
2842
|
border-right: 0; border-bottom: 1px solid var(--line);
|
|
2764
2843
|
padding: 8px;
|
|
@@ -3552,7 +3631,7 @@ var stateAdminRoutes = (routes) => {
|
|
|
3552
3631
|
};
|
|
3553
3632
|
|
|
3554
3633
|
// ../core/dist/version.js
|
|
3555
|
-
var PACKAGE_VERSION = true ? "1.6.
|
|
3634
|
+
var PACKAGE_VERSION = true ? "1.6.1" : UNRELEASED_VERSION;
|
|
3556
3635
|
|
|
3557
3636
|
// ../core/dist/signing.js
|
|
3558
3637
|
var encoder = new TextEncoder();
|
|
@@ -5906,4 +5985,4 @@ export {
|
|
|
5906
5985
|
twilioError,
|
|
5907
5986
|
TwilioAPI
|
|
5908
5987
|
};
|
|
5909
|
-
//# sourceMappingURL=chunk-
|
|
5988
|
+
//# sourceMappingURL=chunk-KBYCDOZD.js.map
|