@flowtty/core 1.0.0-alpha.1 → 1.0.0-alpha.11

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.
@@ -1,106 +0,0 @@
1
- // src/cells.ts
2
- var Buffer = class {
3
- width;
4
- height;
5
- cells;
6
- constructor(width, height) {
7
- this.width = Math.max(0, width);
8
- this.height = Math.max(0, height);
9
- this.cells = Array.from({ length: this.width * this.height }, () => ({
10
- char: " ",
11
- style: {}
12
- }));
13
- }
14
- set(x, y, char, style = {}) {
15
- if (x < 0 || y < 0 || x >= this.width || y >= this.height) return;
16
- this.cells[y * this.width + x] = { char, style };
17
- }
18
- // Out-of-bounds reads return a fresh blank cell (mirrors set()'s no-op).
19
- get(x, y) {
20
- return this.cells[y * this.width + x] ?? { char: " ", style: {} };
21
- }
22
- // Plain-text frame. Trailing ASCII spaces are trimmed (cosmetic), but NBSP
23
- // (U+00A0) and other content are preserved — NBSP-safety is a flowtty value.
24
- toString() {
25
- const lines = [];
26
- for (let y = 0; y < this.height; y++) {
27
- let line = "";
28
- for (let x = 0; x < this.width; x++) line += this.get(x, y).char;
29
- lines.push(line.replace(/ +$/u, ""));
30
- }
31
- return lines.join("\n").replace(/\n+$/u, "");
32
- }
33
- };
34
-
35
- // src/host/borders.ts
36
- var DEFAULT_BORDER_STYLE = "round";
37
- var GRID_CHARS = {
38
- single: { h: "\u2500", v: "\u2502", tl: "\u250C", tr: "\u2510", bl: "\u2514", br: "\u2518", tDown: "\u252C", tUp: "\u2534", tRight: "\u251C", tLeft: "\u2524", cross: "\u253C" },
39
- round: { h: "\u2500", v: "\u2502", tl: "\u256D", tr: "\u256E", bl: "\u2570", br: "\u256F", tDown: "\u252C", tUp: "\u2534", tRight: "\u251C", tLeft: "\u2524", cross: "\u253C" },
40
- double: { h: "\u2550", v: "\u2551", tl: "\u2554", tr: "\u2557", bl: "\u255A", br: "\u255D", tDown: "\u2566", tUp: "\u2569", tRight: "\u2560", tLeft: "\u2563", cross: "\u256C" },
41
- bold: { h: "\u2501", v: "\u2503", tl: "\u250F", tr: "\u2513", bl: "\u2517", br: "\u251B", tDown: "\u2533", tUp: "\u253B", tRight: "\u2523", tLeft: "\u252B", cross: "\u254B" },
42
- classic: { h: "-", v: "|", tl: "+", tr: "+", bl: "+", br: "+", tDown: "+", tUp: "+", tRight: "+", tLeft: "+", cross: "+" }
43
- };
44
- var BORDER_CHARS = GRID_CHARS;
45
-
46
- // src/wrap.ts
47
- var ELLIPSIS = "\u2026";
48
- function wrapText(text, width, mode) {
49
- if (width < 0) width = 0;
50
- const out = [];
51
- for (const source of text.split("\n")) {
52
- if (mode === "none") {
53
- out.push(source);
54
- continue;
55
- }
56
- if (mode === "truncate") {
57
- out.push(truncateLine(source, width));
58
- continue;
59
- }
60
- wrapLine(source, width, out);
61
- }
62
- if (out.length === 0) out.push("");
63
- return out;
64
- }
65
- function truncateLine(line, width) {
66
- if (width <= 0) return "";
67
- const chars = [...line];
68
- if (chars.length <= width) return line;
69
- if (width === 1) return ELLIPSIS;
70
- return chars.slice(0, width - 1).join("") + ELLIPSIS;
71
- }
72
- function wrapLine(line, width, out) {
73
- if (width === 0) {
74
- out.push("");
75
- return;
76
- }
77
- if (line === "") {
78
- out.push("");
79
- return;
80
- }
81
- let current = "";
82
- for (const word of line.split(" ")) {
83
- const candidate = current ? current + " " + word : word;
84
- if ([...candidate].length <= width) {
85
- current = candidate;
86
- continue;
87
- }
88
- if (current) {
89
- out.push(current);
90
- current = "";
91
- }
92
- if ([...word].length > width) {
93
- let remainder = [...word];
94
- while (remainder.length > width) {
95
- out.push(remainder.slice(0, width).join(""));
96
- remainder = remainder.slice(width);
97
- }
98
- current = remainder.join("");
99
- } else {
100
- current = word;
101
- }
102
- }
103
- if (current) out.push(current);
104
- }
105
-
106
- export { BORDER_CHARS, Buffer, DEFAULT_BORDER_STYLE, GRID_CHARS, wrapText };
@@ -1,151 +0,0 @@
1
- import { loadYoga } from 'yoga-layout/load';
2
-
3
- type Yoga = Awaited<ReturnType<typeof loadYoga>>;
4
- type YogaNode = ReturnType<Yoga['Node']['create']>;
5
- declare function getYoga(): Promise<Yoga>;
6
-
7
- type BorderStyle = 'single' | 'double' | 'round' | 'bold' | 'classic';
8
- /** The library-wide default for components that draw a box-border chrome
9
- * (DialogHost wrappers, Menu panels, Table grids). Declared once so the
10
- * default is a single edit, not one per component. */
11
- declare const DEFAULT_BORDER_STYLE: BorderStyle;
12
- interface GridChars {
13
- h: string;
14
- v: string;
15
- tl: string;
16
- tr: string;
17
- bl: string;
18
- br: string;
19
- tDown: string;
20
- tUp: string;
21
- tRight: string;
22
- tLeft: string;
23
- cross: string;
24
- }
25
- declare const GRID_CHARS: Record<BorderStyle, GridChars>;
26
- type BorderChars = Pick<GridChars, 'h' | 'v' | 'tl' | 'tr' | 'bl' | 'br'>;
27
- declare const BORDER_CHARS: Record<BorderStyle, BorderChars>;
28
-
29
- interface Rect {
30
- left: number;
31
- top: number;
32
- width: number;
33
- height: number;
34
- }
35
- declare function computeLayout(container: Container, width: number, height: number): void;
36
- declare function layoutOf(inst: Instance, offsetX?: number, offsetY?: number): Rect;
37
-
38
- type HostType = 'flowtty-box';
39
- interface BoxProps {
40
- /** Fixed size in cells. Strings like '100%' use Yoga's percentage sizing. */
41
- width?: number | string;
42
- height?: number | string;
43
- flexDirection?: 'row' | 'column';
44
- /** Default 'static' (Yoga's stack flow). 'absolute' positions via top/left/right/bottom relative to the nearest non-static ancestor. */
45
- position?: 'static' | 'absolute';
46
- top?: number;
47
- left?: number;
48
- right?: number;
49
- bottom?: number;
50
- /** Main-axis alignment of children (flexbox). */
51
- justifyContent?: 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around' | 'space-evenly';
52
- /** Cross-axis alignment of children. */
53
- alignItems?: 'flex-start' | 'flex-end' | 'center' | 'stretch';
54
- wrap?: 'wrap' | 'truncate' | 'none';
55
- color?: string;
56
- bold?: boolean;
57
- dim?: boolean;
58
- underline?: boolean;
59
- inverse?: boolean;
60
- strikethrough?: boolean;
61
- link?: string;
62
- backgroundColor?: string;
63
- border?: BorderStyle;
64
- borderColor?: string;
65
- borderTitle?: string;
66
- padding?: number;
67
- paddingX?: number;
68
- paddingY?: number;
69
- paddingTop?: number;
70
- paddingRight?: number;
71
- paddingBottom?: number;
72
- paddingLeft?: number;
73
- margin?: number;
74
- marginX?: number;
75
- marginY?: number;
76
- marginTop?: number;
77
- marginRight?: number;
78
- marginBottom?: number;
79
- marginLeft?: number;
80
- gap?: number;
81
- rowGap?: number;
82
- columnGap?: number;
83
- flexGrow?: number;
84
- flexShrink?: number;
85
- flexBasis?: number | 'auto' | `${number}%`;
86
- flexWrap?: 'nowrap' | 'wrap' | 'wrap-reverse';
87
- /** Cross-axis distribution of wrap lines. Only effective when flexWrap is 'wrap' or 'wrap-reverse'
88
- * AND the parent has extra cross-axis space. Default 'flex-start'. */
89
- alignContent?: 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around' | 'space-evenly' | 'stretch';
90
- /** Minimum cell size — Yoga prevents the box from shrinking below this.
91
- * Accepts a number (cells) or a percent string (e.g. '50%'). Undefined = no minimum. */
92
- minWidth?: number | `${number}%`;
93
- maxWidth?: number | `${number}%`;
94
- minHeight?: number | `${number}%`;
95
- maxHeight?: number | `${number}%`;
96
- /** Width / height ratio. Yoga derives the missing dimension from the constrained one.
97
- * CSS convention: `aspectRatio: 2` = twice as wide as tall; `0.5` = twice as tall as wide; `1` = square. */
98
- aspectRatio?: number;
99
- /** 'none' removes this box and all descendants from layout (siblings don't reserve space for it,
100
- * and paint skips the subtree). Default 'flex'. Useful for conditional UI without unmounting. */
101
- display?: 'flex' | 'none';
102
- /** Fires after layout with this box's computed rect. Use to read allocated dimensions
103
- * for responsive rendering (e.g. paginating an article reader). **Diff before setState** —
104
- * this fires on EVERY paint, and unconditionally calling setState with a new object
105
- * will infinite-loop. Pattern:
106
- * onLayout={(r) => { if (!size || size.width !== r.width || size.height !== r.height) setSize(r); }} */
107
- onLayout?: (rect: Rect) => void;
108
- /** Stacking order within the same paint pass. Higher values paint on top.
109
- * Default 0. Tree order is the tiebreaker. Does NOT cross pass boundaries:
110
- * absolutes always overlay stack-flow regardless of zIndex. */
111
- zIndex?: number;
112
- /** Clip descendants to this box's content rect. Default 'visible' (no clipping).
113
- * 'hidden' clips ALL descendant writes including their backgrounds and borders.
114
- * Does NOT clip this box's own background or border (those are this box's own area). */
115
- overflow?: 'visible' | 'hidden';
116
- }
117
- interface Instance {
118
- type: 'box';
119
- props: BoxProps;
120
- yogaNode: YogaNode;
121
- children: Array<Instance | TextInstance>;
122
- }
123
- interface TextInstance {
124
- type: 'text';
125
- text: string;
126
- parent?: Instance;
127
- }
128
- /**
129
- * Adapter-facing root container: a list of top-level Instances plus the loaded
130
- * Yoga module. Each framework adapter (React reconciler, Vue, …) builds one of
131
- * these and passes it to `computeLayout` + `paint`. Lives in host so layout /
132
- * paint (in core) can depend on it without pulling in any adapter code.
133
- */
134
- interface Container {
135
- children: Instance[];
136
- Yoga: Yoga;
137
- }
138
- declare function createInstance(type: HostType, props: BoxProps, Yoga: Yoga): Instance;
139
- declare function createTextInstance(text: string, _Yoga: Yoga): TextInstance;
140
- declare function applyProps(inst: Instance, props: BoxProps, _Yoga: Yoga): void;
141
- declare function measureText(text: string): {
142
- width: number;
143
- height: number;
144
- };
145
- declare function ownText(inst: Instance): string;
146
- declare function refreshMeasure(inst: Instance, _Yoga: Yoga): void;
147
- declare function appendChild(parent: Instance, child: Instance | TextInstance, Yoga: Yoga): void;
148
- declare function removeChild(parent: Instance, child: Instance | TextInstance, Yoga: Yoga): void;
149
- declare function insertBefore(parent: Instance, child: Instance | TextInstance, before: Instance | TextInstance, Yoga: Yoga): void;
150
-
151
- export { BORDER_CHARS as B, type Container as C, DEFAULT_BORDER_STYLE as D, GRID_CHARS as G, type HostType as H, type Instance as I, type Rect as R, type TextInstance as T, type Yoga as Y, type BorderChars as a, type BorderStyle as b, type BoxProps as c, type GridChars as d, type YogaNode as e, appendChild as f, applyProps as g, computeLayout as h, createInstance as i, createTextInstance as j, getYoga as k, insertBefore as l, layoutOf as m, measureText as n, ownText as o, removeChild as p, refreshMeasure as r };