@effect-tui/core 0.1.0 → 0.1.4
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 +31 -11
- package/dist/ansi.d.ts +127 -32
- package/dist/ansi.d.ts.map +1 -1
- package/dist/ansi.js +159 -37
- package/dist/ansi.js.map +1 -1
- package/dist/colors.d.ts +139 -0
- package/dist/colors.d.ts.map +1 -0
- package/dist/colors.js +339 -0
- package/dist/colors.js.map +1 -0
- package/dist/index.d.ts +6 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -11
- package/dist/index.js.map +1 -1
- package/dist/keys.d.ts +21 -0
- package/dist/keys.d.ts.map +1 -1
- package/dist/keys.js +199 -58
- package/dist/keys.js.map +1 -1
- package/dist/layout/axis-helpers.d.ts +19 -0
- package/dist/layout/axis-helpers.d.ts.map +1 -0
- package/dist/layout/axis-helpers.js +19 -0
- package/dist/layout/axis-helpers.js.map +1 -0
- package/dist/output.d.ts +59 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +142 -0
- package/dist/output.js.map +1 -0
- package/dist/render/buffer.d.ts.map +1 -1
- package/dist/render/buffer.js +6 -25
- package/dist/render/buffer.js.map +1 -1
- package/dist/render/graphemes.d.ts +15 -0
- package/dist/render/graphemes.d.ts.map +1 -0
- package/dist/render/graphemes.js +28 -0
- package/dist/render/graphemes.js.map +1 -0
- package/dist/render/measure.d.ts +1 -0
- package/dist/render/measure.d.ts.map +1 -1
- package/dist/render/measure.js +14 -36
- package/dist/render/measure.js.map +1 -1
- package/dist/render/palette.d.ts.map +1 -1
- package/dist/render/palette.js +26 -1
- package/dist/render/palette.js.map +1 -1
- package/dist/render/segmenter.d.ts +8 -0
- package/dist/render/segmenter.d.ts.map +1 -0
- package/dist/render/segmenter.js +23 -0
- package/dist/render/segmenter.js.map +1 -0
- package/dist/render/surface.d.ts +6 -32
- package/dist/render/surface.d.ts.map +1 -1
- package/dist/render/surface.js +11 -80
- package/dist/render/surface.js.map +1 -1
- package/dist/runtime/backend_node.d.ts.map +1 -1
- package/dist/runtime/backend_node.js.map +1 -1
- package/dist/tailwind-colors.d.ts +291 -0
- package/dist/tailwind-colors.d.ts.map +1 -0
- package/dist/tailwind-colors.js +291 -0
- package/dist/tailwind-colors.js.map +1 -0
- package/dist/types.d.ts +15 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +55 -55
- package/src/ansi.ts +201 -73
- package/src/colors.ts +468 -0
- package/src/index.ts +28 -14
- package/src/keys.ts +467 -287
- package/src/layout/axis-helpers.ts +33 -0
- package/src/output.ts +175 -0
- package/src/render/buffer.ts +161 -184
- package/src/render/graphemes.ts +34 -0
- package/src/render/measure.ts +15 -38
- package/src/render/palette.ts +98 -77
- package/src/render/segmenter.ts +27 -0
- package/src/render/surface.ts +139 -225
- package/src/runtime/backend_node.ts +71 -71
- package/src/tailwind-colors.ts +295 -0
- package/src/types.ts +18 -0
- package/dist/anim.d.ts +0 -4
- package/dist/anim.d.ts.map +0 -1
- package/dist/anim.js +0 -5
- package/dist/anim.js.map +0 -1
- package/dist/layout/linearStack.d.ts +0 -17
- package/dist/layout/linearStack.d.ts.map +0 -1
- package/dist/layout/linearStack.js +0 -86
- package/dist/layout/linearStack.js.map +0 -1
- package/dist/motion-value.d.ts +0 -58
- package/dist/motion-value.d.ts.map +0 -1
- package/dist/motion-value.js +0 -250
- package/dist/motion-value.js.map +0 -1
- package/dist/present/display.d.ts +0 -58
- package/dist/present/display.d.ts.map +0 -1
- package/dist/present/display.js +0 -168
- package/dist/present/display.js.map +0 -1
- package/dist/present/writers/fullscreen.d.ts +0 -19
- package/dist/present/writers/fullscreen.d.ts.map +0 -1
- package/dist/present/writers/fullscreen.js +0 -55
- package/dist/present/writers/fullscreen.js.map +0 -1
- package/dist/present/writers/inline.d.ts +0 -20
- package/dist/present/writers/inline.d.ts.map +0 -1
- package/dist/present/writers/inline.js +0 -92
- package/dist/present/writers/inline.js.map +0 -1
- package/dist/render/color-utils.d.ts +0 -18
- package/dist/render/color-utils.d.ts.map +0 -1
- package/dist/render/color-utils.js +0 -58
- package/dist/render/color-utils.js.map +0 -1
- package/dist/render/diff.d.ts +0 -30
- package/dist/render/diff.d.ts.map +0 -1
- package/dist/render/diff.js +0 -83
- package/dist/render/diff.js.map +0 -1
- package/dist/spring-physics.d.ts +0 -36
- package/dist/spring-physics.d.ts.map +0 -1
- package/dist/spring-physics.js +0 -113
- package/dist/spring-physics.js.map +0 -1
- package/dist/spring.d.ts +0 -73
- package/dist/spring.d.ts.map +0 -1
- package/dist/spring.js +0 -136
- package/dist/spring.js.map +0 -1
- package/dist/ui/containers/canvas.d.ts +0 -13
- package/dist/ui/containers/canvas.d.ts.map +0 -1
- package/dist/ui/containers/canvas.js +0 -16
- package/dist/ui/containers/canvas.js.map +0 -1
- package/dist/ui/containers/geometry-reader.d.ts +0 -17
- package/dist/ui/containers/geometry-reader.d.ts.map +0 -1
- package/dist/ui/containers/geometry-reader.js +0 -24
- package/dist/ui/containers/geometry-reader.js.map +0 -1
- package/dist/ui/containers/hstack.d.ts +0 -12
- package/dist/ui/containers/hstack.d.ts.map +0 -1
- package/dist/ui/containers/hstack.js +0 -28
- package/dist/ui/containers/hstack.js.map +0 -1
- package/dist/ui/containers/scroll.d.ts +0 -28
- package/dist/ui/containers/scroll.d.ts.map +0 -1
- package/dist/ui/containers/scroll.js +0 -97
- package/dist/ui/containers/scroll.js.map +0 -1
- package/dist/ui/containers/shared.d.ts +0 -12
- package/dist/ui/containers/shared.d.ts.map +0 -1
- package/dist/ui/containers/shared.js +0 -19
- package/dist/ui/containers/shared.js.map +0 -1
- package/dist/ui/containers/vstack.d.ts +0 -12
- package/dist/ui/containers/vstack.d.ts.map +0 -1
- package/dist/ui/containers/vstack.js +0 -28
- package/dist/ui/containers/vstack.js.map +0 -1
- package/dist/ui/containers/zstack.d.ts +0 -14
- package/dist/ui/containers/zstack.d.ts.map +0 -1
- package/dist/ui/containers/zstack.js +0 -36
- package/dist/ui/containers/zstack.js.map +0 -1
- package/dist/ui/core/geometry-store.d.ts +0 -22
- package/dist/ui/core/geometry-store.d.ts.map +0 -1
- package/dist/ui/core/geometry-store.js +0 -29
- package/dist/ui/core/geometry-store.js.map +0 -1
- package/dist/ui/core/geometry.d.ts +0 -34
- package/dist/ui/core/geometry.d.ts.map +0 -1
- package/dist/ui/core/geometry.js +0 -14
- package/dist/ui/core/geometry.js.map +0 -1
- package/dist/ui/core/view.d.ts +0 -25
- package/dist/ui/core/view.d.ts.map +0 -1
- package/dist/ui/core/view.js +0 -34
- package/dist/ui/core/view.js.map +0 -1
- package/dist/ui/index.d.ts +0 -44
- package/dist/ui/index.d.ts.map +0 -1
- package/dist/ui/index.js +0 -39
- package/dist/ui/index.js.map +0 -1
- package/dist/ui/inlinetext.d.ts +0 -24
- package/dist/ui/inlinetext.d.ts.map +0 -1
- package/dist/ui/inlinetext.js +0 -131
- package/dist/ui/inlinetext.js.map +0 -1
- package/dist/ui/install.d.ts +0 -22
- package/dist/ui/install.d.ts.map +0 -1
- package/dist/ui/install.js +0 -66
- package/dist/ui/install.js.map +0 -1
- package/dist/ui/markdown.d.ts +0 -40
- package/dist/ui/markdown.d.ts.map +0 -1
- package/dist/ui/markdown.js +0 -351
- package/dist/ui/markdown.js.map +0 -1
- package/dist/ui/modifiers/border.d.ts +0 -33
- package/dist/ui/modifiers/border.d.ts.map +0 -1
- package/dist/ui/modifiers/border.js +0 -82
- package/dist/ui/modifiers/border.js.map +0 -1
- package/dist/ui/modifiers/fill.d.ts +0 -14
- package/dist/ui/modifiers/fill.d.ts.map +0 -1
- package/dist/ui/modifiers/fill.js +0 -25
- package/dist/ui/modifiers/fill.js.map +0 -1
- package/dist/ui/modifiers/frame.d.ts +0 -23
- package/dist/ui/modifiers/frame.d.ts.map +0 -1
- package/dist/ui/modifiers/frame.js +0 -54
- package/dist/ui/modifiers/frame.js.map +0 -1
- package/dist/ui/modifiers/offset.d.ts +0 -15
- package/dist/ui/modifiers/offset.d.ts.map +0 -1
- package/dist/ui/modifiers/offset.js +0 -21
- package/dist/ui/modifiers/offset.js.map +0 -1
- package/dist/ui/modifiers/opacity.d.ts +0 -15
- package/dist/ui/modifiers/opacity.d.ts.map +0 -1
- package/dist/ui/modifiers/opacity.js +0 -95
- package/dist/ui/modifiers/opacity.js.map +0 -1
- package/dist/ui/modifiers/padding.d.ts +0 -20
- package/dist/ui/modifiers/padding.d.ts.map +0 -1
- package/dist/ui/modifiers/padding.js +0 -36
- package/dist/ui/modifiers/padding.js.map +0 -1
- package/dist/ui/modifiers/styled.d.ts +0 -14
- package/dist/ui/modifiers/styled.d.ts.map +0 -1
- package/dist/ui/modifiers/styled.js +0 -26
- package/dist/ui/modifiers/styled.js.map +0 -1
- package/dist/ui/primitives/rectangle.d.ts +0 -15
- package/dist/ui/primitives/rectangle.d.ts.map +0 -1
- package/dist/ui/primitives/rectangle.js +0 -23
- package/dist/ui/primitives/rectangle.js.map +0 -1
- package/dist/ui/primitives/spacer.d.ts +0 -13
- package/dist/ui/primitives/spacer.d.ts.map +0 -1
- package/dist/ui/primitives/spacer.js +0 -16
- package/dist/ui/primitives/spacer.js.map +0 -1
- package/dist/ui/primitives/text.d.ts +0 -15
- package/dist/ui/primitives/text.d.ts.map +0 -1
- package/dist/ui/primitives/text.js +0 -79
- package/dist/ui/primitives/text.js.map +0 -1
- package/dist/ui/primitives/wrapped-text.d.ts +0 -30
- package/dist/ui/primitives/wrapped-text.d.ts.map +0 -1
- package/dist/ui/primitives/wrapped-text.js +0 -117
- package/dist/ui/primitives/wrapped-text.js.map +0 -1
- package/dist/ui/shinytext.d.ts +0 -66
- package/dist/ui/shinytext.d.ts.map +0 -1
- package/dist/ui/shinytext.js +0 -99
- package/dist/ui/shinytext.js.map +0 -1
- package/dist/ui/text/layout.d.ts +0 -35
- package/dist/ui/text/layout.d.ts.map +0 -1
- package/dist/ui/text/layout.js +0 -102
- package/dist/ui/text/layout.js.map +0 -1
- package/dist/ui/textinput.d.ts +0 -140
- package/dist/ui/textinput.d.ts.map +0 -1
- package/dist/ui/textinput.js +0 -402
- package/dist/ui/textinput.js.map +0 -1
- package/dist/ui/view-constructors.d.ts +0 -72
- package/dist/ui/view-constructors.d.ts.map +0 -1
- package/dist/ui/view-constructors.js +0 -74
- package/dist/ui/view-constructors.js.map +0 -1
- package/src/anim.ts +0 -5
- package/src/layout/linearStack.ts +0 -115
- package/src/motion-value.ts +0 -335
- package/src/present/display.ts +0 -206
- package/src/present/writers/fullscreen.ts +0 -58
- package/src/present/writers/inline.ts +0 -101
- package/src/render/color-utils.ts +0 -60
- package/src/render/diff.ts +0 -95
- package/src/spring-physics.ts +0 -151
- package/src/spring.ts +0 -234
- package/src/ui/__snapshots__/wrappedtext.test.ts.snap +0 -57
- package/src/ui/containers/canvas.ts +0 -18
- package/src/ui/containers/geometry-reader.ts +0 -32
- package/src/ui/containers/hstack.ts +0 -33
- package/src/ui/containers/scroll.ts +0 -106
- package/src/ui/containers/shared.ts +0 -27
- package/src/ui/containers/vstack.ts +0 -34
- package/src/ui/containers/zstack.ts +0 -37
- package/src/ui/core/geometry-store.ts +0 -42
- package/src/ui/core/geometry.ts +0 -30
- package/src/ui/core/view.ts +0 -49
- package/src/ui/index.ts +0 -84
- package/src/ui/inlinetext.ts +0 -135
- package/src/ui/install.ts +0 -110
- package/src/ui/markdown.test.ts +0 -74
- package/src/ui/markdown.ts +0 -388
- package/src/ui/modifiers/border.ts +0 -100
- package/src/ui/modifiers/fill.ts +0 -28
- package/src/ui/modifiers/frame.ts +0 -74
- package/src/ui/modifiers/offset.ts +0 -23
- package/src/ui/modifiers/opacity.ts +0 -93
- package/src/ui/modifiers/padding.ts +0 -53
- package/src/ui/modifiers/styled.ts +0 -31
- package/src/ui/primitives/rectangle.ts +0 -25
- package/src/ui/primitives/spacer.ts +0 -18
- package/src/ui/primitives/text.ts +0 -85
- package/src/ui/primitives/wrapped-text.ts +0 -131
- package/src/ui/shinytext.ts +0 -159
- package/src/ui/text/layout.ts +0 -119
- package/src/ui/textinput.ts +0 -496
- package/src/ui/view-constructors.ts +0 -96
- package/src/ui/wrappedtext.test.ts +0 -138
package/src/colors.ts
ADDED
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
// colors.ts — Comprehensive color parsing and utilities
|
|
2
|
+
// Supports indexed colors (0-255), RGB, hex, named colors, HSL, and alpha
|
|
3
|
+
|
|
4
|
+
import { tailwindColors, type TailwindShade, type TailwindColorFamily } from "./tailwind-colors.js"
|
|
5
|
+
|
|
6
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
7
|
+
// Type-safe color types
|
|
8
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Hex color string: #rgb, #rrggbb, #rgba, or #rrggbbaa
|
|
12
|
+
*
|
|
13
|
+
* Note: We use `#${string}` because enumerating all valid hex digit combinations
|
|
14
|
+
* (22^6 = 113M for 6-char hex) exceeds TypeScript's union type limits.
|
|
15
|
+
* The # prefix is validated at compile time; hex digits are validated at runtime.
|
|
16
|
+
*/
|
|
17
|
+
export type HexColor = `#${string}`
|
|
18
|
+
|
|
19
|
+
/** Base ANSI terminal color names */
|
|
20
|
+
export type BaseColorName =
|
|
21
|
+
| "black"
|
|
22
|
+
| "red"
|
|
23
|
+
| "green"
|
|
24
|
+
| "yellow"
|
|
25
|
+
| "blue"
|
|
26
|
+
| "magenta"
|
|
27
|
+
| "cyan"
|
|
28
|
+
| "white"
|
|
29
|
+
| "brightBlack"
|
|
30
|
+
| "brightRed"
|
|
31
|
+
| "brightGreen"
|
|
32
|
+
| "brightYellow"
|
|
33
|
+
| "brightBlue"
|
|
34
|
+
| "brightMagenta"
|
|
35
|
+
| "brightCyan"
|
|
36
|
+
| "brightWhite"
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Color input type - the main public type for color props.
|
|
40
|
+
*
|
|
41
|
+
* Accepts:
|
|
42
|
+
* - Palette index: 0-255
|
|
43
|
+
* - RGB object: { r, g, b }
|
|
44
|
+
* - Named color: "red", "brightBlue", etc. (type-checked)
|
|
45
|
+
* - Hex color: "#f00", "#ff0000" (# prefix required)
|
|
46
|
+
*/
|
|
47
|
+
export type Color = number | { r: number; g: number; b: number } | BaseColorName | HexColor
|
|
48
|
+
|
|
49
|
+
/** RGBA color with alpha channel - used for color springs/interpolation */
|
|
50
|
+
export type RGBA = { r: number; g: number; b: number; a: number }
|
|
51
|
+
|
|
52
|
+
/** Color input for springs (includes alpha variants) */
|
|
53
|
+
export type ColorInput = string | RGBA | { r: number; g: number; b: number }
|
|
54
|
+
|
|
55
|
+
/** Standard ANSI color names mapped to 256-color indices */
|
|
56
|
+
export const BASE_NAMES = {
|
|
57
|
+
black: 0,
|
|
58
|
+
red: 1,
|
|
59
|
+
green: 2,
|
|
60
|
+
yellow: 3,
|
|
61
|
+
blue: 4,
|
|
62
|
+
magenta: 5,
|
|
63
|
+
cyan: 6,
|
|
64
|
+
white: 7,
|
|
65
|
+
brightBlack: 8,
|
|
66
|
+
brightRed: 9,
|
|
67
|
+
brightGreen: 10,
|
|
68
|
+
brightYellow: 11,
|
|
69
|
+
brightBlue: 12,
|
|
70
|
+
brightMagenta: 13,
|
|
71
|
+
brightCyan: 14,
|
|
72
|
+
brightWhite: 15,
|
|
73
|
+
} as const
|
|
74
|
+
|
|
75
|
+
// ============================================================================
|
|
76
|
+
// Utility functions
|
|
77
|
+
// ============================================================================
|
|
78
|
+
|
|
79
|
+
/** Clamp a number to 0-255 range */
|
|
80
|
+
export function clamp255(n: number): number {
|
|
81
|
+
return n < 0 ? 0 : n > 255 ? 255 : n | 0
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Clamp a number to 0-1 range */
|
|
85
|
+
export function clamp1(n: number): number {
|
|
86
|
+
return n < 0 ? 0 : n > 1 ? 1 : n
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// ============================================================================
|
|
90
|
+
// parseColor - For Palette/styles (returns ColorValue)
|
|
91
|
+
// ============================================================================
|
|
92
|
+
|
|
93
|
+
/** Internal type for resolved colors (palette index or RGB) */
|
|
94
|
+
type ColorValue = number | { r: number; g: number; b: number }
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Parse flexible color inputs into a resolved color value.
|
|
98
|
+
* Supports: number (0-255), {r,g,b}, "#rgb", "#rrggbb", base names, gray0-23.
|
|
99
|
+
* Used by Palette and style systems.
|
|
100
|
+
*/
|
|
101
|
+
export function parseColor(c: Color): ColorValue {
|
|
102
|
+
if (typeof c === "number") return c
|
|
103
|
+
if (typeof c === "object") return { r: c.r | 0, g: c.g | 0, b: c.b | 0 }
|
|
104
|
+
const s = String(c).trim()
|
|
105
|
+
|
|
106
|
+
// Hex color
|
|
107
|
+
if (s.startsWith("#")) {
|
|
108
|
+
const hex = s.slice(1)
|
|
109
|
+
if (hex.length === 3) {
|
|
110
|
+
// #rgb -> #rrggbb
|
|
111
|
+
return {
|
|
112
|
+
r: parseInt(hex[0] + hex[0], 16),
|
|
113
|
+
g: parseInt(hex[1] + hex[1], 16),
|
|
114
|
+
b: parseInt(hex[2] + hex[2], 16),
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (hex.length === 6) {
|
|
118
|
+
return {
|
|
119
|
+
r: parseInt(hex.slice(0, 2), 16),
|
|
120
|
+
g: parseInt(hex.slice(2, 4), 16),
|
|
121
|
+
b: parseInt(hex.slice(4, 6), 16),
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Named color
|
|
127
|
+
if (s in BASE_NAMES) return BASE_NAMES[s as keyof typeof BASE_NAMES]
|
|
128
|
+
|
|
129
|
+
// gray0-gray23
|
|
130
|
+
const m = /^(?:gray|grey)(\d{1,2})$/.exec(s)
|
|
131
|
+
if (m?.[1]) {
|
|
132
|
+
const n = Math.max(0, Math.min(23, parseInt(m[1], 10)))
|
|
133
|
+
return 232 + n
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return 7 // default to white if unrecognized
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// ============================================================================
|
|
140
|
+
// parseColorRGBA - For color springs (returns RGBA with alpha)
|
|
141
|
+
// ============================================================================
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Parse any supported color format to RGBA (with alpha).
|
|
145
|
+
* Supports: hex (#rgb, #rrggbb, #rgba, #rrggbbaa), rgb(), rgba(), hsl(), hsla(), {r,g,b,a}.
|
|
146
|
+
* Used by color springs for interpolation.
|
|
147
|
+
*/
|
|
148
|
+
export function parseColorRGBA(input: ColorInput): RGBA {
|
|
149
|
+
if (typeof input === "object") {
|
|
150
|
+
return {
|
|
151
|
+
r: input.r,
|
|
152
|
+
g: input.g,
|
|
153
|
+
b: input.b,
|
|
154
|
+
a: "a" in input ? input.a : 1,
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const str = input.trim().toLowerCase()
|
|
159
|
+
|
|
160
|
+
// Hex: #rgb, #rrggbb, #rgba, #rrggbbaa
|
|
161
|
+
if (str.startsWith("#")) {
|
|
162
|
+
return parseHex(str)
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// rgb(r, g, b) or rgba(r, g, b, a)
|
|
166
|
+
if (str.startsWith("rgb")) {
|
|
167
|
+
return parseRgb(str)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// hsl(h, s%, l%) or hsla(h, s%, l%, a)
|
|
171
|
+
if (str.startsWith("hsl")) {
|
|
172
|
+
return parseHsl(str)
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Unknown format, return black
|
|
176
|
+
return { r: 0, g: 0, b: 0, a: 1 }
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function parseHex(hex: string): RGBA {
|
|
180
|
+
const h = hex.slice(1)
|
|
181
|
+
|
|
182
|
+
if (h.length === 3) {
|
|
183
|
+
return {
|
|
184
|
+
r: parseInt(h[0] + h[0], 16),
|
|
185
|
+
g: parseInt(h[1] + h[1], 16),
|
|
186
|
+
b: parseInt(h[2] + h[2], 16),
|
|
187
|
+
a: 1,
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (h.length === 4) {
|
|
192
|
+
return {
|
|
193
|
+
r: parseInt(h[0] + h[0], 16),
|
|
194
|
+
g: parseInt(h[1] + h[1], 16),
|
|
195
|
+
b: parseInt(h[2] + h[2], 16),
|
|
196
|
+
a: parseInt(h[3] + h[3], 16) / 255,
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (h.length === 6) {
|
|
201
|
+
return {
|
|
202
|
+
r: parseInt(h.slice(0, 2), 16),
|
|
203
|
+
g: parseInt(h.slice(2, 4), 16),
|
|
204
|
+
b: parseInt(h.slice(4, 6), 16),
|
|
205
|
+
a: 1,
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (h.length === 8) {
|
|
210
|
+
return {
|
|
211
|
+
r: parseInt(h.slice(0, 2), 16),
|
|
212
|
+
g: parseInt(h.slice(2, 4), 16),
|
|
213
|
+
b: parseInt(h.slice(4, 6), 16),
|
|
214
|
+
a: parseInt(h.slice(6, 8), 16) / 255,
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return { r: 0, g: 0, b: 0, a: 1 }
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function parseRgb(str: string): RGBA {
|
|
222
|
+
const match = str.match(/rgba?\(\s*(\d+)\s*[,\s]\s*(\d+)\s*[,\s]\s*(\d+)\s*(?:[,/]\s*([\d.]+))?\s*\)/)
|
|
223
|
+
if (match) {
|
|
224
|
+
return {
|
|
225
|
+
r: clamp255(parseInt(match[1], 10)),
|
|
226
|
+
g: clamp255(parseInt(match[2], 10)),
|
|
227
|
+
b: clamp255(parseInt(match[3], 10)),
|
|
228
|
+
a: match[4] ? clamp1(parseFloat(match[4])) : 1,
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return { r: 0, g: 0, b: 0, a: 1 }
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function parseHsl(str: string): RGBA {
|
|
235
|
+
const match = str.match(/hsla?\(\s*(\d+)\s*[,\s]\s*([\d.]+)%?\s*[,\s]\s*([\d.]+)%?\s*(?:[,/]\s*([\d.]+))?\s*\)/)
|
|
236
|
+
if (match) {
|
|
237
|
+
const h = parseFloat(match[1])
|
|
238
|
+
const s = parseFloat(match[2])
|
|
239
|
+
const l = parseFloat(match[3])
|
|
240
|
+
const a = match[4] ? clamp1(parseFloat(match[4])) : 1
|
|
241
|
+
return hslToRgba(h, s, l, a)
|
|
242
|
+
}
|
|
243
|
+
return { r: 0, g: 0, b: 0, a: 1 }
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Convert HSL to RGBA.
|
|
248
|
+
* h: 0-360, s: 0-100, l: 0-100, a: 0-1
|
|
249
|
+
*/
|
|
250
|
+
export function hslToRgba(h: number, s: number, l: number, a: number): RGBA {
|
|
251
|
+
// Normalize
|
|
252
|
+
h = ((h % 360) + 360) % 360
|
|
253
|
+
s = clamp1(s / 100)
|
|
254
|
+
l = clamp1(l / 100)
|
|
255
|
+
|
|
256
|
+
const c = (1 - Math.abs(2 * l - 1)) * s
|
|
257
|
+
const x = c * (1 - Math.abs(((h / 60) % 2) - 1))
|
|
258
|
+
const m = l - c / 2
|
|
259
|
+
|
|
260
|
+
let r = 0
|
|
261
|
+
let g = 0
|
|
262
|
+
let b = 0
|
|
263
|
+
|
|
264
|
+
if (h < 60) {
|
|
265
|
+
r = c
|
|
266
|
+
g = x
|
|
267
|
+
b = 0
|
|
268
|
+
} else if (h < 120) {
|
|
269
|
+
r = x
|
|
270
|
+
g = c
|
|
271
|
+
b = 0
|
|
272
|
+
} else if (h < 180) {
|
|
273
|
+
r = 0
|
|
274
|
+
g = c
|
|
275
|
+
b = x
|
|
276
|
+
} else if (h < 240) {
|
|
277
|
+
r = 0
|
|
278
|
+
g = x
|
|
279
|
+
b = c
|
|
280
|
+
} else if (h < 300) {
|
|
281
|
+
r = x
|
|
282
|
+
g = 0
|
|
283
|
+
b = c
|
|
284
|
+
} else {
|
|
285
|
+
r = c
|
|
286
|
+
g = 0
|
|
287
|
+
b = x
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
return {
|
|
291
|
+
r: Math.round((r + m) * 255),
|
|
292
|
+
g: Math.round((g + m) * 255),
|
|
293
|
+
b: Math.round((b + m) * 255),
|
|
294
|
+
a,
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Convert a 256-color index to RGB values (approximate xterm palette).
|
|
300
|
+
* 0-15: Standard ANSI, 16-231: 6x6x6 RGB cube, 232-255: Grayscale ramp
|
|
301
|
+
*/
|
|
302
|
+
export function idxToRGB(idx: number): { r: number; g: number; b: number } {
|
|
303
|
+
if (idx < 0) idx = 0
|
|
304
|
+
if (idx > 255) idx = 255
|
|
305
|
+
|
|
306
|
+
// Standard ANSI colors (0-15)
|
|
307
|
+
if (idx < 16) {
|
|
308
|
+
const base: Array<[number, number, number]> = [
|
|
309
|
+
[0x00, 0x00, 0x00], // 0: black
|
|
310
|
+
[0x80, 0x00, 0x00], // 1: red
|
|
311
|
+
[0x00, 0x80, 0x00], // 2: green
|
|
312
|
+
[0x80, 0x80, 0x00], // 3: yellow
|
|
313
|
+
[0x00, 0x00, 0x80], // 4: blue
|
|
314
|
+
[0x80, 0x00, 0x80], // 5: magenta
|
|
315
|
+
[0x00, 0x80, 0x80], // 6: cyan
|
|
316
|
+
[0xc0, 0xc0, 0xc0], // 7: white
|
|
317
|
+
[0x80, 0x80, 0x80], // 8: bright black (gray)
|
|
318
|
+
[0xff, 0x00, 0x00], // 9: bright red
|
|
319
|
+
[0x00, 0xff, 0x00], // 10: bright green
|
|
320
|
+
[0xff, 0xff, 0x00], // 11: bright yellow
|
|
321
|
+
[0x00, 0x00, 0xff], // 12: bright blue
|
|
322
|
+
[0xff, 0x00, 0xff], // 13: bright magenta
|
|
323
|
+
[0x00, 0xff, 0xff], // 14: bright cyan
|
|
324
|
+
[0xff, 0xff, 0xff], // 15: bright white
|
|
325
|
+
]
|
|
326
|
+
const [r, g, b] = base[idx] ?? [0, 0, 0]
|
|
327
|
+
return { r, g, b }
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// Grayscale ramp (232-255)
|
|
331
|
+
if (idx >= 232) {
|
|
332
|
+
const n = idx - 232 // 0..23
|
|
333
|
+
const v = 8 + n * 10
|
|
334
|
+
return { r: v, g: v, b: v }
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// 6x6x6 RGB cube (16-231)
|
|
338
|
+
const n = idx - 16 // 0..215
|
|
339
|
+
const r = Math.floor(n / 36) % 6
|
|
340
|
+
const g = Math.floor(n / 6) % 6
|
|
341
|
+
const b = n % 6
|
|
342
|
+
const steps = [0, 95, 135, 175, 215, 255]
|
|
343
|
+
return { r: steps[r] ?? 0, g: steps[g] ?? 0, b: steps[b] ?? 0 }
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Check if a value looks like a color input.
|
|
348
|
+
*/
|
|
349
|
+
export function isColorInput(value: unknown): value is ColorInput {
|
|
350
|
+
if (typeof value === "string") {
|
|
351
|
+
const s = value.trim().toLowerCase()
|
|
352
|
+
return s.startsWith("#") || s.startsWith("rgb") || s.startsWith("hsl")
|
|
353
|
+
}
|
|
354
|
+
if (typeof value === "object" && value !== null) {
|
|
355
|
+
const obj = value as Record<string, unknown>
|
|
356
|
+
return typeof obj.r === "number" && typeof obj.g === "number" && typeof obj.b === "number"
|
|
357
|
+
}
|
|
358
|
+
return false
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// ============================================================================
|
|
362
|
+
// Colors API - Convenience object for creating colors
|
|
363
|
+
// ============================================================================
|
|
364
|
+
|
|
365
|
+
type RGB = { r: number; g: number; b: number }
|
|
366
|
+
|
|
367
|
+
/** Parse hex string to RGB */
|
|
368
|
+
function hexToRgb(hex: string): RGB {
|
|
369
|
+
const h = hex.startsWith("#") ? hex.slice(1) : hex
|
|
370
|
+
return {
|
|
371
|
+
r: parseInt(h.slice(0, 2), 16),
|
|
372
|
+
g: parseInt(h.slice(2, 4), 16),
|
|
373
|
+
b: parseInt(h.slice(4, 6), 16),
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/** Create a Tailwind color function for a given family */
|
|
378
|
+
function makeTailwindColor(family: TailwindColorFamily): (shade: TailwindShade) => RGB {
|
|
379
|
+
const palette = tailwindColors[family]
|
|
380
|
+
return (shade: TailwindShade): RGB => {
|
|
381
|
+
const hex = palette[shade]
|
|
382
|
+
return hexToRgb(hex)
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
type TailwindColorFn = (shade: TailwindShade) => RGB
|
|
387
|
+
|
|
388
|
+
type TailwindColors = {
|
|
389
|
+
slate: TailwindColorFn
|
|
390
|
+
gray: TailwindColorFn
|
|
391
|
+
zinc: TailwindColorFn
|
|
392
|
+
neutral: TailwindColorFn
|
|
393
|
+
stone: TailwindColorFn
|
|
394
|
+
red: TailwindColorFn
|
|
395
|
+
orange: TailwindColorFn
|
|
396
|
+
amber: TailwindColorFn
|
|
397
|
+
yellow: TailwindColorFn
|
|
398
|
+
lime: TailwindColorFn
|
|
399
|
+
green: TailwindColorFn
|
|
400
|
+
emerald: TailwindColorFn
|
|
401
|
+
teal: TailwindColorFn
|
|
402
|
+
cyan: TailwindColorFn
|
|
403
|
+
sky: TailwindColorFn
|
|
404
|
+
blue: TailwindColorFn
|
|
405
|
+
indigo: TailwindColorFn
|
|
406
|
+
violet: TailwindColorFn
|
|
407
|
+
purple: TailwindColorFn
|
|
408
|
+
fuchsia: TailwindColorFn
|
|
409
|
+
pink: TailwindColorFn
|
|
410
|
+
rose: TailwindColorFn
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
type ColorsApi = typeof BASE_NAMES & {
|
|
414
|
+
rgb(r: number, g: number, b: number): RGB
|
|
415
|
+
hex(hex: HexColor): RGB
|
|
416
|
+
/** Gray - 24-level grayscale palette (0-23) */
|
|
417
|
+
gray(level: number): number
|
|
418
|
+
/** Tailwind color palette */
|
|
419
|
+
tw: TailwindColors
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/** Tailwind color palette under Colors.tw namespace */
|
|
423
|
+
const tw: TailwindColors = {
|
|
424
|
+
slate: makeTailwindColor("slate"),
|
|
425
|
+
gray: makeTailwindColor("gray"),
|
|
426
|
+
zinc: makeTailwindColor("zinc"),
|
|
427
|
+
neutral: makeTailwindColor("neutral"),
|
|
428
|
+
stone: makeTailwindColor("stone"),
|
|
429
|
+
red: makeTailwindColor("red"),
|
|
430
|
+
orange: makeTailwindColor("orange"),
|
|
431
|
+
amber: makeTailwindColor("amber"),
|
|
432
|
+
yellow: makeTailwindColor("yellow"),
|
|
433
|
+
lime: makeTailwindColor("lime"),
|
|
434
|
+
green: makeTailwindColor("green"),
|
|
435
|
+
emerald: makeTailwindColor("emerald"),
|
|
436
|
+
teal: makeTailwindColor("teal"),
|
|
437
|
+
cyan: makeTailwindColor("cyan"),
|
|
438
|
+
sky: makeTailwindColor("sky"),
|
|
439
|
+
blue: makeTailwindColor("blue"),
|
|
440
|
+
indigo: makeTailwindColor("indigo"),
|
|
441
|
+
violet: makeTailwindColor("violet"),
|
|
442
|
+
purple: makeTailwindColor("purple"),
|
|
443
|
+
fuchsia: makeTailwindColor("fuchsia"),
|
|
444
|
+
pink: makeTailwindColor("pink"),
|
|
445
|
+
rose: makeTailwindColor("rose"),
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
/** Convenience API for creating color values */
|
|
449
|
+
export const Colors: ColorsApi = Object.assign(
|
|
450
|
+
{
|
|
451
|
+
rgb(r: number, g: number, b: number): RGB {
|
|
452
|
+
return { r, g, b }
|
|
453
|
+
},
|
|
454
|
+
hex(hex: HexColor): RGB {
|
|
455
|
+
const result = parseColor(hex)
|
|
456
|
+
// parseColor returns number for named colors, but hex always returns RGB
|
|
457
|
+
return typeof result === "number" ? { r: 0, g: 0, b: 0 } : result
|
|
458
|
+
},
|
|
459
|
+
/** Gray - 24-level grayscale palette (0-23) */
|
|
460
|
+
gray(level: number): number {
|
|
461
|
+
const n = Math.max(0, Math.min(23, level | 0))
|
|
462
|
+
return 232 + n
|
|
463
|
+
},
|
|
464
|
+
/** Tailwind color palette */
|
|
465
|
+
tw,
|
|
466
|
+
},
|
|
467
|
+
BASE_NAMES,
|
|
468
|
+
) as ColorsApi
|
package/src/index.ts
CHANGED
|
@@ -1,21 +1,35 @@
|
|
|
1
|
-
//
|
|
1
|
+
// Core types
|
|
2
|
+
export * from "./types.js"
|
|
3
|
+
|
|
4
|
+
// Rendering primitives
|
|
2
5
|
export * from "./render/surface.js"
|
|
3
6
|
export * from "./render/buffer.js"
|
|
7
|
+
export * from "./render/palette.js"
|
|
4
8
|
export * from "./render/measure.js"
|
|
5
|
-
|
|
9
|
+
|
|
10
|
+
// Colors - additional exports not in surface.js (RGBA, parseColorRGBA for springs)
|
|
11
|
+
export {
|
|
12
|
+
parseColorRGBA,
|
|
13
|
+
hslToRgba,
|
|
14
|
+
idxToRGB,
|
|
15
|
+
isColorInput,
|
|
16
|
+
clamp255,
|
|
17
|
+
clamp1,
|
|
18
|
+
type RGBA,
|
|
19
|
+
type ColorInput,
|
|
20
|
+
} from "./colors.js"
|
|
21
|
+
|
|
22
|
+
// Input handling
|
|
6
23
|
export * from "./keys.js"
|
|
7
24
|
|
|
8
|
-
//
|
|
9
|
-
export
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
export
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
export { geometryStore } from "./ui/core/geometry-store.js"
|
|
17
|
-
export type { ViewId, Rect as GeometryRect, InputGeom } from "./ui/core/geometry-store.js"
|
|
25
|
+
// ANSI escape sequences
|
|
26
|
+
export * from "./ansi.js"
|
|
27
|
+
|
|
28
|
+
// Output helpers (buffer diffing and emission)
|
|
29
|
+
export * from "./output.js"
|
|
30
|
+
|
|
31
|
+
// Layout utilities
|
|
32
|
+
export * from "./layout/axis-helpers.js"
|
|
18
33
|
|
|
19
|
-
//
|
|
20
|
-
export * from "./present/display.js"
|
|
34
|
+
// Terminal backend (optional)
|
|
21
35
|
export type { TerminalBackend } from "./runtime/backend_node.js"
|