@opencode/ui 0.0.0-dev-19530 → 0.0.0-dev-19531

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.
@@ -14,6 +14,10 @@ export interface ScrollViewProps extends ComponentProps<"div"> {
14
14
  thumbContainer?: HTMLElement;
15
15
  /** Element whose hover reveals the thumb. Defaults to the ScrollView root when unset. */
16
16
  thumbHoverTarget?: HTMLElement;
17
+ /** Reconcile native scroll geometry before keyboard or scrollbar navigation reads it. */
18
+ onBeforeScroll?: () => void;
19
+ /** Offset/extent correction for a virtualized vertical scrollbar. */
20
+ verticalScrollAdjustment?: number;
17
21
  }
18
22
  export declare const scrollKey: (event: Pick<KeyboardEvent, "key" | "altKey" | "ctrlKey" | "metaKey" | "shiftKey">) => "end" | "home" | "page-down" | "page-up" | "up" | "down" | undefined;
19
23
  export declare function canScrollKey(element: HTMLElement, key: NonNullable<ReturnType<typeof scrollKey>>): boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opencode/ui",
3
- "version": "0.0.0-dev-19530",
3
+ "version": "0.0.0-dev-19531",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -20,6 +20,10 @@ export interface ScrollViewProps extends ComponentProps<"div"> {
20
20
  thumbContainer?: HTMLElement
21
21
  /** Element whose hover reveals the thumb. Defaults to the ScrollView root when unset. */
22
22
  thumbHoverTarget?: HTMLElement
23
+ /** Reconcile native scroll geometry before keyboard or scrollbar navigation reads it. */
24
+ onBeforeScroll?: () => void
25
+ /** Offset/extent correction for a virtualized vertical scrollbar. */
26
+ verticalScrollAdjustment?: number
23
27
  }
24
28
 
25
29
  export const scrollKey = (event: Pick<KeyboardEvent, "key" | "altKey" | "ctrlKey" | "metaKey" | "shiftKey">) => {
@@ -124,6 +128,8 @@ export function ScrollView(props: ScrollViewProps) {
124
128
  "thumbVisibility",
125
129
  "thumbContainer",
126
130
  "thumbHoverTarget",
131
+ "onBeforeScroll",
132
+ "verticalScrollAdjustment",
127
133
  "style",
128
134
  ],
129
135
  [
@@ -189,17 +195,19 @@ export function ScrollView(props: ScrollViewProps) {
189
195
  const minThumbSize = 32
190
196
 
191
197
  if (vertical()) {
198
+ const adjustment = local.verticalScrollAdjustment ?? 0
199
+ const scrollHeight = viewportRef.scrollHeight + adjustment
192
200
  const trackSize = Math.max(0, (thumbMount()?.clientHeight || viewportRef.clientHeight) - trackPadding * 2)
193
201
  const size = trackSize
194
- ? Math.min(trackSize, Math.max((viewportRef.clientHeight / viewportRef.scrollHeight) * trackSize, minThumbSize))
202
+ ? Math.min(trackSize, Math.max((viewportRef.clientHeight / scrollHeight) * trackSize, minThumbSize))
195
203
  : 0
196
- const maxScroll = viewportRef.scrollHeight - viewportRef.clientHeight
204
+ const maxScroll = scrollHeight - viewportRef.clientHeight
197
205
  const maxStart = trackSize - size
198
206
  setState("showVerticalThumb", maxScroll > 0)
199
207
  setState("verticalThumbSize", size)
200
208
  setState(
201
209
  "verticalThumbStart",
202
- trackPadding + (maxScroll > 0 ? (viewportRef.scrollTop / maxScroll) * maxStart : 0),
210
+ trackPadding + (maxScroll > 0 ? ((viewportRef.scrollTop + adjustment) / maxScroll) * maxStart : 0),
203
211
  )
204
212
  } else {
205
213
  setState("showVerticalThumb", false)
@@ -263,9 +271,17 @@ export function ScrollView(props: ScrollViewProps) {
263
271
  })
264
272
  })
265
273
 
274
+ const prepareScroll = () => {
275
+ if (local.onBeforeScroll) {
276
+ local.onBeforeScroll()
277
+ updateThumb()
278
+ }
279
+ }
280
+
266
281
  const onThumbPointerDown = (axis: "vertical" | "horizontal", e: PointerEvent) => {
267
282
  e.preventDefault()
268
283
  e.stopPropagation()
284
+ prepareScroll()
269
285
  setState("dragging", axis)
270
286
  const thumb = axis === "vertical" ? verticalThumbRef : horizontalThumbRef
271
287
  const grabOffset =
@@ -277,6 +293,7 @@ export function ScrollView(props: ScrollViewProps) {
277
293
  thumb.setPointerCapture(e.pointerId)
278
294
 
279
295
  const onPointerMove = (e: PointerEvent) => {
296
+ prepareScroll()
280
297
  const vertical = axis === "vertical"
281
298
  const rtl = !vertical && getComputedStyle(viewportRef).direction === "rtl"
282
299
  const offset = scrollOffsetFromThumbPointer({
@@ -355,10 +372,23 @@ export function ScrollView(props: ScrollViewProps) {
355
372
  return
356
373
  }
357
374
  const next = scrollKey(e)
358
- if (!next) return
359
- if (!isScrollKeyTarget(e.target, next)) return
360
- if (scrollKeyOwner(viewportRef, e.target, next) !== viewportRef) return
375
+ // Modified navigation (for example Ctrl+Home) stays native, but must read
376
+ // the same reconciled geometry as the keys handled by this component.
377
+ const intent =
378
+ next ??
379
+ scrollKey({
380
+ key: e.key,
381
+ shiftKey: e.key === " " && e.shiftKey,
382
+ altKey: false,
383
+ ctrlKey: false,
384
+ metaKey: false,
385
+ })
386
+ if (!intent) return
387
+ if (!isScrollKeyTarget(e.target, intent)) return
388
+ if (scrollKeyOwner(viewportRef, e.target, intent) !== viewportRef) return
361
389
 
390
+ prepareScroll()
391
+ if (!next) return
362
392
  const scrollAmount = viewportRef.clientHeight * 0.8
363
393
  const lineAmount = 40
364
394