@effect-tui/react 0.15.2 → 0.16.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.md +2 -2
- package/dist/src/components/ListView.d.ts +4 -4
- package/dist/src/components/ListView.d.ts.map +1 -1
- package/dist/src/components/ListView.js +16 -17
- package/dist/src/components/ListView.js.map +1 -1
- package/dist/src/console/ConsolePopover.d.ts +7 -1
- package/dist/src/console/ConsolePopover.d.ts.map +1 -1
- package/dist/src/console/ConsolePopover.js +55 -74
- package/dist/src/console/ConsolePopover.js.map +1 -1
- package/dist/src/debug/DebugOverlay.d.ts.map +1 -1
- package/dist/src/debug/DebugOverlay.js +3 -57
- package/dist/src/debug/DebugOverlay.js.map +1 -1
- package/dist/src/debug/DiagnosticsPanel.js +1 -1
- package/dist/src/debug/DiagnosticsPanel.js.map +1 -1
- package/dist/src/dev.d.ts +5 -117
- package/dist/src/dev.d.ts.map +1 -1
- package/dist/src/dev.js +3 -333
- package/dist/src/dev.js.map +1 -1
- package/dist/src/hooks/use-scroll.d.ts +31 -35
- package/dist/src/hooks/use-scroll.d.ts.map +1 -1
- package/dist/src/hooks/use-scroll.js +51 -90
- package/dist/src/hooks/use-scroll.js.map +1 -1
- package/dist/src/hosts/canvas.d.ts +2 -2
- package/dist/src/hosts/canvas.d.ts.map +1 -1
- package/dist/src/hosts/canvas.js +8 -10
- package/dist/src/hosts/canvas.js.map +1 -1
- package/dist/src/hosts/codeblock.d.ts +2 -2
- package/dist/src/hosts/codeblock.js +2 -2
- package/dist/src/hosts/flex-container.d.ts +1 -1
- package/dist/src/hosts/flex-container.d.ts.map +1 -1
- package/dist/src/hosts/flex-container.js +3 -3
- package/dist/src/hosts/flex-container.js.map +1 -1
- package/dist/src/hosts/index.d.ts +2 -1
- package/dist/src/hosts/index.d.ts.map +1 -1
- package/dist/src/hosts/index.js +2 -1
- package/dist/src/hosts/index.js.map +1 -1
- package/dist/src/hosts/layout-helpers.d.ts +10 -0
- package/dist/src/hosts/layout-helpers.d.ts.map +1 -0
- package/dist/src/hosts/layout-helpers.js +10 -0
- package/dist/src/hosts/layout-helpers.js.map +1 -0
- package/dist/src/hosts/leaf.d.ts +14 -0
- package/dist/src/hosts/leaf.d.ts.map +1 -0
- package/dist/src/hosts/leaf.js +31 -0
- package/dist/src/hosts/leaf.js.map +1 -0
- package/dist/src/hosts/overlay.d.ts.map +1 -1
- package/dist/src/hosts/overlay.js +4 -7
- package/dist/src/hosts/overlay.js.map +1 -1
- package/dist/src/hosts/scroll.d.ts +47 -24
- package/dist/src/hosts/scroll.d.ts.map +1 -1
- package/dist/src/hosts/scroll.js +68 -51
- package/dist/src/hosts/scroll.js.map +1 -1
- package/dist/src/hosts/spacer.d.ts +2 -2
- package/dist/src/hosts/spacer.js +2 -2
- package/dist/src/hosts/text.d.ts +2 -3
- package/dist/src/hosts/text.d.ts.map +1 -1
- package/dist/src/hosts/text.js +5 -61
- package/dist/src/hosts/text.js.map +1 -1
- package/dist/src/hosts/vstack.js +1 -1
- package/dist/src/hosts/vstack.js.map +1 -1
- package/dist/src/hosts/zstack.d.ts +1 -1
- package/dist/src/hosts/zstack.d.ts.map +1 -1
- package/dist/src/hosts/zstack.js +6 -6
- package/dist/src/hosts/zstack.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/internal/dev/hmr.d.ts +20 -0
- package/dist/src/internal/dev/hmr.d.ts.map +1 -0
- package/dist/src/internal/dev/hmr.js +93 -0
- package/dist/src/internal/dev/hmr.js.map +1 -0
- package/dist/src/internal/dev/runtime.d.ts +24 -0
- package/dist/src/internal/dev/runtime.d.ts.map +1 -0
- package/dist/src/internal/dev/runtime.js +135 -0
- package/dist/src/internal/dev/runtime.js.map +1 -0
- package/dist/src/internal/dev/ui.d.ts +13 -0
- package/dist/src/internal/dev/ui.d.ts.map +1 -0
- package/dist/src/internal/dev/ui.js +51 -0
- package/dist/src/internal/dev/ui.js.map +1 -0
- package/dist/src/internal/renderer/context.d.ts +9 -0
- package/dist/src/internal/renderer/context.d.ts.map +1 -0
- package/dist/src/internal/renderer/context.js +22 -0
- package/dist/src/internal/renderer/context.js.map +1 -0
- package/dist/src/internal/renderer/core/FrameBuilder.d.ts +18 -0
- package/dist/src/internal/renderer/core/FrameBuilder.d.ts.map +1 -0
- package/dist/src/internal/renderer/core/FrameBuilder.js +40 -0
- package/dist/src/internal/renderer/core/FrameBuilder.js.map +1 -0
- package/dist/src/internal/renderer/core/RendererState.d.ts +41 -0
- package/dist/src/internal/renderer/core/RendererState.d.ts.map +1 -0
- package/dist/src/internal/renderer/core/RendererState.js +70 -0
- package/dist/src/internal/renderer/core/RendererState.js.map +1 -0
- package/dist/src/internal/renderer/core/index.d.ts +3 -0
- package/dist/src/internal/renderer/core/index.d.ts.map +1 -0
- package/dist/src/internal/renderer/core/index.js +3 -0
- package/dist/src/internal/renderer/core/index.js.map +1 -0
- package/dist/src/internal/renderer/index.d.ts +40 -0
- package/dist/src/internal/renderer/index.d.ts.map +1 -0
- package/dist/src/internal/renderer/index.js +518 -0
- package/dist/src/internal/renderer/index.js.map +1 -0
- package/dist/src/internal/renderer/input/InputProcessor.d.ts +30 -0
- package/dist/src/internal/renderer/input/InputProcessor.d.ts.map +1 -0
- package/dist/src/internal/renderer/input/InputProcessor.js +122 -0
- package/dist/src/internal/renderer/input/InputProcessor.js.map +1 -0
- package/dist/src/internal/renderer/input/index.d.ts +2 -0
- package/dist/src/internal/renderer/input/index.d.ts.map +1 -0
- package/dist/src/internal/renderer/input/index.js +2 -0
- package/dist/src/internal/renderer/input/index.js.map +1 -0
- package/dist/src/internal/renderer/lifecycle/EventBus.d.ts +42 -0
- package/dist/src/internal/renderer/lifecycle/EventBus.d.ts.map +1 -0
- package/dist/src/internal/renderer/lifecycle/EventBus.js +97 -0
- package/dist/src/internal/renderer/lifecycle/EventBus.js.map +1 -0
- package/dist/src/internal/renderer/lifecycle/ProcessLifecycle.d.ts +13 -0
- package/dist/src/internal/renderer/lifecycle/ProcessLifecycle.d.ts.map +1 -0
- package/dist/src/internal/renderer/lifecycle/ProcessLifecycle.js +111 -0
- package/dist/src/internal/renderer/lifecycle/ProcessLifecycle.js.map +1 -0
- package/dist/src/internal/renderer/lifecycle/RenderCache.d.ts +3 -0
- package/dist/src/internal/renderer/lifecycle/RenderCache.d.ts.map +1 -0
- package/dist/src/internal/renderer/lifecycle/RenderCache.js +9 -0
- package/dist/src/internal/renderer/lifecycle/RenderCache.js.map +1 -0
- package/dist/src/internal/renderer/lifecycle/index.d.ts +4 -0
- package/dist/src/internal/renderer/lifecycle/index.d.ts.map +1 -0
- package/dist/src/internal/renderer/lifecycle/index.js +4 -0
- package/dist/src/internal/renderer/lifecycle/index.js.map +1 -0
- package/dist/src/internal/renderer/modes/FullscreenRenderer.d.ts +12 -0
- package/dist/src/internal/renderer/modes/FullscreenRenderer.d.ts.map +1 -0
- package/dist/src/internal/renderer/modes/FullscreenRenderer.js +54 -0
- package/dist/src/internal/renderer/modes/FullscreenRenderer.js.map +1 -0
- package/dist/src/internal/renderer/modes/InlineRenderer.d.ts +25 -0
- package/dist/src/internal/renderer/modes/InlineRenderer.d.ts.map +1 -0
- package/dist/src/internal/renderer/modes/InlineRenderer.js +166 -0
- package/dist/src/internal/renderer/modes/InlineRenderer.js.map +1 -0
- package/dist/src/internal/renderer/modes/RendererMode.d.ts +42 -0
- package/dist/src/internal/renderer/modes/RendererMode.d.ts.map +1 -0
- package/dist/src/internal/renderer/modes/RendererMode.js +2 -0
- package/dist/src/internal/renderer/modes/RendererMode.js.map +1 -0
- package/dist/src/internal/renderer/modes/StaticContentRenderer.d.ts +25 -0
- package/dist/src/internal/renderer/modes/StaticContentRenderer.d.ts.map +1 -0
- package/dist/src/internal/renderer/modes/StaticContentRenderer.js +49 -0
- package/dist/src/internal/renderer/modes/StaticContentRenderer.js.map +1 -0
- package/dist/src/internal/renderer/modes/index.d.ts +5 -0
- package/dist/src/internal/renderer/modes/index.d.ts.map +1 -0
- package/dist/src/internal/renderer/modes/index.js +4 -0
- package/dist/src/internal/renderer/modes/index.js.map +1 -0
- package/dist/src/internal/renderer/terminal/KeyboardCapabilityProbe.d.ts +13 -0
- package/dist/src/internal/renderer/terminal/KeyboardCapabilityProbe.d.ts.map +1 -0
- package/dist/src/internal/renderer/terminal/KeyboardCapabilityProbe.js +75 -0
- package/dist/src/internal/renderer/terminal/KeyboardCapabilityProbe.js.map +1 -0
- package/dist/src/internal/renderer/terminal/TerminalSetup.d.ts +29 -0
- package/dist/src/internal/renderer/terminal/TerminalSetup.d.ts.map +1 -0
- package/dist/src/internal/renderer/terminal/TerminalSetup.js +82 -0
- package/dist/src/internal/renderer/terminal/TerminalSetup.js.map +1 -0
- package/dist/src/internal/renderer/terminal/index.d.ts +3 -0
- package/dist/src/internal/renderer/terminal/index.d.ts.map +1 -0
- package/dist/src/internal/renderer/terminal/index.js +3 -0
- package/dist/src/internal/renderer/terminal/index.js.map +1 -0
- package/dist/src/internal/renderer/types.d.ts +118 -0
- package/dist/src/internal/renderer/types.d.ts.map +1 -0
- package/dist/src/internal/renderer/types.js +2 -0
- package/dist/src/internal/renderer/types.js.map +1 -0
- package/dist/src/renderer-context.d.ts +1 -8
- package/dist/src/renderer-context.d.ts.map +1 -1
- package/dist/src/renderer-context.js +1 -21
- package/dist/src/renderer-context.js.map +1 -1
- package/dist/src/renderer-types.d.ts +1 -115
- package/dist/src/renderer-types.d.ts.map +1 -1
- package/dist/src/renderer.d.ts +1 -31
- package/dist/src/renderer.d.ts.map +1 -1
- package/dist/src/renderer.js +1 -495
- package/dist/src/renderer.js.map +1 -1
- package/dist/src/test/render-tui.d.ts +3 -3
- package/dist/src/test/render-tui.d.ts.map +1 -1
- package/dist/src/test/render-tui.js +16 -9
- package/dist/src/test/render-tui.js.map +1 -1
- package/dist/src/utils/alignment.d.ts +1 -1
- package/dist/src/utils/alignment.d.ts.map +1 -1
- package/dist/src/utils/alignment.js +0 -2
- package/dist/src/utils/alignment.js.map +1 -1
- package/dist/src/utils/console-helpers.d.ts +19 -0
- package/dist/src/utils/console-helpers.d.ts.map +1 -0
- package/dist/src/utils/console-helpers.js +61 -0
- package/dist/src/utils/console-helpers.js.map +1 -0
- 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/src/utils/styles.d.ts +8 -1
- package/dist/src/utils/styles.d.ts.map +1 -1
- package/dist/src/utils/styles.js +10 -8
- package/dist/src/utils/styles.js.map +1 -1
- package/dist/src/utils/text-wrap.d.ts +5 -0
- package/dist/src/utils/text-wrap.d.ts.map +1 -1
- package/dist/src/utils/text-wrap.js +110 -48
- package/dist/src/utils/text-wrap.js.map +1 -1
- package/dist/src/visualize/index.js +1 -1
- package/dist/src/visualize/index.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/components/ListView.tsx +21 -23
- package/src/console/ConsolePopover.tsx +124 -107
- package/src/debug/DebugOverlay.ts +15 -74
- package/src/debug/DiagnosticsPanel.tsx +1 -1
- package/src/dev.tsx +5 -458
- package/src/hooks/use-scroll.ts +85 -145
- package/src/hosts/canvas.ts +8 -11
- package/src/hosts/codeblock.ts +2 -2
- package/src/hosts/flex-container.ts +4 -4
- package/src/hosts/index.ts +10 -1
- package/src/hosts/layout-helpers.ts +20 -0
- package/src/hosts/leaf.ts +36 -0
- package/src/hosts/overlay.ts +11 -9
- package/src/hosts/scroll.ts +94 -69
- package/src/hosts/spacer.ts +2 -2
- package/src/hosts/text.ts +5 -58
- package/src/hosts/vstack.ts +1 -1
- package/src/hosts/zstack.ts +7 -7
- package/src/index.ts +1 -1
- package/src/internal/dev/hmr.ts +101 -0
- package/src/internal/dev/runtime.ts +170 -0
- package/src/internal/dev/ui.tsx +87 -0
- package/src/internal/renderer/context.ts +27 -0
- package/src/{renderer → internal/renderer}/core/FrameBuilder.ts +2 -2
- package/src/internal/renderer/index.ts +656 -0
- package/src/{renderer → internal/renderer}/input/InputProcessor.ts +10 -1
- package/src/{renderer → internal/renderer}/lifecycle/EventBus.ts +9 -1
- package/src/internal/renderer/lifecycle/ProcessLifecycle.ts +125 -0
- package/src/internal/renderer/lifecycle/index.ts +3 -0
- package/src/{renderer → internal/renderer}/modes/InlineRenderer.ts +5 -2
- package/src/{renderer → internal/renderer}/modes/RendererMode.ts +1 -1
- package/src/{renderer → internal/renderer}/modes/StaticContentRenderer.ts +5 -2
- package/src/internal/renderer/terminal/KeyboardCapabilityProbe.ts +91 -0
- package/src/{renderer/lifecycle → internal/renderer/terminal}/TerminalSetup.ts +4 -22
- package/src/internal/renderer/terminal/index.ts +2 -0
- package/src/internal/renderer/types.ts +125 -0
- package/src/renderer-context.ts +1 -27
- package/src/renderer-types.ts +10 -123
- package/src/renderer.ts +1 -619
- package/src/test/render-tui.ts +16 -10
- package/src/utils/alignment.ts +1 -3
- package/src/utils/console-helpers.ts +86 -0
- package/src/utils/index.ts +1 -1
- package/src/utils/styles.ts +16 -4
- package/src/utils/text-wrap.ts +139 -48
- package/src/visualize/index.tsx +1 -1
- package/src/renderer/lifecycle/ResizeManager.ts +0 -65
- package/src/renderer/lifecycle/index.ts +0 -4
- /package/src/{renderer → internal/renderer}/core/RendererState.ts +0 -0
- /package/src/{renderer → internal/renderer}/core/index.ts +0 -0
- /package/src/{renderer → internal/renderer}/input/index.ts +0 -0
- /package/src/{renderer → internal/renderer}/lifecycle/RenderCache.ts +0 -0
- /package/src/{renderer → internal/renderer}/modes/FullscreenRenderer.ts +0 -0
- /package/src/{renderer → internal/renderer}/modes/index.ts +0 -0
package/src/hooks/use-scroll.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import type { KeyMsg } from "@effect-tui/core"
|
|
4
4
|
import { useCallback, useLayoutEffect, useMemo, useReducer, useRef } from "react"
|
|
5
|
-
import type { ScrollProps } from "../hosts/scroll.js"
|
|
5
|
+
import type { ScrollAlign, ScrollAxis, ScrollLayoutChange, ScrollProps } from "../hosts/scroll.js"
|
|
6
6
|
import { useTerminalSize } from "../renderer.js"
|
|
7
7
|
import { useKeyboard } from "./use-keyboard.js"
|
|
8
8
|
|
|
@@ -86,21 +86,21 @@ class MacOSScrollAccel implements ScrollAcceleration {
|
|
|
86
86
|
// ============================================================================
|
|
87
87
|
|
|
88
88
|
export interface ScrollState {
|
|
89
|
-
/** Current
|
|
90
|
-
|
|
91
|
-
/** Maximum
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
|
|
95
|
-
/** Whether viewport size has been measured by the host
|
|
96
|
-
|
|
97
|
-
/** Total content size
|
|
98
|
-
|
|
99
|
-
/** Whether we're at the
|
|
100
|
-
|
|
101
|
-
/** Whether we're at the
|
|
102
|
-
|
|
103
|
-
/** Current horizontal offset (pixels from
|
|
89
|
+
/** Current vertical offset (pixels from top) */
|
|
90
|
+
offsetY: number
|
|
91
|
+
/** Maximum vertical offset */
|
|
92
|
+
maxOffsetY: number
|
|
93
|
+
/** Vertical viewport size */
|
|
94
|
+
viewportSizeY: number
|
|
95
|
+
/** Whether vertical viewport size has been measured by the host */
|
|
96
|
+
viewportMeasuredY: boolean
|
|
97
|
+
/** Total vertical content size */
|
|
98
|
+
contentSizeY: number
|
|
99
|
+
/** Whether we're at the top edge */
|
|
100
|
+
atStartY: boolean
|
|
101
|
+
/** Whether we're at the bottom edge */
|
|
102
|
+
atEndY: boolean
|
|
103
|
+
/** Current horizontal offset (pixels from left) */
|
|
104
104
|
offsetX: number
|
|
105
105
|
/** Maximum horizontal offset */
|
|
106
106
|
maxOffsetX: number
|
|
@@ -118,31 +118,25 @@ export interface ScrollState {
|
|
|
118
118
|
|
|
119
119
|
export interface UseScrollOptions {
|
|
120
120
|
/** Scroll axis: "vertical" (default), "horizontal", or "both" */
|
|
121
|
-
axis?:
|
|
122
|
-
/** Controlled content size for the primary axis (skips host measurement when provided) */
|
|
123
|
-
contentSize?: number
|
|
121
|
+
axis?: ScrollAxis
|
|
124
122
|
/** Controlled content width (skips host measurement when provided) */
|
|
125
123
|
contentWidth?: number
|
|
126
124
|
/** Controlled content height (skips host measurement when provided) */
|
|
127
125
|
contentHeight?: number
|
|
128
|
-
/** @internal Initial viewport size override (useful for tests) */
|
|
129
|
-
initialViewportSize?: number
|
|
130
126
|
/** @internal Initial viewport width override (useful for tests) */
|
|
131
127
|
initialViewportWidth?: number
|
|
132
128
|
/** @internal Initial viewport height override (useful for tests) */
|
|
133
129
|
initialViewportHeight?: number
|
|
134
|
-
/** @internal Initial content size override (useful for tests) */
|
|
135
|
-
initialContentSize?: number
|
|
136
130
|
/** @internal Initial content width override (useful for tests) */
|
|
137
131
|
initialContentWidth?: number
|
|
138
132
|
/** @internal Initial content height override (useful for tests) */
|
|
139
133
|
initialContentHeight?: number
|
|
140
|
-
/** Initial scroll offset
|
|
141
|
-
|
|
134
|
+
/** Initial vertical scroll offset */
|
|
135
|
+
initialOffsetY?: number
|
|
142
136
|
/** Initial horizontal scroll offset */
|
|
143
137
|
initialOffsetX?: number
|
|
144
138
|
/** Alignment when content is smaller than viewport */
|
|
145
|
-
align?:
|
|
139
|
+
align?: ScrollAlign
|
|
146
140
|
/** Whether to show scrollbars */
|
|
147
141
|
showScrollbar?: boolean
|
|
148
142
|
/** Enable keyboard navigation (default: true) */
|
|
@@ -157,23 +151,25 @@ export interface UseScrollOptions {
|
|
|
157
151
|
arrowSpeed?: number
|
|
158
152
|
/** Scroll speed for page up/down (fraction of viewport, default: 0.5) */
|
|
159
153
|
pageSpeed?: number
|
|
154
|
+
/** Optional layout callback (content/viewport/offset/rect). */
|
|
155
|
+
onScrollLayoutChange?: (event: ScrollLayoutChange) => void
|
|
160
156
|
}
|
|
161
157
|
|
|
162
158
|
export interface UseScrollReturn {
|
|
163
159
|
/** Current scroll state */
|
|
164
160
|
state: ScrollState
|
|
165
|
-
/** Set scroll offset directly
|
|
166
|
-
|
|
161
|
+
/** Set vertical scroll offset directly */
|
|
162
|
+
setOffsetY: (offsetY: number) => void
|
|
167
163
|
/** Set horizontal scroll offset directly */
|
|
168
164
|
setOffsetX: (offsetX: number) => void
|
|
169
|
-
/** Scroll by delta pixels
|
|
170
|
-
|
|
165
|
+
/** Scroll by delta pixels vertically */
|
|
166
|
+
scrollByY: (delta: number) => void
|
|
171
167
|
/** Scroll by delta pixels horizontally */
|
|
172
168
|
scrollByX: (delta: number) => void
|
|
173
|
-
/** Scroll to
|
|
174
|
-
|
|
175
|
-
/** Scroll to
|
|
176
|
-
|
|
169
|
+
/** Scroll to top */
|
|
170
|
+
scrollToStartY: () => void
|
|
171
|
+
/** Scroll to bottom */
|
|
172
|
+
scrollToEndY: () => void
|
|
177
173
|
/** Scroll to horizontal start */
|
|
178
174
|
scrollToStartX: () => void
|
|
179
175
|
/** Scroll to horizontal end */
|
|
@@ -187,7 +183,7 @@ export interface UseScrollReturn {
|
|
|
187
183
|
* @param totalSize - Optional known total content size (avoids stale state issues)
|
|
188
184
|
* @param axis - Axis to scroll (defaults to vertical)
|
|
189
185
|
*/
|
|
190
|
-
|
|
186
|
+
scrollIntoView: (
|
|
191
187
|
position: number,
|
|
192
188
|
itemSize?: number,
|
|
193
189
|
padding?: number,
|
|
@@ -287,18 +283,15 @@ const reduceScroll = (state: ScrollInternalState, action: ScrollAction): ScrollI
|
|
|
287
283
|
export function useScroll(options: UseScrollOptions = {}): UseScrollReturn {
|
|
288
284
|
const {
|
|
289
285
|
axis = "vertical",
|
|
290
|
-
contentSize,
|
|
291
286
|
contentWidth,
|
|
292
287
|
contentHeight,
|
|
293
|
-
initialViewportSize,
|
|
294
288
|
initialViewportWidth,
|
|
295
289
|
initialViewportHeight,
|
|
296
|
-
initialContentSize,
|
|
297
290
|
initialContentWidth,
|
|
298
291
|
initialContentHeight,
|
|
299
|
-
|
|
292
|
+
initialOffsetY = 0,
|
|
300
293
|
initialOffsetX = 0,
|
|
301
|
-
align
|
|
294
|
+
align,
|
|
302
295
|
showScrollbar = true,
|
|
303
296
|
enableKeyboard = true,
|
|
304
297
|
enableMouseWheel = true,
|
|
@@ -306,31 +299,30 @@ export function useScroll(options: UseScrollOptions = {}): UseScrollReturn {
|
|
|
306
299
|
sticky = false,
|
|
307
300
|
arrowSpeed = 1,
|
|
308
301
|
pageSpeed = 0.5,
|
|
302
|
+
onScrollLayoutChange,
|
|
309
303
|
} = options
|
|
310
304
|
|
|
311
305
|
const { width: termWidth, height: termHeight } = useTerminalSize()
|
|
312
306
|
const enableY = axis === "vertical" || axis === "both"
|
|
313
307
|
const enableX = axis === "horizontal" || axis === "both"
|
|
314
|
-
const
|
|
308
|
+
const useHorizontalPrimary = axis === "horizontal"
|
|
315
309
|
|
|
316
|
-
const controlledContentHeight = contentHeight
|
|
317
|
-
const controlledContentWidth = contentWidth
|
|
310
|
+
const controlledContentHeight = contentHeight
|
|
311
|
+
const controlledContentWidth = contentWidth
|
|
318
312
|
|
|
319
|
-
const baseViewportHeight =
|
|
320
|
-
|
|
321
|
-
const baseViewportWidth =
|
|
322
|
-
initialViewportWidth ?? (axis === "horizontal" ? initialViewportSize : undefined) ?? termWidth
|
|
313
|
+
const baseViewportHeight = initialViewportHeight ?? termHeight
|
|
314
|
+
const baseViewportWidth = initialViewportWidth ?? termWidth
|
|
323
315
|
|
|
324
316
|
const baseContentHeight =
|
|
325
|
-
controlledContentHeight ?? initialContentHeight ??
|
|
317
|
+
controlledContentHeight ?? initialContentHeight ?? 0
|
|
326
318
|
const baseContentWidth =
|
|
327
|
-
controlledContentWidth ?? initialContentWidth ??
|
|
319
|
+
controlledContentWidth ?? initialContentWidth ?? 0
|
|
328
320
|
|
|
329
|
-
const
|
|
330
|
-
const initialOffsetXResolved = axis === "
|
|
321
|
+
const initialOffsetYResolved = axis === "horizontal" ? 0 : initialOffsetY
|
|
322
|
+
const initialOffsetXResolved = axis === "vertical" ? 0 : initialOffsetX
|
|
331
323
|
|
|
332
324
|
const [internalY, dispatchY] = useReducer(reduceScroll, {
|
|
333
|
-
offset: clampOffset(
|
|
325
|
+
offset: clampOffset(initialOffsetYResolved, baseContentHeight, baseViewportHeight),
|
|
334
326
|
contentSize: baseContentHeight,
|
|
335
327
|
viewportSize: baseViewportHeight,
|
|
336
328
|
viewportMeasured: false,
|
|
@@ -398,17 +390,6 @@ export function useScroll(options: UseScrollOptions = {}): UseScrollReturn {
|
|
|
398
390
|
[dispatchX, enableX],
|
|
399
391
|
)
|
|
400
392
|
|
|
401
|
-
const scrollBy = useCallback(
|
|
402
|
-
(delta: number) => {
|
|
403
|
-
if (primaryAxis === "horizontal") {
|
|
404
|
-
scrollByX(delta)
|
|
405
|
-
} else {
|
|
406
|
-
scrollByY(delta)
|
|
407
|
-
}
|
|
408
|
-
},
|
|
409
|
-
[primaryAxis, scrollByX, scrollByY],
|
|
410
|
-
)
|
|
411
|
-
|
|
412
393
|
const scrollToStartY = useCallback(() => {
|
|
413
394
|
dispatchY({ type: "set-offset", offset: 0 })
|
|
414
395
|
accumulatorYRef.current = 0
|
|
@@ -421,14 +402,6 @@ export function useScroll(options: UseScrollOptions = {}): UseScrollReturn {
|
|
|
421
402
|
accelX.reset()
|
|
422
403
|
}, [dispatchX, accelX])
|
|
423
404
|
|
|
424
|
-
const scrollToStart = useCallback(() => {
|
|
425
|
-
if (primaryAxis === "horizontal") {
|
|
426
|
-
scrollToStartX()
|
|
427
|
-
} else {
|
|
428
|
-
scrollToStartY()
|
|
429
|
-
}
|
|
430
|
-
}, [primaryAxis, scrollToStartX, scrollToStartY])
|
|
431
|
-
|
|
432
405
|
const scrollToEndY = useCallback(() => {
|
|
433
406
|
const current = stateYRef.current
|
|
434
407
|
const maxOffset = Math.max(0, current.contentSize - current.viewportSize)
|
|
@@ -445,27 +418,6 @@ export function useScroll(options: UseScrollOptions = {}): UseScrollReturn {
|
|
|
445
418
|
accelX.reset()
|
|
446
419
|
}, [dispatchX, accelX])
|
|
447
420
|
|
|
448
|
-
const scrollToEnd = useCallback(() => {
|
|
449
|
-
if (primaryAxis === "horizontal") {
|
|
450
|
-
scrollToEndX()
|
|
451
|
-
} else {
|
|
452
|
-
scrollToEndY()
|
|
453
|
-
}
|
|
454
|
-
}, [primaryAxis, scrollToEndX, scrollToEndY])
|
|
455
|
-
|
|
456
|
-
// Handle content size changes (for sticky scroll)
|
|
457
|
-
const handleContentSize = useCallback(
|
|
458
|
-
(width: number, height: number) => {
|
|
459
|
-
if (enableY && controlledContentHeight === undefined) {
|
|
460
|
-
dispatchY({ type: "set-content", size: height })
|
|
461
|
-
}
|
|
462
|
-
if (enableX && controlledContentWidth === undefined) {
|
|
463
|
-
dispatchX({ type: "set-content", size: width })
|
|
464
|
-
}
|
|
465
|
-
},
|
|
466
|
-
[controlledContentHeight, controlledContentWidth, dispatchX, dispatchY, enableX, enableY],
|
|
467
|
-
)
|
|
468
|
-
|
|
469
421
|
useLayoutEffect(() => {
|
|
470
422
|
if (!enableY || controlledContentHeight === undefined) return
|
|
471
423
|
dispatchY({ type: "set-content", size: controlledContentHeight })
|
|
@@ -476,19 +428,35 @@ export function useScroll(options: UseScrollOptions = {}): UseScrollReturn {
|
|
|
476
428
|
dispatchX({ type: "set-content", size: controlledContentWidth })
|
|
477
429
|
}, [controlledContentWidth, dispatchX, enableX])
|
|
478
430
|
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
(width: number, height: number) => {
|
|
431
|
+
const handleScrollLayout = useCallback(
|
|
432
|
+
(event: ScrollLayoutChange) => {
|
|
482
433
|
if (enableY) {
|
|
483
|
-
viewportYRef.current = height
|
|
484
|
-
dispatchY({ type: "set-viewport", size: height })
|
|
434
|
+
viewportYRef.current = event.viewport.height
|
|
435
|
+
dispatchY({ type: "set-viewport", size: event.viewport.height })
|
|
436
|
+
if (controlledContentHeight === undefined) {
|
|
437
|
+
dispatchY({ type: "set-content", size: event.content.height })
|
|
438
|
+
}
|
|
439
|
+
dispatchY({ type: "sync-effective-offset", offset: event.offset.y })
|
|
485
440
|
}
|
|
486
441
|
if (enableX) {
|
|
487
|
-
viewportXRef.current = width
|
|
488
|
-
dispatchX({ type: "set-viewport", size: width })
|
|
442
|
+
viewportXRef.current = event.viewport.width
|
|
443
|
+
dispatchX({ type: "set-viewport", size: event.viewport.width })
|
|
444
|
+
if (controlledContentWidth === undefined) {
|
|
445
|
+
dispatchX({ type: "set-content", size: event.content.width })
|
|
446
|
+
}
|
|
447
|
+
dispatchX({ type: "sync-effective-offset", offset: event.offset.x })
|
|
489
448
|
}
|
|
449
|
+
onScrollLayoutChange?.(event)
|
|
490
450
|
},
|
|
491
|
-
[
|
|
451
|
+
[
|
|
452
|
+
controlledContentHeight,
|
|
453
|
+
controlledContentWidth,
|
|
454
|
+
dispatchX,
|
|
455
|
+
dispatchY,
|
|
456
|
+
enableX,
|
|
457
|
+
enableY,
|
|
458
|
+
onScrollLayoutChange,
|
|
459
|
+
],
|
|
492
460
|
)
|
|
493
461
|
|
|
494
462
|
// Keyboard handler
|
|
@@ -497,7 +465,7 @@ export function useScroll(options: UseScrollOptions = {}): UseScrollReturn {
|
|
|
497
465
|
// Mouse wheel comes as pageup/pagedown with meta=true
|
|
498
466
|
// Handle separately from keyboard since enableKeyboard shouldn't disable mouse
|
|
499
467
|
if (key.meta && enableMouseWheel && (key.name === "pageup" || key.name === "pagedown")) {
|
|
500
|
-
const multiplier =
|
|
468
|
+
const multiplier = useHorizontalPrimary && !enableY ? accelX.tick() : accelY.tick()
|
|
501
469
|
const delta = Math.ceil(arrowSpeed * multiplier)
|
|
502
470
|
if (axis === "horizontal") {
|
|
503
471
|
scrollByX(key.name === "pageup" ? -delta : delta)
|
|
@@ -569,7 +537,7 @@ export function useScroll(options: UseScrollOptions = {}): UseScrollReturn {
|
|
|
569
537
|
accelX,
|
|
570
538
|
accelY,
|
|
571
539
|
enableY,
|
|
572
|
-
|
|
540
|
+
useHorizontalPrimary,
|
|
573
541
|
scrollByX,
|
|
574
542
|
scrollByY,
|
|
575
543
|
scrollToEndX,
|
|
@@ -585,7 +553,7 @@ export function useScroll(options: UseScrollOptions = {}): UseScrollReturn {
|
|
|
585
553
|
// Uses refs to avoid stale closures, but re-creates when viewport size changes
|
|
586
554
|
// so selection effects can re-run after measurement updates.
|
|
587
555
|
// Bypasses clampOffset because it uses totalSize for accurate clamping
|
|
588
|
-
const
|
|
556
|
+
const scrollIntoView = useCallback(
|
|
589
557
|
(
|
|
590
558
|
position: number,
|
|
591
559
|
itemSize = 1,
|
|
@@ -633,17 +601,6 @@ export function useScroll(options: UseScrollOptions = {}): UseScrollReturn {
|
|
|
633
601
|
[dispatchX],
|
|
634
602
|
)
|
|
635
603
|
|
|
636
|
-
const setOffset = useCallback(
|
|
637
|
-
(newOffset: number) => {
|
|
638
|
-
if (primaryAxis === "horizontal") {
|
|
639
|
-
setOffsetX(newOffset)
|
|
640
|
-
} else {
|
|
641
|
-
setOffsetY(newOffset)
|
|
642
|
-
}
|
|
643
|
-
},
|
|
644
|
-
[primaryAxis, setOffsetX, setOffsetY],
|
|
645
|
-
)
|
|
646
|
-
|
|
647
604
|
// Calculate derived state
|
|
648
605
|
const maxOffsetY = Math.max(0, internalY.contentSize - internalY.viewportSize)
|
|
649
606
|
const maxOffsetX = Math.max(0, internalX.contentSize - internalX.viewportSize)
|
|
@@ -652,19 +609,14 @@ export function useScroll(options: UseScrollOptions = {}): UseScrollReturn {
|
|
|
652
609
|
const atStartX = internalX.offset <= 0
|
|
653
610
|
const atEndX = internalX.offset >= maxOffsetX
|
|
654
611
|
|
|
655
|
-
const primaryState = primaryAxis === "horizontal" ? internalX : internalY
|
|
656
|
-
const primaryMaxOffset = primaryAxis === "horizontal" ? maxOffsetX : maxOffsetY
|
|
657
|
-
const primaryAtStart = primaryAxis === "horizontal" ? atStartX : atStartY
|
|
658
|
-
const primaryAtEnd = primaryAxis === "horizontal" ? atEndX : atEndY
|
|
659
|
-
|
|
660
612
|
const state: ScrollState = {
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
613
|
+
offsetY: internalY.offset,
|
|
614
|
+
maxOffsetY,
|
|
615
|
+
viewportSizeY: internalY.viewportSize,
|
|
616
|
+
viewportMeasuredY: internalY.viewportMeasured,
|
|
617
|
+
contentSizeY: internalY.contentSize,
|
|
618
|
+
atStartY,
|
|
619
|
+
atEndY,
|
|
668
620
|
offsetX: internalX.offset,
|
|
669
621
|
maxOffsetX,
|
|
670
622
|
viewportSizeX: internalX.viewportSize,
|
|
@@ -674,39 +626,27 @@ export function useScroll(options: UseScrollOptions = {}): UseScrollReturn {
|
|
|
674
626
|
atEndX,
|
|
675
627
|
}
|
|
676
628
|
|
|
677
|
-
// Handle effective offset sync from host (when sticky adjusts the offset)
|
|
678
|
-
const handleEffectiveOffset = useCallback((effectiveOffset: number) => {
|
|
679
|
-
dispatchY({ type: "sync-effective-offset", offset: effectiveOffset })
|
|
680
|
-
}, [dispatchY])
|
|
681
|
-
|
|
682
|
-
const handleEffectiveOffsetX = useCallback((effectiveOffsetX: number) => {
|
|
683
|
-
dispatchX({ type: "sync-effective-offset", offset: effectiveOffsetX })
|
|
684
|
-
}, [dispatchX])
|
|
685
|
-
|
|
686
629
|
const scrollProps: ScrollProps = {
|
|
687
|
-
|
|
630
|
+
offsetY: enableY ? internalY.offset : 0,
|
|
688
631
|
offsetX: enableX ? internalX.offset : 0,
|
|
689
632
|
axis,
|
|
690
633
|
align,
|
|
691
634
|
sticky,
|
|
692
635
|
showScrollbar,
|
|
693
|
-
|
|
694
|
-
onViewportSize: handleViewportSize,
|
|
695
|
-
onEffectiveOffset: enableY ? handleEffectiveOffset : undefined,
|
|
696
|
-
onEffectiveOffsetX: enableX ? handleEffectiveOffsetX : undefined,
|
|
636
|
+
onScrollLayoutChange: handleScrollLayout,
|
|
697
637
|
}
|
|
698
638
|
|
|
699
639
|
return {
|
|
700
640
|
state,
|
|
701
|
-
|
|
641
|
+
setOffsetY,
|
|
702
642
|
setOffsetX,
|
|
703
|
-
|
|
643
|
+
scrollByY,
|
|
704
644
|
scrollByX,
|
|
705
|
-
|
|
706
|
-
|
|
645
|
+
scrollToStartY,
|
|
646
|
+
scrollToEndY,
|
|
707
647
|
scrollToStartX,
|
|
708
648
|
scrollToEndX,
|
|
709
|
-
|
|
649
|
+
scrollIntoView,
|
|
710
650
|
scrollProps,
|
|
711
651
|
}
|
|
712
652
|
}
|
package/src/hosts/canvas.ts
CHANGED
|
@@ -5,12 +5,12 @@ import {
|
|
|
5
5
|
type BorderKind,
|
|
6
6
|
borderChars,
|
|
7
7
|
drawBorder,
|
|
8
|
+
fillRectWithInheritedBg,
|
|
8
9
|
resolveBgStyle,
|
|
9
|
-
resolveInheritedBgStyle,
|
|
10
10
|
styleIdFromProps,
|
|
11
11
|
toColorValue,
|
|
12
12
|
} from "../utils/index.js"
|
|
13
|
-
import {
|
|
13
|
+
import { LeafHost } from "./leaf.js"
|
|
14
14
|
|
|
15
15
|
export type { BorderKind }
|
|
16
16
|
|
|
@@ -67,7 +67,7 @@ export interface CanvasProps extends CommonProps {
|
|
|
67
67
|
inheritBg?: boolean
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
export class CanvasHost extends
|
|
70
|
+
export class CanvasHost extends LeafHost {
|
|
71
71
|
draw: CanvasProps["draw"] = () => {}
|
|
72
72
|
fixedWidth?: number
|
|
73
73
|
fixedHeight?: number
|
|
@@ -91,15 +91,12 @@ export class CanvasHost extends BaseHost {
|
|
|
91
91
|
if (!this.rect) return
|
|
92
92
|
const { x: ox, y: oy, w, h } = this.rect
|
|
93
93
|
|
|
94
|
-
// Get inherited background for use in drawing functions
|
|
95
|
-
const { value: inheritedBgValue, styleId: inheritedBgStyleId } = this.inheritBg
|
|
96
|
-
? resolveInheritedBgStyle(palette, undefined, this.parent)
|
|
97
|
-
: { value: undefined, styleId: 0 }
|
|
98
|
-
|
|
99
94
|
// Pre-fill with inherited background if requested
|
|
100
|
-
|
|
101
|
-
buffer
|
|
102
|
-
|
|
95
|
+
const inheritedBgValue = this.inheritBg
|
|
96
|
+
? fillRectWithInheritedBg(buffer, palette, { x: ox, y: oy, w, h }, undefined, this.parent, {
|
|
97
|
+
skipWhenUndefined: true,
|
|
98
|
+
}).value
|
|
99
|
+
: undefined
|
|
103
100
|
|
|
104
101
|
// Create draw context
|
|
105
102
|
const ctx: DrawContext = {
|
package/src/hosts/codeblock.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { type CellBuffer, type Color, Colors, displayWidth, type Palette } from
|
|
|
2
2
|
import type { HighlightLine } from "../highlight.js"
|
|
3
3
|
import type { CommonProps, HostContext, Size } from "../reconciler/types.js"
|
|
4
4
|
import { type Padding, type PaddingInput, resolveBgStyle, resolvePadding, styleIdFromProps } from "../utils/index.js"
|
|
5
|
-
import {
|
|
5
|
+
import { LeafHost } from "./leaf.js"
|
|
6
6
|
|
|
7
7
|
export interface CodeBlockProps extends CommonProps {
|
|
8
8
|
lines: HighlightLine[]
|
|
@@ -17,7 +17,7 @@ function lineDisplayWidth(line: HighlightLine): number {
|
|
|
17
17
|
return line.reduce((w, token) => w + displayWidth(token.text), 0)
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
export class CodeBlockHost extends
|
|
20
|
+
export class CodeBlockHost extends LeafHost {
|
|
21
21
|
lines: HighlightLine[] = [[]]
|
|
22
22
|
lineNumbers = false
|
|
23
23
|
padding: Padding = { top: 0, right: 0, bottom: 0, left: 0 }
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
import { BaseHost } from "./base.js"
|
|
16
16
|
|
|
17
17
|
export type CrossAlignment<A extends FlexAxis> = A extends "vertical"
|
|
18
|
-
? "
|
|
18
|
+
? "left" | "center" | "right"
|
|
19
19
|
: "top" | "center" | "bottom"
|
|
20
20
|
|
|
21
21
|
export interface FlexContainerProps<A extends FlexAxis> extends CommonProps {
|
|
@@ -30,7 +30,7 @@ export interface FlexContainerProps<A extends FlexAxis> extends CommonProps {
|
|
|
30
30
|
function toFlexAlignment<A extends FlexAxis>(axis: A, alignment: CrossAlignment<A>): FlexAlignment {
|
|
31
31
|
if (alignment === "center") return "center"
|
|
32
32
|
if (axis === "vertical") {
|
|
33
|
-
return alignment === "
|
|
33
|
+
return alignment === "left" ? "start" : "end"
|
|
34
34
|
} else {
|
|
35
35
|
return alignment === "top" ? "start" : "end"
|
|
36
36
|
}
|
|
@@ -104,7 +104,7 @@ export class FlexContainerHost<A extends FlexAxis> extends BaseHost {
|
|
|
104
104
|
|
|
105
105
|
override layout(rect: Rect): void {
|
|
106
106
|
const layoutRect = this.layoutWithConstraints(rect)
|
|
107
|
-
const stretchCross = this.axis === "vertical" ? this.alignment === "
|
|
107
|
+
const stretchCross = this.axis === "vertical" ? this.alignment === "left" : this.alignment === "top"
|
|
108
108
|
const insetX = this.padding.left + this.padding.right
|
|
109
109
|
const insetY = this.padding.top + this.padding.bottom
|
|
110
110
|
const innerRect: Rect = {
|
|
@@ -146,7 +146,7 @@ export class FlexContainerHost<A extends FlexAxis> extends BaseHost {
|
|
|
146
146
|
// Reset to axis-specific default when undefined
|
|
147
147
|
this.alignment =
|
|
148
148
|
(props.alignment as CrossAlignment<A> | undefined) ??
|
|
149
|
-
((this.axis === "vertical" ? "
|
|
149
|
+
((this.axis === "vertical" ? "left" : "top") as CrossAlignment<A>)
|
|
150
150
|
this.padding = resolvePadding(props.padding as FlexContainerProps<A>["padding"])
|
|
151
151
|
this.bg = props.bg as Color | undefined
|
|
152
152
|
}
|
package/src/hosts/index.ts
CHANGED
|
@@ -19,8 +19,17 @@ export { CodeBlockHost, type CodeBlockProps } from "./codeblock.js"
|
|
|
19
19
|
export { HStackHost, type HStackProps } from "./hstack.js"
|
|
20
20
|
export { OverlayHost, type OverlayProps } from "./overlay.js"
|
|
21
21
|
export { OverlayItemHost, type OverlayItemProps } from "./overlay-item.js"
|
|
22
|
-
export {
|
|
22
|
+
export {
|
|
23
|
+
ScrollHost,
|
|
24
|
+
type ScrollAlign,
|
|
25
|
+
type ScrollAlignX,
|
|
26
|
+
type ScrollAlignY,
|
|
27
|
+
type ScrollAxis,
|
|
28
|
+
type ScrollLayoutChange,
|
|
29
|
+
type ScrollProps,
|
|
30
|
+
} from "./scroll.js"
|
|
23
31
|
export { SingleChildHost } from "./single-child.js"
|
|
32
|
+
export { LeafHost } from "./leaf.js"
|
|
24
33
|
export { SpacerHost, type SpacerProps } from "./spacer.js"
|
|
25
34
|
export {
|
|
26
35
|
RawTextHost,
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Rect, Size } from "../reconciler/types.js"
|
|
2
|
+
import type { HostInstance } from "../reconciler/types.js"
|
|
3
|
+
import { alignedChildRect, type HAlign, type VAlign } from "../utils/index.js"
|
|
4
|
+
|
|
5
|
+
type Alignment = { h?: HAlign; v?: VAlign }
|
|
6
|
+
|
|
7
|
+
export function layoutAlignedChildren(
|
|
8
|
+
layoutRect: Rect,
|
|
9
|
+
children: HostInstance[],
|
|
10
|
+
cachedSizes: Size[],
|
|
11
|
+
alignmentForChild: (child: HostInstance, index: number) => Alignment,
|
|
12
|
+
startIndex = 0,
|
|
13
|
+
): void {
|
|
14
|
+
for (let i = startIndex; i < children.length; i++) {
|
|
15
|
+
const child = children[i]
|
|
16
|
+
const size = cachedSizes[i] ?? child.measure(layoutRect.w, layoutRect.h)
|
|
17
|
+
const alignment = alignmentForChild(child, i)
|
|
18
|
+
child.layout(alignedChildRect(layoutRect, size, alignment.h ?? "center", alignment.v ?? "center"))
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { HostInstance } from "../reconciler/types.js"
|
|
2
|
+
import { BaseHost } from "./base.js"
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Base host that rejects children.
|
|
6
|
+
* Any attempted child insertion is ignored with a warning (once).
|
|
7
|
+
*/
|
|
8
|
+
export abstract class LeafHost extends BaseHost {
|
|
9
|
+
private warned = false
|
|
10
|
+
|
|
11
|
+
override appendChild(child: HostInstance): void {
|
|
12
|
+
this.rejectChild(child)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
override insertBefore(child: HostInstance, _before: HostInstance): void {
|
|
16
|
+
this.rejectChild(child)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
override removeChild(child: HostInstance): void {
|
|
20
|
+
const idx = this.children.indexOf(child)
|
|
21
|
+
if (idx >= 0) {
|
|
22
|
+
this.children.splice(idx, 1)
|
|
23
|
+
}
|
|
24
|
+
if (child.parent === this) {
|
|
25
|
+
child.parent = null
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
private rejectChild(child: HostInstance): void {
|
|
30
|
+
if (!this.warned) {
|
|
31
|
+
console.warn(`[effect-tui] <${this.type}> does not support children; child ignored.`)
|
|
32
|
+
this.warned = true
|
|
33
|
+
}
|
|
34
|
+
child.parent = null
|
|
35
|
+
}
|
|
36
|
+
}
|
package/src/hosts/overlay.ts
CHANGED
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
|
|
19
19
|
import type { CellBuffer, Palette, Rect, Size } from "@effect-tui/core"
|
|
20
20
|
import type { CommonProps, HostContext } from "../reconciler/types.js"
|
|
21
|
-
import { alignedChildRect } from "../utils/index.js"
|
|
22
21
|
import { BaseHost } from "./base.js"
|
|
22
|
+
import { layoutAlignedChildren } from "./layout-helpers.js"
|
|
23
23
|
import type { OverlayItemHost } from "./overlay-item.js"
|
|
24
24
|
|
|
25
25
|
export interface OverlayProps extends CommonProps {}
|
|
@@ -66,14 +66,16 @@ export class OverlayHost extends BaseHost {
|
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
// Layout overlay children with their alignment
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
69
|
+
layoutAlignedChildren(
|
|
70
|
+
layoutRect,
|
|
71
|
+
this.children,
|
|
72
|
+
this.cachedSizes,
|
|
73
|
+
(child) => {
|
|
74
|
+
// Read alignment from OverlayItemHost (use type check, not instanceof, for bundler compatibility)
|
|
75
|
+
return child.type === "overlayItem" ? (child as OverlayItemHost).alignment : {}
|
|
76
|
+
},
|
|
77
|
+
1,
|
|
78
|
+
)
|
|
77
79
|
}
|
|
78
80
|
|
|
79
81
|
override render(buffer: CellBuffer, palette: Palette): void {
|