@tooee/renderers 0.1.9 → 0.1.12
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/CodeView.d.ts +3 -7
- package/dist/CodeView.d.ts.map +1 -1
- package/dist/CodeView.js +5 -31
- package/dist/CodeView.js.map +1 -1
- package/dist/CommandPalette.d.ts.map +1 -1
- package/dist/CommandPalette.js +1 -23
- package/dist/CommandPalette.js.map +1 -1
- package/dist/DecorationLayer.d.ts +14 -0
- package/dist/DecorationLayer.d.ts.map +1 -0
- package/dist/DecorationLayer.js +2 -0
- package/dist/DecorationLayer.js.map +1 -0
- package/dist/MarkdownView.d.ts +3 -9
- package/dist/MarkdownView.d.ts.map +1 -1
- package/dist/MarkdownView.js +11 -32
- package/dist/MarkdownView.js.map +1 -1
- package/dist/RowDocumentRenderable.d.ts +14 -26
- package/dist/RowDocumentRenderable.d.ts.map +1 -1
- package/dist/RowDocumentRenderable.js +74 -78
- package/dist/RowDocumentRenderable.js.map +1 -1
- package/dist/Table.d.ts +5 -9
- package/dist/Table.d.ts.map +1 -1
- package/dist/Table.js +17 -46
- package/dist/Table.js.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/parsers.d.ts.map +1 -1
- package/dist/parsers.js.map +1 -1
- package/dist/useGutterPalette.d.ts +3 -0
- package/dist/useGutterPalette.d.ts.map +1 -0
- package/dist/useGutterPalette.js +10 -0
- package/dist/useGutterPalette.js.map +1 -0
- package/package.json +18 -16
- package/src/CodeView.tsx +11 -54
- package/src/CommandPalette.tsx +1 -25
- package/src/DecorationLayer.ts +11 -0
- package/src/MarkdownView.tsx +19 -51
- package/src/RowDocumentRenderable.ts +91 -135
- package/src/Table.tsx +35 -71
- package/src/index.ts +4 -7
- package/src/parsers.ts +4 -1
- package/src/useGutterPalette.ts +15 -0
package/src/Table.tsx
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import { useTerminalDimensions } from "@opentui/react"
|
|
2
2
|
import { useTheme } from "@tooee/themes"
|
|
3
|
-
import {
|
|
3
|
+
import { type RefObject } from "react"
|
|
4
|
+
import type { MarkState } from "@tooee/marks"
|
|
4
5
|
import type { ColumnDef, TableRow } from "./table-types.js"
|
|
5
|
-
import
|
|
6
|
+
import {
|
|
7
|
+
computeRowDocumentGutterWidth,
|
|
8
|
+
type RowDocumentRenderable,
|
|
9
|
+
} from "./RowDocumentRenderable.js"
|
|
10
|
+
import { useGutterPalette } from "./useGutterPalette.js"
|
|
6
11
|
import "./row-document.js"
|
|
7
12
|
|
|
8
13
|
export interface TableProps {
|
|
@@ -18,12 +23,7 @@ export interface TableProps {
|
|
|
18
23
|
sampleSize?: number
|
|
19
24
|
/** Show line numbers in the gutter (default: true) */
|
|
20
25
|
showLineNumbers?: boolean
|
|
21
|
-
|
|
22
|
-
selectionStart?: number
|
|
23
|
-
selectionEnd?: number
|
|
24
|
-
matchingRows?: Set<number>
|
|
25
|
-
currentMatchRow?: number
|
|
26
|
-
toggledRows?: Set<number>
|
|
26
|
+
marks?: MarkState
|
|
27
27
|
docRef?: RefObject<RowDocumentRenderable | null>
|
|
28
28
|
/** Column width mode: "content" sizes to content (default), "fill" expands to fill available width */
|
|
29
29
|
columnWidthMode?: "content" | "fill"
|
|
@@ -73,7 +73,10 @@ function computeColumnWidths(
|
|
|
73
73
|
// Use Bun.stringWidth for correct display width with CJK/emoji
|
|
74
74
|
const naturalWidths = headers.map((header, col) => {
|
|
75
75
|
const headerLen = Bun.stringWidth(header)
|
|
76
|
-
const maxRowLen = sampledRows.reduce(
|
|
76
|
+
const maxRowLen = sampledRows.reduce(
|
|
77
|
+
(max, row) => Math.max(max, Bun.stringWidth(row[col] ?? "")),
|
|
78
|
+
0,
|
|
79
|
+
)
|
|
77
80
|
const contentWidth = Math.max(headerLen, maxRowLen)
|
|
78
81
|
// Apply min/max constraints before adding padding
|
|
79
82
|
const constrainedWidth = Math.min(maxColumnWidth, Math.max(minColumnWidth, contentWidth))
|
|
@@ -124,22 +127,6 @@ function computeColumnWidths(
|
|
|
124
127
|
})
|
|
125
128
|
}
|
|
126
129
|
|
|
127
|
-
/**
|
|
128
|
-
* Pre-compute gutter width to subtract from available column space.
|
|
129
|
-
* Mirrors RowDocumentRenderable._computeGutterWidth logic.
|
|
130
|
-
*/
|
|
131
|
-
function computeGutterWidth(rowCount: number, showLineNumbers: boolean): number {
|
|
132
|
-
let width = 0
|
|
133
|
-
if (showLineNumbers) {
|
|
134
|
-
// lineNumberStart defaults to 1, so max line number = rowCount
|
|
135
|
-
const maxLineNum = rowCount
|
|
136
|
-
width += Math.max(String(maxLineNum).length, 1)
|
|
137
|
-
}
|
|
138
|
-
width += 1 // signColumnWidth
|
|
139
|
-
width += 1 // gutterPaddingRight (default)
|
|
140
|
-
return width
|
|
141
|
-
}
|
|
142
|
-
|
|
143
130
|
function formatCellValue(value: unknown): string {
|
|
144
131
|
if (value == null) return ""
|
|
145
132
|
if (typeof value === "string") return value
|
|
@@ -160,20 +147,20 @@ export function Table({
|
|
|
160
147
|
maxColumnWidth = DEFAULT_MAX_COL_WIDTH,
|
|
161
148
|
sampleSize = DEFAULT_SAMPLE_SIZE,
|
|
162
149
|
showLineNumbers = true,
|
|
163
|
-
|
|
164
|
-
selectionStart,
|
|
165
|
-
selectionEnd,
|
|
166
|
-
matchingRows,
|
|
167
|
-
currentMatchRow,
|
|
168
|
-
toggledRows,
|
|
150
|
+
marks,
|
|
169
151
|
docRef,
|
|
170
152
|
columnWidthMode = "content",
|
|
171
153
|
}: TableProps) {
|
|
172
154
|
const { theme } = useTheme()
|
|
155
|
+
const palette = useGutterPalette()
|
|
173
156
|
const { width: terminalWidth } = useTerminalDimensions()
|
|
174
157
|
|
|
175
158
|
// Compute available content width: start with total space, subtract margins and gutter
|
|
176
|
-
const gutterWidth =
|
|
159
|
+
const gutterWidth = computeRowDocumentGutterWidth({
|
|
160
|
+
showLineNumbers,
|
|
161
|
+
rowCount: rows.length,
|
|
162
|
+
signColumnWidth: 1,
|
|
163
|
+
})
|
|
177
164
|
const effectiveMaxWidth = Math.max(0, (maxWidth ?? terminalWidth) - MARGIN * 2 - gutterWidth)
|
|
178
165
|
|
|
179
166
|
const headers = columns.map((column) => column.header ?? column.key)
|
|
@@ -197,37 +184,16 @@ export function Table({
|
|
|
197
184
|
return numericCount > sampleValues.length / 2
|
|
198
185
|
})
|
|
199
186
|
|
|
200
|
-
const internalRef = useRef<RowDocumentRenderable>(null)
|
|
201
|
-
const effectiveRef = docRef ?? internalRef
|
|
202
|
-
|
|
203
|
-
const palette: RowDocumentPalette = {
|
|
204
|
-
gutterFg: theme.textMuted,
|
|
205
|
-
gutterBg: theme.backgroundElement,
|
|
206
|
-
cursorSignFg: theme.primary,
|
|
207
|
-
matchSignFg: theme.warning,
|
|
208
|
-
currentMatchSignFg: theme.primary,
|
|
209
|
-
cursorBg: theme.cursorLine,
|
|
210
|
-
selectionBg: theme.selection,
|
|
211
|
-
matchBg: theme.warning,
|
|
212
|
-
currentMatchBg: theme.primary,
|
|
213
|
-
toggledBg: theme.backgroundPanel,
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
useEffect(() => {
|
|
217
|
-
const decorations: RowDocumentDecorations = {
|
|
218
|
-
cursorRow: cursor,
|
|
219
|
-
selection: selectionStart != null && selectionEnd != null
|
|
220
|
-
? { start: selectionStart, end: selectionEnd }
|
|
221
|
-
: null,
|
|
222
|
-
matchingRows: matchingRows,
|
|
223
|
-
currentMatchRow: currentMatchRow,
|
|
224
|
-
toggledRows: toggledRows,
|
|
225
|
-
}
|
|
226
|
-
effectiveRef.current?.setDecorations(decorations)
|
|
227
|
-
}, [cursor, selectionStart, selectionEnd, matchingRows, currentMatchRow, toggledRows])
|
|
228
|
-
|
|
229
187
|
return (
|
|
230
|
-
<box
|
|
188
|
+
<box
|
|
189
|
+
style={{
|
|
190
|
+
flexDirection: "column",
|
|
191
|
+
flexGrow: 1,
|
|
192
|
+
marginLeft: MARGIN,
|
|
193
|
+
marginRight: MARGIN,
|
|
194
|
+
marginBottom: MARGIN,
|
|
195
|
+
}}
|
|
196
|
+
>
|
|
231
197
|
{/* Fixed header row — outside row-document so it stays visible */}
|
|
232
198
|
<box style={{ flexDirection: "row", flexShrink: 0, paddingLeft: gutterWidth }}>
|
|
233
199
|
{headers.map((h, i) => (
|
|
@@ -254,13 +220,14 @@ export function Table({
|
|
|
254
220
|
|
|
255
221
|
{/* Scrollable data rows */}
|
|
256
222
|
<row-document
|
|
257
|
-
ref={
|
|
223
|
+
ref={docRef}
|
|
258
224
|
mode="multi"
|
|
259
225
|
rowChildOffset={0}
|
|
260
226
|
showGutter={true}
|
|
261
227
|
showLineNumbers={showLineNumbers}
|
|
262
228
|
signColumnWidth={1}
|
|
263
229
|
palette={palette}
|
|
230
|
+
decorations={marks?.sets}
|
|
264
231
|
style={{ flexGrow: 1 }}
|
|
265
232
|
>
|
|
266
233
|
{normalizedRows.map((row, i) => (
|
|
@@ -268,9 +235,10 @@ export function Table({
|
|
|
268
235
|
{row.map((cell, j) => {
|
|
269
236
|
const contentWidth = colWidths[j] - PADDING * 2
|
|
270
237
|
const cellWidth = Bun.stringWidth(cell)
|
|
271
|
-
const displayCell =
|
|
272
|
-
|
|
273
|
-
|
|
238
|
+
const displayCell =
|
|
239
|
+
alignments[j] && cellWidth <= contentWidth
|
|
240
|
+
? " ".repeat(contentWidth - cellWidth) + cell
|
|
241
|
+
: cell
|
|
274
242
|
return (
|
|
275
243
|
<text
|
|
276
244
|
key={j}
|
|
@@ -293,9 +261,5 @@ export function Table({
|
|
|
293
261
|
}
|
|
294
262
|
|
|
295
263
|
// Exported for testing and MarkdownView
|
|
296
|
-
export {
|
|
297
|
-
computeColumnWidths,
|
|
298
|
-
isNumeric,
|
|
299
|
-
sampleRows,
|
|
300
|
-
}
|
|
264
|
+
export { computeColumnWidths, isNumeric, sampleRows }
|
|
301
265
|
export type { ColumnWidthOptions }
|
package/src/index.ts
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
export { MarkdownView } from "./MarkdownView.js"
|
|
2
2
|
export { CodeView } from "./CodeView.js"
|
|
3
3
|
export { ImageView } from "./ImageView.js"
|
|
4
|
-
export {
|
|
5
|
-
Table,
|
|
6
|
-
computeColumnWidths,
|
|
7
|
-
isNumeric,
|
|
8
|
-
sampleRows,
|
|
9
|
-
} from "./Table.js"
|
|
4
|
+
export { Table, computeColumnWidths, isNumeric, sampleRows } from "./Table.js"
|
|
10
5
|
export type { TableProps, ColumnWidthOptions } from "./Table.js"
|
|
11
6
|
export type { ColumnDef, TableRow } from "./table-types.js"
|
|
12
7
|
export { CommandPalette } from "./CommandPalette.js"
|
|
@@ -14,8 +9,10 @@ export type { CommandPaletteEntry } from "./CommandPalette.js"
|
|
|
14
9
|
export { parseCSV, parseTSV, parseJSON, parseAuto, detectFormat } from "./parsers.js"
|
|
15
10
|
export type { Format, ParsedTable } from "./parsers.js"
|
|
16
11
|
export { RowDocumentRenderable } from "./RowDocumentRenderable.js"
|
|
12
|
+
export { computeRowDocumentGutterWidth } from "./RowDocumentRenderable.js"
|
|
17
13
|
export type {
|
|
18
14
|
RowDocumentOptions,
|
|
19
15
|
RowDocumentPalette,
|
|
20
|
-
RowDocumentDecorations,
|
|
21
16
|
} from "./RowDocumentRenderable.js"
|
|
17
|
+
export type { DecorationLayer, RowDecoration } from "./DecorationLayer.js"
|
|
18
|
+
export { useGutterPalette } from "./useGutterPalette.js"
|
package/src/parsers.ts
CHANGED
|
@@ -56,7 +56,10 @@ export function parseTSV(input: string): { columns: ColumnDef[]; rows: TableRow[
|
|
|
56
56
|
const lines = splitLines(input)
|
|
57
57
|
if (lines.length === 0) return { columns: [], rows: [] }
|
|
58
58
|
const columns = createColumnDefs(lines[0].split("\t"))
|
|
59
|
-
const rows = buildRows(
|
|
59
|
+
const rows = buildRows(
|
|
60
|
+
columns,
|
|
61
|
+
lines.slice(1).map((line) => line.split("\t")),
|
|
62
|
+
)
|
|
60
63
|
return { columns, rows }
|
|
61
64
|
}
|
|
62
65
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { useMemo } from "react"
|
|
2
|
+
import { useTheme } from "@tooee/themes"
|
|
3
|
+
import type { RowDocumentPalette } from "./RowDocumentRenderable.js"
|
|
4
|
+
|
|
5
|
+
export function useGutterPalette(): RowDocumentPalette {
|
|
6
|
+
const { theme } = useTheme()
|
|
7
|
+
|
|
8
|
+
return useMemo(
|
|
9
|
+
() => ({
|
|
10
|
+
gutterFg: theme.textMuted,
|
|
11
|
+
gutterBg: theme.backgroundElement,
|
|
12
|
+
}),
|
|
13
|
+
[theme.textMuted, theme.backgroundElement],
|
|
14
|
+
)
|
|
15
|
+
}
|