@effect-tui/react 0.15.2 → 2.0.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 +11 -2
- package/dist/src/codeblock.d.ts +1 -1
- package/dist/src/codeblock.d.ts.map +1 -1
- package/dist/src/codeblock.js +2 -2
- package/dist/src/codeblock.js.map +1 -1
- 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/components/Markdown.js +3 -3
- package/dist/src/components/Markdown.js.map +1 -1
- package/dist/src/components/MultilineTextInput.d.ts.map +1 -1
- package/dist/src/components/MultilineTextInput.js +133 -305
- package/dist/src/components/MultilineTextInput.js.map +1 -1
- package/dist/src/components/TextInput.d.ts.map +1 -1
- package/dist/src/components/TextInput.js +51 -98
- package/dist/src/components/TextInput.js.map +1 -1
- package/dist/src/components/text-editing.d.ts +61 -0
- package/dist/src/components/text-editing.d.ts.map +1 -1
- package/dist/src/components/text-editing.js +131 -0
- package/dist/src/components/text-editing.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/base.d.ts +13 -2
- package/dist/src/hosts/base.d.ts.map +1 -1
- package/dist/src/hosts/base.js +74 -2
- package/dist/src/hosts/base.js.map +1 -1
- package/dist/src/hosts/box.d.ts +2 -2
- package/dist/src/hosts/box.d.ts.map +1 -1
- package/dist/src/hosts/box.js +29 -2
- package/dist/src/hosts/box.js.map +1 -1
- package/dist/src/hosts/canvas.d.ts +24 -4
- package/dist/src/hosts/canvas.d.ts.map +1 -1
- package/dist/src/hosts/canvas.js +107 -41
- package/dist/src/hosts/canvas.js.map +1 -1
- package/dist/src/hosts/codeblock.d.ts +10 -12
- package/dist/src/hosts/codeblock.d.ts.map +1 -1
- package/dist/src/hosts/codeblock.js +38 -35
- package/dist/src/hosts/codeblock.js.map +1 -1
- package/dist/src/hosts/flex-container.d.ts +3 -3
- package/dist/src/hosts/flex-container.d.ts.map +1 -1
- package/dist/src/hosts/flex-container.js +20 -5
- package/dist/src/hosts/flex-container.js.map +1 -1
- package/dist/src/hosts/index.d.ts +3 -2
- 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-item.d.ts +2 -2
- package/dist/src/hosts/overlay-item.d.ts.map +1 -1
- package/dist/src/hosts/overlay-item.js +7 -2
- package/dist/src/hosts/overlay-item.js.map +1 -1
- package/dist/src/hosts/overlay.d.ts +2 -2
- package/dist/src/hosts/overlay.d.ts.map +1 -1
- package/dist/src/hosts/overlay.js +6 -9
- package/dist/src/hosts/overlay.js.map +1 -1
- package/dist/src/hosts/scroll.d.ts +54 -26
- package/dist/src/hosts/scroll.d.ts.map +1 -1
- package/dist/src/hosts/scroll.js +185 -87
- package/dist/src/hosts/scroll.js.map +1 -1
- package/dist/src/hosts/single-child.d.ts.map +1 -1
- package/dist/src/hosts/single-child.js +2 -0
- package/dist/src/hosts/single-child.js.map +1 -1
- package/dist/src/hosts/spacer.d.ts +3 -3
- package/dist/src/hosts/spacer.d.ts.map +1 -1
- package/dist/src/hosts/spacer.js +8 -3
- package/dist/src/hosts/spacer.js.map +1 -1
- package/dist/src/hosts/text.d.ts +22 -18
- package/dist/src/hosts/text.d.ts.map +1 -1
- package/dist/src/hosts/text.js +108 -131
- 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 +3 -3
- package/dist/src/hosts/zstack.d.ts.map +1 -1
- package/dist/src/hosts/zstack.js +13 -8
- package/dist/src/hosts/zstack.js.map +1 -1
- package/dist/src/index.d.ts +2 -2
- 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 +543 -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 +122 -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/motion/hooks.d.ts +1 -1
- package/dist/src/motion/hooks.js +1 -1
- package/dist/src/reconciler/host-config.js +2 -2
- package/dist/src/reconciler/host-config.js.map +1 -1
- package/dist/src/reconciler/types.d.ts +5 -1
- package/dist/src/reconciler/types.d.ts.map +1 -1
- 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/border.d.ts +1 -1
- package/dist/src/utils/border.d.ts.map +1 -1
- package/dist/src/utils/border.js +2 -0
- package/dist/src/utils/border.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 +2 -1
- package/dist/src/utils/index.d.ts.map +1 -1
- package/dist/src/utils/index.js +2 -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-layout.d.ts +22 -0
- package/dist/src/utils/text-layout.d.ts.map +1 -0
- package/dist/src/utils/text-layout.js +37 -0
- package/dist/src/utils/text-layout.js.map +1 -0
- package/dist/src/utils/text-wrap.d.ts +31 -1
- package/dist/src/utils/text-wrap.d.ts.map +1 -1
- package/dist/src/utils/text-wrap.js +205 -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/codeblock.tsx +2 -2
- package/src/components/ListView.tsx +21 -23
- package/src/components/Markdown.tsx +3 -3
- package/src/components/MultilineTextInput.tsx +138 -344
- package/src/components/TextInput.tsx +54 -99
- package/src/components/text-editing.ts +180 -0
- 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/base.ts +86 -3
- package/src/hosts/box.ts +37 -2
- package/src/hosts/canvas.ts +128 -42
- package/src/hosts/codeblock.ts +48 -35
- package/src/hosts/flex-container.ts +25 -6
- package/src/hosts/index.ts +11 -2
- package/src/hosts/layout-helpers.ts +20 -0
- package/src/hosts/leaf.ts +36 -0
- package/src/hosts/overlay-item.ts +8 -2
- package/src/hosts/overlay.ts +13 -11
- package/src/hosts/scroll.ts +228 -106
- package/src/hosts/single-child.ts +2 -0
- package/src/hosts/spacer.ts +8 -3
- package/src/hosts/text.ts +126 -132
- package/src/hosts/vstack.ts +1 -1
- package/src/hosts/zstack.ts +14 -9
- package/src/index.ts +2 -2
- 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 +689 -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 +129 -0
- package/src/motion/hooks.ts +1 -1
- package/src/reconciler/host-config.ts +2 -2
- package/src/reconciler/types.ts +7 -1
- 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/border.ts +11 -1
- package/src/utils/console-helpers.ts +86 -0
- package/src/utils/index.ts +15 -1
- package/src/utils/styles.ts +16 -4
- package/src/utils/text-layout.ts +65 -0
- package/src/utils/text-wrap.ts +261 -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/hosts/scroll.ts
CHANGED
|
@@ -4,15 +4,32 @@ import type { CommonProps, HostContext, Rect, Size } from "../reconciler/types.j
|
|
|
4
4
|
import { fillRectWithInheritedBg } from "../utils/index.js"
|
|
5
5
|
import { SingleChildHost } from "./single-child.js"
|
|
6
6
|
|
|
7
|
+
export type ScrollAxis = "vertical" | "horizontal" | "both"
|
|
8
|
+
export type ScrollAlignX = "left" | "center" | "right"
|
|
9
|
+
export type ScrollAlignY = "top" | "center" | "bottom"
|
|
10
|
+
export type ScrollAlign = ScrollAlignX | ScrollAlignY | { x?: ScrollAlignX; y?: ScrollAlignY }
|
|
11
|
+
export interface ScrollLayoutChange {
|
|
12
|
+
content: { width: number; height: number }
|
|
13
|
+
viewport: { width: number; height: number }
|
|
14
|
+
offset: { x: number; y: number }
|
|
15
|
+
rect: { x: number; y: number; w: number; h: number }
|
|
16
|
+
axis: ScrollAxis
|
|
17
|
+
}
|
|
18
|
+
|
|
7
19
|
export interface ScrollProps extends CommonProps {
|
|
8
20
|
/** Scroll axis: "vertical" (default), "horizontal", or "both" */
|
|
9
|
-
axis?:
|
|
10
|
-
/**
|
|
11
|
-
|
|
12
|
-
/** Horizontal offset
|
|
21
|
+
axis?: ScrollAxis
|
|
22
|
+
/** Vertical scroll offset in pixels (0 = top) */
|
|
23
|
+
offsetY?: number
|
|
24
|
+
/** Horizontal scroll offset in pixels (0 = left) */
|
|
13
25
|
offsetX?: number
|
|
14
|
-
/**
|
|
15
|
-
|
|
26
|
+
/**
|
|
27
|
+
* Alignment when content is smaller than viewport.
|
|
28
|
+
* - axis="vertical": "top" | "center" | "bottom"
|
|
29
|
+
* - axis="horizontal": "left" | "center" | "right"
|
|
30
|
+
* - axis="both": { x, y }
|
|
31
|
+
*/
|
|
32
|
+
align?: ScrollAlign
|
|
16
33
|
/** Background color for the scroll viewport */
|
|
17
34
|
bg?: Color
|
|
18
35
|
/** Whether to show scrollbar indicators */
|
|
@@ -22,38 +39,53 @@ export interface ScrollProps extends CommonProps {
|
|
|
22
39
|
* This is handled in the host itself for instant updates (no React roundtrip).
|
|
23
40
|
*/
|
|
24
41
|
sticky?: boolean
|
|
25
|
-
/** Called when
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
42
|
+
/** Called when scroll layout changes (content/viewport/offset/rect). */
|
|
43
|
+
onScrollLayoutChange?: (event: ScrollLayoutChange) => void
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const isAlignX = (value: string): value is ScrollAlignX => value === "left" || value === "center" || value === "right"
|
|
47
|
+
const isAlignY = (value: string): value is ScrollAlignY => value === "top" || value === "center" || value === "bottom"
|
|
48
|
+
|
|
49
|
+
const resolveAlign = (align: ScrollAlign | undefined): { x: ScrollAlignX; y: ScrollAlignY } => {
|
|
50
|
+
let x: ScrollAlignX | undefined
|
|
51
|
+
let y: ScrollAlignY | undefined
|
|
52
|
+
|
|
53
|
+
if (typeof align === "string") {
|
|
54
|
+
if (isAlignX(align)) x = align
|
|
55
|
+
if (isAlignY(align)) y = align
|
|
56
|
+
} else if (align) {
|
|
57
|
+
x = align.x
|
|
58
|
+
y = align.y
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
x: x ?? "left",
|
|
63
|
+
y: y ?? "top",
|
|
64
|
+
}
|
|
35
65
|
}
|
|
36
66
|
|
|
37
67
|
export class ScrollHost extends SingleChildHost {
|
|
38
|
-
axis:
|
|
39
|
-
|
|
68
|
+
axis: ScrollAxis = "vertical"
|
|
69
|
+
offsetY = 0
|
|
40
70
|
offsetX = 0
|
|
41
|
-
align
|
|
71
|
+
align?: ScrollAlign
|
|
42
72
|
bg?: Color
|
|
43
73
|
showScrollbar = true
|
|
44
74
|
sticky = false
|
|
45
75
|
|
|
46
76
|
// Scroll is greedy by default - expands to fill available space
|
|
47
77
|
override greedy: boolean | number | undefined = 1
|
|
48
|
-
|
|
49
|
-
onViewportSize?: (width: number, height: number) => void
|
|
50
|
-
onEffectiveOffset?: (offset: number) => void
|
|
51
|
-
onEffectiveOffsetX?: (offsetX: number) => void
|
|
52
|
-
onRect?: (x: number, y: number, w: number, h: number) => void
|
|
78
|
+
onScrollLayoutChange?: (event: ScrollLayoutChange) => void
|
|
53
79
|
|
|
54
80
|
// Measured content dimensions (full size before clipping)
|
|
55
81
|
private contentWidth = 0
|
|
56
82
|
private contentHeight = 0
|
|
83
|
+
// Effective viewport dimensions (excludes scrollbar gutter when visible)
|
|
84
|
+
private viewportWidth = 0
|
|
85
|
+
private viewportHeight = 0
|
|
86
|
+
// Scrollbar visibility after accounting for content overflow
|
|
87
|
+
private showVerticalScrollbar = false
|
|
88
|
+
private showHorizontalScrollbar = false
|
|
57
89
|
// Track last reported sizes to avoid redundant callbacks
|
|
58
90
|
private lastReportedContentW = -1
|
|
59
91
|
private lastReportedContentH = -1
|
|
@@ -63,6 +95,8 @@ export class ScrollHost extends SingleChildHost {
|
|
|
63
95
|
private lastRectY = -1
|
|
64
96
|
private lastRectW = -1
|
|
65
97
|
private lastRectH = -1
|
|
98
|
+
private lastOffsetY = -1
|
|
99
|
+
private lastOffsetX = -1
|
|
66
100
|
// Track if we were at end (for sticky behavior)
|
|
67
101
|
private wasAtEnd = true
|
|
68
102
|
private wasAtEndX = true
|
|
@@ -75,78 +109,129 @@ export class ScrollHost extends SingleChildHost {
|
|
|
75
109
|
this.updateProps(props as unknown as Record<string, unknown>)
|
|
76
110
|
}
|
|
77
111
|
|
|
78
|
-
|
|
112
|
+
private computeViewport(baseW: number, baseH: number, contentW: number, contentH: number): {
|
|
113
|
+
viewportW: number
|
|
114
|
+
viewportH: number
|
|
115
|
+
showV: boolean
|
|
116
|
+
showH: boolean
|
|
117
|
+
} {
|
|
118
|
+
const allowV = this.showScrollbar && (this.axis === "vertical" || this.axis === "both")
|
|
119
|
+
const allowH = this.showScrollbar && (this.axis === "horizontal" || this.axis === "both")
|
|
120
|
+
let viewportW = Math.max(0, baseW)
|
|
121
|
+
let viewportH = Math.max(0, baseH)
|
|
122
|
+
let showV = false
|
|
123
|
+
let showH = false
|
|
124
|
+
|
|
125
|
+
for (let i = 0; i < 2; i++) {
|
|
126
|
+
const nextShowV = allowV && contentH > viewportH
|
|
127
|
+
const nextShowH = allowH && contentW > viewportW
|
|
128
|
+
if (nextShowV === showV && nextShowH === showH) break
|
|
129
|
+
showV = nextShowV
|
|
130
|
+
showH = nextShowH
|
|
131
|
+
viewportW = Math.max(0, baseW - (showV ? 1 : 0))
|
|
132
|
+
viewportH = Math.max(0, baseH - (showH ? 1 : 0))
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return { viewportW, viewportH, showV, showH }
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
protected measureSelf(maxW: number, maxH: number): Size {
|
|
79
139
|
// Apply frame constraints to determine our size
|
|
80
140
|
const constrained = this.constrainProposal(maxW, maxH)
|
|
81
141
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
142
|
+
const child = this.child
|
|
143
|
+
if (!child) {
|
|
144
|
+
this.contentWidth = 0
|
|
145
|
+
this.contentHeight = 0
|
|
146
|
+
const viewport = this.computeViewport(constrained.w, constrained.h, 0, 0)
|
|
147
|
+
this.viewportWidth = viewport.viewportW
|
|
148
|
+
this.viewportHeight = viewport.viewportH
|
|
149
|
+
this.showVerticalScrollbar = viewport.showV
|
|
150
|
+
this.showHorizontalScrollbar = viewport.showH
|
|
151
|
+
return this.constrainResult({ w: 0, h: 0 })
|
|
88
152
|
}
|
|
89
|
-
|
|
90
|
-
|
|
153
|
+
|
|
154
|
+
const measureChild = (proposalW: number, proposalH: number): Size => {
|
|
155
|
+
let childMaxW = proposalW
|
|
156
|
+
let childMaxH = proposalH
|
|
157
|
+
|
|
158
|
+
if (this.axis === "vertical" || this.axis === "both") {
|
|
159
|
+
childMaxH = Number.MAX_SAFE_INTEGER
|
|
160
|
+
}
|
|
161
|
+
if (this.axis === "horizontal" || this.axis === "both") {
|
|
162
|
+
childMaxW = Number.MAX_SAFE_INTEGER
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return child.measure(childMaxW, childMaxH)
|
|
91
166
|
}
|
|
92
167
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
168
|
+
let viewportW = constrained.w
|
|
169
|
+
let viewportH = constrained.h
|
|
170
|
+
let contentW = 0
|
|
171
|
+
let contentH = 0
|
|
172
|
+
let showV = false
|
|
173
|
+
let showH = false
|
|
174
|
+
|
|
175
|
+
for (let i = 0; i < 3; i++) {
|
|
176
|
+
const childSize = measureChild(viewportW, viewportH)
|
|
177
|
+
contentW = childSize.w
|
|
178
|
+
contentH = childSize.h
|
|
179
|
+
const viewport = this.computeViewport(constrained.w, constrained.h, contentW, contentH)
|
|
180
|
+
if (viewport.viewportW === viewportW && viewport.viewportH === viewportH) {
|
|
181
|
+
showV = viewport.showV
|
|
182
|
+
showH = viewport.showH
|
|
183
|
+
break
|
|
184
|
+
}
|
|
185
|
+
viewportW = viewport.viewportW
|
|
186
|
+
viewportH = viewport.viewportH
|
|
187
|
+
showV = viewport.showV
|
|
188
|
+
showH = viewport.showH
|
|
100
189
|
}
|
|
101
190
|
|
|
191
|
+
this.contentWidth = contentW
|
|
192
|
+
this.contentHeight = contentH
|
|
193
|
+
this.viewportWidth = viewportW
|
|
194
|
+
this.viewportHeight = viewportH
|
|
195
|
+
this.showVerticalScrollbar = showV
|
|
196
|
+
this.showHorizontalScrollbar = showH
|
|
197
|
+
|
|
102
198
|
// Report natural content size (clamped to constrained bounds)
|
|
103
199
|
// Greedy expansion happens in layout phase via layoutFlex
|
|
104
|
-
const naturalW = Math.min(this.contentWidth, constrained.w)
|
|
105
|
-
const naturalH = Math.min(this.contentHeight, constrained.h)
|
|
200
|
+
const naturalW = Math.min(this.contentWidth + (this.showVerticalScrollbar ? 1 : 0), constrained.w)
|
|
201
|
+
const naturalH = Math.min(this.contentHeight + (this.showHorizontalScrollbar ? 1 : 0), constrained.h)
|
|
106
202
|
|
|
107
203
|
return this.constrainResult({ w: naturalW, h: naturalH })
|
|
108
204
|
}
|
|
109
205
|
|
|
110
|
-
override
|
|
206
|
+
protected override layoutSelf(rect: Rect): void {
|
|
111
207
|
const layoutRect = this.layoutWithConstraints(rect)
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
this.
|
|
124
|
-
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// Report rect if position changed (for hit testing)
|
|
128
|
-
if (
|
|
208
|
+
const viewport = this.computeViewport(layoutRect.w, layoutRect.h, this.contentWidth, this.contentHeight)
|
|
209
|
+
this.viewportWidth = viewport.viewportW
|
|
210
|
+
this.viewportHeight = viewport.viewportH
|
|
211
|
+
this.showVerticalScrollbar = viewport.showV
|
|
212
|
+
this.showHorizontalScrollbar = viewport.showH
|
|
213
|
+
|
|
214
|
+
const { x: alignX, y: alignY } = resolveAlign(this.align)
|
|
215
|
+
|
|
216
|
+
const contentChanged =
|
|
217
|
+
this.contentWidth !== this.lastReportedContentW || this.contentHeight !== this.lastReportedContentH
|
|
218
|
+
const viewportChanged =
|
|
219
|
+
this.viewportWidth !== this.lastViewportW || this.viewportHeight !== this.lastViewportH
|
|
220
|
+
const rectChanged =
|
|
129
221
|
layoutRect.x !== this.lastRectX ||
|
|
130
222
|
layoutRect.y !== this.lastRectY ||
|
|
131
223
|
layoutRect.w !== this.lastRectW ||
|
|
132
224
|
layoutRect.h !== this.lastRectH
|
|
133
|
-
) {
|
|
134
|
-
this.lastRectX = layoutRect.x
|
|
135
|
-
this.lastRectY = layoutRect.y
|
|
136
|
-
this.lastRectW = layoutRect.w
|
|
137
|
-
this.lastRectH = layoutRect.h
|
|
138
|
-
this.onRect?.(layoutRect.x, layoutRect.y, layoutRect.w, layoutRect.h)
|
|
139
|
-
}
|
|
140
225
|
|
|
141
226
|
const child = this.child
|
|
142
227
|
if (!child) return
|
|
143
228
|
|
|
144
229
|
// Calculate max scroll offsets
|
|
145
|
-
const maxScrollY = Math.max(0, this.contentHeight -
|
|
146
|
-
const maxScrollX = Math.max(0, this.contentWidth -
|
|
230
|
+
const maxScrollY = Math.max(0, this.contentHeight - this.viewportHeight)
|
|
231
|
+
const maxScrollX = Math.max(0, this.contentWidth - this.viewportWidth)
|
|
147
232
|
|
|
148
233
|
// Start with the offset from props (controlled by useScroll)
|
|
149
|
-
let scrollY = this.
|
|
234
|
+
let scrollY = this.offsetY
|
|
150
235
|
let scrollX = this.offsetX
|
|
151
236
|
|
|
152
237
|
// Sticky scroll logic (vertical):
|
|
@@ -154,7 +239,7 @@ export class ScrollHost extends SingleChildHost {
|
|
|
154
239
|
// - If at end (or was at end and content grew), stay stuck
|
|
155
240
|
if (this.sticky && (this.axis === "vertical" || this.axis === "both")) {
|
|
156
241
|
// Detect if user scrolled away (offset prop is less than where we rendered)
|
|
157
|
-
const userScrolledAway = this.
|
|
242
|
+
const userScrolledAway = this.offsetY < this.effectiveOffset - 1
|
|
158
243
|
|
|
159
244
|
if (userScrolledAway) {
|
|
160
245
|
// User scrolled up - unstick
|
|
@@ -185,25 +270,23 @@ export class ScrollHost extends SingleChildHost {
|
|
|
185
270
|
scrollX = Math.max(0, Math.min(maxScrollX, scrollX))
|
|
186
271
|
|
|
187
272
|
// Store effective offsets for rendering (scrollbar position)
|
|
188
|
-
// Report back if clamped or changed (keep controller in sync)
|
|
189
|
-
if (scrollY !== this.effectiveOffset || scrollY !== this.offset) {
|
|
190
|
-
this.onEffectiveOffset?.(scrollY)
|
|
191
|
-
}
|
|
192
|
-
if (scrollX !== this.effectiveOffsetX || scrollX !== this.offsetX) {
|
|
193
|
-
this.onEffectiveOffsetX?.(scrollX)
|
|
194
|
-
}
|
|
195
273
|
this.effectiveOffset = scrollY
|
|
196
274
|
this.effectiveOffsetX = scrollX
|
|
275
|
+
const offsetChanged = this.effectiveOffset !== this.lastOffsetY || this.effectiveOffsetX !== this.lastOffsetX
|
|
197
276
|
|
|
198
277
|
// Handle alignment when content is smaller than viewport
|
|
199
|
-
if (this.
|
|
200
|
-
if (
|
|
201
|
-
|
|
202
|
-
|
|
278
|
+
if (this.contentHeight < this.viewportHeight && (this.axis === "vertical" || this.axis === "both")) {
|
|
279
|
+
if (alignY === "bottom") {
|
|
280
|
+
scrollY = -(this.viewportHeight - this.contentHeight)
|
|
281
|
+
} else if (alignY === "center") {
|
|
282
|
+
scrollY = -Math.floor((this.viewportHeight - this.contentHeight) / 2)
|
|
203
283
|
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
284
|
+
}
|
|
285
|
+
if (this.contentWidth < this.viewportWidth && (this.axis === "horizontal" || this.axis === "both")) {
|
|
286
|
+
if (alignX === "right") {
|
|
287
|
+
scrollX = -(this.viewportWidth - this.contentWidth)
|
|
288
|
+
} else if (alignX === "center") {
|
|
289
|
+
scrollX = -Math.floor((this.viewportWidth - this.contentWidth) / 2)
|
|
207
290
|
}
|
|
208
291
|
}
|
|
209
292
|
|
|
@@ -215,6 +298,27 @@ export class ScrollHost extends SingleChildHost {
|
|
|
215
298
|
h: this.contentHeight,
|
|
216
299
|
}
|
|
217
300
|
child.layout(childRect)
|
|
301
|
+
|
|
302
|
+
if (this.onScrollLayoutChange && (contentChanged || viewportChanged || rectChanged || offsetChanged)) {
|
|
303
|
+
this.lastReportedContentW = this.contentWidth
|
|
304
|
+
this.lastReportedContentH = this.contentHeight
|
|
305
|
+
this.lastViewportW = this.viewportWidth
|
|
306
|
+
this.lastViewportH = this.viewportHeight
|
|
307
|
+
this.lastRectX = layoutRect.x
|
|
308
|
+
this.lastRectY = layoutRect.y
|
|
309
|
+
this.lastRectW = layoutRect.w
|
|
310
|
+
this.lastRectH = layoutRect.h
|
|
311
|
+
this.lastOffsetY = this.effectiveOffset
|
|
312
|
+
this.lastOffsetX = this.effectiveOffsetX
|
|
313
|
+
|
|
314
|
+
this.onScrollLayoutChange({
|
|
315
|
+
content: { width: this.contentWidth, height: this.contentHeight },
|
|
316
|
+
viewport: { width: this.viewportWidth, height: this.viewportHeight },
|
|
317
|
+
offset: { x: this.effectiveOffsetX, y: this.effectiveOffset },
|
|
318
|
+
rect: { x: layoutRect.x, y: layoutRect.y, w: layoutRect.w, h: layoutRect.h },
|
|
319
|
+
axis: this.axis,
|
|
320
|
+
})
|
|
321
|
+
}
|
|
218
322
|
}
|
|
219
323
|
|
|
220
324
|
render(buffer: CellBuffer, palette: Palette): void {
|
|
@@ -224,8 +328,8 @@ export class ScrollHost extends SingleChildHost {
|
|
|
224
328
|
// Fill background (inherit from parent if not explicitly set)
|
|
225
329
|
fillRectWithInheritedBg(buffer, palette, { x, y, w, h }, this.bg, this.parent)
|
|
226
330
|
|
|
227
|
-
// Render children with clipping
|
|
228
|
-
buffer.withClip(x, y,
|
|
331
|
+
// Render children with clipping (exclude scrollbar gutters)
|
|
332
|
+
buffer.withClip(x, y, this.viewportWidth, this.viewportHeight, () => {
|
|
229
333
|
const child = this.child
|
|
230
334
|
if (child) {
|
|
231
335
|
child.render(buffer, palette)
|
|
@@ -243,18 +347,18 @@ export class ScrollHost extends SingleChildHost {
|
|
|
243
347
|
const { x, y, w, h } = this.rect
|
|
244
348
|
|
|
245
349
|
// Vertical scrollbar
|
|
246
|
-
if (
|
|
247
|
-
const maxScroll = this.contentHeight -
|
|
350
|
+
if (this.showVerticalScrollbar) {
|
|
351
|
+
const maxScroll = Math.max(1, this.contentHeight - this.viewportHeight)
|
|
248
352
|
const scrollRatio = Math.min(1, this.effectiveOffset / maxScroll)
|
|
249
|
-
const thumbRatio =
|
|
250
|
-
const thumbHeight = Math.max(1, Math.floor(
|
|
251
|
-
const thumbY = Math.floor((
|
|
353
|
+
const thumbRatio = this.viewportHeight / this.contentHeight
|
|
354
|
+
const thumbHeight = Math.max(1, Math.floor(this.viewportHeight * thumbRatio))
|
|
355
|
+
const thumbY = Math.floor((this.viewportHeight - thumbHeight) * scrollRatio)
|
|
252
356
|
|
|
253
357
|
const trackStyle = palette.id({ fg: 8 }) // dim
|
|
254
358
|
const thumbStyle = palette.id({ fg: 7 }) // brighter
|
|
255
359
|
|
|
256
360
|
// Draw track
|
|
257
|
-
for (let row = 0; row <
|
|
361
|
+
for (let row = 0; row < this.viewportHeight; row++) {
|
|
258
362
|
const char = row >= thumbY && row < thumbY + thumbHeight ? "┃" : "│"
|
|
259
363
|
const style = row >= thumbY && row < thumbY + thumbHeight ? thumbStyle : trackStyle
|
|
260
364
|
buffer.drawCP(x + w - 1, y + row, char.codePointAt(0)!, style)
|
|
@@ -262,18 +366,18 @@ export class ScrollHost extends SingleChildHost {
|
|
|
262
366
|
}
|
|
263
367
|
|
|
264
368
|
// Horizontal scrollbar
|
|
265
|
-
if (
|
|
266
|
-
const maxScroll = this.contentWidth -
|
|
369
|
+
if (this.showHorizontalScrollbar) {
|
|
370
|
+
const maxScroll = Math.max(1, this.contentWidth - this.viewportWidth)
|
|
267
371
|
const scrollRatio = Math.min(1, this.effectiveOffsetX / maxScroll)
|
|
268
|
-
const thumbRatio =
|
|
269
|
-
const thumbWidth = Math.max(1, Math.floor(
|
|
270
|
-
const thumbX = Math.floor((
|
|
372
|
+
const thumbRatio = this.viewportWidth / this.contentWidth
|
|
373
|
+
const thumbWidth = Math.max(1, Math.floor(this.viewportWidth * thumbRatio))
|
|
374
|
+
const thumbX = Math.floor((this.viewportWidth - thumbWidth) * scrollRatio)
|
|
271
375
|
|
|
272
376
|
const trackStyle = palette.id({ fg: 8 })
|
|
273
377
|
const thumbStyle = palette.id({ fg: 7 })
|
|
274
378
|
|
|
275
379
|
// Draw track
|
|
276
|
-
for (let col = 0; col <
|
|
380
|
+
for (let col = 0; col < this.viewportWidth; col++) {
|
|
277
381
|
const char = col >= thumbX && col < thumbX + thumbWidth ? "━" : "─"
|
|
278
382
|
const style = col >= thumbX && col < thumbX + thumbWidth ? thumbStyle : trackStyle
|
|
279
383
|
buffer.drawCP(x + col, y + h - 1, char.codePointAt(0)!, style)
|
|
@@ -285,17 +389,35 @@ export class ScrollHost extends SingleChildHost {
|
|
|
285
389
|
super.updateProps(props)
|
|
286
390
|
// Scroll is greedy by default unless explicitly set to false
|
|
287
391
|
this.applyGreedyDefault(props, 1)
|
|
392
|
+
const prevAxis = this.axis
|
|
393
|
+
const prevOffsetY = this.offsetY
|
|
394
|
+
const prevOffsetX = this.offsetX
|
|
395
|
+
const prevAlign = this.align
|
|
396
|
+
const prevBg = this.bg
|
|
397
|
+
const prevShowScrollbar = this.showScrollbar
|
|
398
|
+
const prevSticky = this.sticky
|
|
399
|
+
|
|
288
400
|
if (props.axis !== undefined) this.axis = (props.axis as ScrollProps["axis"]) ?? "vertical"
|
|
289
|
-
if (props.
|
|
401
|
+
if (props.offsetY !== undefined) this.offsetY = props.offsetY as number
|
|
290
402
|
if (props.offsetX !== undefined) this.offsetX = props.offsetX as number
|
|
291
|
-
if (props.align !== undefined) this.align =
|
|
403
|
+
if (props.align !== undefined) this.align = props.align as ScrollProps["align"]
|
|
292
404
|
this.bg = props.bg as Color | undefined
|
|
293
405
|
if (props.showScrollbar !== undefined) this.showScrollbar = props.showScrollbar as boolean
|
|
294
406
|
if (props.sticky !== undefined) this.sticky = props.sticky as boolean
|
|
295
|
-
this.
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
407
|
+
this.onScrollLayoutChange = props.onScrollLayoutChange as ScrollProps["onScrollLayoutChange"]
|
|
408
|
+
|
|
409
|
+
const layoutChanged =
|
|
410
|
+
prevAxis !== this.axis ||
|
|
411
|
+
prevOffsetY !== this.offsetY ||
|
|
412
|
+
prevOffsetX !== this.offsetX ||
|
|
413
|
+
prevSticky !== this.sticky ||
|
|
414
|
+
prevAlign !== this.align ||
|
|
415
|
+
prevShowScrollbar !== this.showScrollbar
|
|
416
|
+
|
|
417
|
+
if (layoutChanged) {
|
|
418
|
+
this.invalidateLayout()
|
|
419
|
+
} else if (prevBg !== this.bg) {
|
|
420
|
+
this.invalidateRender()
|
|
421
|
+
}
|
|
300
422
|
}
|
|
301
423
|
}
|
|
@@ -26,6 +26,7 @@ export abstract class SingleChildHost extends BaseHost {
|
|
|
26
26
|
this.children.splice(0, 1)
|
|
27
27
|
}
|
|
28
28
|
child.parent = null
|
|
29
|
+
this.invalidateLayout()
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
private setSingleChild(child: HostInstance): void {
|
|
@@ -44,5 +45,6 @@ export abstract class SingleChildHost extends BaseHost {
|
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
child.parent = this
|
|
48
|
+
this.invalidateLayout()
|
|
47
49
|
}
|
|
48
50
|
}
|
package/src/hosts/spacer.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { CellBuffer, Palette } from "@effect-tui/core"
|
|
2
2
|
import type { CommonProps, HostContext, Size } from "../reconciler/types.js"
|
|
3
|
-
import {
|
|
3
|
+
import { LeafHost } from "./leaf.js"
|
|
4
4
|
|
|
5
5
|
export interface SpacerProps extends CommonProps {
|
|
6
6
|
/** Minimum width (default 0) */
|
|
@@ -9,7 +9,7 @@ export interface SpacerProps extends CommonProps {
|
|
|
9
9
|
minHeight?: number
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
export class SpacerHost extends
|
|
12
|
+
export class SpacerHost extends LeafHost {
|
|
13
13
|
minWidth = 0
|
|
14
14
|
minHeight = 0
|
|
15
15
|
|
|
@@ -21,7 +21,7 @@ export class SpacerHost extends BaseHost {
|
|
|
21
21
|
this.updateProps(props as unknown as Record<string, unknown>)
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
protected measureSelf(_maxW: number, _maxH: number): Size {
|
|
25
25
|
// Spacers have no natural size, they expand via greedy
|
|
26
26
|
return { w: this.minWidth, h: this.minHeight }
|
|
27
27
|
}
|
|
@@ -34,7 +34,12 @@ export class SpacerHost extends BaseHost {
|
|
|
34
34
|
super.updateProps(props)
|
|
35
35
|
// Spacer is greedy by default unless explicitly set to false
|
|
36
36
|
this.applyGreedyDefault(props, 1)
|
|
37
|
+
const prevMinWidth = this.minWidth
|
|
38
|
+
const prevMinHeight = this.minHeight
|
|
37
39
|
if (props.minWidth !== undefined) this.minWidth = props.minWidth as number
|
|
38
40
|
if (props.minHeight !== undefined) this.minHeight = props.minHeight as number
|
|
41
|
+
if (prevMinWidth !== this.minWidth || prevMinHeight !== this.minHeight) {
|
|
42
|
+
this.invalidateLayout()
|
|
43
|
+
}
|
|
39
44
|
}
|
|
40
45
|
}
|