@promptctl/rich-js 0.16.0 → 0.18.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 +14 -27
- package/package.json +7 -3
- package/dist/core/box.d.ts +0 -144
- package/dist/core/box.js +0 -391
- package/dist/core/cells.d.ts +0 -148
- package/dist/core/cells.js +0 -266
- package/dist/core/color.d.ts +0 -229
- package/dist/core/color.js +0 -992
- package/dist/core/console.d.ts +0 -142
- package/dist/core/console.js +0 -477
- package/dist/core/emoji.d.ts +0 -24
- package/dist/core/emoji.js +0 -391
- package/dist/core/export-html.d.ts +0 -24
- package/dist/core/export-html.js +0 -106
- package/dist/core/export-lines.d.ts +0 -121
- package/dist/core/export-lines.js +0 -141
- package/dist/core/highlighter.d.ts +0 -33
- package/dist/core/highlighter.js +0 -124
- package/dist/core/json.d.ts +0 -27
- package/dist/core/json.js +0 -53
- package/dist/core/markup.d.ts +0 -97
- package/dist/core/markup.js +0 -619
- package/dist/core/measure.d.ts +0 -27
- package/dist/core/measure.js +0 -61
- package/dist/core/oklch.d.ts +0 -161
- package/dist/core/oklch.js +0 -312
- package/dist/core/osc8.d.ts +0 -68
- package/dist/core/osc8.js +0 -90
- package/dist/core/pretty.d.ts +0 -141
- package/dist/core/pretty.js +0 -472
- package/dist/core/protocol.d.ts +0 -137
- package/dist/core/protocol.js +0 -101
- package/dist/core/render.d.ts +0 -69
- package/dist/core/render.js +0 -140
- package/dist/core/segment.d.ts +0 -142
- package/dist/core/segment.js +0 -433
- package/dist/core/spinnerData.d.ts +0 -10
- package/dist/core/spinnerData.js +0 -115
- package/dist/core/strip.d.ts +0 -139
- package/dist/core/strip.js +0 -302
- package/dist/core/style.d.ts +0 -149
- package/dist/core/style.js +0 -741
- package/dist/core/subscription.d.ts +0 -12
- package/dist/core/subscription.js +0 -12
- package/dist/core/text.d.ts +0 -255
- package/dist/core/text.js +0 -990
- package/dist/core/wrap.d.ts +0 -41
- package/dist/core/wrap.js +0 -127
- package/dist/host/host-stream.d.ts +0 -30
- package/dist/host/host-stream.js +0 -35
- package/dist/host/index.d.ts +0 -3
- package/dist/host/index.js +0 -2
- package/dist/host/terminal-host.d.ts +0 -143
- package/dist/host/terminal-host.js +0 -132
- package/dist/index.d.ts +0 -87
- package/dist/index.js +0 -104
- package/dist/node/prompt.d.ts +0 -21
- package/dist/node/prompt.js +0 -30
- package/dist/node/save.d.ts +0 -17
- package/dist/node/save.js +0 -21
- package/dist/node/terminal-host.d.ts +0 -84
- package/dist/node/terminal-host.js +0 -160
- package/dist/node/traceback.d.ts +0 -27
- package/dist/node/traceback.js +0 -112
- package/dist/renderables/align.d.ts +0 -16
- package/dist/renderables/align.js +0 -46
- package/dist/renderables/columns.d.ts +0 -61
- package/dist/renderables/columns.js +0 -168
- package/dist/renderables/constrain.d.ts +0 -15
- package/dist/renderables/constrain.js +0 -37
- package/dist/renderables/flexStrip.d.ts +0 -41
- package/dist/renderables/flexStrip.js +0 -200
- package/dist/renderables/group.d.ts +0 -11
- package/dist/renderables/group.js +0 -15
- package/dist/renderables/layout.d.ts +0 -92
- package/dist/renderables/layout.js +0 -315
- package/dist/renderables/live.d.ts +0 -47
- package/dist/renderables/live.js +0 -131
- package/dist/renderables/markdown.d.ts +0 -24
- package/dist/renderables/markdown.js +0 -182
- package/dist/renderables/padding.d.ts +0 -38
- package/dist/renderables/padding.js +0 -140
- package/dist/renderables/panel.d.ts +0 -116
- package/dist/renderables/panel.js +0 -322
- package/dist/renderables/progress.d.ts +0 -90
- package/dist/renderables/progress.js +0 -241
- package/dist/renderables/progressBar.d.ts +0 -31
- package/dist/renderables/progressBar.js +0 -52
- package/dist/renderables/prompt.d.ts +0 -49
- package/dist/renderables/prompt.js +0 -125
- package/dist/renderables/rule.d.ts +0 -24
- package/dist/renderables/rule.js +0 -90
- package/dist/renderables/spinner.d.ts +0 -29
- package/dist/renderables/spinner.js +0 -64
- package/dist/renderables/status.d.ts +0 -23
- package/dist/renderables/status.js +0 -60
- package/dist/renderables/syntax.d.ts +0 -35
- package/dist/renderables/syntax.js +0 -114
- package/dist/renderables/table.d.ts +0 -182
- package/dist/renderables/table.js +0 -697
- package/dist/renderables/traceback.d.ts +0 -31
- package/dist/renderables/traceback.js +0 -109
- package/dist/renderables/tree.d.ts +0 -54
- package/dist/renderables/tree.js +0 -159
- package/dist/template-bindings/color-funcs.d.ts +0 -87
- package/dist/template-bindings/color-funcs.js +0 -219
- package/dist/template-bindings/helpers.d.ts +0 -24
- package/dist/template-bindings/helpers.js +0 -48
- package/dist/template-bindings/index.d.ts +0 -107
- package/dist/template-bindings/index.js +0 -144
- package/dist/template-bindings/palette-funcs.d.ts +0 -94
- package/dist/template-bindings/palette-funcs.js +0 -151
- package/dist/template-bindings/style-funcs.d.ts +0 -28
- package/dist/template-bindings/style-funcs.js +0 -151
- package/dist/themes/buildPalette.d.ts +0 -36
- package/dist/themes/buildPalette.js +0 -56
- package/dist/themes/colorMath.d.ts +0 -82
- package/dist/themes/colorMath.js +0 -254
- package/dist/themes/colorRef.d.ts +0 -51
- package/dist/themes/colorRef.js +0 -96
- package/dist/themes/data/atom-one-dark.d.ts +0 -3
- package/dist/themes/data/atom-one-dark.js +0 -158
- package/dist/themes/data/atom-one-light.d.ts +0 -3
- package/dist/themes/data/atom-one-light.js +0 -158
- package/dist/themes/data/catppuccin-frappe.d.ts +0 -3
- package/dist/themes/data/catppuccin-frappe.js +0 -158
- package/dist/themes/data/catppuccin-latte.d.ts +0 -3
- package/dist/themes/data/catppuccin-latte.js +0 -158
- package/dist/themes/data/catppuccin-macchiato.d.ts +0 -3
- package/dist/themes/data/catppuccin-macchiato.js +0 -158
- package/dist/themes/data/catppuccin-mocha.d.ts +0 -3
- package/dist/themes/data/catppuccin-mocha.js +0 -158
- package/dist/themes/data/cyberpunk.d.ts +0 -17
- package/dist/themes/data/cyberpunk.js +0 -191
- package/dist/themes/data/default.d.ts +0 -3
- package/dist/themes/data/default.js +0 -158
- package/dist/themes/data/dracula.d.ts +0 -3
- package/dist/themes/data/dracula.js +0 -158
- package/dist/themes/data/flexoki.d.ts +0 -3
- package/dist/themes/data/flexoki.js +0 -158
- package/dist/themes/data/gruvbox.d.ts +0 -3
- package/dist/themes/data/gruvbox.js +0 -158
- package/dist/themes/data/index.d.ts +0 -35
- package/dist/themes/data/index.js +0 -64
- package/dist/themes/data/monokai.d.ts +0 -3
- package/dist/themes/data/monokai.js +0 -158
- package/dist/themes/data/nord.d.ts +0 -3
- package/dist/themes/data/nord.js +0 -158
- package/dist/themes/data/rose-pine-dawn.d.ts +0 -3
- package/dist/themes/data/rose-pine-dawn.js +0 -158
- package/dist/themes/data/rose-pine-moon.d.ts +0 -3
- package/dist/themes/data/rose-pine-moon.js +0 -158
- package/dist/themes/data/rose-pine.d.ts +0 -3
- package/dist/themes/data/rose-pine.js +0 -158
- package/dist/themes/data/solarized-dark.d.ts +0 -3
- package/dist/themes/data/solarized-dark.js +0 -158
- package/dist/themes/data/solarized-light.d.ts +0 -3
- package/dist/themes/data/solarized-light.js +0 -158
- package/dist/themes/data/svg-export.d.ts +0 -3
- package/dist/themes/data/svg-export.js +0 -158
- package/dist/themes/data/textual-ansi.d.ts +0 -3
- package/dist/themes/data/textual-ansi.js +0 -158
- package/dist/themes/data/textual-dark.d.ts +0 -3
- package/dist/themes/data/textual-dark.js +0 -158
- package/dist/themes/data/textual-light.d.ts +0 -3
- package/dist/themes/data/textual-light.js +0 -158
- package/dist/themes/data/tokyo-night.d.ts +0 -3
- package/dist/themes/data/tokyo-night.js +0 -158
- package/dist/themes/data/types.d.ts +0 -15
- package/dist/themes/data/types.js +0 -1
- package/dist/themes/palette.d.ts +0 -21
- package/dist/themes/palette.js +0 -28
- package/dist/themes/ramp.d.ts +0 -83
- package/dist/themes/ramp.js +0 -122
- package/dist/themes/registry.d.ts +0 -43
- package/dist/themes/registry.js +0 -82
- package/dist/themes/terminalThemes.d.ts +0 -54
- package/dist/themes/terminalThemes.js +0 -68
- package/dist/themes/transpose.d.ts +0 -87
- package/dist/themes/transpose.js +0 -138
- package/dist/widgets/button.d.ts +0 -49
- package/dist/widgets/button.js +0 -206
- package/dist/widgets/checkbox.d.ts +0 -41
- package/dist/widgets/checkbox.js +0 -155
- package/dist/widgets/dropdown.d.ts +0 -67
- package/dist/widgets/dropdown.js +0 -453
- package/dist/widgets/event-router.d.ts +0 -78
- package/dist/widgets/event-router.js +0 -622
- package/dist/widgets/focus-manager.d.ts +0 -26
- package/dist/widgets/focus-manager.js +0 -193
- package/dist/widgets/index.d.ts +0 -22
- package/dist/widgets/index.js +0 -15
- package/dist/widgets/screen.d.ts +0 -98
- package/dist/widgets/screen.js +0 -542
- package/dist/widgets/slider.d.ts +0 -57
- package/dist/widgets/slider.js +0 -270
- package/dist/widgets/static-item.d.ts +0 -40
- package/dist/widgets/static-item.js +0 -60
- package/dist/widgets/text-input.d.ts +0 -274
- package/dist/widgets/text-input.js +0 -1162
- package/dist/widgets/toggle.d.ts +0 -44
- package/dist/widgets/toggle.js +0 -179
- package/dist/widgets/types.d.ts +0 -108
- package/dist/widgets/types.js +0 -31
- package/dist/widgets/widget-base.d.ts +0 -42
- package/dist/widgets/widget-base.js +0 -173
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Columns — arranges renderables in a multi-column layout.
|
|
3
|
-
*/
|
|
4
|
-
import { Segment } from "../core/segment.js";
|
|
5
|
-
import type { PaddingDimensions } from "./padding.js";
|
|
6
|
-
import type { Renderable, Measurable, RenderOptions } from "../core/protocol.js";
|
|
7
|
-
export interface ColumnsOptions {
|
|
8
|
-
expand?: boolean;
|
|
9
|
-
equal?: boolean;
|
|
10
|
-
width?: number;
|
|
11
|
-
padding?: PaddingDimensions;
|
|
12
|
-
columnFirst?: boolean;
|
|
13
|
-
}
|
|
14
|
-
export declare class Columns implements Renderable, Measurable {
|
|
15
|
-
renderables: (Renderable & Partial<Measurable>)[];
|
|
16
|
-
readonly expand: boolean;
|
|
17
|
-
readonly equal: boolean;
|
|
18
|
-
readonly colWidth: number | undefined;
|
|
19
|
-
readonly columnFirst: boolean;
|
|
20
|
-
readonly gutterWidth: number;
|
|
21
|
-
constructor(items?: Iterable<unknown>, options?: ColumnsOptions);
|
|
22
|
-
render(rawOptions: RenderOptions): Iterable<Segment>;
|
|
23
|
-
/**
|
|
24
|
-
* The requested width divided into columns, once.
|
|
25
|
-
*
|
|
26
|
-
* [LAW:single-enforcer] The three modes disagree only about how many columns
|
|
27
|
-
* there are and how wide each one is, so they disagree in one place. `render`
|
|
28
|
-
* lays out against this division and `_naturalWidth` is the width at which it
|
|
29
|
-
* comes out as one row of every item.
|
|
30
|
-
*/
|
|
31
|
-
private _divide;
|
|
32
|
-
/**
|
|
33
|
-
* The widest any one item wants to be.
|
|
34
|
-
*
|
|
35
|
-
* An item that cannot measure itself wants the offer, which is what `Panel`,
|
|
36
|
-
* `Padding`, `Layout` and `Tree` all answer for the same case — and under an
|
|
37
|
-
* unbounded offer that is `Infinity`, so `withBoundedWidth` throws and says
|
|
38
|
-
* the request was unanswerable. Counting it as one cell instead reported a
|
|
39
|
-
* natural width of 1, which resolved an unbounded offer to a single column and
|
|
40
|
-
* cropped forty cells of content down to `"x"` with no error at all.
|
|
41
|
-
*/
|
|
42
|
-
private _itemWidth;
|
|
43
|
-
/**
|
|
44
|
-
* The declared column width, bounded by the width offered.
|
|
45
|
-
*
|
|
46
|
-
* [LAW:single-enforcer] A declared width is what a column asks for, not what
|
|
47
|
-
* it takes — the contract `Table._outerWidth` keeps for a declared table
|
|
48
|
-
* width. Read by `_divide` for render and by `_naturalWidth` for measure, so
|
|
49
|
-
* the two answer from one number: laid out at the raw declared width, a
|
|
50
|
-
* six-cell column offered three emitted six-cell lines while `measure`
|
|
51
|
-
* reported three, and the terminal's soft wrap took the frame of everything
|
|
52
|
-
* printed after it.
|
|
53
|
-
*/
|
|
54
|
-
private _declaredWidth;
|
|
55
|
-
/** The width at which every item sits on one row: n columns and the gutters between them. */
|
|
56
|
-
private _naturalWidth;
|
|
57
|
-
measure(rawOptions: RenderOptions): {
|
|
58
|
-
minimum: number;
|
|
59
|
-
maximum: number;
|
|
60
|
-
};
|
|
61
|
-
}
|
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Columns — arranges renderables in a multi-column layout.
|
|
3
|
-
*/
|
|
4
|
-
import { Segment } from "../core/segment.js";
|
|
5
|
-
import { Measurement } from "../core/measure.js";
|
|
6
|
-
import { RichText } from "../core/text.js";
|
|
7
|
-
import { isMeasurable, withBoundedWidth, withCellWidth } from "../core/protocol.js";
|
|
8
|
-
import { cellCount } from "../core/cells.js";
|
|
9
|
-
function toRenderable(item) {
|
|
10
|
-
// [LAW:single-enforcer] A `RichText` passed directly implements `render`
|
|
11
|
-
// and would otherwise leave through the passthrough arm below untouched,
|
|
12
|
-
// keeping its default `end: "\n"` (rich-text-5ai) — the same gap the code
|
|
13
|
-
// review found in table.ts's `toRenderable`. A column item is a row
|
|
14
|
-
// fragment, not a printed unit, same as every other embedding site.
|
|
15
|
-
if (item instanceof RichText) {
|
|
16
|
-
const copy = item.copy();
|
|
17
|
-
copy.end = "";
|
|
18
|
-
return copy;
|
|
19
|
-
}
|
|
20
|
-
if (typeof item === "object" && item !== null && "render" in item) {
|
|
21
|
-
return item;
|
|
22
|
-
}
|
|
23
|
-
return new RichText(String(item ?? ""), { end: "" });
|
|
24
|
-
}
|
|
25
|
-
export class Columns {
|
|
26
|
-
renderables;
|
|
27
|
-
expand;
|
|
28
|
-
equal;
|
|
29
|
-
colWidth;
|
|
30
|
-
columnFirst;
|
|
31
|
-
gutterWidth;
|
|
32
|
-
constructor(items, options) {
|
|
33
|
-
this.renderables = items ? [...items].map(toRenderable) : [];
|
|
34
|
-
this.expand = options?.expand ?? false;
|
|
35
|
-
this.equal = options?.equal ?? false;
|
|
36
|
-
// A declared column width is a cell count like any other, and it reaches
|
|
37
|
-
// the layout without passing through `withCellWidth`, which parses only
|
|
38
|
-
// what the *caller of render* supplied. Left raw, `width: NaN` made
|
|
39
|
-
// `Math.max(1, NaN)` a NaN column count and `new Array` threw `Invalid
|
|
40
|
-
// array length` before a single column was laid out. Absence is preserved
|
|
41
|
-
// rather than parsed: `undefined` selects auto-fit, and `cellCount` would
|
|
42
|
-
// read it as a declared zero.
|
|
43
|
-
this.colWidth = options?.width === undefined ? undefined : cellCount(options.width);
|
|
44
|
-
this.columnFirst = options?.columnFirst ?? false;
|
|
45
|
-
this.gutterWidth = 2; // default gutter between columns
|
|
46
|
-
}
|
|
47
|
-
*render(rawOptions) {
|
|
48
|
-
const items = this.renderables;
|
|
49
|
-
if (items.length === 0)
|
|
50
|
-
return;
|
|
51
|
-
// The parsed options, not just a parsed local: `_divide` hands them to
|
|
52
|
-
// `Measurement.get`, and a raw NaN reaching it comes back as a NaN item
|
|
53
|
-
// width, then a NaN column count, then `Invalid array length` out of
|
|
54
|
-
// `new Array(numCols)` before a single column is laid out. An unbounded
|
|
55
|
-
// width reaches the same `new Array` by the same route, which is why the
|
|
56
|
-
// parse here is the bounded one.
|
|
57
|
-
const options = withBoundedWidth(rawOptions, this);
|
|
58
|
-
const { numCols, colWidths } = this._divide(options);
|
|
59
|
-
// Layout items into rows
|
|
60
|
-
const numRows = Math.ceil(items.length / numCols);
|
|
61
|
-
// [LAW:types-are-the-program] The element type is Renderable — any number
|
|
62
|
-
// of lines. Each grid cell renders to its full set of lines; an out-of-range
|
|
63
|
-
// slot (the last row is rarely full) is an empty cell. mergeHorizontal then
|
|
64
|
-
// stacks every row of every cell line-by-line, so multi-line children
|
|
65
|
-
// (Panels, Tables) compose instead of being truncated to their first row.
|
|
66
|
-
for (let row = 0; row < numRows; row++) {
|
|
67
|
-
const cells = colWidths.map((width, col) => {
|
|
68
|
-
const idx = this.columnFirst ? col * numRows + row : row * numCols + col;
|
|
69
|
-
const item = items[idx];
|
|
70
|
-
const lines = item === undefined
|
|
71
|
-
? []
|
|
72
|
-
: Segment.splitLines([
|
|
73
|
-
...item.render({ ...options, maxWidth: width }),
|
|
74
|
-
]);
|
|
75
|
-
return { lines, width };
|
|
76
|
-
});
|
|
77
|
-
yield* Segment.mergeHorizontal(cells, this.gutterWidth);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* The requested width divided into columns, once.
|
|
82
|
-
*
|
|
83
|
-
* [LAW:single-enforcer] The three modes disagree only about how many columns
|
|
84
|
-
* there are and how wide each one is, so they disagree in one place. `render`
|
|
85
|
-
* lays out against this division and `_naturalWidth` is the width at which it
|
|
86
|
-
* comes out as one row of every item.
|
|
87
|
-
*/
|
|
88
|
-
_divide(options) {
|
|
89
|
-
const maxWidth = options.maxWidth;
|
|
90
|
-
const gutter = this.gutterWidth;
|
|
91
|
-
const declared = this._declaredWidth(options);
|
|
92
|
-
if (declared !== undefined) {
|
|
93
|
-
const numCols = Math.max(1, Math.floor((maxWidth + gutter) / (declared + gutter)));
|
|
94
|
-
return { numCols, colWidths: new Array(numCols).fill(declared) };
|
|
95
|
-
}
|
|
96
|
-
if (this.equal) {
|
|
97
|
-
const itemWidth = this._itemWidth(options);
|
|
98
|
-
const numCols = Math.max(1, Math.floor((maxWidth + gutter) / (itemWidth + gutter)));
|
|
99
|
-
const equalWidth = Math.floor((maxWidth - gutter * (numCols - 1)) / numCols);
|
|
100
|
-
return { numCols, colWidths: new Array(numCols).fill(equalWidth) };
|
|
101
|
-
}
|
|
102
|
-
// Auto: as many columns as the widest item fits into, capped at the item
|
|
103
|
-
// count. Sized from the content rather than from a flat four cells per
|
|
104
|
-
// column, because `_naturalWidth` below is the inverse of *this* expression
|
|
105
|
-
// and a constant has no inverse: six two-cell items reported a natural
|
|
106
|
-
// width of 22 and then wrapped into two rows at 22, since `floor(22 / 4)`
|
|
107
|
-
// is five columns no matter how narrow the items are.
|
|
108
|
-
const itemWidth = this._itemWidth(options);
|
|
109
|
-
const numCols = Math.min(this.renderables.length, Math.max(1, Math.floor((maxWidth + gutter) / (itemWidth + gutter))));
|
|
110
|
-
const colW = Math.floor((maxWidth - gutter * (numCols - 1)) / numCols);
|
|
111
|
-
return { numCols, colWidths: new Array(numCols).fill(colW) };
|
|
112
|
-
}
|
|
113
|
-
/**
|
|
114
|
-
* The widest any one item wants to be.
|
|
115
|
-
*
|
|
116
|
-
* An item that cannot measure itself wants the offer, which is what `Panel`,
|
|
117
|
-
* `Padding`, `Layout` and `Tree` all answer for the same case — and under an
|
|
118
|
-
* unbounded offer that is `Infinity`, so `withBoundedWidth` throws and says
|
|
119
|
-
* the request was unanswerable. Counting it as one cell instead reported a
|
|
120
|
-
* natural width of 1, which resolved an unbounded offer to a single column and
|
|
121
|
-
* cropped forty cells of content down to `"x"` with no error at all.
|
|
122
|
-
*/
|
|
123
|
-
_itemWidth(options) {
|
|
124
|
-
let widest = 1;
|
|
125
|
-
for (const item of this.renderables) {
|
|
126
|
-
widest = Math.max(widest, isMeasurable(item)
|
|
127
|
-
? Measurement.get(options, item).maximum
|
|
128
|
-
: options.maxWidth);
|
|
129
|
-
}
|
|
130
|
-
return widest;
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* The declared column width, bounded by the width offered.
|
|
134
|
-
*
|
|
135
|
-
* [LAW:single-enforcer] A declared width is what a column asks for, not what
|
|
136
|
-
* it takes — the contract `Table._outerWidth` keeps for a declared table
|
|
137
|
-
* width. Read by `_divide` for render and by `_naturalWidth` for measure, so
|
|
138
|
-
* the two answer from one number: laid out at the raw declared width, a
|
|
139
|
-
* six-cell column offered three emitted six-cell lines while `measure`
|
|
140
|
-
* reported three, and the terminal's soft wrap took the frame of everything
|
|
141
|
-
* printed after it.
|
|
142
|
-
*/
|
|
143
|
-
_declaredWidth(options) {
|
|
144
|
-
return this.colWidth === undefined ? undefined : Math.min(this.colWidth, options.maxWidth);
|
|
145
|
-
}
|
|
146
|
-
/** The width at which every item sits on one row: n columns and the gutters between them. */
|
|
147
|
-
_naturalWidth(options) {
|
|
148
|
-
const count = this.renderables.length;
|
|
149
|
-
if (count === 0)
|
|
150
|
-
return 0;
|
|
151
|
-
const width = this._declaredWidth(options) ?? this._itemWidth(options);
|
|
152
|
-
return count * width + this.gutterWidth * (count - 1);
|
|
153
|
-
}
|
|
154
|
-
measure(rawOptions) {
|
|
155
|
-
// A floor of one cell is what Columns asks for; the ceiling is what it was
|
|
156
|
-
// offered, and the ceiling wins. Stated as a bare `minimum: 1`, a Columns
|
|
157
|
-
// measured into no width at all reported the range 1..0 — a floor above
|
|
158
|
-
// its own ceiling, which the parent that asked cannot divide.
|
|
159
|
-
//
|
|
160
|
-
// The ceiling is not the whole answer, though: reported as the offer alone,
|
|
161
|
-
// a Columns claimed every cell it was shown, so `Panel` in fit mode drew a
|
|
162
|
-
// 40-cell frame around five cells of content and an unbounded offer came
|
|
163
|
-
// back unbounded.
|
|
164
|
-
const parsed = withCellWidth(rawOptions);
|
|
165
|
-
const maximum = Math.min(this._naturalWidth(parsed), parsed.maxWidth);
|
|
166
|
-
return { minimum: Math.min(1, maximum), maximum };
|
|
167
|
-
}
|
|
168
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Constrain — wraps a renderable and constrains its maximum width.
|
|
3
|
-
*/
|
|
4
|
-
import { Segment } from "../core/segment.js";
|
|
5
|
-
import type { Renderable, Measurable, RenderOptions } from "../core/protocol.js";
|
|
6
|
-
export declare class Constrain implements Renderable, Measurable {
|
|
7
|
-
readonly renderable: Renderable;
|
|
8
|
-
readonly width: number | undefined;
|
|
9
|
-
constructor(renderable: Renderable, width?: number);
|
|
10
|
-
render(options: RenderOptions): Iterable<Segment>;
|
|
11
|
-
measure(options: RenderOptions): {
|
|
12
|
-
minimum: number;
|
|
13
|
-
maximum: number;
|
|
14
|
-
};
|
|
15
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Constrain — wraps a renderable and constrains its maximum width.
|
|
3
|
-
*/
|
|
4
|
-
import { Measurement } from "../core/measure.js";
|
|
5
|
-
import { isMeasurable } from "../core/protocol.js";
|
|
6
|
-
export class Constrain {
|
|
7
|
-
renderable;
|
|
8
|
-
width;
|
|
9
|
-
constructor(renderable, width) {
|
|
10
|
-
this.renderable = renderable;
|
|
11
|
-
this.width = width;
|
|
12
|
-
}
|
|
13
|
-
*render(options) {
|
|
14
|
-
// [LAW:dataflow-not-control-flow] Always compute constrainedWidth; undefined means no constraint
|
|
15
|
-
const constrainedWidth = this.width !== undefined
|
|
16
|
-
? Math.min(this.width, options.maxWidth)
|
|
17
|
-
: options.maxWidth;
|
|
18
|
-
const innerOptions = {
|
|
19
|
-
...options,
|
|
20
|
-
maxWidth: constrainedWidth,
|
|
21
|
-
};
|
|
22
|
-
yield* this.renderable.render(innerOptions);
|
|
23
|
-
}
|
|
24
|
-
measure(options) {
|
|
25
|
-
if (isMeasurable(this.renderable)) {
|
|
26
|
-
const measurement = Measurement.get(options, this.renderable);
|
|
27
|
-
const maxWidth = this.width !== undefined
|
|
28
|
-
? Math.min(this.width, options.maxWidth)
|
|
29
|
-
: options.maxWidth;
|
|
30
|
-
return {
|
|
31
|
-
minimum: measurement.minimum,
|
|
32
|
-
maximum: Math.min(measurement.maximum, maxWidth),
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
return { minimum: 1, maximum: options.maxWidth };
|
|
36
|
-
}
|
|
37
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* FlexStrip — wrap-to-width horizontal layout for `StyledRenderable` items.
|
|
3
|
-
*
|
|
4
|
-
* Pack as many items as fit on a line, then break and continue. Each line is
|
|
5
|
-
* an independent sub-strip: optional `Joiner` end-caps fire at every line
|
|
6
|
-
* boundary (not just the strip's first/last position), so a line break looks
|
|
7
|
-
* the same as an endpoint to the joiner. Composes with the Strip + Joiner
|
|
8
|
-
* primitive in `core/strip` — same `Joiner` protocol, no new join semantics.
|
|
9
|
-
*
|
|
10
|
-
* [LAW:dataflow-not-control-flow] The pack walk is the same shape every
|
|
11
|
-
* render: measure each item, render every joiner form (start-cap, end-cap,
|
|
12
|
-
* mid-join) up-front, then sweep items into lines. Line breaks are decided by
|
|
13
|
-
* width data, not by control-flow special cases.
|
|
14
|
-
*
|
|
15
|
-
* [LAW:one-source-of-truth] The Strip primitive owns the join protocol;
|
|
16
|
-
* FlexStrip reuses it verbatim. There is no second concept of "join."
|
|
17
|
-
*/
|
|
18
|
-
import { Segment } from "../core/segment.js";
|
|
19
|
-
import type { Renderable, Measurable, RenderOptions } from "../core/protocol.js";
|
|
20
|
-
import type { Joiner, StyledRenderable } from "../core/strip.js";
|
|
21
|
-
export type FlexAlign = "left" | "center" | "right" | "justify";
|
|
22
|
-
export interface FlexStripOptions<T extends StyledRenderable> {
|
|
23
|
-
/** Joiner used between items within a line, and at line endpoints. */
|
|
24
|
-
joiner?: Joiner<T>;
|
|
25
|
-
/** Cells of horizontal space inserted on each side of an inter-item joiner (default 0). */
|
|
26
|
-
gap?: number;
|
|
27
|
-
/** Line alignment when packed items don't fill the available width (default "left"). */
|
|
28
|
-
align?: FlexAlign;
|
|
29
|
-
}
|
|
30
|
-
export declare class FlexStrip<T extends StyledRenderable = StyledRenderable> implements Renderable, Measurable {
|
|
31
|
-
readonly items: readonly T[];
|
|
32
|
-
readonly joiner: Joiner<T> | undefined;
|
|
33
|
-
readonly gap: number;
|
|
34
|
-
readonly align: FlexAlign;
|
|
35
|
-
constructor(items: readonly T[], options?: FlexStripOptions<T>);
|
|
36
|
-
render(options: RenderOptions): Iterable<Segment>;
|
|
37
|
-
measure(options: RenderOptions): {
|
|
38
|
-
minimum: number;
|
|
39
|
-
maximum: number;
|
|
40
|
-
};
|
|
41
|
-
}
|
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* FlexStrip — wrap-to-width horizontal layout for `StyledRenderable` items.
|
|
3
|
-
*
|
|
4
|
-
* Pack as many items as fit on a line, then break and continue. Each line is
|
|
5
|
-
* an independent sub-strip: optional `Joiner` end-caps fire at every line
|
|
6
|
-
* boundary (not just the strip's first/last position), so a line break looks
|
|
7
|
-
* the same as an endpoint to the joiner. Composes with the Strip + Joiner
|
|
8
|
-
* primitive in `core/strip` — same `Joiner` protocol, no new join semantics.
|
|
9
|
-
*
|
|
10
|
-
* [LAW:dataflow-not-control-flow] The pack walk is the same shape every
|
|
11
|
-
* render: measure each item, render every joiner form (start-cap, end-cap,
|
|
12
|
-
* mid-join) up-front, then sweep items into lines. Line breaks are decided by
|
|
13
|
-
* width data, not by control-flow special cases.
|
|
14
|
-
*
|
|
15
|
-
* [LAW:one-source-of-truth] The Strip primitive owns the join protocol;
|
|
16
|
-
* FlexStrip reuses it verbatim. There is no second concept of "join."
|
|
17
|
-
*/
|
|
18
|
-
import { Segment } from "../core/segment.js";
|
|
19
|
-
function renderToBlock(r, options) {
|
|
20
|
-
const segments = [...r.render(options)];
|
|
21
|
-
let width = 0;
|
|
22
|
-
for (const s of segments)
|
|
23
|
-
width += s.cellLength;
|
|
24
|
-
return { segments, width };
|
|
25
|
-
}
|
|
26
|
-
const EMPTY_BLOCK = { segments: [], width: 0 };
|
|
27
|
-
const PAD_LEFT_BY_ALIGN = {
|
|
28
|
-
left: () => 0,
|
|
29
|
-
justify: () => 0,
|
|
30
|
-
center: (spare) => Math.floor(spare / 2),
|
|
31
|
-
right: (spare) => spare,
|
|
32
|
-
};
|
|
33
|
-
function computePadLeft(align, spare) {
|
|
34
|
-
return PAD_LEFT_BY_ALIGN[align](spare);
|
|
35
|
-
}
|
|
36
|
-
// Return per-slot fill widths (length = itemCount - 1, possibly empty).
|
|
37
|
-
// Non-justify cases produce all zeros — the emit loop runs the same way.
|
|
38
|
-
function computeSlotFills(align, isFinalLine, spare, itemCount) {
|
|
39
|
-
const slots = Math.max(0, itemCount - 1);
|
|
40
|
-
const distribute = align === "justify" && !isFinalLine && slots > 0 && spare > 0;
|
|
41
|
-
const totalFill = distribute ? spare : 0;
|
|
42
|
-
const base = slots > 0 ? Math.floor(totalFill / slots) : 0;
|
|
43
|
-
const extra = totalFill - base * slots;
|
|
44
|
-
return Array.from({ length: slots }, (_, k) => base + (k < extra ? 1 : 0));
|
|
45
|
-
}
|
|
46
|
-
export class FlexStrip {
|
|
47
|
-
items;
|
|
48
|
-
joiner;
|
|
49
|
-
gap;
|
|
50
|
-
align;
|
|
51
|
-
constructor(items, options) {
|
|
52
|
-
this.items = items;
|
|
53
|
-
this.joiner = options?.joiner;
|
|
54
|
-
this.gap = options?.gap ?? 0;
|
|
55
|
-
this.align = options?.align ?? "left";
|
|
56
|
-
}
|
|
57
|
-
*render(options) {
|
|
58
|
-
const items = this.items;
|
|
59
|
-
if (items.length === 0)
|
|
60
|
-
return;
|
|
61
|
-
const maxWidth = Math.max(1, options.maxWidth);
|
|
62
|
-
const gap = this.gap;
|
|
63
|
-
const joiner = this.joiner;
|
|
64
|
-
// Pre-render every item and every joiner form we might need. Doing this
|
|
65
|
-
// up-front turns packing into a pure data computation over widths.
|
|
66
|
-
const itemBlocks = items.map((it) => renderToBlock(it, options));
|
|
67
|
-
const startCap = (i) => joiner ? renderToBlock(joiner.join(null, items[i]), options) : EMPTY_BLOCK;
|
|
68
|
-
const endCap = (i) => joiner ? renderToBlock(joiner.join(items[i], null), options) : EMPTY_BLOCK;
|
|
69
|
-
const midJoin = (i, j) => joiner ? renderToBlock(joiner.join(items[i], items[j]), options) : EMPTY_BLOCK;
|
|
70
|
-
const lines = [];
|
|
71
|
-
let line = null;
|
|
72
|
-
const gapBlock = gap > 0
|
|
73
|
-
? { segments: [new Segment(" ".repeat(gap))], width: gap }
|
|
74
|
-
: EMPTY_BLOCK;
|
|
75
|
-
for (let i = 0; i < items.length; i++) {
|
|
76
|
-
const item = itemBlocks[i];
|
|
77
|
-
if (line === null) {
|
|
78
|
-
const sc = startCap(i);
|
|
79
|
-
const ec = endCap(i);
|
|
80
|
-
const blocks = sc.width > 0 ? [sc, item] : [item];
|
|
81
|
-
const itemBlockIndices = [blocks.length - 1];
|
|
82
|
-
line = { blocks, width: sc.width + item.width, lastIndex: i, itemBlockIndices };
|
|
83
|
-
// Tentatively reserve space for the line's eventual end-cap by
|
|
84
|
-
// tracking it separately below — `line.width` is the open width
|
|
85
|
-
// (without end-cap). We test fit using width + endCap on each step.
|
|
86
|
-
// Always start a new line with at least the first item (overflow ok
|
|
87
|
-
// per ticket: graceful fallback when an item is wider than terminal).
|
|
88
|
-
// Stash end-cap for the close step.
|
|
89
|
-
line.endCap = ec;
|
|
90
|
-
continue;
|
|
91
|
-
}
|
|
92
|
-
const prev = line.lastIndex;
|
|
93
|
-
const mid = midJoin(prev, i);
|
|
94
|
-
const newEndCap = endCap(i);
|
|
95
|
-
const addCost = (gap > 0 ? gap : 0) + mid.width + (gap > 0 ? gap : 0) + item.width;
|
|
96
|
-
const closedWidthIfAdded = line.width + addCost + newEndCap.width;
|
|
97
|
-
if (closedWidthIfAdded <= maxWidth) {
|
|
98
|
-
if (gap > 0)
|
|
99
|
-
line.blocks.push(gapBlock);
|
|
100
|
-
if (mid.width > 0)
|
|
101
|
-
line.blocks.push(mid);
|
|
102
|
-
if (gap > 0)
|
|
103
|
-
line.blocks.push(gapBlock);
|
|
104
|
-
line.blocks.push(item);
|
|
105
|
-
line.itemBlockIndices.push(line.blocks.length - 1);
|
|
106
|
-
line.width += addCost;
|
|
107
|
-
line.lastIndex = i;
|
|
108
|
-
line.endCap = newEndCap;
|
|
109
|
-
}
|
|
110
|
-
else {
|
|
111
|
-
// Close current line and start a new one with this item.
|
|
112
|
-
const closing = line.endCap;
|
|
113
|
-
if (closing.width > 0)
|
|
114
|
-
line.blocks.push(closing);
|
|
115
|
-
line.width += closing.width;
|
|
116
|
-
lines.push(line);
|
|
117
|
-
const sc = startCap(i);
|
|
118
|
-
const ec = endCap(i);
|
|
119
|
-
const blocks = sc.width > 0 ? [sc, item] : [item];
|
|
120
|
-
const itemBlockIndices = [blocks.length - 1];
|
|
121
|
-
line = { blocks, width: sc.width + item.width, lastIndex: i, itemBlockIndices };
|
|
122
|
-
line.endCap = ec;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
// Close final line. `line` is non-null here: the loop runs at least once
|
|
126
|
-
// (items.length > 0 was handled above).
|
|
127
|
-
const finalLine = line;
|
|
128
|
-
{
|
|
129
|
-
const closing = finalLine.endCap;
|
|
130
|
-
if (closing.width > 0)
|
|
131
|
-
finalLine.blocks.push(closing);
|
|
132
|
-
finalLine.width += closing.width;
|
|
133
|
-
lines.push(finalLine);
|
|
134
|
-
}
|
|
135
|
-
// [LAW:dataflow-not-control-flow] Single emission path for every line:
|
|
136
|
-
// emit pad, walk every block, optionally emit a per-slot fill before each
|
|
137
|
-
// non-first item. Variability lives in two precomputed value sequences
|
|
138
|
-
// (`padLeft` and `slotFills`); the emit loop has no per-mode branch.
|
|
139
|
-
//
|
|
140
|
-
// - `padLeft` pushes the line right by 0 (left/justify), spare/2 (center),
|
|
141
|
-
// or full spare (right). Justify-on-final-line follows the left rule.
|
|
142
|
-
// - `slotFills[k]` is the cells of fill emitted before the (k+1)-th item.
|
|
143
|
-
// Always 0 unless align=justify on a non-final line with ≥2 items.
|
|
144
|
-
//
|
|
145
|
-
// Putting the variability in data means the emit loop is the same shape
|
|
146
|
-
// every render, and "what happens between two items" can never accidentally
|
|
147
|
-
// become "what happens between joiner halves" — the data decides.
|
|
148
|
-
const align = this.align;
|
|
149
|
-
for (let li = 0; li < lines.length; li++) {
|
|
150
|
-
const ln = lines[li];
|
|
151
|
-
const isLast = li === lines.length - 1;
|
|
152
|
-
const spare = Math.max(0, maxWidth - ln.width);
|
|
153
|
-
const padLeft = computePadLeft(align, spare);
|
|
154
|
-
const slotFills = computeSlotFills(align, isLast, spare, ln.itemBlockIndices.length);
|
|
155
|
-
const itemRankOf = new Map();
|
|
156
|
-
ln.itemBlockIndices.forEach((blockIdx, rank) => itemRankOf.set(blockIdx, rank));
|
|
157
|
-
if (padLeft > 0)
|
|
158
|
-
yield new Segment(" ".repeat(padLeft));
|
|
159
|
-
for (let bi = 0; bi < ln.blocks.length; bi++) {
|
|
160
|
-
const rank = itemRankOf.get(bi);
|
|
161
|
-
if (rank !== undefined && rank > 0) {
|
|
162
|
-
const fill = slotFills[rank - 1];
|
|
163
|
-
if (fill > 0)
|
|
164
|
-
yield new Segment(" ".repeat(fill));
|
|
165
|
-
}
|
|
166
|
-
yield* ln.blocks[bi].segments;
|
|
167
|
-
}
|
|
168
|
-
yield Segment.line();
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
measure(options) {
|
|
172
|
-
const items = this.items;
|
|
173
|
-
if (items.length === 0)
|
|
174
|
-
return { minimum: 0, maximum: 0 };
|
|
175
|
-
let minimum = 0;
|
|
176
|
-
let maximum = 0;
|
|
177
|
-
for (let i = 0; i < items.length; i++) {
|
|
178
|
-
const itemWidth = renderToBlock(items[i], options).width;
|
|
179
|
-
const sc = this.joiner
|
|
180
|
-
? renderToBlock(this.joiner.join(null, items[i]), options).width
|
|
181
|
-
: 0;
|
|
182
|
-
const ec = this.joiner
|
|
183
|
-
? renderToBlock(this.joiner.join(items[i], null), options).width
|
|
184
|
-
: 0;
|
|
185
|
-
minimum = Math.max(minimum, itemWidth + sc + ec);
|
|
186
|
-
maximum += itemWidth;
|
|
187
|
-
if (i > 0) {
|
|
188
|
-
maximum += this.gap * 2;
|
|
189
|
-
if (this.joiner) {
|
|
190
|
-
maximum += renderToBlock(this.joiner.join(items[i - 1], items[i]), options).width;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
if (this.joiner) {
|
|
195
|
-
maximum += renderToBlock(this.joiner.join(null, items[0]), options).width;
|
|
196
|
-
maximum += renderToBlock(this.joiner.join(items[items.length - 1], null), options).width;
|
|
197
|
-
}
|
|
198
|
-
return { minimum, maximum };
|
|
199
|
-
}
|
|
200
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Group — renders multiple renderables in sequence.
|
|
3
|
-
* No visual chrome — purely a container.
|
|
4
|
-
*/
|
|
5
|
-
import { Segment } from "../core/segment.js";
|
|
6
|
-
import type { Renderable, RenderOptions } from "../core/protocol.js";
|
|
7
|
-
export declare class Group implements Renderable {
|
|
8
|
-
readonly renderables: Renderable[];
|
|
9
|
-
constructor(...renderables: Renderable[]);
|
|
10
|
-
render(options: RenderOptions): Iterable<Segment>;
|
|
11
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Group — renders multiple renderables in sequence.
|
|
3
|
-
* No visual chrome — purely a container.
|
|
4
|
-
*/
|
|
5
|
-
export class Group {
|
|
6
|
-
renderables;
|
|
7
|
-
constructor(...renderables) {
|
|
8
|
-
this.renderables = renderables;
|
|
9
|
-
}
|
|
10
|
-
*render(options) {
|
|
11
|
-
for (const renderable of this.renderables) {
|
|
12
|
-
yield* renderable.render(options);
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
}
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Layout — divides the screen into rectangular regions.
|
|
3
|
-
*/
|
|
4
|
-
import { Segment } from "../core/segment.js";
|
|
5
|
-
import type { Renderable, Measurable, RenderOptions } from "../core/protocol.js";
|
|
6
|
-
export interface LayoutOptions {
|
|
7
|
-
name?: string;
|
|
8
|
-
ratio?: number;
|
|
9
|
-
size?: number;
|
|
10
|
-
minimumSize?: number;
|
|
11
|
-
visible?: boolean;
|
|
12
|
-
}
|
|
13
|
-
export declare class Layout implements Renderable, Measurable {
|
|
14
|
-
name: string | undefined;
|
|
15
|
-
visible: boolean;
|
|
16
|
-
private _ratio;
|
|
17
|
-
private _size;
|
|
18
|
-
private _minimumSize;
|
|
19
|
-
private _renderable;
|
|
20
|
-
private _children;
|
|
21
|
-
private _splitDirection;
|
|
22
|
-
constructor(renderable?: Renderable | string, options?: LayoutOptions);
|
|
23
|
-
/**
|
|
24
|
-
* The three declared numbers, parsed on assignment rather than at the
|
|
25
|
-
* constructor. All three are public and a caller reaches them long after
|
|
26
|
-
* construction — `layout.getByName("pane")!.ratio = -1` walked straight past a
|
|
27
|
-
* constructor-only parse and put a negative weight back into the division that
|
|
28
|
-
* `_rowBudgetFor` and `_distributeSpace` are written to trust.
|
|
29
|
-
*
|
|
30
|
-
* [LAW:parse-dont-validate] The setter is the border, so the guarantee holds
|
|
31
|
-
* for the object's whole lifetime and nothing downstream re-checks. `size` and
|
|
32
|
-
* `minimumSize` are cell counts; `ratio` is a share weight and keeps its
|
|
33
|
-
* fractions. Absence is preserved rather than parsed: an undefined `size`
|
|
34
|
-
* selects a flex pane, and `cellCount` would read it as a declared zero.
|
|
35
|
-
*/
|
|
36
|
-
get ratio(): number;
|
|
37
|
-
set ratio(value: number);
|
|
38
|
-
get size(): number | undefined;
|
|
39
|
-
set size(value: number | undefined);
|
|
40
|
-
get minimumSize(): number;
|
|
41
|
-
set minimumSize(value: number);
|
|
42
|
-
get children(): Layout[];
|
|
43
|
-
/**
|
|
44
|
-
* Whether this layout draws `_renderable` or its children.
|
|
45
|
-
*
|
|
46
|
-
* [LAW:one-source-of-truth] `render` and `_naturalWidth` must answer this the
|
|
47
|
-
* same way. Asked separately they did not: `_naturalWidth` read it off the
|
|
48
|
-
* *visible* children, so a layout holding content and a single hidden child
|
|
49
|
-
* reported that content's width while `render` emitted nothing at all, and a
|
|
50
|
-
* fit-mode `Panel` framed twelve cells of air.
|
|
51
|
-
*/
|
|
52
|
-
private get _isLeaf();
|
|
53
|
-
splitColumn(...layouts: Layout[]): void;
|
|
54
|
-
splitRow(...layouts: Layout[]): void;
|
|
55
|
-
update(renderable: Renderable | string): void;
|
|
56
|
-
getByName(name: string): Layout | undefined;
|
|
57
|
-
render(rawOptions: RenderOptions): Iterable<Segment>;
|
|
58
|
-
private _renderColumn;
|
|
59
|
-
private _renderRow;
|
|
60
|
-
private _distributeSpace;
|
|
61
|
-
/**
|
|
62
|
-
* The width this layout would take if nothing constrained it: its content's
|
|
63
|
-
* for a leaf, its children's laid out the way the split lays them out.
|
|
64
|
-
*
|
|
65
|
-
* A `size` counts only across a row, which is the one direction in which it
|
|
66
|
-
* is a width — down a column the same field is a height, and reading it as a
|
|
67
|
-
* width there would report a two-line pane as two cells wide.
|
|
68
|
-
*/
|
|
69
|
-
private _naturalWidth;
|
|
70
|
-
/**
|
|
71
|
-
* The budget at which `_distributeSpace` gives every child of a row at least
|
|
72
|
-
* the width it wants — the inverse of the ratio rule above, and the reason
|
|
73
|
-
* this is not the sum of those widths.
|
|
74
|
-
*
|
|
75
|
-
* [LAW:one-source-of-truth] A growing child receives `floor(budget * ratio /
|
|
76
|
-
* totalRatio)`, so to receive `want` cells it needs the budget to reach
|
|
77
|
-
* `want * totalRatio / ratio`, and one budget serves them all: the row needs
|
|
78
|
-
* the largest demand, never their total. Summed instead, a 1:1 split of
|
|
79
|
-
* "left" and "right" reported 9 and then rendered "right" into the 4 cells
|
|
80
|
-
* that `floor(9/2)` actually hands it.
|
|
81
|
-
*
|
|
82
|
-
* The panes that do not grow are paid first here for the same reason they
|
|
83
|
-
* are paid first there — and it is the reason this divides by no zero: a
|
|
84
|
-
* `ratio` of 0 never reaches the division, because a pane that does not grow
|
|
85
|
-
* demands nothing of a budget for growing.
|
|
86
|
-
*/
|
|
87
|
-
private _rowBudgetFor;
|
|
88
|
-
measure(rawOptions: RenderOptions): {
|
|
89
|
-
minimum: number;
|
|
90
|
-
maximum: number;
|
|
91
|
-
};
|
|
92
|
-
}
|