@effect-tui/react 0.2.4 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/components/Table.d.ts +58 -0
- package/dist/src/components/Table.d.ts.map +1 -0
- package/dist/src/components/Table.js +185 -0
- package/dist/src/components/Table.js.map +1 -0
- package/dist/src/components/TextInput.js +1 -1
- package/dist/src/components/TextInput.js.map +1 -1
- package/dist/src/components/index.d.ts +1 -0
- package/dist/src/components/index.d.ts.map +1 -1
- package/dist/src/components/index.js +1 -0
- package/dist/src/components/index.js.map +1 -1
- package/dist/src/hosts/canvas.d.ts.map +1 -1
- package/dist/src/hosts/canvas.js +12 -5
- package/dist/src/hosts/canvas.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/utils/border.d.ts +14 -0
- package/dist/src/utils/border.d.ts.map +1 -1
- package/dist/src/utils/border.js +21 -0
- package/dist/src/utils/border.js.map +1 -1
- package/dist/src/utils/index.d.ts +1 -1
- package/dist/src/utils/index.d.ts.map +1 -1
- package/dist/src/utils/index.js +1 -1
- package/dist/src/utils/index.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/components/Table.tsx +326 -0
- package/src/components/TextInput.tsx +1 -1
- package/src/components/index.ts +1 -0
- package/src/hosts/canvas.ts +13 -5
- package/src/index.ts +4 -0
- package/src/utils/border.ts +33 -0
- package/src/utils/index.ts +9 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effect-tui/react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "React bindings for @effect-tui/core",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"prepublishOnly": "bun run typecheck && bun run build"
|
|
84
84
|
},
|
|
85
85
|
"dependencies": {
|
|
86
|
-
"@effect-tui/core": "^0.
|
|
86
|
+
"@effect-tui/core": "^0.3.1",
|
|
87
87
|
"@effect/platform": "^0.94.0",
|
|
88
88
|
"@effect/platform-bun": "^0.87.0",
|
|
89
89
|
"@effect/rpc": "^0.73.0",
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Table component for rendering tabular data with box-drawing borders.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```tsx
|
|
6
|
+
* <Table data={users} border="square" headerSeparator>
|
|
7
|
+
* <Table.Column header="Name" width={20}>
|
|
8
|
+
* {(user) => <text fg={WHITE}>{user.name}</text>}
|
|
9
|
+
* </Table.Column>
|
|
10
|
+
* <Table.Column header="Score" width={5} align="right">
|
|
11
|
+
* {(user) => <text fg={user.score > 80 ? GREEN : YELLOW}>{user.score}</text>}
|
|
12
|
+
* </Table.Column>
|
|
13
|
+
* </Table>
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { type Color, Colors } from "@effect-tui/core"
|
|
18
|
+
import { Children, isValidElement, type ReactElement, type ReactNode } from "react"
|
|
19
|
+
import { type BorderKind, tableBorderChars } from "../utils/border.js"
|
|
20
|
+
|
|
21
|
+
// ============================================================================
|
|
22
|
+
// Types
|
|
23
|
+
// ============================================================================
|
|
24
|
+
|
|
25
|
+
type Align = "left" | "center" | "right"
|
|
26
|
+
|
|
27
|
+
export interface ColumnProps<T = unknown> {
|
|
28
|
+
/** Column header text or element */
|
|
29
|
+
header?: ReactNode
|
|
30
|
+
/** Fixed column width in characters */
|
|
31
|
+
width?: number
|
|
32
|
+
/** Minimum width when auto-sizing (default: header length) */
|
|
33
|
+
minWidth?: number
|
|
34
|
+
/** Maximum width when auto-sizing */
|
|
35
|
+
maxWidth?: number
|
|
36
|
+
/** Text alignment within cell (default: "left") */
|
|
37
|
+
align?: Align
|
|
38
|
+
/** Render function for cell content */
|
|
39
|
+
children: (item: T, index: number) => ReactNode
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface TableProps<T> {
|
|
43
|
+
/** Data array to render rows from */
|
|
44
|
+
data: readonly T[]
|
|
45
|
+
/** Border style (default: "square") */
|
|
46
|
+
border?: BorderKind
|
|
47
|
+
/** Show separator line between header and body */
|
|
48
|
+
headerSeparator?: boolean
|
|
49
|
+
/** Show separator lines between all rows */
|
|
50
|
+
rowSeparator?: boolean
|
|
51
|
+
/** Cell padding in characters (default: 1) */
|
|
52
|
+
padding?: number
|
|
53
|
+
/** Border color (default: dim gray) */
|
|
54
|
+
borderColor?: Color
|
|
55
|
+
/** Header text color (default: dim gray) */
|
|
56
|
+
headerColor?: Color
|
|
57
|
+
/** Column definitions */
|
|
58
|
+
children: ReactNode
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// ============================================================================
|
|
62
|
+
// Column (data holder, not rendered directly)
|
|
63
|
+
// ============================================================================
|
|
64
|
+
|
|
65
|
+
function Column<T>(_props: ColumnProps<T>): ReactElement | null {
|
|
66
|
+
return null
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// ============================================================================
|
|
70
|
+
// Internal: Extract column configs from children
|
|
71
|
+
// ============================================================================
|
|
72
|
+
|
|
73
|
+
interface ColumnConfig<T> {
|
|
74
|
+
header?: ReactNode
|
|
75
|
+
width: number
|
|
76
|
+
align: Align
|
|
77
|
+
render: (item: T, index: number) => ReactNode
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function extractColumns<T>(children: ReactNode, data: readonly T[]): ColumnConfig<T>[] {
|
|
81
|
+
const columns: ColumnConfig<T>[] = []
|
|
82
|
+
|
|
83
|
+
Children.forEach(children, (child) => {
|
|
84
|
+
if (!isValidElement(child)) return
|
|
85
|
+
// Check if it's a Column element by checking the function name
|
|
86
|
+
if (typeof child.type === "function" && (child.type as { name?: string }).name === "Column") {
|
|
87
|
+
const props = child.props as ColumnProps<T>
|
|
88
|
+
|
|
89
|
+
// Calculate width
|
|
90
|
+
let width = props.width ?? 0
|
|
91
|
+
if (width === 0) {
|
|
92
|
+
// Auto-size: measure header + content
|
|
93
|
+
const headerLen = typeof props.header === "string" ? props.header.length : 0
|
|
94
|
+
const minFromHeader = Math.max(headerLen, props.minWidth ?? 0)
|
|
95
|
+
|
|
96
|
+
// Measure content from data (sample first few rows)
|
|
97
|
+
let maxContentLen = 0
|
|
98
|
+
for (let i = 0; i < Math.min(data.length, 10); i++) {
|
|
99
|
+
const rendered = props.children(data[i]!, i)
|
|
100
|
+
// Rough estimate - extract text content length
|
|
101
|
+
const textLen = estimateTextLength(rendered)
|
|
102
|
+
maxContentLen = Math.max(maxContentLen, textLen)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
width = Math.max(minFromHeader, maxContentLen, 1)
|
|
106
|
+
if (props.maxWidth !== undefined) {
|
|
107
|
+
width = Math.min(width, props.maxWidth)
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
columns.push({
|
|
112
|
+
header: props.header,
|
|
113
|
+
width,
|
|
114
|
+
align: props.align ?? "left",
|
|
115
|
+
render: props.children,
|
|
116
|
+
})
|
|
117
|
+
}
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
return columns
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function estimateTextLength(node: ReactNode): number {
|
|
124
|
+
if (node == null) return 0
|
|
125
|
+
if (typeof node === "string") return node.length
|
|
126
|
+
if (typeof node === "number") return String(node).length
|
|
127
|
+
if (Array.isArray(node)) return node.reduce((sum, n) => sum + estimateTextLength(n), 0)
|
|
128
|
+
if (isValidElement(node)) {
|
|
129
|
+
const children = (node.props as { children?: ReactNode }).children
|
|
130
|
+
return estimateTextLength(children)
|
|
131
|
+
}
|
|
132
|
+
return 0
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// ============================================================================
|
|
136
|
+
// Internal: Helpers
|
|
137
|
+
// ============================================================================
|
|
138
|
+
|
|
139
|
+
function alignText(text: string, width: number, align: Align): string {
|
|
140
|
+
if (text.length >= width) return text.slice(0, width)
|
|
141
|
+
const padding = width - text.length
|
|
142
|
+
switch (align) {
|
|
143
|
+
case "right":
|
|
144
|
+
return " ".repeat(padding) + text
|
|
145
|
+
case "center": {
|
|
146
|
+
const left = Math.floor(padding / 2)
|
|
147
|
+
const right = padding - left
|
|
148
|
+
return " ".repeat(left) + text + " ".repeat(right)
|
|
149
|
+
}
|
|
150
|
+
default:
|
|
151
|
+
return text + " ".repeat(padding)
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function buildBorderLine(
|
|
156
|
+
widths: number[],
|
|
157
|
+
left: string,
|
|
158
|
+
mid: string,
|
|
159
|
+
right: string,
|
|
160
|
+
fill: string,
|
|
161
|
+
padding: number,
|
|
162
|
+
): string {
|
|
163
|
+
return (
|
|
164
|
+
left + widths.map((w) => fill.repeat(w + padding * 2)).join(mid) + right
|
|
165
|
+
)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// ============================================================================
|
|
169
|
+
// Table Component
|
|
170
|
+
// ============================================================================
|
|
171
|
+
|
|
172
|
+
function TableRoot<T>({
|
|
173
|
+
data,
|
|
174
|
+
border = "square",
|
|
175
|
+
headerSeparator = false,
|
|
176
|
+
rowSeparator = false,
|
|
177
|
+
padding = 1,
|
|
178
|
+
borderColor = Colors.gray(12),
|
|
179
|
+
headerColor = Colors.gray(12),
|
|
180
|
+
children,
|
|
181
|
+
}: TableProps<T>) {
|
|
182
|
+
const columns = extractColumns<T>(children, data)
|
|
183
|
+
if (columns.length === 0) return null
|
|
184
|
+
|
|
185
|
+
const chars = tableBorderChars(border)
|
|
186
|
+
const widths = columns.map((c) => c.width)
|
|
187
|
+
const pad = " ".repeat(padding)
|
|
188
|
+
const noBorder = border === "none"
|
|
189
|
+
|
|
190
|
+
// Build border lines
|
|
191
|
+
const topLine = buildBorderLine(widths, chars.tl, chars.tt, chars.tr, chars.h, padding)
|
|
192
|
+
const midLine = buildBorderLine(widths, chars.lt, chars.cross, chars.rt, chars.h, padding)
|
|
193
|
+
const bottomLine = buildBorderLine(widths, chars.bl, chars.bt, chars.br, chars.h, padding)
|
|
194
|
+
|
|
195
|
+
// Check if any column has a header
|
|
196
|
+
const hasHeader = columns.some((c) => c.header !== undefined)
|
|
197
|
+
|
|
198
|
+
const rows: ReactNode[] = []
|
|
199
|
+
|
|
200
|
+
// Top border
|
|
201
|
+
if (!noBorder) {
|
|
202
|
+
rows.push(
|
|
203
|
+
<text key="border-top" fg={borderColor}>
|
|
204
|
+
{topLine}
|
|
205
|
+
</text>,
|
|
206
|
+
)
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Header row
|
|
210
|
+
if (hasHeader) {
|
|
211
|
+
const headerCells: ReactNode[] = []
|
|
212
|
+
columns.forEach((col, i) => {
|
|
213
|
+
// Left border or column separator
|
|
214
|
+
if (!noBorder) {
|
|
215
|
+
headerCells.push(
|
|
216
|
+
<text key={`h-sep-${i}`} fg={borderColor}>
|
|
217
|
+
{chars.v + pad}
|
|
218
|
+
</text>,
|
|
219
|
+
)
|
|
220
|
+
}
|
|
221
|
+
const headerText = typeof col.header === "string" ? col.header : ""
|
|
222
|
+
headerCells.push(
|
|
223
|
+
<text key={`h-${i}`} fg={headerColor}>
|
|
224
|
+
{alignText(headerText, col.width, col.align)}
|
|
225
|
+
</text>,
|
|
226
|
+
)
|
|
227
|
+
// Right padding (border comes from next column's left, or final border)
|
|
228
|
+
if (!noBorder) {
|
|
229
|
+
headerCells.push(
|
|
230
|
+
<text key={`h-pad-${i}`} fg={borderColor}>
|
|
231
|
+
{pad}
|
|
232
|
+
</text>,
|
|
233
|
+
)
|
|
234
|
+
}
|
|
235
|
+
})
|
|
236
|
+
// Final right border
|
|
237
|
+
if (!noBorder) {
|
|
238
|
+
headerCells.push(
|
|
239
|
+
<text key="h-sep-end" fg={borderColor}>
|
|
240
|
+
{chars.v}
|
|
241
|
+
</text>,
|
|
242
|
+
)
|
|
243
|
+
}
|
|
244
|
+
rows.push(<hstack key="header" spacing={0}>{headerCells}</hstack>)
|
|
245
|
+
|
|
246
|
+
// Header separator
|
|
247
|
+
if (headerSeparator && !noBorder) {
|
|
248
|
+
rows.push(
|
|
249
|
+
<text key="border-mid-header" fg={borderColor}>
|
|
250
|
+
{midLine}
|
|
251
|
+
</text>,
|
|
252
|
+
)
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Data rows
|
|
257
|
+
data.forEach((item, rowIdx) => {
|
|
258
|
+
// Row separator (between rows)
|
|
259
|
+
if (rowSeparator && rowIdx > 0 && !noBorder) {
|
|
260
|
+
rows.push(
|
|
261
|
+
<text key={`border-mid-${rowIdx}`} fg={borderColor}>
|
|
262
|
+
{midLine}
|
|
263
|
+
</text>,
|
|
264
|
+
)
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const rowCells: ReactNode[] = []
|
|
268
|
+
columns.forEach((col, colIdx) => {
|
|
269
|
+
// Left border or column separator
|
|
270
|
+
if (!noBorder) {
|
|
271
|
+
rowCells.push(
|
|
272
|
+
<text key={`r${rowIdx}-sep-${colIdx}`} fg={borderColor}>
|
|
273
|
+
{chars.v + pad}
|
|
274
|
+
</text>,
|
|
275
|
+
)
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Cell content
|
|
279
|
+
const content = col.render(item, rowIdx)
|
|
280
|
+
rowCells.push(
|
|
281
|
+
<hstack key={`r${rowIdx}-c${colIdx}`} spacing={0} width={col.width}>
|
|
282
|
+
{content}
|
|
283
|
+
</hstack>,
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
// Right padding
|
|
287
|
+
if (!noBorder) {
|
|
288
|
+
rowCells.push(
|
|
289
|
+
<text key={`r${rowIdx}-pad-${colIdx}`} fg={borderColor}>
|
|
290
|
+
{pad}
|
|
291
|
+
</text>,
|
|
292
|
+
)
|
|
293
|
+
}
|
|
294
|
+
})
|
|
295
|
+
// Final right border
|
|
296
|
+
if (!noBorder) {
|
|
297
|
+
rowCells.push(
|
|
298
|
+
<text key={`r${rowIdx}-sep-end`} fg={borderColor}>
|
|
299
|
+
{chars.v}
|
|
300
|
+
</text>,
|
|
301
|
+
)
|
|
302
|
+
}
|
|
303
|
+
rows.push(<hstack key={`row-${rowIdx}`} spacing={0}>{rowCells}</hstack>)
|
|
304
|
+
})
|
|
305
|
+
|
|
306
|
+
// Bottom border
|
|
307
|
+
if (!noBorder) {
|
|
308
|
+
rows.push(
|
|
309
|
+
<text key="border-bottom" fg={borderColor}>
|
|
310
|
+
{bottomLine}
|
|
311
|
+
</text>,
|
|
312
|
+
)
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
return <vstack spacing={0}>{rows}</vstack>
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// ============================================================================
|
|
319
|
+
// Exports
|
|
320
|
+
// ============================================================================
|
|
321
|
+
|
|
322
|
+
export const Table = Object.assign(TableRoot, {
|
|
323
|
+
Column,
|
|
324
|
+
})
|
|
325
|
+
|
|
326
|
+
export type { Align as TableAlign }
|
package/src/components/index.ts
CHANGED
|
@@ -3,4 +3,5 @@ export { Markdown, type MarkdownProps, type MarkdownTheme } from "./Markdown.js"
|
|
|
3
3
|
export { MultilineTextInput, type MultilineTextInputProps } from "./MultilineTextInput.js"
|
|
4
4
|
export { Overlay, type OverlayItemProps, type OverlayProps } from "./Overlay.js"
|
|
5
5
|
export { Static, type StaticProps } from "./Static.js"
|
|
6
|
+
export { Table, type TableAlign, type ColumnProps, type TableProps } from "./Table.js"
|
|
6
7
|
export { TextInput, type TextInputProps } from "./TextInput.js"
|
package/src/hosts/canvas.ts
CHANGED
|
@@ -89,10 +89,14 @@ export class CanvasHost extends BaseHost {
|
|
|
89
89
|
if (!this.rect) return
|
|
90
90
|
const { x: ox, y: oy, w, h } = this.rect
|
|
91
91
|
|
|
92
|
+
// Get inherited background for use in drawing functions
|
|
93
|
+
const { value: inheritedBgValue, styleId: inheritedBgStyleId } = this.inheritBg
|
|
94
|
+
? resolveInheritedBgStyle(palette, undefined, this.parent)
|
|
95
|
+
: { value: undefined, styleId: 0 }
|
|
96
|
+
|
|
92
97
|
// Pre-fill with inherited background if requested
|
|
93
|
-
if (this.inheritBg) {
|
|
94
|
-
|
|
95
|
-
buffer.fillRect(ox, oy, w, h, " ".codePointAt(0)!, styleId)
|
|
98
|
+
if (this.inheritBg && inheritedBgValue !== undefined) {
|
|
99
|
+
buffer.fillRect(ox, oy, w, h, " ".codePointAt(0)!, inheritedBgStyleId)
|
|
96
100
|
}
|
|
97
101
|
|
|
98
102
|
// Create draw context
|
|
@@ -103,9 +107,11 @@ export class CanvasHost extends BaseHost {
|
|
|
103
107
|
text: (x, y, str, opts) => {
|
|
104
108
|
const px = Math.round(ox + x)
|
|
105
109
|
const py = Math.round(oy + y)
|
|
110
|
+
// Use inherited bg when inheritBg is enabled and no explicit bg provided
|
|
111
|
+
const effectiveBg = opts?.bg ?? (this.inheritBg ? inheritedBgValue : undefined)
|
|
106
112
|
const style = styleIdFromProps(palette, {
|
|
107
113
|
fg: opts?.fg,
|
|
108
|
-
bg:
|
|
114
|
+
bg: effectiveBg,
|
|
109
115
|
bold: opts?.bold,
|
|
110
116
|
italic: opts?.italic,
|
|
111
117
|
underline: opts?.underline,
|
|
@@ -123,9 +129,11 @@ export class CanvasHost extends BaseHost {
|
|
|
123
129
|
const px = Math.round(ox + x)
|
|
124
130
|
const py = Math.round(oy + y)
|
|
125
131
|
const cp = char.codePointAt(0)!
|
|
132
|
+
// Use inherited bg when inheritBg is enabled and no explicit bg provided
|
|
133
|
+
const effectiveBg = opts?.bg ?? (this.inheritBg ? inheritedBgValue : undefined)
|
|
126
134
|
const style = styleIdFromProps(palette, {
|
|
127
135
|
fg: opts?.fg,
|
|
128
|
-
bg:
|
|
136
|
+
bg: effectiveBg,
|
|
129
137
|
bold: opts?.bold,
|
|
130
138
|
italic: opts?.italic,
|
|
131
139
|
underline: opts?.underline,
|
package/src/index.ts
CHANGED
|
@@ -5,6 +5,7 @@ export type { CodeBlockProps } from "./codeblock.js"
|
|
|
5
5
|
export { CodeBlock } from "./codeblock.js"
|
|
6
6
|
// Input components
|
|
7
7
|
export {
|
|
8
|
+
type ColumnProps,
|
|
8
9
|
Markdown,
|
|
9
10
|
type MarkdownProps,
|
|
10
11
|
type MarkdownTheme,
|
|
@@ -15,6 +16,9 @@ export {
|
|
|
15
16
|
type OverlayProps,
|
|
16
17
|
Static,
|
|
17
18
|
type StaticProps,
|
|
19
|
+
Table,
|
|
20
|
+
type TableAlign,
|
|
21
|
+
type TableProps,
|
|
18
22
|
TextInput,
|
|
19
23
|
type TextInputProps,
|
|
20
24
|
} from "./components/index.js"
|
package/src/utils/border.ts
CHANGED
|
@@ -15,6 +15,17 @@ export interface BorderChars {
|
|
|
15
15
|
v: string // vertical
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Extended border chars for tables with T-connectors.
|
|
20
|
+
*/
|
|
21
|
+
export interface TableBorderChars extends BorderChars {
|
|
22
|
+
tt: string // top T (┬)
|
|
23
|
+
bt: string // bottom T (┴)
|
|
24
|
+
lt: string // left T (├)
|
|
25
|
+
rt: string // right T (┤)
|
|
26
|
+
cross: string // cross (┼)
|
|
27
|
+
}
|
|
28
|
+
|
|
18
29
|
/**
|
|
19
30
|
* Get border characters for a given border style.
|
|
20
31
|
* Returns empty strings for "none" (drawing code should skip when border is "none").
|
|
@@ -38,6 +49,28 @@ export function borderChars(kind: BorderKind): BorderChars {
|
|
|
38
49
|
}
|
|
39
50
|
}
|
|
40
51
|
|
|
52
|
+
/**
|
|
53
|
+
* Get table border characters (includes T-connectors and cross).
|
|
54
|
+
*/
|
|
55
|
+
export function tableBorderChars(kind: BorderKind): TableBorderChars {
|
|
56
|
+
switch (kind) {
|
|
57
|
+
case "rounded":
|
|
58
|
+
return { tl: "╭", tr: "╮", bl: "╰", br: "╯", h: "─", v: "│", tt: "┬", bt: "┴", lt: "├", rt: "┤", cross: "┼" }
|
|
59
|
+
case "square":
|
|
60
|
+
return { tl: "┌", tr: "┐", bl: "└", br: "┘", h: "─", v: "│", tt: "┬", bt: "┴", lt: "├", rt: "┤", cross: "┼" }
|
|
61
|
+
case "double":
|
|
62
|
+
return { tl: "╔", tr: "╗", bl: "╚", br: "╝", h: "═", v: "║", tt: "╦", bt: "╩", lt: "╠", rt: "╣", cross: "╬" }
|
|
63
|
+
case "heavy":
|
|
64
|
+
return { tl: "┏", tr: "┓", bl: "┗", br: "┛", h: "━", v: "┃", tt: "┳", bt: "┻", lt: "┣", rt: "┫", cross: "╋" }
|
|
65
|
+
case "dashed":
|
|
66
|
+
return { tl: "┌", tr: "┐", bl: "└", br: "┘", h: "┄", v: "┆", tt: "┬", bt: "┴", lt: "├", rt: "┤", cross: "┼" }
|
|
67
|
+
case "ascii":
|
|
68
|
+
return { tl: "+", tr: "+", bl: "+", br: "+", h: "-", v: "|", tt: "+", bt: "+", lt: "+", rt: "+", cross: "+" }
|
|
69
|
+
default:
|
|
70
|
+
return { tl: "", tr: "", bl: "", br: "", h: "", v: "", tt: "", bt: "", lt: "", rt: "", cross: "" }
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
41
74
|
export interface ClipRect {
|
|
42
75
|
ox: number
|
|
43
76
|
oy: number
|
package/src/utils/index.ts
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
export { alignInRect, type HAlign, type VAlign } from "./alignment.js"
|
|
2
|
-
export {
|
|
2
|
+
export {
|
|
3
|
+
type BorderChars,
|
|
4
|
+
type BorderKind,
|
|
5
|
+
borderChars,
|
|
6
|
+
type ClipRect,
|
|
7
|
+
drawBorder,
|
|
8
|
+
type TableBorderChars,
|
|
9
|
+
tableBorderChars,
|
|
10
|
+
} from "./border.js"
|
|
3
11
|
export { type FlexAlignment, type FlexAxis, type FlexMeasureResult, layoutFlex, measureFlex } from "./flex-layout.js"
|
|
4
12
|
export { type Padding, type PaddingInput, resolvePadding } from "./padding.js"
|
|
5
13
|
export {
|