|
14 | 14 | </script> |
15 | 15 |
|
16 | 16 | <script lang="ts" generics="T"> |
17 | | - import { SETTINGS } from '$lib/settings/userSettings'; |
18 | | - import { chunk } from '$lib/utils/array'; |
| 17 | + import Button from '$components/Button.svelte'; |
| 18 | + import ScrollableContainer from '$components/scroll/ScrollableContainer.svelte'; |
| 19 | +
|
19 | 20 | import { debounce } from '$lib/utils/debounce'; |
20 | | - import { inject } from '@gitbutler/core/context'; |
21 | | - import { Button, ScrollableContainer } from '@gitbutler/ui'; |
22 | 21 |
|
23 | 22 | import { tick, untrack, type Snippet } from 'svelte'; |
24 | 23 | import { fade } from 'svelte/transition'; |
| 24 | + import type { ScrollbarVisilitySettings } from '$components/scroll/Scrollbar.svelte'; |
25 | 25 |
|
26 | 26 | type Props = { |
27 | 27 | items: Array<T>; |
| 28 | + /** Items that are always included. */ |
| 29 | + children?: Snippet<[]>; |
28 | 30 | /** Template for group of items. */ |
29 | 31 | chunkTemplate: Snippet<[T[]]>; |
30 | 32 | /** Number of items grouped together. */ |
|
36 | 38 | initialPosition?: 'top' | 'bottom'; |
37 | 39 | /** Auto-scroll to bottom when new items are added (useful for chat). */ |
38 | 40 | stickToBottom?: boolean; |
| 41 | + visibility: ScrollbarVisilitySettings; |
39 | 42 | padding?: { |
40 | 43 | left?: number; |
41 | 44 | right?: number; |
|
44 | 47 |
|
45 | 48 | const { |
46 | 49 | items, |
| 50 | + children, |
47 | 51 | chunkTemplate, |
48 | 52 | batchSize, |
49 | 53 | onloadmore, |
50 | 54 | grow, |
51 | 55 | padding, |
| 56 | + visibility, |
52 | 57 | initialPosition = 'top', |
53 | 58 | stickToBottom = false |
54 | 59 | }: Props = $props(); |
55 | 60 |
|
56 | | - const userSettings = inject(SETTINGS); |
57 | | -
|
58 | 61 | // Constants |
59 | 62 | const STICKY_DISTANCE = 100; |
60 | 63 | const FALLBACK_HEIGHT = 65; |
|
96 | 99 | chunks.slice(start, end).map((data, i) => ({ id: i + start, data })) |
97 | 100 | ); |
98 | 101 |
|
| 102 | + function chunk<T>(arr: T[], size: number) { |
| 103 | + return Array.from({ length: Math.ceil(arr.length / size) }, (_v, i) => |
| 104 | + arr.slice(i * size, i * size + size) |
| 105 | + ); |
| 106 | + } |
| 107 | +
|
99 | 108 | function sumHeights(startIndex: number, endIndex: number): number { |
100 | 109 | let sum = 0; |
101 | 110 | for (let i = startIndex; i < endIndex; i++) { |
|
349 | 358 | <ScrollableContainer |
350 | 359 | bind:viewportHeight |
351 | 360 | bind:viewport |
352 | | - whenToShow={$userSettings.scrollbarVisibilityState} |
353 | 361 | onscroll={() => { |
354 | 362 | recalculate(true); |
355 | 363 | checkIfNearBottom(); |
356 | 364 | }} |
357 | 365 | wide={grow} |
| 366 | + whenToShow={visibility} |
358 | 367 | {padding} |
359 | 368 | > |
360 | 369 | <div |
|
369 | 378 | {@render chunkTemplate?.(chunk.data)} |
370 | 379 | </div> |
371 | 380 | {/each} |
| 381 | + {@render children?.()} |
372 | 382 | </div> |
373 | 383 | </ScrollableContainer> |
374 | 384 |
|
|
0 commit comments