tinky 0.1.0 → 1.1.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.ja-JP.md +2 -0
- package/README.md +2 -0
- package/README.zh-CN.md +2 -0
- package/lib/components/App.js +6 -6
- package/lib/components/Box.d.ts +2 -2
- package/lib/components/Box.js +2 -2
- package/lib/components/Static.d.ts +1 -1
- package/lib/components/Text.d.ts +1 -1
- package/lib/components/Text.js +3 -3
- package/lib/components/Transform.js +1 -1
- package/lib/contexts/AccessibilityContext.d.ts +30 -0
- package/lib/contexts/AccessibilityContext.js +25 -0
- package/lib/contexts/BackgroundContext.d.ts +25 -0
- package/lib/{components → contexts}/BackgroundContext.js +4 -0
- package/lib/{components → contexts}/FocusContext.d.ts +13 -2
- package/lib/{dom.d.ts → core/dom.d.ts} +28 -2
- package/lib/{dom.js → core/dom.js} +3 -3
- package/lib/{log-update.js → core/log-update.js} +1 -1
- package/lib/{output.d.ts → core/output.d.ts} +7 -15
- package/lib/{output.js → core/output.js} +3 -3
- package/lib/{reconciler.js → core/reconciler.js} +12 -3
- package/lib/{render-border.js → core/render-border.js} +1 -1
- package/lib/{render-node-to-output.js → core/render-node-to-output.js} +4 -4
- package/lib/{render.d.ts → core/render.d.ts} +4 -2
- package/lib/{styles.d.ts → core/styles.d.ts} +1 -1
- package/lib/{styles.js → core/styles.js} +1 -1
- package/lib/{taffy-node.d.ts → core/taffy-node.d.ts} +5 -0
- package/lib/{taffy-node.js → core/taffy-node.js} +5 -0
- package/lib/{tinky.d.ts → core/tinky.d.ts} +18 -0
- package/lib/{tinky.js → core/tinky.js} +30 -18
- package/lib/hooks/use-app.d.ts +1 -1
- package/lib/hooks/use-app.js +2 -2
- package/lib/hooks/use-focus-manager.d.ts +4 -5
- package/lib/hooks/use-focus-manager.js +1 -1
- package/lib/hooks/use-focus.d.ts +4 -5
- package/lib/hooks/use-focus.js +1 -1
- package/lib/hooks/use-input.d.ts +3 -4
- package/lib/hooks/use-input.js +2 -2
- package/lib/hooks/use-is-screen-reader-enabled.js +1 -1
- package/lib/hooks/use-stderr.js +1 -1
- package/lib/hooks/use-stdin.js +1 -1
- package/lib/hooks/use-stdout.d.ts +17 -1
- package/lib/hooks/use-stdout.js +6 -1
- package/lib/index.d.ts +15 -11
- package/lib/index.js +9 -9
- package/lib/utils/check-ci.d.ts +10 -0
- package/lib/utils/check-ci.js +21 -0
- package/lib/utils/cli-cursor.d.ts +20 -0
- package/lib/utils/cli-cursor.js +35 -0
- package/lib/utils/dimension.d.ts +9 -0
- package/lib/utils/dimension.js +1 -0
- package/lib/utils/measure-element.d.ts +9 -0
- package/lib/{measure-text.d.ts → utils/measure-text.d.ts} +2 -6
- package/lib/{parse-keypress.d.ts → utils/parse-keypress.d.ts} +11 -0
- package/lib/utils/patch-console.d.ts +34 -0
- package/lib/utils/patch-console.js +83 -0
- package/lib/{render-background.d.ts → utils/render-background.d.ts} +2 -2
- package/lib/utils/signal-exit.d.ts +15 -0
- package/lib/utils/signal-exit.js +62 -0
- package/lib/{squash-text-nodes.d.ts → utils/squash-text-nodes.d.ts} +1 -1
- package/lib/{wrap-text.d.ts → utils/wrap-text.d.ts} +1 -1
- package/package.json +24 -10
- package/lib/components/AccessibilityContext.d.ts +0 -9
- package/lib/components/AccessibilityContext.js +0 -10
- package/lib/components/BackgroundContext.d.ts +0 -10
- package/lib/measure-element.d.ts +0 -19
- package/lib/signal-exit.d.ts +0 -11
- package/lib/signal-exit.js +0 -24
- /package/lib/{components → contexts}/AppContext.d.ts +0 -0
- /package/lib/{components → contexts}/AppContext.js +0 -0
- /package/lib/{components → contexts}/FocusContext.js +0 -0
- /package/lib/{components → contexts}/StderrContext.d.ts +0 -0
- /package/lib/{components → contexts}/StderrContext.js +0 -0
- /package/lib/{components → contexts}/StdinContext.d.ts +0 -0
- /package/lib/{components → contexts}/StdinContext.js +0 -0
- /package/lib/{components → contexts}/StdoutContext.d.ts +0 -0
- /package/lib/{components → contexts}/StdoutContext.js +0 -0
- /package/lib/{devtools-window-polyfill.d.ts → core/devtools-window-polyfill.d.ts} +0 -0
- /package/lib/{devtools-window-polyfill.js → core/devtools-window-polyfill.js} +0 -0
- /package/lib/{devtools.d.ts → core/devtools.d.ts} +0 -0
- /package/lib/{devtools.js → core/devtools.js} +0 -0
- /package/lib/{instances.d.ts → core/instances.d.ts} +0 -0
- /package/lib/{instances.js → core/instances.js} +0 -0
- /package/lib/{log-update.d.ts → core/log-update.d.ts} +0 -0
- /package/lib/{reconciler.d.ts → core/reconciler.d.ts} +0 -0
- /package/lib/{render-border.d.ts → core/render-border.d.ts} +0 -0
- /package/lib/{render-node-to-output.d.ts → core/render-node-to-output.d.ts} +0 -0
- /package/lib/{render.js → core/render.js} +0 -0
- /package/lib/{renderer.d.ts → core/renderer.d.ts} +0 -0
- /package/lib/{renderer.js → core/renderer.js} +0 -0
- /package/lib/{colorize.d.ts → utils/colorize.d.ts} +0 -0
- /package/lib/{colorize.js → utils/colorize.js} +0 -0
- /package/lib/{get-max-width.d.ts → utils/get-max-width.d.ts} +0 -0
- /package/lib/{get-max-width.js → utils/get-max-width.js} +0 -0
- /package/lib/{measure-element.js → utils/measure-element.js} +0 -0
- /package/lib/{measure-text.js → utils/measure-text.js} +0 -0
- /package/lib/{parse-keypress.js → utils/parse-keypress.js} +0 -0
- /package/lib/{render-background.js → utils/render-background.js} +0 -0
- /package/lib/{squash-text-nodes.js → utils/squash-text-nodes.js} +0 -0
- /package/lib/{wrap-text.js → utils/wrap-text.js} +0 -0
package/README.ja-JP.md
CHANGED
package/README.md
CHANGED
package/README.zh-CN.md
CHANGED
package/lib/components/App.js
CHANGED
|
@@ -2,12 +2,12 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { EventEmitter } from "node:events";
|
|
3
3
|
import process from "node:process";
|
|
4
4
|
import { PureComponent } from "react";
|
|
5
|
-
import cliCursor from "cli-cursor";
|
|
6
|
-
import { AppContext } from "
|
|
7
|
-
import { StdinContext } from "
|
|
8
|
-
import { StdoutContext } from "
|
|
9
|
-
import { StderrContext } from "
|
|
10
|
-
import { FocusContext } from "
|
|
5
|
+
import * as cliCursor from "../utils/cli-cursor.js";
|
|
6
|
+
import { AppContext } from "../contexts/AppContext.js";
|
|
7
|
+
import { StdinContext } from "../contexts/StdinContext.js";
|
|
8
|
+
import { StdoutContext } from "../contexts/StdoutContext.js";
|
|
9
|
+
import { StderrContext } from "../contexts/StderrContext.js";
|
|
10
|
+
import { FocusContext } from "../contexts/FocusContext.js";
|
|
11
11
|
import { ErrorOverview } from "./ErrorOverview.js";
|
|
12
12
|
const tab = "\t";
|
|
13
13
|
const shiftTab = "\u001B[Z";
|
package/lib/components/Box.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type Except } from "type-fest";
|
|
2
|
-
import { type Styles } from "../styles.js";
|
|
3
|
-
import { type DOMElement } from "../dom.js";
|
|
2
|
+
import { type Styles } from "../core/styles.js";
|
|
3
|
+
import { type DOMElement } from "../core/dom.js";
|
|
4
4
|
/**
|
|
5
5
|
* Props for the Box component.
|
|
6
6
|
*/
|
package/lib/components/Box.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef, useContext } from "react";
|
|
3
|
-
import { AccessibilityContext } from "
|
|
4
|
-
import { backgroundContext } from "
|
|
3
|
+
import { AccessibilityContext } from "../contexts/AccessibilityContext.js";
|
|
4
|
+
import { backgroundContext } from "../contexts/BackgroundContext.js";
|
|
5
5
|
/**
|
|
6
6
|
* `<Box>` is an essential Tinky component to build your layout. It's like
|
|
7
7
|
* `<div style="display: flex">` in the browser.
|
package/lib/components/Text.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
2
|
import { type ForegroundColorName } from "chalk";
|
|
3
3
|
import { type LiteralUnion } from "type-fest";
|
|
4
|
-
import { type Styles } from "../styles.js";
|
|
4
|
+
import { type Styles } from "../core/styles.js";
|
|
5
5
|
/**
|
|
6
6
|
* Props for the Text component.
|
|
7
7
|
*/
|
package/lib/components/Text.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useContext } from "react";
|
|
3
3
|
import chalk from "chalk";
|
|
4
|
-
import { colorize } from "../colorize.js";
|
|
5
|
-
import { AccessibilityContext } from "
|
|
6
|
-
import { backgroundContext } from "
|
|
4
|
+
import { colorize } from "../utils/colorize.js";
|
|
5
|
+
import { AccessibilityContext } from "../contexts/AccessibilityContext.js";
|
|
6
|
+
import { backgroundContext } from "../contexts/BackgroundContext.js";
|
|
7
7
|
/**
|
|
8
8
|
* This component can display text and change its style to make it bold,
|
|
9
9
|
* underlined, italic, or strikethrough.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useContext } from "react";
|
|
3
|
-
import { AccessibilityContext } from "
|
|
3
|
+
import { AccessibilityContext } from "../contexts/AccessibilityContext.js";
|
|
4
4
|
/**
|
|
5
5
|
* Transform a string representation of React components before they're written
|
|
6
6
|
* to output. For example, you might want to apply a gradient to text, add a
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Value type for the AccessibilityContext.
|
|
3
|
+
*/
|
|
4
|
+
export interface AccessibilityContextValue {
|
|
5
|
+
/**
|
|
6
|
+
* Whether the screen reader is enabled.
|
|
7
|
+
*
|
|
8
|
+
* @defaultValue false
|
|
9
|
+
*/
|
|
10
|
+
readonly isScreenReaderEnabled: boolean;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Context to manage accessibility settings, specifically screen reader.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```tsx
|
|
17
|
+
* import { useIsScreenReaderEnabled } from 'tinky';
|
|
18
|
+
*
|
|
19
|
+
* const Component = () => {
|
|
20
|
+
* const isScreenReaderEnabled = useIsScreenReaderEnabled();
|
|
21
|
+
*
|
|
22
|
+
* if (isScreenReaderEnabled) {
|
|
23
|
+
* return <Text>Screen reader friendly output</Text>;
|
|
24
|
+
* }
|
|
25
|
+
*
|
|
26
|
+
* return <Text>Regular output</Text>;
|
|
27
|
+
* };
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export declare const AccessibilityContext: import("react").Context<AccessibilityContextValue>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { createContext } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Context to manage accessibility settings, specifically screen reader.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```tsx
|
|
7
|
+
* import { useIsScreenReaderEnabled } from 'tinky';
|
|
8
|
+
*
|
|
9
|
+
* const Component = () => {
|
|
10
|
+
* const isScreenReaderEnabled = useIsScreenReaderEnabled();
|
|
11
|
+
*
|
|
12
|
+
* if (isScreenReaderEnabled) {
|
|
13
|
+
* return <Text>Screen reader friendly output</Text>;
|
|
14
|
+
* }
|
|
15
|
+
*
|
|
16
|
+
* return <Text>Regular output</Text>;
|
|
17
|
+
* };
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export const AccessibilityContext = createContext({
|
|
21
|
+
/**
|
|
22
|
+
* Whether the screen reader is enabled.
|
|
23
|
+
*/
|
|
24
|
+
isScreenReaderEnabled: false,
|
|
25
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type LiteralUnion } from "type-fest";
|
|
2
|
+
import { type ForegroundColorName } from "ansi-styles";
|
|
3
|
+
/**
|
|
4
|
+
* Union type for background colors.
|
|
5
|
+
*
|
|
6
|
+
* Accepts any named color from `ansi-styles`, hex colors, RGB colors,
|
|
7
|
+
* or ANSI 256 color codes.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```tsx
|
|
11
|
+
* backgroundColor="red" // Named color
|
|
12
|
+
* backgroundColor="#ff6600" // Hex color
|
|
13
|
+
* backgroundColor="rgb(255, 102, 0)" // RGB color
|
|
14
|
+
* backgroundColor="ansi256:208" // ANSI 256 color
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export type BackgroundColor = LiteralUnion<ForegroundColorName, string>;
|
|
18
|
+
/**
|
|
19
|
+
* Context to pass the background color down the component tree.
|
|
20
|
+
*
|
|
21
|
+
* Allows nested components to inherit the background color from parents.
|
|
22
|
+
*
|
|
23
|
+
* @defaultValue undefined
|
|
24
|
+
*/
|
|
25
|
+
export declare const backgroundContext: import("react").Context<BackgroundColor | undefined>;
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { createContext } from "react";
|
|
2
2
|
/**
|
|
3
3
|
* Context to pass the background color down the component tree.
|
|
4
|
+
*
|
|
5
|
+
* Allows nested components to inherit the background color from parents.
|
|
6
|
+
*
|
|
7
|
+
* @defaultValue undefined
|
|
4
8
|
*/
|
|
5
9
|
export const backgroundContext = createContext(undefined);
|
|
@@ -8,20 +8,29 @@ export interface FocusProps {
|
|
|
8
8
|
readonly activeId?: string;
|
|
9
9
|
/**
|
|
10
10
|
* Register a new focusable component.
|
|
11
|
+
*
|
|
12
|
+
* @param id - Unique identifier for the focusable component.
|
|
13
|
+
* @param options.autoFocus - Auto-focus the component when registered.
|
|
11
14
|
*/
|
|
12
15
|
readonly add: (id: string, options: {
|
|
13
16
|
autoFocus: boolean;
|
|
14
17
|
}) => void;
|
|
15
18
|
/**
|
|
16
19
|
* Unregister a focusable component.
|
|
20
|
+
*
|
|
21
|
+
* @param id - Unique identifier of the component to unregister.
|
|
17
22
|
*/
|
|
18
23
|
readonly remove: (id: string) => void;
|
|
19
24
|
/**
|
|
20
|
-
* Mark a component as active.
|
|
25
|
+
* Mark a component as active (focused).
|
|
26
|
+
*
|
|
27
|
+
* @param id - Unique identifier of the component to activate.
|
|
21
28
|
*/
|
|
22
29
|
readonly activate: (id: string) => void;
|
|
23
30
|
/**
|
|
24
|
-
* Mark a component as inactive.
|
|
31
|
+
* Mark a component as inactive (unfocused).
|
|
32
|
+
*
|
|
33
|
+
* @param id - Unique identifier of the component to deactivate.
|
|
25
34
|
*/
|
|
26
35
|
readonly deactivate: (id: string) => void;
|
|
27
36
|
/**
|
|
@@ -42,6 +51,8 @@ export interface FocusProps {
|
|
|
42
51
|
readonly focusPrevious: () => void;
|
|
43
52
|
/**
|
|
44
53
|
* Focus a specific component by ID.
|
|
54
|
+
*
|
|
55
|
+
* @param id - Unique identifier of the component to focus.
|
|
45
56
|
*/
|
|
46
57
|
readonly focus: (id: string) => void;
|
|
47
58
|
}
|
|
@@ -4,10 +4,14 @@ import { TaffyNode } from "./taffy-node.js";
|
|
|
4
4
|
/**
|
|
5
5
|
* Interface representing a node in the Tinky tree.
|
|
6
6
|
*/
|
|
7
|
-
interface TinkyNode {
|
|
7
|
+
export interface TinkyNode {
|
|
8
|
+
/** Parent DOM element in the tree. */
|
|
8
9
|
parentNode: DOMElement | undefined;
|
|
10
|
+
/** Taffy layout node for computing dimensions. */
|
|
9
11
|
taffyNode?: TaffyNode;
|
|
12
|
+
/** Whether this node is inside a Static component. */
|
|
10
13
|
internal_static?: boolean;
|
|
14
|
+
/** Styles applied to this node. */
|
|
11
15
|
style: Styles;
|
|
12
16
|
}
|
|
13
17
|
/**
|
|
@@ -26,35 +30,58 @@ export type NodeNames = ElementNames | TextName;
|
|
|
26
30
|
* Interface representing a DOM element in Tinky.
|
|
27
31
|
*/
|
|
28
32
|
export type DOMElement = {
|
|
33
|
+
/** Name of the element type. */
|
|
29
34
|
nodeName: ElementNames;
|
|
35
|
+
/** Key-value pairs of element attributes. */
|
|
30
36
|
attributes: Record<string, DOMNodeAttribute>;
|
|
37
|
+
/** Array of child nodes. */
|
|
31
38
|
childNodes: DOMNode[];
|
|
39
|
+
/** Function to transform the output of this element. */
|
|
32
40
|
internal_transform?: OutputTransformer;
|
|
41
|
+
/** Accessibility attributes for screen readers. */
|
|
33
42
|
internal_accessibility?: {
|
|
43
|
+
/** ARIA role for the element. */
|
|
34
44
|
role?: "button" | "checkbox" | "combobox" | "list" | "listbox" | "listitem" | "menu" | "menuitem" | "option" | "progressbar" | "radio" | "radiogroup" | "tab" | "tablist" | "table" | "textbox" | "timer" | "toolbar";
|
|
45
|
+
/** ARIA state values for the element. */
|
|
35
46
|
state?: {
|
|
47
|
+
/** Whether the element is busy. */
|
|
36
48
|
busy?: boolean;
|
|
49
|
+
/** Whether the element is checked. */
|
|
37
50
|
checked?: boolean;
|
|
51
|
+
/** Whether the element is disabled. */
|
|
38
52
|
disabled?: boolean;
|
|
53
|
+
/** Whether the element is expanded. */
|
|
39
54
|
expanded?: boolean;
|
|
55
|
+
/** Whether the element accepts multiline input. */
|
|
40
56
|
multiline?: boolean;
|
|
57
|
+
/** Whether multiple items can be selected. */
|
|
41
58
|
multiselectable?: boolean;
|
|
59
|
+
/** Whether the element is read-only. */
|
|
42
60
|
readonly?: boolean;
|
|
61
|
+
/** Whether the element is required. */
|
|
43
62
|
required?: boolean;
|
|
63
|
+
/** Whether the element is selected. */
|
|
44
64
|
selected?: boolean;
|
|
45
65
|
};
|
|
46
66
|
};
|
|
67
|
+
/** Whether static nodes need to be re-rendered. */
|
|
47
68
|
isStaticDirty?: boolean;
|
|
69
|
+
/** Reference to the Static component node. */
|
|
48
70
|
staticNode?: DOMElement;
|
|
71
|
+
/** Callback to compute layout before rendering. */
|
|
49
72
|
onComputeLayout?: () => void;
|
|
73
|
+
/** Callback to trigger a render. */
|
|
50
74
|
onRender?: () => void;
|
|
75
|
+
/** Callback to trigger an immediate render. */
|
|
51
76
|
onImmediateRender?: () => void;
|
|
52
77
|
} & TinkyNode;
|
|
53
78
|
/**
|
|
54
79
|
* Interface representing a text node in Tinky.
|
|
55
80
|
*/
|
|
56
81
|
export type TextNode = {
|
|
82
|
+
/** Text node identifier. */
|
|
57
83
|
nodeName: TextName;
|
|
84
|
+
/** Text content of the node. */
|
|
58
85
|
nodeValue: string;
|
|
59
86
|
} & TinkyNode;
|
|
60
87
|
/**
|
|
@@ -127,4 +154,3 @@ export declare const createTextNode: (text: string) => TextNode;
|
|
|
127
154
|
* @param text - The new text value.
|
|
128
155
|
*/
|
|
129
156
|
export declare const setTextNodeValue: (node: TextNode, text: string) => void;
|
|
130
|
-
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import stringWidth from "string-width";
|
|
2
|
-
import { measureText } from "
|
|
3
|
-
import { wrapText } from "
|
|
4
|
-
import { squashTextNodes } from "
|
|
2
|
+
import { measureText } from "../utils/measure-text.js";
|
|
3
|
+
import { wrapText } from "../utils/wrap-text.js";
|
|
4
|
+
import { squashTextNodes } from "../utils/squash-text-nodes.js";
|
|
5
5
|
import { TaffyNode } from "./taffy-node.js";
|
|
6
6
|
/**
|
|
7
7
|
* Creates a new DOM element.
|
|
@@ -1,24 +1,16 @@
|
|
|
1
1
|
import { type OutputTransformer } from "./render-node-to-output.js";
|
|
2
|
-
|
|
3
|
-
* Options for creating an Output instance.
|
|
4
|
-
*/
|
|
5
|
-
interface Options {
|
|
6
|
-
/**
|
|
7
|
-
* Width of the output area.
|
|
8
|
-
*/
|
|
9
|
-
width: number;
|
|
10
|
-
/**
|
|
11
|
-
* Height of the output area.
|
|
12
|
-
*/
|
|
13
|
-
height: number;
|
|
14
|
-
}
|
|
2
|
+
import { type Dimension } from "../utils/dimension.js";
|
|
15
3
|
/**
|
|
16
4
|
* Represents a clipping rectangle.
|
|
17
5
|
*/
|
|
18
6
|
interface Clip {
|
|
7
|
+
/** Left boundary (undefined for no limit). */
|
|
19
8
|
x1: number | undefined;
|
|
9
|
+
/** Right boundary (undefined for no limit). */
|
|
20
10
|
x2: number | undefined;
|
|
11
|
+
/** Top boundary (undefined for no limit). */
|
|
21
12
|
y1: number | undefined;
|
|
13
|
+
/** Bottom boundary (undefined for no limit). */
|
|
22
14
|
y2: number | undefined;
|
|
23
15
|
}
|
|
24
16
|
/**
|
|
@@ -36,9 +28,9 @@ export declare class Output {
|
|
|
36
28
|
/**
|
|
37
29
|
* Creates a new Output instance.
|
|
38
30
|
*
|
|
39
|
-
* @param
|
|
31
|
+
* @param dimension - Dimensions containing width and height.
|
|
40
32
|
*/
|
|
41
|
-
constructor(
|
|
33
|
+
constructor(dimension: Dimension);
|
|
42
34
|
/**
|
|
43
35
|
* Writes text to the output at a specified position.
|
|
44
36
|
*
|
|
@@ -17,10 +17,10 @@ export class Output {
|
|
|
17
17
|
/**
|
|
18
18
|
* Creates a new Output instance.
|
|
19
19
|
*
|
|
20
|
-
* @param
|
|
20
|
+
* @param dimension - Dimensions containing width and height.
|
|
21
21
|
*/
|
|
22
|
-
constructor(
|
|
23
|
-
const { width, height } =
|
|
22
|
+
constructor(dimension) {
|
|
23
|
+
const { width, height } = dimension;
|
|
24
24
|
this.width = width;
|
|
25
25
|
this.height = height;
|
|
26
26
|
}
|
|
@@ -4,7 +4,7 @@ import { DefaultEventPriority, NoEventPriority, } from "react-reconciler/constan
|
|
|
4
4
|
import { Display } from "taffy-layout";
|
|
5
5
|
import { createContext } from "react";
|
|
6
6
|
import { createTextNode, appendChildNode, insertBeforeNode, removeChildNode, setStyle, setTextNodeValue, createNode, setAttribute, } from "./dom.js";
|
|
7
|
-
import {
|
|
7
|
+
import { applyStyles } from "./styles.js";
|
|
8
8
|
// We need to conditionally perform devtools connection to avoid
|
|
9
9
|
// accidentally breaking other third-party code.
|
|
10
10
|
if (process.env["DEV"] === "true") {
|
|
@@ -54,10 +54,19 @@ const diff = (before, after) => {
|
|
|
54
54
|
}
|
|
55
55
|
return isChanged ? changed : undefined;
|
|
56
56
|
};
|
|
57
|
+
/**
|
|
58
|
+
* Cleans up a Taffy node by freeing its resources.
|
|
59
|
+
*
|
|
60
|
+
* @param node - The Taffy node to cleanup.
|
|
61
|
+
*/
|
|
57
62
|
const cleanupTaffyNode = (node) => {
|
|
58
63
|
node?.free();
|
|
59
64
|
};
|
|
60
65
|
let currentUpdatePriority = NoEventPriority;
|
|
66
|
+
/**
|
|
67
|
+
* Reference to the current root DOM element during rendering.
|
|
68
|
+
* Used to track static node state across renders.
|
|
69
|
+
*/
|
|
61
70
|
let currentRootNode;
|
|
62
71
|
/**
|
|
63
72
|
* React reconciler implementation for Tinky.
|
|
@@ -113,7 +122,7 @@ export const reconciler = createReconciler({
|
|
|
113
122
|
if (key === "style") {
|
|
114
123
|
setStyle(node, value);
|
|
115
124
|
if (node.taffyNode) {
|
|
116
|
-
|
|
125
|
+
applyStyles(node.taffyNode, value);
|
|
117
126
|
}
|
|
118
127
|
continue;
|
|
119
128
|
}
|
|
@@ -224,7 +233,7 @@ export const reconciler = createReconciler({
|
|
|
224
233
|
}
|
|
225
234
|
}
|
|
226
235
|
if (style && node.taffyNode) {
|
|
227
|
-
|
|
236
|
+
applyStyles(node.taffyNode, style);
|
|
228
237
|
}
|
|
229
238
|
},
|
|
230
239
|
commitTextUpdate(node, _oldText, newText) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import cliBoxes from "cli-boxes";
|
|
2
2
|
import chalk from "chalk";
|
|
3
|
-
import { colorize } from "
|
|
3
|
+
import { colorize } from "../utils/colorize.js";
|
|
4
4
|
/**
|
|
5
5
|
* Renders the border for a DOM node.
|
|
6
6
|
* Calculates border dimensions and draws border characters with specified
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import widestLine from "widest-line";
|
|
2
2
|
import indentString from "indent-string";
|
|
3
3
|
import { Display } from "taffy-layout";
|
|
4
|
-
import { wrapText } from "
|
|
5
|
-
import { getMaxWidth } from "
|
|
6
|
-
import { squashTextNodes } from "
|
|
4
|
+
import { wrapText } from "../utils/wrap-text.js";
|
|
5
|
+
import { getMaxWidth } from "../utils/get-max-width.js";
|
|
6
|
+
import { squashTextNodes } from "../utils/squash-text-nodes.js";
|
|
7
7
|
import { renderBorder } from "./render-border.js";
|
|
8
|
-
import { renderBackground } from "
|
|
8
|
+
import { renderBackground } from "../utils/render-background.js";
|
|
9
9
|
/**
|
|
10
10
|
* Applies padding to text based on the layout of the first text node.
|
|
11
11
|
*
|
|
@@ -23,7 +23,8 @@ export interface RenderOptions {
|
|
|
23
23
|
*/
|
|
24
24
|
stderr?: NodeJS.WriteStream;
|
|
25
25
|
/**
|
|
26
|
-
* If true, each update will be rendered as separate output, without
|
|
26
|
+
* If true, each update will be rendered as separate output, without
|
|
27
|
+
* replacing.
|
|
27
28
|
*
|
|
28
29
|
* @defaultValue false
|
|
29
30
|
*/
|
|
@@ -63,7 +64,8 @@ export interface RenderOptions {
|
|
|
63
64
|
maxFps?: number;
|
|
64
65
|
/**
|
|
65
66
|
* Enable incremental rendering mode which only updates changed lines instead
|
|
66
|
-
* of redrawing the entire output. Reduces flickering and improves
|
|
67
|
+
* of redrawing the entire output. Reduces flickering and improves
|
|
68
|
+
* performance.
|
|
67
69
|
*
|
|
68
70
|
* @defaultValue false
|
|
69
71
|
*/
|
|
@@ -617,7 +617,7 @@ const applyGridStyles = (taffyStyle, style) => {
|
|
|
617
617
|
}
|
|
618
618
|
}
|
|
619
619
|
};
|
|
620
|
-
export const
|
|
620
|
+
export const applyStyles = (node, style = {}) => {
|
|
621
621
|
const taffyStyle = node.tree.getStyle(node.id);
|
|
622
622
|
applyPositionStyles(taffyStyle, style);
|
|
623
623
|
applyMarginStyles(taffyStyle, style);
|
|
@@ -35,5 +35,10 @@ export declare class TaffyNode {
|
|
|
35
35
|
* Necessary to prevent memory leaks as Taffy nodes aren't GC'd automatically.
|
|
36
36
|
*/
|
|
37
37
|
free(): void;
|
|
38
|
+
/**
|
|
39
|
+
* Recursively removes a node and all its descendants from the Taffy tree.
|
|
40
|
+
*
|
|
41
|
+
* @param id - The ID of the node to remove.
|
|
42
|
+
*/
|
|
38
43
|
private freeRecursive;
|
|
39
44
|
}
|
|
@@ -51,6 +51,11 @@ export class TaffyNode {
|
|
|
51
51
|
}
|
|
52
52
|
this.tree.remove(this.id);
|
|
53
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* Recursively removes a node and all its descendants from the Taffy tree.
|
|
56
|
+
*
|
|
57
|
+
* @param id - The ID of the node to remove.
|
|
58
|
+
*/
|
|
54
59
|
freeRecursive(id) {
|
|
55
60
|
for (const childId of this.tree.children(id)) {
|
|
56
61
|
this.freeRecursive(childId);
|
|
@@ -68,19 +68,33 @@ export interface Options {
|
|
|
68
68
|
* lifecycle, and terminal output.
|
|
69
69
|
*/
|
|
70
70
|
export declare class Tinky {
|
|
71
|
+
/** Configuration options for this instance. */
|
|
71
72
|
private readonly options;
|
|
73
|
+
/** Log update instance for output. */
|
|
72
74
|
private readonly log;
|
|
75
|
+
/** Throttled log update instance for output. */
|
|
73
76
|
private readonly throttledLog;
|
|
77
|
+
/** Whether screen reader support is enabled. */
|
|
74
78
|
private readonly isScreenReaderEnabled;
|
|
79
|
+
/** Whether the app has been unmounted. */
|
|
75
80
|
private isUnmounted;
|
|
81
|
+
/** Last output string that was rendered. */
|
|
76
82
|
private lastOutput;
|
|
83
|
+
/** Height of the last output in lines. */
|
|
77
84
|
private lastOutputHeight;
|
|
85
|
+
/** Width of the terminal at last render. */
|
|
78
86
|
private lastTerminalWidth;
|
|
87
|
+
/** React reconciler container. */
|
|
79
88
|
private readonly container;
|
|
89
|
+
/** Root DOM element for the React tree. */
|
|
80
90
|
private readonly rootNode;
|
|
91
|
+
/** Full static output for debug mode. */
|
|
81
92
|
private fullStaticOutput;
|
|
93
|
+
/** Promise that resolves when the app exits. */
|
|
82
94
|
private exitPromise?;
|
|
95
|
+
/** Function to restore console after patching. */
|
|
83
96
|
private restoreConsole?;
|
|
97
|
+
/** Function to unsubscribe from resize events. */
|
|
84
98
|
private readonly unsubscribeResize?;
|
|
85
99
|
/**
|
|
86
100
|
* Creates an instance of Tinky.
|
|
@@ -99,9 +113,13 @@ export declare class Tinky {
|
|
|
99
113
|
* Clears the screen when width decreases to prevent overlapping re-renders.
|
|
100
114
|
*/
|
|
101
115
|
resized: () => void;
|
|
116
|
+
/** Resolves the exit promise when the app unmounts. */
|
|
102
117
|
resolveExitPromise: () => void;
|
|
118
|
+
/** Rejects the exit promise with an error. */
|
|
103
119
|
rejectExitPromise: (reason?: Error) => void;
|
|
120
|
+
/** Unsubscribes from the exit event. */
|
|
104
121
|
unsubscribeExit: () => void;
|
|
122
|
+
/** Error that occurred during rendering, if any. */
|
|
105
123
|
renderError: Error | null;
|
|
106
124
|
/**
|
|
107
125
|
* Calculates the layout of the UI (TaffyLayout).
|