|
18 | 18 | import { ServerModelStatus } from '$lib/enums'; |
19 | 19 | import { isRouterMode } from '$lib/stores/server.svelte'; |
20 | 20 | import { DialogModelInformation } from '$lib/components/app'; |
21 | | - import { |
22 | | - MENU_MAX_WIDTH, |
23 | | - MENU_OFFSET, |
24 | | - VIEWPORT_GUTTER |
25 | | - } from '$lib/constants/floating-ui-constraints'; |
| 21 | + import { MENU_OFFSET, VIEWPORT_GUTTER } from '$lib/constants/floating-ui-constraints'; |
26 | 22 | import type { ModelOption } from '$lib/types/models'; |
27 | 23 |
|
28 | 24 | interface Props { |
|
256 | 252 | } |
257 | 253 | } |
258 | 254 |
|
259 | | - function updateMenuPosition() { |
| 255 | + async function updateMenuPosition() { |
260 | 256 | if (!isOpen || !triggerButton || !menuRef) return; |
261 | 257 |
|
262 | 258 | const triggerRect = triggerButton.getBoundingClientRect(); |
|
268 | 264 | const scrollHeight = menuRef.scrollHeight; |
269 | 265 |
|
270 | 266 | const availableWidth = Math.max(0, viewportWidth - VIEWPORT_GUTTER * 2); |
271 | | - const safeMaxWidth = availableWidth > 0 ? availableWidth : MENU_MAX_WIDTH; |
272 | | - const desiredMinWidth = Math.min(160, safeMaxWidth || 160); |
| 267 | + const safeMaxWidth = availableWidth || viewportWidth; |
273 | 268 |
|
274 | 269 | if (menuWidth === null) { |
275 | 270 | menuRef.style.width = ''; |
276 | 271 | menuRef.style.maxWidth = ''; |
277 | 272 |
|
278 | | - const idealWidth = Math.max( |
279 | | - triggerRect.width, |
280 | | - Math.min(menuRef.scrollWidth, safeMaxWidth), |
281 | | - 400 |
282 | | - ); |
283 | | -
|
284 | | - menuWidth = Math.min(Math.max(idealWidth, desiredMinWidth), safeMaxWidth); |
285 | | - } else if (safeMaxWidth && menuWidth > safeMaxWidth) { |
286 | | - menuWidth = safeMaxWidth; |
| 273 | + const idealWidth = Math.max(triggerRect.width, Math.min(menuRef.scrollWidth, safeMaxWidth)); |
| 274 | + menuWidth = Math.min(idealWidth, safeMaxWidth); |
287 | 275 | } |
288 | 276 |
|
289 | | - const width = menuWidth ?? desiredMinWidth; |
290 | | -
|
291 | 277 | const availableBelow = Math.max( |
292 | 278 | 0, |
293 | 279 | viewportHeight - VIEWPORT_GUTTER - triggerRect.bottom - MENU_OFFSET |
|
337 | 323 |
|
338 | 324 | const availableRight = viewportWidth - VIEWPORT_GUTTER; |
339 | 325 | const rightAligned = Math.min(triggerRect.right, availableRight); |
340 | | - let left = rightAligned - width; |
341 | | - const maxLeft = viewportWidth - VIEWPORT_GUTTER - width; |
| 326 | + let left = rightAligned - menuWidth; |
| 327 | + const maxLeft = viewportWidth - VIEWPORT_GUTTER - menuWidth; |
342 | 328 | left = Math.min(Math.max(left, VIEWPORT_GUTTER), Math.max(maxLeft, VIEWPORT_GUTTER)); |
343 | 329 |
|
344 | 330 | menuPosition = { |
345 | 331 | top: Math.round(metrics.top), |
346 | 332 | left: Math.round(left), |
347 | | - width: Math.round(width), |
| 333 | + width: Math.round(menuWidth), |
348 | 334 | placement: metrics.placement, |
349 | 335 | maxHeight: Math.round(metrics.maxHeight) |
350 | 336 | }; |
|
491 | 477 | style:width={menuPosition ? `${menuPosition.width}px` : undefined} |
492 | 478 | data-placement={menuPosition?.placement ?? 'bottom'} |
493 | 479 | > |
494 | | - <div class="border-b bg-popover px-3 py-2"> |
| 480 | + <div class="px-3 py-2"> |
495 | 481 | <label class="sr-only" for="model-search">Search models</label> |
496 | 482 | <input |
497 | 483 | id="model-search" |
498 | | - class="h-9 w-full rounded-md border border-input bg-background px-3 text-sm shadow-sm transition focus:border-ring focus:outline-none" |
| 484 | + class="h-9 w-full rounded-lg bg-muted px-3 text-sm outline-none placeholder:text-muted-foreground" |
499 | 485 | placeholder="Search models" |
500 | 486 | bind:value={searchTerm} |
501 | 487 | bind:this={searchInputRef} |
|
504 | 490 | type="search" |
505 | 491 | /> |
506 | 492 | </div> |
507 | | - |
508 | 493 | <div |
509 | 494 | class="overflow-y-auto py-1" |
510 | 495 | style:max-height={menuPosition && menuPosition.maxHeight > 0 |
|
0 commit comments