@wildwinter/app-shell 0.35.1 → 0.37.0
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 +12 -0
- package/dist/index.cjs +71 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +25 -1
- package/dist/index.d.ts +25 -1
- package/dist/index.js +70 -27
- package/dist/index.js.map +1 -1
- package/dist/toast.css +33 -0
- package/dist/toast.css.map +1 -0
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -106,6 +106,18 @@ needing and never had.
|
|
|
106
106
|
staleBar({ subject: "The project", onRestart: () => void rebuild() });
|
|
107
107
|
```
|
|
108
108
|
|
|
109
|
+
- **`toast`** - a transient remark: "Bundle published", "Save refused: ...".
|
|
110
|
+
Bottom-right, an outlined card on the surface colour with the kind in the
|
|
111
|
+
border, on the shared panel motion; one at a time, 4s (7s for an error).
|
|
112
|
+
Both apps had one, and they agreed on nothing but the sentences - place,
|
|
113
|
+
colour, timing, motion and ARIA all differed. It mounts its own node, so a
|
|
114
|
+
second window gets it by importing it. Bring `toast.css`.
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
toast(`Bundle published\n${where}`, "ok");
|
|
118
|
+
toast(`Save refused: ${err}`, "error");
|
|
119
|
+
```
|
|
120
|
+
|
|
109
121
|
- **`--ok`** joins `--danger` and `--warn` in `tokens.css`, with a `light-dark()`
|
|
110
122
|
default every palette should override in its own `theme.css`. It is the only
|
|
111
123
|
colour in the grammar layer, and it is there because it kept not being
|
package/dist/index.cjs
CHANGED
|
@@ -151,23 +151,23 @@ function initTooltips(opts = {}) {
|
|
|
151
151
|
|
|
152
152
|
// src/dom.ts
|
|
153
153
|
function el(tag, classNameOrProps, ...children) {
|
|
154
|
-
const
|
|
154
|
+
const node2 = document.createElement(tag);
|
|
155
155
|
const props = typeof classNameOrProps === "string" ? { className: classNameOrProps } : classNameOrProps ?? {};
|
|
156
|
-
if (props.className)
|
|
157
|
-
if (props.text !== void 0 && props.text !== null)
|
|
158
|
-
if (props.title !== void 0)
|
|
156
|
+
if (props.className) node2.className = props.className;
|
|
157
|
+
if (props.text !== void 0 && props.text !== null) node2.textContent = props.text;
|
|
158
|
+
if (props.title !== void 0) node2.title = props.title;
|
|
159
159
|
if (props.tip !== void 0) {
|
|
160
|
-
|
|
161
|
-
|
|
160
|
+
node2.dataset["tip"] = props.tip;
|
|
161
|
+
node2.setAttribute("aria-label", props.tip);
|
|
162
162
|
ensureTooltipHost();
|
|
163
163
|
}
|
|
164
|
-
if (props.onClick)
|
|
164
|
+
if (props.onClick) node2.addEventListener("click", props.onClick);
|
|
165
165
|
for (const child of children) {
|
|
166
166
|
if (child === null || child === void 0) continue;
|
|
167
|
-
|
|
167
|
+
node2.append(child);
|
|
168
168
|
}
|
|
169
169
|
checkTooltipHost();
|
|
170
|
-
return
|
|
170
|
+
return node2;
|
|
171
171
|
}
|
|
172
172
|
function iconBtn(glyph, title, onClick, disabled = false, danger = false) {
|
|
173
173
|
const b = el("button", `shell-icon${danger ? " danger" : ""}`);
|
|
@@ -199,7 +199,7 @@ function tagChips(holder, onChange) {
|
|
|
199
199
|
const wrap = el("div", "shell-tags");
|
|
200
200
|
const input = el("input", "shell-tag-input");
|
|
201
201
|
input.type = "text";
|
|
202
|
-
input.placeholder = "
|
|
202
|
+
input.placeholder = "Add value";
|
|
203
203
|
input.spellcheck = false;
|
|
204
204
|
const makeChip = (v) => {
|
|
205
205
|
const chip = el("span", "shell-tag", v);
|
|
@@ -335,7 +335,11 @@ var openVar = { nav: "--nav-open-w", inspector: "--insp-open-w" };
|
|
|
335
335
|
var collapseClass = { nav: "no-nav", inspector: "no-inspector" };
|
|
336
336
|
function mountPaneShell(host, opts) {
|
|
337
337
|
const cfg = { nav: opts.nav, inspector: opts.inspector };
|
|
338
|
-
const
|
|
338
|
+
const offered = (side) => cfg[side].offered !== false;
|
|
339
|
+
const open = {
|
|
340
|
+
nav: offered("nav") && (opts.initial?.open?.nav ?? true),
|
|
341
|
+
inspector: offered("inspector") && (opts.initial?.open?.inspector ?? true)
|
|
342
|
+
};
|
|
339
343
|
const width = { ...opts.initial?.width ?? {} };
|
|
340
344
|
const el2 = (tag, cls) => {
|
|
341
345
|
const n = document.createElement(tag);
|
|
@@ -365,6 +369,8 @@ function mountPaneShell(host, opts) {
|
|
|
365
369
|
const root = el2("div", "pane-shell");
|
|
366
370
|
root.append(topbar, panes);
|
|
367
371
|
host.append(root);
|
|
372
|
+
if (!offered("nav")) navToggle.remove();
|
|
373
|
+
if (!offered("inspector")) inspToggle.remove();
|
|
368
374
|
function applyToggleGlyph(side, button) {
|
|
369
375
|
const isOpen = open[side];
|
|
370
376
|
button.textContent = side === "nav" ? isOpen ? "\u2039" : "\u203A" : isOpen ? "\u203A" : "\u2039";
|
|
@@ -381,8 +387,8 @@ function mountPaneShell(host, opts) {
|
|
|
381
387
|
panes.style.setProperty(openVar.inspector, width.inspector !== void 0 ? `${width.inspector}px` : cfg.inspector.defaultWidth);
|
|
382
388
|
applyToggleGlyph("nav", navToggle);
|
|
383
389
|
applyToggleGlyph("inspector", inspToggle);
|
|
384
|
-
navResizer.style.display = cfg.nav.resizable === false ? "none" : "";
|
|
385
|
-
inspResizer.style.display = cfg.inspector.resizable === false ? "none" : "";
|
|
390
|
+
navResizer.style.display = cfg.nav.resizable === false || !offered("nav") ? "none" : "";
|
|
391
|
+
inspResizer.style.display = cfg.inspector.resizable === false || !offered("inspector") ? "none" : "";
|
|
386
392
|
}
|
|
387
393
|
const snapshot = () => ({ open: { ...open }, width: { ...width } });
|
|
388
394
|
const persist = () => opts.onChange?.(snapshot());
|
|
@@ -393,7 +399,7 @@ function mountPaneShell(host, opts) {
|
|
|
393
399
|
persist();
|
|
394
400
|
}
|
|
395
401
|
function togglePane(side) {
|
|
396
|
-
setPaneOpen(side, !open[side]);
|
|
402
|
+
if (offered(side)) setPaneOpen(side, !open[side]);
|
|
397
403
|
}
|
|
398
404
|
function resetWidths() {
|
|
399
405
|
delete width.nav;
|
|
@@ -674,14 +680,14 @@ function closeWithExit(element, done) {
|
|
|
674
680
|
if (fired) return;
|
|
675
681
|
fired = true;
|
|
676
682
|
element.removeEventListener("animationend", onEnd);
|
|
677
|
-
clearTimeout(
|
|
683
|
+
clearTimeout(timer3);
|
|
678
684
|
done();
|
|
679
685
|
};
|
|
680
686
|
const onEnd = (e) => {
|
|
681
687
|
if (e.target === element) finish();
|
|
682
688
|
};
|
|
683
689
|
element.addEventListener("animationend", onEnd);
|
|
684
|
-
const
|
|
690
|
+
const timer3 = setTimeout(finish, seconds * 1e3 + 120);
|
|
685
691
|
}
|
|
686
692
|
|
|
687
693
|
// src/confirm.ts
|
|
@@ -1524,7 +1530,7 @@ function createSaveController(opts) {
|
|
|
1524
1530
|
let auto = true;
|
|
1525
1531
|
let dirty = false;
|
|
1526
1532
|
let dirtySince = 0;
|
|
1527
|
-
let
|
|
1533
|
+
let timer3;
|
|
1528
1534
|
let inFlight;
|
|
1529
1535
|
const setStatus = (next) => {
|
|
1530
1536
|
if (next === status) return;
|
|
@@ -1532,17 +1538,17 @@ function createSaveController(opts) {
|
|
|
1532
1538
|
opts.onStatus?.(status);
|
|
1533
1539
|
};
|
|
1534
1540
|
const clearTimer = () => {
|
|
1535
|
-
if (
|
|
1536
|
-
clearTimeout(
|
|
1537
|
-
|
|
1541
|
+
if (timer3 === void 0) return;
|
|
1542
|
+
clearTimeout(timer3);
|
|
1543
|
+
timer3 = void 0;
|
|
1538
1544
|
};
|
|
1539
1545
|
const arm = () => {
|
|
1540
1546
|
clearTimer();
|
|
1541
1547
|
if (!auto) return;
|
|
1542
1548
|
const deadline = dirtySince + maxWaitMs;
|
|
1543
1549
|
const wait = Math.max(0, Math.min(delayMs, deadline - Date.now()));
|
|
1544
|
-
|
|
1545
|
-
|
|
1550
|
+
timer3 = setTimeout(() => {
|
|
1551
|
+
timer3 = void 0;
|
|
1546
1552
|
void run();
|
|
1547
1553
|
}, wait);
|
|
1548
1554
|
};
|
|
@@ -1616,13 +1622,13 @@ var WORDS = {
|
|
|
1616
1622
|
unsaved: "Unsaved"
|
|
1617
1623
|
};
|
|
1618
1624
|
function saveIndicator(initial = "saved") {
|
|
1619
|
-
const
|
|
1625
|
+
const node2 = el("span");
|
|
1620
1626
|
const set = (status) => {
|
|
1621
|
-
|
|
1622
|
-
|
|
1627
|
+
node2.className = `savestat ${status}`;
|
|
1628
|
+
node2.textContent = WORDS[status];
|
|
1623
1629
|
};
|
|
1624
1630
|
set(initial);
|
|
1625
|
-
return { el:
|
|
1631
|
+
return { el: node2, set };
|
|
1626
1632
|
}
|
|
1627
1633
|
|
|
1628
1634
|
// src/stale.ts
|
|
@@ -1643,6 +1649,43 @@ function staleBar(opts) {
|
|
|
1643
1649
|
);
|
|
1644
1650
|
}
|
|
1645
1651
|
|
|
1652
|
+
// src/toast.ts
|
|
1653
|
+
var DURATION = { info: 4e3, ok: 4e3, error: 7e3 };
|
|
1654
|
+
var node;
|
|
1655
|
+
var timer2 = 0;
|
|
1656
|
+
var seq = 0;
|
|
1657
|
+
function mount() {
|
|
1658
|
+
if (node && node.isConnected) return node;
|
|
1659
|
+
node = el("div", { className: "shell-toast" });
|
|
1660
|
+
node.setAttribute("role", "status");
|
|
1661
|
+
node.setAttribute("aria-live", "polite");
|
|
1662
|
+
node.hidden = true;
|
|
1663
|
+
document.body.append(node);
|
|
1664
|
+
return node;
|
|
1665
|
+
}
|
|
1666
|
+
function toast(message, kind = "info", opts = {}) {
|
|
1667
|
+
const t = mount();
|
|
1668
|
+
const id = ++seq;
|
|
1669
|
+
t.textContent = message;
|
|
1670
|
+
t.className = `shell-toast ${kind}`;
|
|
1671
|
+
t.hidden = false;
|
|
1672
|
+
window.clearTimeout(timer2);
|
|
1673
|
+
timer2 = window.setTimeout(() => {
|
|
1674
|
+
closeWithExit(t, () => {
|
|
1675
|
+
if (seq === id) t.hidden = true;
|
|
1676
|
+
});
|
|
1677
|
+
}, opts.duration ?? DURATION[kind]);
|
|
1678
|
+
}
|
|
1679
|
+
function dismissToast() {
|
|
1680
|
+
if (!node || node.hidden) return;
|
|
1681
|
+
window.clearTimeout(timer2);
|
|
1682
|
+
const id = seq;
|
|
1683
|
+
const t = node;
|
|
1684
|
+
closeWithExit(t, () => {
|
|
1685
|
+
if (seq === id) t.hidden = true;
|
|
1686
|
+
});
|
|
1687
|
+
}
|
|
1688
|
+
|
|
1646
1689
|
// src/stepper.ts
|
|
1647
1690
|
function renderStepperBar(host, opts) {
|
|
1648
1691
|
const { items } = opts;
|
|
@@ -1783,6 +1826,7 @@ exports.colourIndex = colourIndex;
|
|
|
1783
1826
|
exports.confirmDialog = confirmDialog;
|
|
1784
1827
|
exports.createNavHistory = createNavHistory;
|
|
1785
1828
|
exports.createSaveController = createSaveController;
|
|
1829
|
+
exports.dismissToast = dismissToast;
|
|
1786
1830
|
exports.dupGuard = dupGuard;
|
|
1787
1831
|
exports.el = el;
|
|
1788
1832
|
exports.expandableRow = expandableRow;
|
|
@@ -1824,6 +1868,7 @@ exports.staleBar = staleBar;
|
|
|
1824
1868
|
exports.tagChips = tagChips;
|
|
1825
1869
|
exports.tipAt = tipAt;
|
|
1826
1870
|
exports.tipBold = tipBold;
|
|
1871
|
+
exports.toast = toast;
|
|
1827
1872
|
exports.vcBadgeFor = vcBadgeFor;
|
|
1828
1873
|
//# sourceMappingURL=index.cjs.map
|
|
1829
1874
|
//# sourceMappingURL=index.cjs.map
|