@ashley-shrok/viewmodel-shell 0.4.8 → 0.4.9

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/tui.d.ts CHANGED
@@ -62,12 +62,18 @@ export declare class TuiAdapter implements Adapter {
62
62
  * interactive TTY; "content" = legacy intrinsic-content size, no
63
63
  * alt-screen (the opt-out escape hatch — pre-0.4.5 behavior). */
64
64
  private readonly viewport;
65
+ /** `sidebar` rail width as a fraction of the terminal (fill path only).
66
+ * Default 1/3; clamped to a sane [0.15, 0.6] so a bad value can't break
67
+ * the layout. Adapter-level styling knob (NOT wire — appearance, not
68
+ * arrangement). */
69
+ private readonly sidebarFraction;
65
70
  /** Set once ESC[?1049h was written, so dispose() emits the paired
66
71
  * ESC[?1049l exactly once (idempotent restore — same discipline as the
67
72
  * cursor restore Ink does on unmount). */
68
73
  private altEntered;
69
74
  constructor(opts?: {
70
75
  viewport?: "fill" | "content";
76
+ sidebarFraction?: number;
71
77
  });
72
78
  /** Injected by tui-cli.ts: lets a keyboard Ctrl-C (which, under Ink's raw
73
79
  * mode, is delivered as input 0x03 and never raises SIGINT) reach the
package/dist/tui.js CHANGED
@@ -990,6 +990,7 @@ function App(props) {
990
990
  interactive,
991
991
  fill: fillViewport,
992
992
  fillCols: fillViewport ? vp.cols : undefined,
993
+ railFraction: props.railFraction,
993
994
  draft: (k) => draftFor(k),
994
995
  onFieldChange: (k, v) => setDraft((s) => ({ ...s, [k]: v })),
995
996
  onFieldSubmit,
@@ -1046,12 +1047,19 @@ export class TuiAdapter {
1046
1047
  * interactive TTY; "content" = legacy intrinsic-content size, no
1047
1048
  * alt-screen (the opt-out escape hatch — pre-0.4.5 behavior). */
1048
1049
  viewport;
1050
+ /** `sidebar` rail width as a fraction of the terminal (fill path only).
1051
+ * Default 1/3; clamped to a sane [0.15, 0.6] so a bad value can't break
1052
+ * the layout. Adapter-level styling knob (NOT wire — appearance, not
1053
+ * arrangement). */
1054
+ sidebarFraction;
1049
1055
  /** Set once ESC[?1049h was written, so dispose() emits the paired
1050
1056
  * ESC[?1049l exactly once (idempotent restore — same discipline as the
1051
1057
  * cursor restore Ink does on unmount). */
1052
1058
  altEntered = false;
1053
1059
  constructor(opts) {
1054
1060
  this.viewport = opts?.viewport ?? "fill";
1061
+ const f = opts?.sidebarFraction ?? 1 / 3;
1062
+ this.sidebarFraction = Math.min(0.6, Math.max(0.15, f));
1055
1063
  }
1056
1064
  /** Injected by tui-cli.ts: lets a keyboard Ctrl-C (which, under Ink's raw
1057
1065
  * mode, is delivered as input 0x03 and never raises SIGINT) reach the
@@ -1107,7 +1115,7 @@ export class TuiAdapter {
1107
1115
  }
1108
1116
  /** The interactive element used by render() and by interaction unit tests. */
1109
1117
  createApp(vm, onAction, opts) {
1110
- return (_jsx(App, { vm: vm, onAction: onAction, requestExit: opts?.requestExit ?? this.requestExit, interstitial: this.interstitial, viewport: this.viewport, renderWith: (v, rctx) => this.renderNode(v, 0, "comfortable", undefined, rctx) }));
1118
+ return (_jsx(App, { vm: vm, onAction: onAction, requestExit: opts?.requestExit ?? this.requestExit, interstitial: this.interstitial, viewport: this.viewport, railFraction: this.sidebarFraction, renderWith: (v, rctx) => this.renderNode(v, 0, "comfortable", undefined, rctx) }));
1111
1119
  }
1112
1120
  /** Render a full-screen loud notice through the SINGLE existing Ink instance
1113
1121
  * (never a 2nd inkRender, never a raw stdout write that would corrupt Ink's
@@ -1275,7 +1283,15 @@ export class TuiAdapter {
1275
1283
  // ORIGINAL flex props, byte-identical.
1276
1284
  const cols = topLevel && rctx.fillCols ? rctx.fillCols : 0;
1277
1285
  const filling = cols > 0;
1278
- const RAIL = 24;
1286
+ // 0.4.9 PROPORTIONAL rail (default 1/3, clamped [24,56]) instead of
1287
+ // a hardcoded 24 (unusable on wide terminals: 24/146 ≈ 16%). Never
1288
+ // below the old 24 on small terminals; capped so ultra-wide keeps the
1289
+ // detail pane dominant. Tunable via `new TuiAdapter({ sidebarFraction })`.
1290
+ // Only the filling branches use RAIL; the non-fill path keeps the
1291
+ // literal flexBasis:24/minWidth:18 (byte-identical).
1292
+ const RAIL = filling
1293
+ ? Math.min(56, Math.max(24, Math.round(cols * (rctx.railFraction ?? 1 / 3))))
1294
+ : 24;
1279
1295
  const g = sp.gap || 1;
1280
1296
  const mw = Math.max(1, cols - RAIL - g);
1281
1297
  if (rest.length === 0) {
@@ -1284,7 +1300,11 @@ export class TuiAdapter {
1284
1300
  // numeric width (a default-row box would not width-stretch it).
1285
1301
  _jsx(Box, { flexDirection: "column", flexShrink: 0, ...fillW, children: rail })) : (_jsx(Box, { flexShrink: 0, flexBasis: 24, minWidth: 18, children: rail }));
1286
1302
  }
1287
- return (_jsxs(Box, { flexDirection: "row", gap: g, ...fillW, children: [filling ? (_jsx(Box, { flexShrink: 0, width: RAIL, children: rail })) : (_jsx(Box, { flexShrink: 0, flexBasis: 24, minWidth: 18, children: rail })), filling ? (
1303
+ return (_jsxs(Box, { flexDirection: "row", gap: g, ...fillW, children: [filling ? (
1304
+ // flexDirection:column ⇒ the rail's section align-stretches to
1305
+ // the numeric RAIL width (a default-row box sizes it to content
1306
+ // — same lesson as the single-child branch).
1307
+ _jsx(Box, { flexDirection: "column", flexShrink: 0, width: RAIL, children: rail })) : (_jsx(Box, { flexShrink: 0, flexBasis: 24, minWidth: 18, children: rail })), filling ? (
1288
1308
  // Single numeric-width column directly holding the detail
1289
1309
  // sections — exactly the `stack` shape the oracle proves scales
1290
1310
  // (a card section align-stretches to a numeric-width parent).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ashley-shrok/viewmodel-shell",
3
- "version": "0.4.8",
3
+ "version": "0.4.9",
4
4
  "description": "A server-driven UI framework where the wire format is structured enough that agents can build full-stack apps without ever opening a browser and all UI tests are pure unit tests with no browser runtime. Server returns a JSON tree of typed nodes; a thin TypeScript adapter renders it to DOM. Backend-agnostic — a .NET reference backend ships with the repo, but any language can produce the JSON contract.",
5
5
  "type": "module",
6
6
  "license": "MIT",