@getorrery/cells 0.2.2 → 0.2.3
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/dist/el/chrome.d.ts +2 -0
- package/dist/el/extensions.d.ts +26 -1
- package/dist/el/mod.d.ts +6 -0
- package/dist/from.d.ts +2 -2
- package/dist/index.js +103 -31
- package/package.json +3 -3
package/dist/el/chrome.d.ts
CHANGED
|
@@ -97,6 +97,8 @@ export interface DockView {
|
|
|
97
97
|
}
|
|
98
98
|
/** The dock: a rule with title and step, the question, its body. */
|
|
99
99
|
export declare function dock(p: DockView, w: number, m: boolean): Item[];
|
|
100
|
+
/** The most choices the dock shows at once; a longer list scrolls. */
|
|
101
|
+
export declare const DOCK_ROWS = 10;
|
|
100
102
|
/** A choice on the consent bar. */
|
|
101
103
|
export interface ConsentChoice {
|
|
102
104
|
key: string;
|
package/dist/el/extensions.d.ts
CHANGED
|
@@ -4,12 +4,16 @@
|
|
|
4
4
|
* the processes behind `p`; one row's details behind Enter — port of
|
|
5
5
|
* `el/extensions.rs`. The host formats every row (`orrery_registry::browse`);
|
|
6
6
|
* this draws them. The marks are glyphs (● ○ ↑) and every state is also in
|
|
7
|
-
* words, so mono reads the same.
|
|
7
|
+
* words, so mono reads the same. Decision 0107: two-line rows, the search box
|
|
8
|
+
* on top, the focus (search, filters, list) and the marks are the client's,
|
|
9
|
+
* merged into the props before drawing; a batch in flight is drawn under the list.
|
|
8
10
|
*/
|
|
9
11
|
import { type Item } from "../cells";
|
|
10
12
|
/** One row of the list, as the host formats it (`orrery_registry::browse::Row`). The chat draws the same fields. */
|
|
11
13
|
export interface ExtRowV {
|
|
12
14
|
id: string;
|
|
15
|
+
/** Its name; the id when absent. */
|
|
16
|
+
name?: string;
|
|
13
17
|
/** The installed version, else the listed one. */
|
|
14
18
|
version?: string;
|
|
15
19
|
/** What it is, kebab-case: `tools`, `session-store`. */
|
|
@@ -41,6 +45,21 @@ export interface ProcRowV {
|
|
|
41
45
|
up: string;
|
|
42
46
|
hosts: string;
|
|
43
47
|
}
|
|
48
|
+
/** One extension of a batch in flight (decision 0107 §4). */
|
|
49
|
+
export interface BatchItemV {
|
|
50
|
+
id: string;
|
|
51
|
+
/** `download`, `verify`, `consent`, `install`. */
|
|
52
|
+
step?: string;
|
|
53
|
+
/** `running`, `done` or `failed`. */
|
|
54
|
+
state?: string;
|
|
55
|
+
/** What to do when it failed. */
|
|
56
|
+
fix?: string | null;
|
|
57
|
+
}
|
|
58
|
+
/** A batch in flight: a line per extension and a summary (empty while it runs). */
|
|
59
|
+
export interface BatchV {
|
|
60
|
+
items?: BatchItemV[];
|
|
61
|
+
summary?: string;
|
|
62
|
+
}
|
|
44
63
|
/** One row's details. A third item is the value's style class (`d` is dim). */
|
|
45
64
|
export interface DetailV {
|
|
46
65
|
title: string;
|
|
@@ -85,6 +104,12 @@ export interface ExtensionsView {
|
|
|
85
104
|
selected?: number | null;
|
|
86
105
|
/** The screen rows the client has for the overlay: past it the rows are windowed around the cursor, the head, totals and keys always drawn. */
|
|
87
106
|
height?: number | null;
|
|
107
|
+
/** Where the keys are (the client's): `search`, `filters` or `list` (the default). */
|
|
108
|
+
focus?: string | null;
|
|
109
|
+
/** The ids marked with Space (the client's). */
|
|
110
|
+
marked?: string[];
|
|
111
|
+
/** A batch in flight (the host's). */
|
|
112
|
+
batch?: BatchV | null;
|
|
88
113
|
}
|
|
89
114
|
/** Draw the overlay at `w` cells: the list, the processes, or one row's details. */
|
|
90
115
|
export declare function extensions(p: ExtensionsView, w: number, m: boolean): Item[];
|
package/dist/el/mod.d.ts
CHANGED
|
@@ -23,6 +23,12 @@ export declare class BadProps extends Error {
|
|
|
23
23
|
readonly reason: string;
|
|
24
24
|
constructor(id: string, reason: string);
|
|
25
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* A `null` object member is the member absent, as the Rust crate reads it:
|
|
28
|
+
* every defaulted field takes its default rather than failing on `null`.
|
|
29
|
+
* Nulls in arrays stay. Returns a copy; the host's props are not changed.
|
|
30
|
+
*/
|
|
31
|
+
export declare function dropNulls(v: unknown): unknown;
|
|
26
32
|
/**
|
|
27
33
|
* Draw element `id` from its props at `w` columns, in mono when `m`.
|
|
28
34
|
*
|
package/dist/from.d.ts
CHANGED
|
@@ -123,8 +123,8 @@ export declare function turn(tv: TurnView, o: TurnOpts, w: number, m: boolean):
|
|
|
123
123
|
export declare function options(el: string, props: unknown): number | null;
|
|
124
124
|
/** An element's props with this client's cursor put in them. */
|
|
125
125
|
export declare function withCursor(el: string, props: unknown, cursor: string | null | undefined): unknown;
|
|
126
|
-
/** An overlay's child as rows: as {@link node}, and an element that windows its rows (`/extensions`) is told the `rows` the overlay has. */
|
|
127
|
-
export declare function overlayNode(doc: UiDoc, id: string, cursor: string | null | undefined, rows: number, w: number, m: boolean): Line[];
|
|
126
|
+
/** An overlay's child as rows: as {@link node}, and an element that windows its rows (`/extensions`) is told the `rows` the overlay has and gets the client's own state merged in (`view`: its focus and marks). */
|
|
127
|
+
export declare function overlayNode(doc: UiDoc, id: string, cursor: string | null | undefined, view: Record<string, unknown>, rows: number, w: number, m: boolean): Line[];
|
|
128
128
|
/** A UI node (Tier 2, or an element) as rows. `cursor` is where this client moved a list's cursor. */
|
|
129
129
|
export declare function node(doc: UiDoc, id: string, cursor: string | null | undefined, w: number, m: boolean): Line[];
|
|
130
130
|
/** Whether a node's children are drawn by the node itself. */
|
package/dist/index.js
CHANGED
|
@@ -636,6 +636,7 @@ ${text2(got)}`;
|
|
|
636
636
|
// src/el/chrome.ts
|
|
637
637
|
var chrome_exports = {};
|
|
638
638
|
__export(chrome_exports, {
|
|
639
|
+
DOCK_ROWS: () => DOCK_ROWS,
|
|
639
640
|
INDICATOR_MARK: () => INDICATOR_MARK,
|
|
640
641
|
SLASH_ROWS: () => SLASH_ROWS,
|
|
641
642
|
SWITCHER_NARROW: () => SWITCHER_NARROW,
|
|
@@ -1619,18 +1620,33 @@ function dock(p, w, m) {
|
|
|
1619
1620
|
} else {
|
|
1620
1621
|
rows2 = [hd];
|
|
1621
1622
|
if (prompt !== "" || (p.items ?? []).length > 0) rows2.push(q);
|
|
1622
|
-
const
|
|
1623
|
+
const items2 = p.items ?? [];
|
|
1624
|
+
const base = w < 60 ? 17 : 20;
|
|
1625
|
+
const longest = Math.max(0, ...items2.map((it) => chars(it.label)));
|
|
1626
|
+
const lw = Math.min(Math.max(longest + 1, base), Math.max(w - 4, base));
|
|
1623
1627
|
const sl = p.selected ?? 0;
|
|
1624
|
-
|
|
1628
|
+
const n = items2.length;
|
|
1629
|
+
let from = 0;
|
|
1630
|
+
let to = n;
|
|
1631
|
+
if (n > DOCK_ROWS) {
|
|
1632
|
+
const cur = Math.min(sl, n - 1);
|
|
1633
|
+
from = Math.min(Math.max(cur - Math.floor(DOCK_ROWS / 2), 0), n - DOCK_ROWS);
|
|
1634
|
+
to = from + DOCK_ROWS;
|
|
1635
|
+
}
|
|
1636
|
+
if (from > 0) rows2.push([sp(4), t(`${from} more above`, "d")]);
|
|
1637
|
+
items2.forEach((it, i) => {
|
|
1638
|
+
if (i < from || i >= to) return;
|
|
1625
1639
|
const on = i === sl;
|
|
1626
1640
|
const d0 = it.detail ?? "";
|
|
1627
1641
|
const detail2 = w < 60 ? d0.split(" \xB7 ")[1] ?? d0 : d0;
|
|
1628
1642
|
const l = [sp(2), t(on ? "\u276F " : " ", on ? "ac" : ""), t(ps(it.label, lw), on ? "b" : "i"), t(detail2, "d")];
|
|
1629
1643
|
rows2.push(on ? sel(l) : l);
|
|
1630
1644
|
});
|
|
1645
|
+
if (to < n) rows2.push([sp(4), t(`${n - to} more below`, "d")]);
|
|
1631
1646
|
}
|
|
1632
1647
|
return out(rows2);
|
|
1633
1648
|
}
|
|
1649
|
+
var DOCK_ROWS = 10;
|
|
1634
1650
|
function consent(p, w, m) {
|
|
1635
1651
|
const state = p.state ?? "asking";
|
|
1636
1652
|
const selected = p.selected ?? 0;
|
|
@@ -1951,6 +1967,7 @@ __export(mod_exports, {
|
|
|
1951
1967
|
chrome: () => chrome_exports,
|
|
1952
1968
|
content: () => content_exports,
|
|
1953
1969
|
context: () => context_exports,
|
|
1970
|
+
dropNulls: () => dropNulls,
|
|
1954
1971
|
errLines: () => errLines,
|
|
1955
1972
|
extensions: () => extensions_exports,
|
|
1956
1973
|
feedback: () => feedback_exports,
|
|
@@ -3078,19 +3095,19 @@ function options(el, props) {
|
|
|
3078
3095
|
}
|
|
3079
3096
|
function withCursor(el, props, cursor) {
|
|
3080
3097
|
if (cursor == null || !/^\d+$/.test(cursor)) return props;
|
|
3081
|
-
if (el === "tasks" && props !== null && typeof props === "object" && !Array.isArray(props)) {
|
|
3098
|
+
if ((el === "tasks" || el === "extensions") && props !== null && typeof props === "object" && !Array.isArray(props)) {
|
|
3082
3099
|
return { ...props, cursor: Number(cursor) };
|
|
3083
3100
|
}
|
|
3084
3101
|
if (options(el, props) == null) return props;
|
|
3085
3102
|
if (props === null || typeof props !== "object" || Array.isArray(props)) return props;
|
|
3086
3103
|
return { ...props, selected: Number(cursor) };
|
|
3087
3104
|
}
|
|
3088
|
-
function overlayNode(doc, id, cursor, rows2, w, m) {
|
|
3105
|
+
function overlayNode(doc, id, cursor, view, rows2, w, m) {
|
|
3089
3106
|
const n = doc.nodes[id];
|
|
3090
3107
|
if (n?.type !== "element" || n.el !== "extensions") return node(doc, id, cursor, w, m);
|
|
3091
3108
|
const p = withCursor(n.el, n.props ?? {}, cursor);
|
|
3092
3109
|
try {
|
|
3093
|
-
return linesOf(render2(n.el, p !== null && typeof p === "object" ? { ...p, height: rows2 } : p, w, m));
|
|
3110
|
+
return linesOf(render2(n.el, p !== null && typeof p === "object" ? { ...p, ...view, height: rows2 } : p, w, m));
|
|
3094
3111
|
} catch (e) {
|
|
3095
3112
|
const msg = e instanceof BadProps ? e.message : e instanceof Error ? e.message : String(e);
|
|
3096
3113
|
return para([g(m, "\u2717", "error", "er"), sp(1)], msg, w, "er", null);
|
|
@@ -3524,29 +3541,36 @@ function list2(p, w, m) {
|
|
|
3524
3541
|
const noList = l.age == null;
|
|
3525
3542
|
const loading = noList && l.refreshing === true;
|
|
3526
3543
|
const lost = noList && l.refreshing !== true && (l.offline === true || l.failed != null);
|
|
3527
|
-
const searching = p.query != null;
|
|
3528
3544
|
const c = p.counts ?? {};
|
|
3529
3545
|
const age = l.age ?? "";
|
|
3530
3546
|
const fail = l.failed ?? "";
|
|
3531
3547
|
const head = lost ? l.offline ? "offline" : "no list" : !noList && l.offline ? `offline \xB7 list from ${age} ago` : !noList && l.failed != null ? `list from ${age} ago` : "esc close";
|
|
3532
3548
|
const lines = [panelHead(w, "Extensions", [], head, true, m)];
|
|
3549
|
+
const on = p.filter ? p.filter : "all";
|
|
3550
|
+
const query = p.query != null && p.query !== "" ? p.query : null;
|
|
3551
|
+
const focus = p.focus ?? "list";
|
|
3552
|
+
const lead = (at) => focus === at ? t("\u276F ", "ac") : sp(2);
|
|
3533
3553
|
const unknown = (n2) => noList ? "\u2014" : String(n2 ?? 0);
|
|
3534
3554
|
const tabs = [
|
|
3535
3555
|
["All", unknown(c.all), "all"],
|
|
3536
3556
|
["Installed", String(c.installed ?? 0), "installed"],
|
|
3537
3557
|
["Updates", unknown(c.updates), "updates"]
|
|
3538
3558
|
];
|
|
3539
|
-
const
|
|
3540
|
-
const f = [sp(2)];
|
|
3559
|
+
const f = [lead("filters")];
|
|
3541
3560
|
tabs.forEach(([name, n2, key], i) => {
|
|
3542
3561
|
if (i > 0) f.push(sp(narrow ? 1 : 2));
|
|
3543
3562
|
f.push(key === on ? m ? t(`[${name} ${n2}]`, "b") : t(` ${name} ${n2} `, "btn b") : t(` ${name} ${n2} `, "d"));
|
|
3544
3563
|
});
|
|
3545
|
-
lines.push(lr(f, narrow ? [] : [t("
|
|
3546
|
-
|
|
3564
|
+
lines.push(lr(f, narrow ? [] : [t("\u2190\u2192 filter", "dd")], w, true));
|
|
3565
|
+
const typing = focus === "search";
|
|
3566
|
+
let sbox = query != null ? [t(query, "i")] : [];
|
|
3567
|
+
if (typing) sbox.push(t(" ", "cur"));
|
|
3568
|
+
if (query == null) sbox.push(t("Search extensions\u2026", "dd"));
|
|
3569
|
+
if (query != null) {
|
|
3547
3570
|
const total = on === "installed" ? c.installed ?? 0 : on === "updates" ? c.updates ?? 0 : c.all ?? 0;
|
|
3548
|
-
|
|
3571
|
+
sbox = lr(sbox, [t(`${rows2.length} of ${total}`, "d")], Math.max(w - 4, 0), true);
|
|
3549
3572
|
}
|
|
3573
|
+
lines.push(...typing ? inputBox(sbox, w, m) : boxed([sbox], w));
|
|
3550
3574
|
const missing = [];
|
|
3551
3575
|
if (p.roles) {
|
|
3552
3576
|
const r = p.roles;
|
|
@@ -3590,34 +3614,55 @@ function list2(p, w, m) {
|
|
|
3590
3614
|
}
|
|
3591
3615
|
for (const role of missing) {
|
|
3592
3616
|
const [fix, why] = role === "provider" ? ["Orrery cannot answer", "Orrery cannot answer until one is"] : role === "client" ? ["nothing draws Orrery", "nothing draws Orrery until one is"] : ["sessions are not kept", "sessions are not kept until one is"];
|
|
3593
|
-
const text2 = narrow ? `No ${role}: ${fix}.` : `No ${role} is installed: ${why}.
|
|
3617
|
+
const text2 = narrow ? `No ${role}: ${fix}.` : `No ${role} is installed: ${why}. Search "${role}" to find one; orrery install <id> adds it.`;
|
|
3594
3618
|
lines.push(...para([sp(2), g(m, "\u2717", "missing", "er"), sp(1)], text2, w, "er"));
|
|
3595
3619
|
lines.push([]);
|
|
3596
3620
|
}
|
|
3597
3621
|
if (rows2.length === 0) {
|
|
3598
|
-
let
|
|
3599
|
-
let
|
|
3600
|
-
if (
|
|
3601
|
-
|
|
3602
|
-
|
|
3622
|
+
let first2;
|
|
3623
|
+
let then2;
|
|
3624
|
+
if (query != null) {
|
|
3625
|
+
first2 = `Nothing matches "${query}" in names, descriptions, authors, tags or kinds.`;
|
|
3626
|
+
then2 = "Esc clears the search. Not in the list? orrery install takes a git URL, a folder or npm:<package>.";
|
|
3603
3627
|
} else if (on === "updates") {
|
|
3604
|
-
|
|
3605
|
-
|
|
3628
|
+
first2 = "No updates: every installed extension is on its listed version.";
|
|
3629
|
+
then2 = "Built-ins update with Orrery (/update).";
|
|
3606
3630
|
} else {
|
|
3607
3631
|
const platform = globalThis.process?.platform;
|
|
3608
3632
|
const sep = platform === "win32" ? "\\" : "/";
|
|
3609
|
-
|
|
3610
|
-
|
|
3633
|
+
first2 = `No extensions in ~${sep}.orrery${sep}extensions or .orrery${sep}extensions`;
|
|
3634
|
+
then2 = "orrery install <source>";
|
|
3611
3635
|
}
|
|
3612
|
-
lines.push(...para([sp(2)],
|
|
3613
|
-
lines.push(...para([sp(2)],
|
|
3636
|
+
lines.push(...para([sp(2)], first2, w, "i"));
|
|
3637
|
+
lines.push(...para([sp(2)], then2, w, "d"));
|
|
3614
3638
|
}
|
|
3615
3639
|
const tail = [[]];
|
|
3640
|
+
if (p.batch) {
|
|
3641
|
+
for (const it of p.batch.items ?? []) {
|
|
3642
|
+
const mark2 = it.state === "done" ? g(m, "\u2713", "done", "ok") : it.state === "failed" ? g(m, "\u2717", "failed", "er") : m ? t("[running]", "i") : spin("lv");
|
|
3643
|
+
tail.push(fit([sp(2), mark2, sp(1), t(it.id, "b"), t(` \xB7 ${it.step ?? ""}`, "d")], w));
|
|
3644
|
+
if (it.state === "failed" && it.fix) tail.push(...para([sp(4)], it.fix, w, "er"));
|
|
3645
|
+
}
|
|
3646
|
+
if (p.batch.summary) tail.push(fit([sp(2), t(p.batch.summary, "d")], w));
|
|
3647
|
+
}
|
|
3616
3648
|
if (p.totals) tail.push([sp(2), t(fitTotals(p.totals, w - 2), "d")]);
|
|
3617
3649
|
const retry2 = lost || l.failed != null && l.offline !== true;
|
|
3618
|
-
const
|
|
3619
|
-
|
|
3620
|
-
|
|
3650
|
+
const esc = (p.marked ?? []).length === 0 ? "esc close" : "esc unselect";
|
|
3651
|
+
let first;
|
|
3652
|
+
let then = null;
|
|
3653
|
+
if (focus === "search") {
|
|
3654
|
+
first = narrow ? "enter the list|esc clear" : "type to search|\u2191 filters|\u2193 the list|enter the list|esc clear";
|
|
3655
|
+
} else if (focus === "filters") {
|
|
3656
|
+
first = narrow ? "\u2190\u2192 filter|enter the list" : "\u2190\u2192 filter|\u2193 search|enter the list|esc the list";
|
|
3657
|
+
} else if (narrow) {
|
|
3658
|
+
first = `${retry2 ? "r retry|" : ""}space select|enter details|${esc}`;
|
|
3659
|
+
then = "i install|x remove|p processes";
|
|
3660
|
+
} else {
|
|
3661
|
+
first = `${retry2 ? "r retry the list|" : ""}\u2191\u2193 move|space select|enter details|\u2190\u2192 filter|${esc}`;
|
|
3662
|
+
then = "i install|u update|x remove|l load or unload|p processes";
|
|
3663
|
+
}
|
|
3664
|
+
tail.push(keys(first, w, 2));
|
|
3665
|
+
if (then) tail.push(keys(then, w, 2));
|
|
3621
3666
|
const n = rows2.length;
|
|
3622
3667
|
const room = p.height == null ? Infinity : Math.max(p.height - lines.length - tail.length, 0);
|
|
3623
3668
|
let from = 0;
|
|
@@ -3629,21 +3674,40 @@ function list2(p, w, m) {
|
|
|
3629
3674
|
to = from + k;
|
|
3630
3675
|
}
|
|
3631
3676
|
if (from > 0) lines.push([sp(4), t(`${from} more above`, "d")]);
|
|
3632
|
-
for (let i = from; i < to; i++)
|
|
3677
|
+
for (let i = from; i < to; i++) {
|
|
3678
|
+
const r = rows2[i];
|
|
3679
|
+
lines.push(...row2(r, focus === "list" && cursor === i, (p.marked ?? []).includes(r.id), w));
|
|
3680
|
+
}
|
|
3633
3681
|
if (to < n) lines.push([sp(4), t(`${n - to} more below`, "d")]);
|
|
3634
3682
|
lines.push(...tail);
|
|
3635
3683
|
return lines;
|
|
3636
3684
|
}
|
|
3637
|
-
function row2(r, cur, w) {
|
|
3685
|
+
function row2(r, cur, marked2, w) {
|
|
3638
3686
|
const installed = r.installed === true;
|
|
3639
3687
|
const dim2 = installed && r.loaded !== true;
|
|
3640
3688
|
const mark2 = r.update != null ? t("\u2191", "ac") : !installed ? t("\u25CB", "d") : t("\u25CF", dim2 ? "dd" : "ok");
|
|
3641
|
-
const
|
|
3689
|
+
const name = r.name ? r.name : r.id;
|
|
3690
|
+
const left = [t(cur ? "\u276F " : " ", cur ? "ac" : ""), marked2 ? t("\u2713 ", "ok") : sp(2), mark2, sp(1), t(name, dim2 ? "dd" : "b")];
|
|
3691
|
+
if (r.version) left.push(t(dim2 ? ` (${r.version} \xB7 unloaded)` : ` (${r.version})`, dim2 ? "dd" : "d"));
|
|
3642
3692
|
const right = r.update != null ? [t(`\u2191 ${r.update}`, "ac")] : [];
|
|
3643
3693
|
let first = lr(left, right, w, true);
|
|
3644
3694
|
if (cur) first = sel(first);
|
|
3645
3695
|
const cls2 = r.failed === true ? "er" : dim2 ? "dd" : "d";
|
|
3646
|
-
const
|
|
3696
|
+
const author = r.author ?? "";
|
|
3697
|
+
const description = r.description ?? "";
|
|
3698
|
+
const old = r.failed === true || author === "" && description === "";
|
|
3699
|
+
let text2;
|
|
3700
|
+
if (old && r.subtitle) {
|
|
3701
|
+
text2 = r.subtitle;
|
|
3702
|
+
} else {
|
|
3703
|
+
const parts3 = [];
|
|
3704
|
+
if ((r.kinds ?? []).length > 0) parts3.push(r.kinds.join(", "));
|
|
3705
|
+
if (author) parts3.push(`by ${author}`);
|
|
3706
|
+
else if (r.builtin === true) parts3.push("comes with Orrery");
|
|
3707
|
+
if (w >= WIDE && description) parts3.push(description);
|
|
3708
|
+
text2 = parts3.join(" \xB7 ");
|
|
3709
|
+
}
|
|
3710
|
+
const second = fit([sp(6), t(tr(text2, Math.max(w - 6, 0)), cls2)], w);
|
|
3647
3711
|
return [first, second];
|
|
3648
3712
|
}
|
|
3649
3713
|
function grid(head, rows2, keep, cursor, w) {
|
|
@@ -4593,13 +4657,21 @@ var REGISTRY = {
|
|
|
4593
4657
|
extensions,
|
|
4594
4658
|
blocks: (p, w, m) => out(blocks(p.blocks, w, m))
|
|
4595
4659
|
};
|
|
4660
|
+
function dropNulls(v) {
|
|
4661
|
+
if (Array.isArray(v)) return v.map(dropNulls);
|
|
4662
|
+
if (v === null || typeof v !== "object") return v;
|
|
4663
|
+
const o = {};
|
|
4664
|
+
for (const [k, x] of Object.entries(v)) if (x !== null) o[k] = dropNulls(x);
|
|
4665
|
+
return o;
|
|
4666
|
+
}
|
|
4596
4667
|
function render2(id, props, w, m) {
|
|
4597
4668
|
const f = Object.prototype.hasOwnProperty.call(REGISTRY, id) ? REGISTRY[id] : void 0;
|
|
4598
4669
|
if (f === void 0) throw new BadProps(id, "no such element");
|
|
4599
4670
|
if (props === null || typeof props !== "object" || Array.isArray(props)) throw new BadProps(id, "expected an object");
|
|
4600
4671
|
let items2;
|
|
4601
4672
|
try {
|
|
4602
|
-
|
|
4673
|
+
const p = dropNulls(props);
|
|
4674
|
+
items2 = soft(() => f(p, w, m));
|
|
4603
4675
|
} catch (e) {
|
|
4604
4676
|
if (e instanceof BadProps) throw e;
|
|
4605
4677
|
throw new BadProps(id, e instanceof Error ? e.message : String(e));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getorrery/cells",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "The terminal design as cells: every harness element drawn as rows of styled cells, checked against the design's own goldens. A port of the orrery-cells crate.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
"directory": "harness/clients/cells-ts"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@getorrery/client": "0.2.
|
|
16
|
-
"@getorrery/protocol": "0.2.
|
|
15
|
+
"@getorrery/client": "0.2.3",
|
|
16
|
+
"@getorrery/protocol": "0.2.3"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
19
|
"typescript": "^5.9.3",
|