@@ -133,22 +133,25 @@ function placeholderOptions(count: number): SelectOption[] {
133133}
134134
135135/**
136- * SelectRenderable keeps scroll offset and visible-item capacity private
137- * (@opentui/core 0.5.10 exposes no accessors), so read them reflectively
138- * and narrow instead of asserting a shape .
136+ * SelectRenderable keeps its scroll offset private. The painted window is the
137+ * same centered slice Select computes from its public height and selection,
138+ * so callers can read it without reflecting into private fields .
139139 */
140- function selectScrollState ( select : SelectRenderable ) : {
141- offset : number ;
142- visible : number ;
143- } {
144- const numberProp = ( name : string ) : number => {
145- const value = Object . getOwnPropertyDescriptor ( select , name ) ?. value ;
146- return typeof value === "number" ? value : 1 ;
147- } ;
148- return {
149- offset : numberProp ( "scrollOffset" ) ,
150- visible : Math . max ( 1 , numberProp ( "maxVisibleItems" ) ) ,
151- } ;
140+ function selectWindow (
141+ select : SelectRenderable ,
142+ count : number ,
143+ rowsPerItem : number ,
144+ ) : { offset : number ; visible : number } {
145+ if ( count === 0 ) return { offset : 0 , visible : 0 } ;
146+ const linesPerItem = Math . max ( 1 , rowsPerItem ) ;
147+ const visible = Math . max ( 1 , Math . floor ( select . height / linesPerItem ) ) ;
148+ const half = Math . floor ( visible / 2 ) ;
149+ const index = select . getSelectedIndex ( ) ;
150+ const offset = Math . max (
151+ 0 ,
152+ Math . min ( index - half , Math . max ( 0 , count - visible ) ) ,
153+ ) ;
154+ return { offset, visible } ;
152155}
153156
154157export function createOverlayList (
@@ -165,6 +168,7 @@ export function createOverlayList(
165168
166169 const build = ( ) : SelectRenderable =>
167170 new SelectRenderable ( ctx , {
171+ id : "shell-overlay-select" ,
168172 options,
169173 selectedIndex : activeIndex ,
170174 height : shape . items * shape . rowsPerItem ,
@@ -221,7 +225,7 @@ export function createOverlayList(
221225 return shape . rowsPerItem ;
222226 } ,
223227 get offset ( ) {
224- return selectScrollState ( select ) . offset ;
228+ return selectWindow ( select , count , shape . rowsPerItem ) . offset ;
225229 } ,
226230 get count ( ) {
227231 return count ;
@@ -251,7 +255,7 @@ export function createOverlayList(
251255 } ) ;
252256 } ,
253257 visibleRange ( ) {
254- const { offset, visible } = selectScrollState ( select ) ;
258+ const { offset, visible } = selectWindow ( select , count , shape . rowsPerItem ) ;
255259 return { start : offset , end : Math . min ( count , offset + visible ) } ;
256260 } ,
257261 } ;
0 commit comments