termcast 1.3.50 → 1.3.52
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/apis/environment.d.ts +1 -0
- package/dist/apis/environment.d.ts.map +1 -1
- package/dist/apis/environment.js +5 -0
- package/dist/apis/environment.js.map +1 -1
- package/dist/app.d.ts +33 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +1130 -0
- package/dist/app.js.map +1 -0
- package/dist/cli.js +80 -0
- package/dist/cli.js.map +1 -1
- package/dist/compile.d.ts.map +1 -1
- package/dist/compile.js +5 -2
- package/dist/compile.js.map +1 -1
- package/dist/components/actions.d.ts +4 -1
- package/dist/components/actions.d.ts.map +1 -1
- package/dist/components/actions.js +8 -5
- package/dist/components/actions.js.map +1 -1
- package/dist/components/detail.d.ts.map +1 -1
- package/dist/components/detail.js +21 -18
- package/dist/components/detail.js.map +1 -1
- package/dist/components/dropdown.d.ts.map +1 -1
- package/dist/components/dropdown.js +3 -2
- package/dist/components/dropdown.js.map +1 -1
- package/dist/components/footer.d.ts +6 -0
- package/dist/components/footer.d.ts.map +1 -1
- package/dist/components/footer.js +15 -6
- package/dist/components/footer.js.map +1 -1
- package/dist/components/form/checkbox.d.ts.map +1 -1
- package/dist/components/form/checkbox.js +1 -13
- package/dist/components/form/checkbox.js.map +1 -1
- package/dist/components/form/date-picker.js +2 -2
- package/dist/components/form/date-picker.js.map +1 -1
- package/dist/components/form/description.js +1 -1
- package/dist/components/form/description.js.map +1 -1
- package/dist/components/form/dropdown.d.ts.map +1 -1
- package/dist/components/form/dropdown.js +19 -3
- package/dist/components/form/dropdown.js.map +1 -1
- package/dist/components/form/file-picker.d.ts.map +1 -1
- package/dist/components/form/file-picker.js +22 -4
- package/dist/components/form/file-picker.js.map +1 -1
- package/dist/components/form/index.d.ts +3 -1
- package/dist/components/form/index.d.ts.map +1 -1
- package/dist/components/form/index.js +7 -5
- package/dist/components/form/index.js.map +1 -1
- package/dist/components/form/password-field.js +3 -3
- package/dist/components/form/password-field.js.map +1 -1
- package/dist/components/form/text-area.d.ts.map +1 -1
- package/dist/components/form/text-area.js +29 -6
- package/dist/components/form/text-area.js.map +1 -1
- package/dist/components/form/text-field.js +3 -3
- package/dist/components/form/text-field.js.map +1 -1
- package/dist/components/graph.d.ts.map +1 -1
- package/dist/components/graph.js +21 -25
- package/dist/components/graph.js.map +1 -1
- package/dist/components/heatmap.d.ts +80 -0
- package/dist/components/heatmap.d.ts.map +1 -0
- package/dist/components/heatmap.js +424 -0
- package/dist/components/heatmap.js.map +1 -0
- package/dist/components/list.d.ts +2 -0
- package/dist/components/list.d.ts.map +1 -1
- package/dist/components/list.js +91 -58
- package/dist/components/list.js.map +1 -1
- package/dist/components/markdown.d.ts +7 -0
- package/dist/components/markdown.d.ts.map +1 -0
- package/dist/components/markdown.js +19 -0
- package/dist/components/markdown.js.map +1 -0
- package/dist/components/metadata.d.ts.map +1 -1
- package/dist/components/metadata.js +4 -1
- package/dist/components/metadata.js.map +1 -1
- package/dist/components/progress-bar.d.ts +37 -0
- package/dist/components/progress-bar.d.ts.map +1 -0
- package/dist/components/progress-bar.js +34 -0
- package/dist/components/progress-bar.js.map +1 -0
- package/dist/components/table.d.ts +3 -2
- package/dist/components/table.d.ts.map +1 -1
- package/dist/components/table.js +78 -63
- package/dist/components/table.js.map +1 -1
- package/dist/diagram-parser.d.ts +17 -3
- package/dist/diagram-parser.d.ts.map +1 -1
- package/dist/diagram-parser.js +17 -3
- package/dist/diagram-parser.js.map +1 -1
- package/dist/examples/list-slot.d.ts +2 -0
- package/dist/examples/list-slot.d.ts.map +1 -0
- package/dist/examples/list-slot.js +14 -0
- package/dist/examples/list-slot.js.map +1 -0
- package/dist/examples/list-with-dropdown.js +2 -4
- package/dist/examples/list-with-dropdown.js.map +1 -1
- package/dist/examples/simple-heatmap.d.ts +2 -0
- package/dist/examples/simple-heatmap.d.ts.map +1 -0
- package/dist/examples/simple-heatmap.js +37 -0
- package/dist/examples/simple-heatmap.js.map +1 -0
- package/dist/examples/simple-progress-bar.d.ts +2 -0
- package/dist/examples/simple-progress-bar.d.ts.map +1 -0
- package/dist/examples/simple-progress-bar.js +36 -0
- package/dist/examples/simple-progress-bar.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/internal/date-picker-widget.d.ts.map +1 -1
- package/dist/internal/date-picker-widget.js +5 -4
- package/dist/internal/date-picker-widget.js.map +1 -1
- package/dist/internal/navigation.d.ts.map +1 -1
- package/dist/internal/navigation.js +7 -2
- package/dist/internal/navigation.js.map +1 -1
- package/dist/internal/providers.d.ts.map +1 -1
- package/dist/internal/providers.js +42 -4
- package/dist/internal/providers.js.map +1 -1
- package/dist/logger.js +6 -1
- package/dist/logger.js.map +1 -1
- package/dist/state.d.ts +2 -0
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js +31 -2
- package/dist/state.js.map +1 -1
- package/dist/theme.d.ts +1 -0
- package/dist/theme.d.ts.map +1 -1
- package/dist/theme.js +23 -1
- package/dist/theme.js.map +1 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +6 -1
- package/dist/utils.js.map +1 -1
- package/package.json +3 -3
- package/src/apis/environment.tsx +6 -0
- package/src/app.tsx +1492 -0
- package/src/assets/default-app-icon.png +0 -0
- package/src/cli.tsx +105 -0
- package/src/compile.tsx +5 -2
- package/src/components/actions.tsx +9 -6
- package/src/components/detail.tsx +33 -23
- package/src/components/dropdown.tsx +3 -2
- package/src/components/footer.tsx +40 -7
- package/src/components/form/checkbox.tsx +2 -17
- package/src/components/form/date-picker.tsx +2 -2
- package/src/components/form/description.tsx +1 -1
- package/src/components/form/dropdown.tsx +22 -3
- package/src/components/form/file-picker.tsx +33 -10
- package/src/components/form/index.tsx +11 -7
- package/src/components/form/password-field.tsx +3 -3
- package/src/components/form/text-area.tsx +31 -6
- package/src/components/form/text-field.tsx +3 -3
- package/src/components/graph.tsx +21 -24
- package/src/components/heatmap.tsx +602 -0
- package/src/components/list.tsx +147 -78
- package/src/components/markdown.tsx +30 -0
- package/src/components/metadata.tsx +9 -2
- package/src/components/progress-bar.tsx +112 -0
- package/src/components/table.tsx +88 -71
- package/src/diagram-parser.tsx +17 -3
- package/src/examples/bar-graph-weekly.vitest.tsx +4 -4
- package/src/examples/detail-metadata-showcase.vitest.tsx +12 -12
- package/src/examples/form-basic.vitest.tsx +117 -16
- package/src/examples/graph-bar-chart.vitest.tsx +7 -7
- package/src/examples/graph-row.vitest.tsx +45 -45
- package/src/examples/graph-styles.vitest.tsx +19 -19
- package/src/examples/internal/descendants-rerender.vitest.tsx +94 -46
- package/src/examples/internal/simple-scrollbox.vitest.tsx +38 -14
- package/src/examples/list-dropdown-default.vitest.tsx +78 -58
- package/src/examples/list-slot.tsx +38 -0
- package/src/examples/list-with-detail.vitest.tsx +8 -8
- package/src/examples/list-with-dropdown.tsx +2 -2
- package/src/examples/list-with-dropdown.vitest.tsx +16 -16
- package/src/examples/list-with-sections.vitest.tsx +45 -32
- package/src/examples/simple-detail-table.vitest.tsx +2 -2
- package/src/examples/simple-file-picker.vitest.tsx +1 -1
- package/src/examples/simple-grid.vitest.tsx +27 -53
- package/src/examples/simple-heatmap.tsx +63 -0
- package/src/examples/simple-heatmap.vitest.tsx +88 -0
- package/src/examples/simple-progress-bar.tsx +82 -0
- package/src/examples/simple-progress-bar.vitest.tsx +72 -0
- package/src/examples/table-edge-cases.vitest.tsx +1 -1
- package/src/index.tsx +19 -0
- package/src/internal/date-picker-widget.tsx +23 -12
- package/src/internal/navigation.tsx +7 -2
- package/src/internal/providers.tsx +48 -3
- package/src/logger.tsx +6 -1
- package/src/state.tsx +38 -2
- package/src/theme.tsx +26 -2
- package/src/utils.tsx +6 -1
|
@@ -15,7 +15,7 @@ import { useDialog } from 'termcast/src/internal/dialog'
|
|
|
15
15
|
import { Offscreen } from 'termcast/src/internal/offscreen'
|
|
16
16
|
import { useTheme } from 'termcast/src/theme'
|
|
17
17
|
import { useStore } from 'termcast/src/state'
|
|
18
|
-
import { Footer } from 'termcast/src/components/footer'
|
|
18
|
+
import { Footer, Hoverable } from 'termcast/src/components/footer'
|
|
19
19
|
import {
|
|
20
20
|
TextAttributes,
|
|
21
21
|
ScrollBoxRenderable,
|
|
@@ -77,7 +77,7 @@ export const useFormScrollContext = () => {
|
|
|
77
77
|
// Context for managing focused field and loading state
|
|
78
78
|
interface FocusContextValue {
|
|
79
79
|
focusedField: string | null
|
|
80
|
-
setFocusedField: (id: string | null) => void
|
|
80
|
+
setFocusedField: (id: string | null, opts?: { skipScroll?: boolean }) => void
|
|
81
81
|
isLoading: boolean
|
|
82
82
|
}
|
|
83
83
|
|
|
@@ -121,12 +121,16 @@ function FormFooter(): any {
|
|
|
121
121
|
</text>
|
|
122
122
|
<text flexShrink={0} fg={theme.textMuted}>navigate</text>
|
|
123
123
|
</box>
|
|
124
|
-
<
|
|
124
|
+
<Hoverable
|
|
125
|
+
onMouseDown={() => {
|
|
126
|
+
useStore.setState({ showActionsDialog: true })
|
|
127
|
+
}}
|
|
128
|
+
>
|
|
125
129
|
<text flexShrink={0} fg={theme.text} attributes={TextAttributes.BOLD}>
|
|
126
130
|
^k
|
|
127
131
|
</text>
|
|
128
132
|
<text flexShrink={0} fg={theme.textMuted}>actions</text>
|
|
129
|
-
</
|
|
133
|
+
</Hoverable>
|
|
130
134
|
</box>
|
|
131
135
|
)
|
|
132
136
|
|
|
@@ -221,11 +225,11 @@ export const Form: FormType = ((props) => {
|
|
|
221
225
|
scrollBox.scrollTo(Math.max(0, targetScrollTop))
|
|
222
226
|
}
|
|
223
227
|
|
|
224
|
-
const setFocusedField = (id: string | null) => {
|
|
228
|
+
const setFocusedField = (id: string | null, opts?: { skipScroll?: boolean }) => {
|
|
225
229
|
flushSync(() => {
|
|
226
230
|
setFocusedFieldRaw(id)
|
|
227
231
|
})
|
|
228
|
-
if (id) {
|
|
232
|
+
if (id && !opts?.skipScroll) {
|
|
229
233
|
scrollToField(id)
|
|
230
234
|
}
|
|
231
235
|
}
|
|
@@ -330,7 +334,7 @@ export const Form: FormType = ((props) => {
|
|
|
330
334
|
return
|
|
331
335
|
}
|
|
332
336
|
|
|
333
|
-
if (evt.name === 'k' && evt.ctrl) {
|
|
337
|
+
if (evt.name === 'k' && (evt.ctrl || evt.super)) {
|
|
334
338
|
// Always open — built-in actions (Change Theme, etc.) are always available
|
|
335
339
|
useStore.setState({ showActionsDialog: true })
|
|
336
340
|
} else if ((evt.name === 'return' && evt.ctrl) || (evt.name === 'return' && evt.meta)) {
|
|
@@ -40,12 +40,12 @@ export const PasswordField = (props: PasswordFieldProps): any => {
|
|
|
40
40
|
const displayValue = '*'.repeat(displayLength)
|
|
41
41
|
|
|
42
42
|
return (
|
|
43
|
-
<box ref={elementRef} flexDirection="column">
|
|
43
|
+
<box ref={elementRef} flexDirection="column" onMouseDown={() => { setFocusedField(props.id, { skipScroll: true }) }}>
|
|
44
44
|
<WithLeftBorder isFocused={isFocused} paddingBottom={1}>
|
|
45
45
|
<TitleIndicator isFocused={isFocused} isLoading={focusContext.isLoading}>
|
|
46
46
|
<box
|
|
47
47
|
onMouseDown={() => {
|
|
48
|
-
setFocusedField(props.id)
|
|
48
|
+
setFocusedField(props.id, { skipScroll: true })
|
|
49
49
|
}}
|
|
50
50
|
>
|
|
51
51
|
<LoadingText
|
|
@@ -83,7 +83,7 @@ export const PasswordField = (props: PasswordFieldProps): any => {
|
|
|
83
83
|
placeholder={props.placeholder}
|
|
84
84
|
focused={isFocused}
|
|
85
85
|
onMouseDown={() => {
|
|
86
|
-
setFocusedField(props.id)
|
|
86
|
+
setFocusedField(props.id, { skipScroll: true })
|
|
87
87
|
}}
|
|
88
88
|
/>
|
|
89
89
|
{(fieldState.error || props.error || props.info) && <box height={1} />}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import React, { useRef, useCallback } from 'react'
|
|
2
2
|
import { BoxRenderable, TextareaRenderable } from '@opentui/core'
|
|
3
|
+
import { useKeyboard } from '@opentui/react'
|
|
3
4
|
import { useFormContext } from 'react-hook-form'
|
|
4
5
|
import { useFocusContext, useFormFieldDescendant } from './index'
|
|
5
6
|
import { FormItemProps, FormItemRef } from './types'
|
|
6
7
|
import { useTheme } from 'termcast/src/theme'
|
|
7
8
|
import { WithLeftBorder, TitleIndicator } from './with-left-border'
|
|
8
|
-
import { useFormNavigation } from './use-form-navigation'
|
|
9
|
+
import { useFormNavigation, useFormNavigationHelpers } from './use-form-navigation'
|
|
9
10
|
import { createTextareaFormRef } from './form-ref'
|
|
11
|
+
import { useIsInFocus } from 'termcast/src/internal/focus-context'
|
|
10
12
|
import { LoadingText } from 'termcast/src/components/loading-text'
|
|
11
13
|
|
|
12
14
|
export interface TextAreaProps extends FormItemProps<string> {
|
|
@@ -21,7 +23,9 @@ export const TextArea = (props: TextAreaProps): any => {
|
|
|
21
23
|
const { register, formState } = useFormContext()
|
|
22
24
|
const focusContext = useFocusContext()
|
|
23
25
|
const { focusedField, setFocusedField } = focusContext
|
|
26
|
+
const isInFocus = useIsInFocus()
|
|
24
27
|
const isFocused = focusedField === props.id
|
|
28
|
+
const { navigateToPrevious, navigateToNext } = useFormNavigationHelpers(props.id)
|
|
25
29
|
|
|
26
30
|
const elementRef = useRef<BoxRenderable>(null)
|
|
27
31
|
const textareaRef = useRef<TextareaRenderable>(null)
|
|
@@ -32,8 +36,29 @@ export const TextArea = (props: TextAreaProps): any => {
|
|
|
32
36
|
elementRef: elementRef.current,
|
|
33
37
|
})
|
|
34
38
|
|
|
35
|
-
|
|
36
|
-
|
|
39
|
+
useFormNavigation(props.id, { handleArrows: false })
|
|
40
|
+
|
|
41
|
+
useKeyboard((evt) => {
|
|
42
|
+
if (!isFocused || !isInFocus) return
|
|
43
|
+
if (evt.name !== 'up' && evt.name !== 'down') return
|
|
44
|
+
|
|
45
|
+
const textarea = textareaRef.current
|
|
46
|
+
if (!textarea) return
|
|
47
|
+
|
|
48
|
+
const cursorLine = textarea.logicalCursor.row
|
|
49
|
+
const lastLine = textarea.lineCount - 1
|
|
50
|
+
|
|
51
|
+
if (evt.name === 'up' && cursorLine <= 0) {
|
|
52
|
+
navigateToPrevious()
|
|
53
|
+
evt.stopPropagation()
|
|
54
|
+
return
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (evt.name === 'down' && cursorLine >= lastLine) {
|
|
58
|
+
navigateToNext()
|
|
59
|
+
evt.stopPropagation()
|
|
60
|
+
}
|
|
61
|
+
})
|
|
37
62
|
|
|
38
63
|
// Get register props
|
|
39
64
|
const registration = register(props.id)
|
|
@@ -60,12 +85,12 @@ export const TextArea = (props: TextAreaProps): any => {
|
|
|
60
85
|
const fieldError = formState.errors[props.id]
|
|
61
86
|
|
|
62
87
|
return (
|
|
63
|
-
<box ref={elementRef} flexDirection="column">
|
|
88
|
+
<box ref={elementRef} flexDirection="column" onMouseDown={() => { setFocusedField(props.id, { skipScroll: true }) }}>
|
|
64
89
|
<WithLeftBorder isFocused={isFocused} paddingBottom={1}>
|
|
65
90
|
<TitleIndicator isFocused={isFocused} isLoading={focusContext.isLoading}>
|
|
66
91
|
<box
|
|
67
92
|
onMouseDown={() => {
|
|
68
|
-
setFocusedField(props.id)
|
|
93
|
+
setFocusedField(props.id, { skipScroll: true })
|
|
69
94
|
}}
|
|
70
95
|
>
|
|
71
96
|
<LoadingText
|
|
@@ -86,7 +111,7 @@ export const TextArea = (props: TextAreaProps): any => {
|
|
|
86
111
|
placeholder={props.placeholder}
|
|
87
112
|
focused={isFocused}
|
|
88
113
|
onMouseDown={() => {
|
|
89
|
-
setFocusedField(props.id)
|
|
114
|
+
setFocusedField(props.id, { skipScroll: true })
|
|
90
115
|
}}
|
|
91
116
|
/>
|
|
92
117
|
</box>
|
|
@@ -61,12 +61,12 @@ export const TextField = (props: TextFieldProps): any => {
|
|
|
61
61
|
const fieldError = formState.errors[props.id]
|
|
62
62
|
|
|
63
63
|
return (
|
|
64
|
-
<box ref={elementRef} flexDirection="column">
|
|
64
|
+
<box ref={elementRef} flexDirection="column" onMouseDown={() => { setFocusedField(props.id, { skipScroll: true }) }}>
|
|
65
65
|
<WithLeftBorder isFocused={isFocused} paddingBottom={1}>
|
|
66
66
|
<TitleIndicator isFocused={isFocused} isLoading={focusContext.isLoading}>
|
|
67
67
|
<box
|
|
68
68
|
onMouseDown={() => {
|
|
69
|
-
setFocusedField(props.id)
|
|
69
|
+
setFocusedField(props.id, { skipScroll: true })
|
|
70
70
|
}}
|
|
71
71
|
>
|
|
72
72
|
<LoadingText
|
|
@@ -90,7 +90,7 @@ export const TextField = (props: TextFieldProps): any => {
|
|
|
90
90
|
placeholder={props.placeholder}
|
|
91
91
|
focused={isFocused}
|
|
92
92
|
onMouseDown={() => {
|
|
93
|
-
setFocusedField(props.id)
|
|
93
|
+
setFocusedField(props.id, { skipScroll: true })
|
|
94
94
|
}}
|
|
95
95
|
/>
|
|
96
96
|
{(fieldError || props.error || props.info) && <box height={1} />}
|
package/src/components/graph.tsx
CHANGED
|
@@ -38,14 +38,15 @@ import { Color, resolveColor } from 'termcast/src/colors'
|
|
|
38
38
|
export type GraphVariant = 'area' | 'filled' | 'striped'
|
|
39
39
|
|
|
40
40
|
// ── Block characters for Filled/Striped modes ───────────────────────
|
|
41
|
-
// We use
|
|
42
|
-
//
|
|
43
|
-
//
|
|
44
|
-
//
|
|
45
|
-
//
|
|
46
|
-
|
|
47
|
-
const
|
|
48
|
-
const
|
|
41
|
+
// We use left-half and quadrant characters so each bar column is 50%
|
|
42
|
+
// cell width, creating visible vertical gaps between adjacent bars.
|
|
43
|
+
// ▌ = left half block (full height, left 50%)
|
|
44
|
+
// ▘ = quadrant upper left (top half height, left 50%)
|
|
45
|
+
// ▖ = quadrant lower left (bottom half height, left 50%)
|
|
46
|
+
// All three align at left 50%, maintaining 2x vertical sub-row resolution.
|
|
47
|
+
const LEFT_HALF = '▌' // U+258C
|
|
48
|
+
const QUAD_UL = '▘' // U+2598
|
|
49
|
+
const QUAD_LL = '▖' // U+2596
|
|
49
50
|
|
|
50
51
|
// ── Braille bit map ──────────────────────────────────────────────────
|
|
51
52
|
// Maps (subCol, subRow) to the braille bit for that dot position.
|
|
@@ -287,8 +288,8 @@ export class GraphPlotRenderable extends Renderable {
|
|
|
287
288
|
}
|
|
288
289
|
|
|
289
290
|
// ── Style: Filled / Striped (block characters) ───────────────
|
|
290
|
-
//
|
|
291
|
-
//
|
|
291
|
+
// Uses left-half and quadrant characters for thin bars with visible gaps.
|
|
292
|
+
// ▌ (left half) for full rows, ▘/▖ (quadrants) for top/bottom edge rows.
|
|
292
293
|
// Filled: every column uses the series color.
|
|
293
294
|
// Striped: all columns filled, even cols = stripeColor1, odd = stripeColor2.
|
|
294
295
|
// Pass a transparent color to skip those columns (gap-style bars).
|
|
@@ -323,10 +324,10 @@ export class GraphPlotRenderable extends Renderable {
|
|
|
323
324
|
const topVRow = lineY[col]!
|
|
324
325
|
if (topVRow >= virtualH) continue
|
|
325
326
|
|
|
326
|
-
// Fill from topVRow down
|
|
327
|
-
//
|
|
328
|
-
//
|
|
329
|
-
//
|
|
327
|
+
// Fill from topVRow down using left-half/quadrant chars.
|
|
328
|
+
// ▌: full height left-half (both sub-rows filled)
|
|
329
|
+
// ▘: upper-left quadrant (top sub-row only)
|
|
330
|
+
// ▖: lower-left quadrant (bottom sub-row only)
|
|
330
331
|
for (let row = 0; row < plotH; row++) {
|
|
331
332
|
const vTop = row * 2 // virtual row for top half
|
|
332
333
|
const vBot = row * 2 + 1 // virtual row for bottom half
|
|
@@ -336,18 +337,14 @@ export class GraphPlotRenderable extends Renderable {
|
|
|
336
337
|
if (!topFilled && !botFilled) continue
|
|
337
338
|
|
|
338
339
|
if (topFilled && botFilled) {
|
|
339
|
-
// Both halves:
|
|
340
|
-
buffer.setCell(plotX + col, plotY + row,
|
|
340
|
+
// Both halves: ▌ left half block
|
|
341
|
+
buffer.setCell(plotX + col, plotY + row, LEFT_HALF, fillColor, transparent)
|
|
341
342
|
} else if (topFilled) {
|
|
342
|
-
// Top only:
|
|
343
|
-
buffer.setCell(plotX + col, plotY + row,
|
|
344
|
-
} else if (topVRow >= virtualH - 1) {
|
|
345
|
-
// Minimum fill: only the very last virtual row is filled (zero/min value).
|
|
346
|
-
// Use ▁ (lower 1/8 block) for a thin baseline indicator.
|
|
347
|
-
buffer.setCell(plotX + col, plotY + row, LOWER_EIGHTH, fillColor, transparent)
|
|
343
|
+
// Top only: ▘ quadrant upper left
|
|
344
|
+
buffer.setCell(plotX + col, plotY + row, QUAD_UL, fillColor, transparent)
|
|
348
345
|
} else {
|
|
349
|
-
// Bottom only:
|
|
350
|
-
buffer.setCell(plotX + col, plotY + row,
|
|
346
|
+
// Bottom only: ▖ quadrant lower left
|
|
347
|
+
buffer.setCell(plotX + col, plotY + row, QUAD_LL, fillColor, transparent)
|
|
351
348
|
}
|
|
352
349
|
}
|
|
353
350
|
}
|