@opengeni/react 3.7.0-canary.2 → 3.7.0-canary.4

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.
@@ -1,6 +1,5 @@
1
1
  import type { ClientModel, LatencyMode, ReasoningEffort } from "@opengeni/sdk";
2
2
  import {
3
- CheckIcon,
4
3
  ChevronDownIcon,
5
4
  ChevronLeftIcon,
6
5
  ChevronRightIcon,
@@ -9,11 +8,11 @@ import {
9
8
  ZapIcon,
10
9
  } from "lucide-react";
11
10
  import { motion, useReducedMotion } from "motion/react";
12
- import { DropdownMenu } from "radix-ui";
13
11
  import {
14
- useEffect,
12
+ Suspense,
13
+ lazy,
15
14
  useMemo,
16
- useRef,
15
+ useId,
17
16
  useState,
18
17
  type CSSProperties,
19
18
  type ReactNode,
@@ -22,28 +21,20 @@ import {
22
21
  import { cn } from "../lib/cn";
23
22
  import { usePortalTokenSource, usePortalTokenStyle } from "../lib/use-portal-token-style";
24
23
  import {
25
- effortOptionsForModel,
26
24
  findPickerRow,
27
- groupPickerRowsByBillingClass,
28
25
  labelReasoningEffort,
29
- payerSummaryForModel,
30
26
  projectClientModelRows,
31
- runnableLatencyModesForModel,
32
27
  type PickerBillingClass,
33
28
  type PickerModelRow,
34
29
  } from "../model-policy";
35
30
 
36
- type ClientPickerModelRow = PickerModelRow<ClientModel>;
37
-
38
- type NavLevel = "providers" | "models" | "thinking";
31
+ const LazyModelPolicyPickerMenu = lazy(() =>
32
+ import("./model-policy-picker-menu").then(({ ModelPolicyPickerPopover }) => ({
33
+ default: ModelPolicyPickerPopover,
34
+ })),
35
+ );
39
36
 
40
- type PickerNavState = {
41
- level: NavLevel;
42
- rail: PickerBillingClass | null;
43
- modelId: string | null;
44
- };
45
-
46
- type NavUpdater = PickerNavState | ((previous: PickerNavState) => PickerNavState);
37
+ type ClientPickerModelRow = PickerModelRow<ClientModel>;
47
38
 
48
39
  export type ModelPolicyPickerMessages = {
49
40
  label: string;
@@ -53,6 +44,14 @@ export type ModelPolicyPickerMessages = {
53
44
  fast: string;
54
45
  fastRateHint: string;
55
46
  codexOnly: string;
47
+ searchLabel?: string;
48
+ searchPlaceholder?: string;
49
+ currentModel?: string;
50
+ noMatches?: string;
51
+ unsupportedAttachments?: string;
52
+ thinkingEffort?: string;
53
+ selected?: string;
54
+
56
55
  billingHints: Record<PickerBillingClass, string>;
57
56
  };
58
57
 
@@ -64,6 +63,15 @@ export const defaultModelPolicyPickerMessages: ModelPolicyPickerMessages = {
64
63
  fast: "Fast",
65
64
  fastRateHint: "2× rate",
66
65
  codexOnly: "Codex-only session",
66
+ searchLabel: "Search models or providers",
67
+ searchPlaceholder: "Search models or providers…",
68
+ currentModel: "Current model",
69
+ noMatches: "No matching models. Try a model or provider name.",
70
+ unsupportedAttachments:
71
+ "Unsupported attachments stay in the session but are hidden from this model.",
72
+ thinkingEffort: "Thinking effort",
73
+ selected: "Selected",
74
+
67
75
  billingHints: {
68
76
  opengeni_credits: "Will use credits",
69
77
  external: "Provider terms and limits apply",
@@ -92,7 +100,7 @@ export type ModelPolicyPickerProps = {
92
100
  onOpenChange?: ((open: boolean) => void) | undefined;
93
101
  /** Non-Codex models stay visible but cannot be selected. */
94
102
  codexOnly?: boolean | undefined;
95
- /** Resets drill-down navigation when the session scope changes. */
103
+ /** Identity of the current session scope. */
96
104
  sessionKey?: string | undefined;
97
105
  /** Prefer bottom on new-chat surfaces and top for bottom-docked composers. */
98
106
  menuSide?: "top" | "bottom" | undefined;
@@ -227,42 +235,12 @@ function applyCodexOnly(
227
235
  );
228
236
  }
229
237
 
230
- function effectiveRows(props: ModelPolicyPickerProps): ClientPickerModelRow[] {
238
+ export function effectiveRows(props: ModelPolicyPickerProps): ClientPickerModelRow[] {
231
239
  const rows = props.rows !== undefined ? props.rows : projectClientModelRows(props.models ?? []);
232
240
  const messages = { ...defaultModelPolicyPickerMessages, ...props.messages };
233
241
  return applyCodexOnly(rows, props.codexOnly === true, messages.codexOnly);
234
242
  }
235
243
 
236
- function defaultNavState(rows: ClientPickerModelRow[], modelId: string): PickerNavState {
237
- const selected = findPickerRow(rows, modelId);
238
- if (!selected) {
239
- const rails = new Set(rows.map((row) => row.billingClass));
240
- const onlyRail = rails.size === 1 ? rows[0]?.billingClass : null;
241
- return onlyRail
242
- ? { level: "models", rail: onlyRail, modelId: null }
243
- : { level: "providers", rail: null, modelId: null };
244
- }
245
- return {
246
- level: "thinking",
247
- rail: selected.billingClass,
248
- modelId: selected.id,
249
- };
250
- }
251
-
252
- function usePickerNavState(
253
- sessionKey: string | undefined,
254
- rows: ClientPickerModelRow[],
255
- model: string,
256
- ): [PickerNavState, (next: NavUpdater) => void] {
257
- const [state, setState] = useState<PickerNavState>(() => defaultNavState(rows, model));
258
- useEffect(() => {
259
- setState(defaultNavState(rows, model));
260
- // The menu deliberately preserves its drill-down while the same session is mounted.
261
- // eslint-disable-next-line react-hooks/exhaustive-deps
262
- }, [sessionKey]);
263
- return [state, setState];
264
- }
265
-
266
244
  export function PickerNavRow(props: {
267
245
  label: string;
268
246
  hint?: string | undefined;
@@ -348,265 +326,26 @@ export function PickerAnimatedPage(props: {
348
326
  );
349
327
  }
350
328
 
351
- export function ModelPolicyPickerMenu(
352
- props: ModelPolicyPickerProps & {
353
- nav?: PickerNavState | undefined;
354
- onNavChange?: ((next: NavUpdater) => void) | undefined;
355
- },
356
- ) {
357
- const messages = useMemo(
358
- () => ({ ...defaultModelPolicyPickerMessages, ...props.messages }),
359
- [props.messages],
360
- );
361
- const rows = effectiveRows(props);
362
- const groups = useMemo(() => groupPickerRowsByBillingClass(rows), [rows]);
363
- const [localNav, setLocalNav] = usePickerNavState(
364
- props.nav === undefined ? props.sessionKey : undefined,
365
- rows,
366
- props.model,
367
- );
368
- const nav = props.nav ?? localNav;
369
- const setNav = props.onNavChange ?? setLocalNav;
370
- const [direction, setDirection] = useState<1 | -1>(1);
371
-
372
- const effectiveNav =
373
- nav.level === "providers" && groups.length === 1
374
- ? {
375
- level: "models" as const,
376
- rail: groups[0]!.billingClass,
377
- modelId: null,
378
- }
379
- : nav;
380
- const activeGroup =
381
- effectiveNav.rail === null
382
- ? undefined
383
- : groups.find((group) => group.billingClass === effectiveNav.rail);
384
- const focusModel =
385
- effectiveNav.modelId === null ? undefined : findPickerRow(rows, effectiveNav.modelId);
386
- const selectedRow = findPickerRow(rows, props.model);
387
-
388
- const go = (next: PickerNavState, nextDirection: 1 | -1) => {
389
- setDirection(nextDirection);
390
- setNav(next);
391
- };
392
-
393
- const selectEffort = (row: ClientPickerModelRow, effort: ReasoningEffort) => {
394
- if (!row.selectable) return;
395
- if (row.id !== props.model) props.onModelChange(row.id);
396
- props.onEffortChange(effort);
397
- };
398
-
399
- const pageKey =
400
- effectiveNav.level === "providers"
401
- ? "providers"
402
- : effectiveNav.level === "models"
403
- ? `models:${effectiveNav.rail ?? ""}`
404
- : `thinking:${effectiveNav.modelId ?? ""}`;
405
-
406
- let body: ReactNode;
407
- if (props.loading) {
408
- body = <p className="px-2 py-3 text-og-control text-og-fg-subtle">{messages.loading}</p>;
409
- } else if (groups.length === 0) {
410
- body = <p className="px-2 py-3 text-og-control text-og-fg-subtle">{messages.noModels}</p>;
411
- } else if (effectiveNav.level === "providers") {
412
- body = (
413
- <div className="flex flex-col gap-0.5" data-testid="model-picker-providers">
414
- {groups.map((group) => (
415
- <PickerNavRow
416
- key={group.billingClass}
417
- label={group.label}
418
- hint={messages.billingHints[group.billingClass]}
419
- icon={<BillingClassMark billingClass={group.billingClass} />}
420
- active={selectedRow?.billingClass === group.billingClass}
421
- testId={`model-picker-rail-${group.billingClass}`}
422
- onClick={() => go({ level: "models", rail: group.billingClass, modelId: null }, 1)}
423
- />
424
- ))}
425
- </div>
426
- );
427
- } else if (effectiveNav.level === "models" && activeGroup) {
428
- body = (
429
- <div data-testid="model-picker-models">
430
- {groups.length > 1 ? (
431
- <PickerBackHeader
432
- label={activeGroup.label}
433
- icon={<BillingClassMark billingClass={activeGroup.billingClass} />}
434
- onBack={() => go({ level: "providers", rail: null, modelId: null }, -1)}
435
- />
436
- ) : null}
437
- <div className="flex flex-col gap-0.5">
438
- {activeGroup.rows.map((row) => (
439
- <PickerNavRow
440
- key={`${row.billingClass}:${row.id}`}
441
- label={row.label}
442
- hint={row.unavailableReason ?? payerSummaryForModel(row.catalog)}
443
- disabled={!row.selectable}
444
- title={row.unavailableReason ?? undefined}
445
- active={row.id === props.model}
446
- testId={`model-picker-choice-${row.id}`}
447
- onClick={() => {
448
- if (row.selectable) {
449
- go(
450
- {
451
- level: "thinking",
452
- rail: row.billingClass,
453
- modelId: row.id,
454
- },
455
- 1,
456
- );
457
- }
458
- }}
459
- />
460
- ))}
461
- </div>
462
- </div>
463
- );
464
- } else if (effectiveNav.level === "thinking" && focusModel) {
465
- const activeModel = focusModel.id === props.model;
466
- const supportsFast = runnableLatencyModesForModel(focusModel.catalog).includes("fast");
467
- body = (
468
- <div data-testid="model-picker-reasoning">
469
- <PickerBackHeader
470
- label={focusModel.label}
471
- icon={<BillingClassMark billingClass={focusModel.billingClass} />}
472
- onBack={() => go({ level: "models", rail: focusModel.billingClass, modelId: null }, -1)}
473
- trailing={
474
- supportsFast && props.allowLatencyMode !== false ? (
475
- <button
476
- type="button"
477
- disabled={!focusModel.selectable}
478
- aria-pressed={activeModel && props.latencyMode === "fast"}
479
- aria-label={
480
- activeModel && props.latencyMode === "fast"
481
- ? `Disable ${messages.fast}`
482
- : `Enable ${messages.fast}`
483
- }
484
- title={`${messages.fast} · ${messages.fastRateHint}`}
485
- data-testid="model-picker-fast"
486
- onClick={() => {
487
- if (!activeModel) {
488
- props.onModelChange(focusModel.id);
489
- }
490
- props.onLatencyModeChange(
491
- activeModel && props.latencyMode === "fast" ? "standard" : "fast",
492
- );
493
- }}
494
- className={cn(
495
- "flex size-8 shrink-0 cursor-pointer items-center justify-center rounded-og-sm text-og-fg-subtle outline-hidden transition-colors hover:bg-og-surface-2 focus-visible:ring-2 focus-visible:ring-og-accent/40 disabled:cursor-not-allowed disabled:opacity-50",
496
- activeModel && props.latencyMode === "fast" && "text-og-fg",
497
- )}
498
- >
499
- <ZapIcon
500
- className={cn(
501
- "size-3.5",
502
- activeModel && props.latencyMode === "fast" && "fill-current",
503
- )}
504
- />
505
- </button>
506
- ) : null
507
- }
508
- />
509
- <p className="px-2.5 pt-1 pb-1 text-og-control font-medium tracking-wide text-og-fg-subtle uppercase">
510
- {messages.thinking}
511
- </p>
512
- {focusModel.catalog.capabilities?.inputModalities.includes("image") === false ? (
513
- <p className="px-2.5 pb-1.5 text-og-control leading-relaxed text-og-fg-subtle">
514
- Unsupported attachments stay in the session but are hidden from this model.
515
- </p>
516
- ) : null}
517
- <div className="flex flex-col gap-0.5">
518
- {effortOptionsForModel(focusModel.catalog).map((effort) => {
519
- const selected = activeModel && effort === props.effort;
520
- return (
521
- <button
522
- key={effort}
523
- type="button"
524
- disabled={!focusModel.selectable}
525
- onClick={() => selectEffort(focusModel, effort)}
526
- className={cn(
527
- "flex h-[var(--og-model-picker-effort-height)] w-full cursor-pointer items-center rounded-og-sm px-[var(--og-model-picker-row-padding-x)] text-left text-og-menu text-og-fg outline-hidden transition-colors hover:bg-og-surface-2 focus-visible:ring-2 focus-visible:ring-og-accent/40 disabled:cursor-not-allowed disabled:opacity-50",
528
- selected && "bg-og-surface-2",
529
- )}
530
- >
531
- <span className="min-w-0 flex-1 truncate">{labelReasoningEffort(effort)}</span>
532
- {selected ? (
533
- <CheckIcon
534
- className="ml-auto size-3.5 shrink-0"
535
- data-testid="model-picker-effort-check"
536
- />
537
- ) : null}
538
- </button>
539
- );
540
- })}
541
- </div>
542
- </div>
543
- );
544
- } else {
545
- body = (
546
- <div className="flex flex-col gap-0.5" data-testid="model-picker-providers">
547
- {groups.map((group) => (
548
- <PickerNavRow
549
- key={group.billingClass}
550
- label={group.label}
551
- hint={messages.billingHints[group.billingClass]}
552
- icon={<BillingClassMark billingClass={group.billingClass} />}
553
- testId={`model-picker-rail-${group.billingClass}`}
554
- onClick={() => go({ level: "models", rail: group.billingClass, modelId: null }, 1)}
555
- />
556
- ))}
557
- </div>
558
- );
559
- }
560
-
561
- return (
562
- <div data-testid="model-picker-menu" className="relative overflow-hidden">
563
- {props.error ? (
564
- <p className="px-2 py-1 text-og-control text-og-status-failed" role="alert">
565
- {props.error}
566
- </p>
567
- ) : null}
568
- <PickerAnimatedPage pageKey={pageKey} direction={direction}>
569
- {body}
570
- </PickerAnimatedPage>
571
- </div>
572
- );
573
- }
574
-
575
- /** @internal Shared state seam kept outside the Radix portal for deterministic testing. */
329
+ /** @internal Shared controlled/uncontrolled state seam. */
576
330
  export function useModelPolicyPickerState(props: ModelPolicyPickerProps) {
577
331
  const [uncontrolledOpen, setUncontrolledOpen] = useState(props.defaultOpen ?? false);
578
332
  const open = props.open ?? uncontrolledOpen;
579
- const rows = effectiveRows(props);
580
- const [nav, setNav] = usePickerNavState(props.sessionKey, rows, props.model);
581
- const previousControlledOpen = useRef(props.open);
582
- useEffect(() => {
583
- const wasOpen = previousControlledOpen.current;
584
- previousControlledOpen.current = props.open;
585
- if (props.open === true && wasOpen !== true) {
586
- setNav(defaultNavState(rows, props.model));
587
- }
588
- // Reset only on the controlled closed-to-open edge; ordinary rerenders
589
- // deliberately preserve the current drill-down page.
590
- // eslint-disable-next-line react-hooks/exhaustive-deps
591
- }, [props.open]);
592
333
  const setOpen = (next: boolean) => {
593
- if (next) {
594
- setNav(defaultNavState(rows, props.model));
595
- }
596
334
  if (props.open === undefined) setUncontrolledOpen(next);
597
335
  props.onOpenChange?.(next);
598
336
  };
599
- return { open, setOpen, rows, nav, setNav };
337
+ return { open, setOpen, rows: effectiveRows(props) };
600
338
  }
601
339
 
602
340
  export function ModelPolicyPicker(props: ModelPolicyPickerProps) {
341
+ const contentId = useId();
603
342
  const trigger = usePortalTokenSource<HTMLButtonElement>();
604
343
  const portalStyle = usePortalTokenStyle(trigger.source);
605
344
  const messages = useMemo(
606
345
  () => ({ ...defaultModelPolicyPickerMessages, ...props.messages }),
607
346
  [props.messages],
608
347
  );
609
- const { open, setOpen, rows, nav, setNav } = useModelPolicyPickerState(props);
348
+ const { open, setOpen, rows } = useModelPolicyPickerState(props);
610
349
  const selected = findPickerRow(rows, props.model);
611
350
 
612
351
  if (props.loading) {
@@ -622,60 +361,59 @@ export function ModelPolicyPicker(props: ModelPolicyPickerProps) {
622
361
  );
623
362
  }
624
363
  return (
625
- <DropdownMenu.Root open={open} onOpenChange={setOpen}>
626
- <DropdownMenu.Trigger asChild>
627
- <button
628
- ref={trigger.ref}
629
- type="button"
630
- disabled={props.disabled}
631
- aria-label={messages.label}
632
- className={cn(
633
- "og-root og-model-policy-trigger inline-flex h-[var(--og-model-picker-trigger-height)] min-w-0 max-w-64 items-center gap-1 rounded-full border border-transparent px-2.5 text-og-control text-og-fg-muted outline-hidden transition-colors hover:border-og-border hover:bg-og-surface-2 hover:text-og-fg focus-visible:ring-2 focus-visible:ring-og-accent/40 disabled:cursor-not-allowed disabled:opacity-50 max-sm:h-11 max-sm:max-w-[7.5rem] max-sm:px-2",
634
- props.className,
635
- )}
364
+ <>
365
+ <button
366
+ ref={trigger.ref}
367
+ type="button"
368
+ aria-haspopup="dialog"
369
+ aria-expanded={open}
370
+ aria-controls={open ? contentId : undefined}
371
+ data-state={open ? "open" : "closed"}
372
+ onClick={() => setOpen(!open)}
373
+ disabled={props.disabled}
374
+ aria-label={messages.label}
375
+ className={cn(
376
+ "og-root og-model-policy-trigger inline-flex h-[var(--og-model-picker-trigger-height)] min-w-0 max-w-64 items-center gap-1 rounded-full border border-transparent px-2.5 text-og-control text-og-fg-muted outline-hidden transition-colors hover:border-og-border hover:bg-og-surface-2 hover:text-og-fg focus-visible:ring-2 focus-visible:ring-og-accent/40 disabled:cursor-not-allowed disabled:opacity-50 max-sm:h-11 max-sm:max-w-[7.5rem] max-sm:px-2",
377
+ props.className,
378
+ )}
379
+ >
380
+ <BillingClassMark
381
+ billingClass={selected?.billingClass ?? billingClassForMissingSelection(props.model)}
382
+ className="text-og-fg"
383
+ />
384
+ <span className="og-model-policy-label-full min-w-0 truncate font-medium text-og-fg max-sm:hidden @max-[20rem]/model-controls:hidden">
385
+ {selected?.label ?? props.model}
386
+ </span>
387
+ <span className="og-model-policy-label-short min-w-0 truncate font-medium text-og-fg sm:hidden @max-[20rem]/model-controls:block">
388
+ {selected?.shortLabel ?? selected?.label ?? props.model}
389
+ </span>
390
+ <span
391
+ className="og-model-policy-effort min-w-0 shrink-[9999] truncate"
392
+ title={labelReasoningEffort(props.effort)}
636
393
  >
637
- <BillingClassMark
638
- billingClass={selected?.billingClass ?? billingClassForMissingSelection(props.model)}
639
- className="text-og-fg"
394
+ {labelReasoningEffort(props.effort)}
395
+ </span>
396
+ {props.latencyMode === "fast" ? (
397
+ <ZapIcon
398
+ className="size-3.5 shrink-0 fill-current stroke-current text-og-fg"
399
+ aria-label={messages.fast}
400
+ data-testid="model-picker-fast-icon"
640
401
  />
641
- <span className="og-model-policy-label-full min-w-0 truncate font-medium text-og-fg max-sm:hidden">
642
- {selected?.label ?? props.model}
643
- </span>
644
- <span className="og-model-policy-label-short min-w-0 truncate font-medium text-og-fg sm:hidden">
645
- {selected?.shortLabel ?? selected?.label ?? props.model}
646
- </span>
647
- <span className="og-model-policy-effort max-sm:hidden">
648
- {labelReasoningEffort(props.effort)}
649
- </span>
650
- {props.latencyMode === "fast" ? (
651
- <ZapIcon
652
- className="size-3.5 shrink-0 fill-current stroke-current text-og-fg"
653
- aria-label={messages.fast}
654
- data-testid="model-picker-fast-icon"
655
- />
656
- ) : null}
657
- <ChevronDownIcon className="size-3 shrink-0" />
658
- </button>
659
- </DropdownMenu.Trigger>
660
- <DropdownMenu.Portal>
661
- <DropdownMenu.Content
662
- align="start"
663
- side={props.menuSide ?? "bottom"}
664
- sideOffset={8}
665
- collisionPadding={12}
666
- onCloseAutoFocus={(event) => event.preventDefault()}
667
- className={cn(
668
- "og-root og-model-policy-menu z-50 flex max-h-[min(20rem,var(--radix-dropdown-menu-content-available-height))] w-[var(--og-model-picker-menu-width)] max-w-[calc(100vw-16px)] flex-col overflow-hidden rounded-og-lg border border-og-border bg-og-surface-1 p-[var(--og-model-picker-menu-padding)] text-og-fg shadow-og-lg",
669
- props.contentClassName,
670
- )}
671
- style={{ ...portalStyle, ...props.contentStyle }}
672
- data-testid="model-picker-content"
673
- >
674
- <div className="min-h-0 flex-1 overflow-y-auto overscroll-contain">
675
- <ModelPolicyPickerMenu {...props} nav={nav} onNavChange={setNav} />
676
- </div>
677
- </DropdownMenu.Content>
678
- </DropdownMenu.Portal>
679
- </DropdownMenu.Root>
402
+ ) : null}
403
+ <ChevronDownIcon className="size-3 shrink-0" />
404
+ </button>
405
+
406
+ {open ? (
407
+ <Suspense fallback={null}>
408
+ <LazyModelPolicyPickerMenu
409
+ {...props}
410
+ anchor={trigger.currentRef}
411
+ contentId={contentId}
412
+ portalStyle={portalStyle}
413
+ onOpenChange={setOpen}
414
+ />
415
+ </Suspense>
416
+ ) : null}
417
+ </>
680
418
  );
681
419
  }
@@ -59,7 +59,10 @@ function Conversation({
59
59
  const error = detail.error ?? feed.error ?? human.error;
60
60
  return (
61
61
  <div
62
- className={cn("og-root flex min-h-0 min-w-0 flex-col gap-2 overflow-hidden", className)}
62
+ className={cn(
63
+ "og-root flex min-h-0 min-w-0 flex-col gap-2 overflow-hidden bg-og-bg text-og-fg",
64
+ className,
65
+ )}
63
66
  ref={region}
64
67
  style={{ height }}
65
68
  data-og-conversation=""
package/src/composer.ts CHANGED
@@ -7,7 +7,6 @@ export { OPEN_WORKSTREAM_CONTROL_EVENT } from "./workstream-control-event";
7
7
  export {
8
8
  BillingClassMark,
9
9
  ModelPolicyPicker,
10
- ModelPolicyPickerMenu,
11
10
  PickerAnimatedPage,
12
11
  PickerBackHeader,
13
12
  PickerNavRow,
@@ -109,3 +108,5 @@ export type {
109
108
  VoiceRecordingTranscriptionState,
110
109
  VoiceRecordingUploadState,
111
110
  } from "./voice-recording-store";
111
+
112
+ export { ModelPolicyPickerMenu } from "./components/model-policy-picker-menu";
package/src/index.ts CHANGED
@@ -477,12 +477,12 @@ export type { ModelPickerProps } from "./components/model-picker";
477
477
  export {
478
478
  BillingClassMark,
479
479
  ModelPolicyPicker,
480
- ModelPolicyPickerMenu,
481
480
  PickerAnimatedPage,
482
481
  PickerBackHeader,
483
482
  PickerNavRow,
484
483
  defaultModelPolicyPickerMessages,
485
484
  } from "./components/model-policy-picker";
485
+ export { ModelPolicyPickerMenu } from "./components/model-policy-picker-menu";
486
486
  export type {
487
487
  ModelPolicyPickerMessages,
488
488
  ModelPolicyPickerProps,
@@ -1346,9 +1346,6 @@
1346
1346
  :where(.og-root).h-\[min\(28rem\,50dvh\)\],:where(.og-root) .h-\[min\(28rem\,50dvh\)\] {
1347
1347
  height: min(28rem, 50dvh);
1348
1348
  }
1349
- :where(.og-root).h-\[var\(--og-model-picker-effort-height\)\],:where(.og-root) .h-\[var\(--og-model-picker-effort-height\)\] {
1350
- height: var(--og-model-picker-effort-height);
1351
- }
1352
1349
  :where(.og-root).h-\[var\(--og-model-picker-trigger-height\)\],:where(.og-root) .h-\[var\(--og-model-picker-trigger-height\)\] {
1353
1350
  height: var(--og-model-picker-trigger-height);
1354
1351
  }
@@ -1412,6 +1409,9 @@
1412
1409
  :where(.og-root).max-h-\[min\(32rem\,70vh\)\],:where(.og-root) .max-h-\[min\(32rem\,70vh\)\] {
1413
1410
  max-height: min(32rem, 70vh);
1414
1411
  }
1412
+ :where(.og-root).max-h-\[min\(32rem\,var\(--radix-popover-content-available-height\)\)\],:where(.og-root) .max-h-\[min\(32rem\,var\(--radix-popover-content-available-height\)\)\] {
1413
+ max-height: min(32rem, var(--radix-popover-content-available-height));
1414
+ }
1415
1415
  :where(.og-root).max-h-full,:where(.og-root) .max-h-full {
1416
1416
  max-height: 100%;
1417
1417
  }
@@ -1502,6 +1502,9 @@
1502
1502
  :where(.og-root).w-\[3\.75rem\],:where(.og-root) .w-\[3\.75rem\] {
1503
1503
  width: 3.75rem;
1504
1504
  }
1505
+ :where(.og-root).w-\[22rem\],:where(.og-root) .w-\[22rem\] {
1506
+ width: 22rem;
1507
+ }
1505
1508
  :where(.og-root).w-\[52px\],:where(.og-root) .w-\[52px\] {
1506
1509
  width: 52px;
1507
1510
  }
@@ -1517,9 +1520,6 @@
1517
1520
  :where(.og-root).w-\[min\(36rem\,calc\(100vw-2rem\)\)\],:where(.og-root) .w-\[min\(36rem\,calc\(100vw-2rem\)\)\] {
1518
1521
  width: min(36rem, calc(100vw - 2rem));
1519
1522
  }
1520
- :where(.og-root).w-\[var\(--og-model-picker-menu-width\)\],:where(.og-root) .w-\[var\(--og-model-picker-menu-width\)\] {
1521
- width: var(--og-model-picker-menu-width);
1522
- }
1523
1523
  :where(.og-root).w-auto,:where(.og-root) .w-auto {
1524
1524
  width: auto;
1525
1525
  }
@@ -1640,6 +1640,9 @@
1640
1640
  :where(.og-root).shrink-0,:where(.og-root) .shrink-0 {
1641
1641
  flex-shrink: 0;
1642
1642
  }
1643
+ :where(.og-root).shrink-\[9999\],:where(.og-root) .shrink-\[9999\] {
1644
+ flex-shrink: 9999;
1645
+ }
1643
1646
  :where(.og-root).grow,:where(.og-root) .grow {
1644
1647
  flex-grow: 1;
1645
1648
  }
@@ -2157,6 +2160,12 @@
2157
2160
  border-color: color-mix(in oklab, var(--og-color-border) 50%, transparent);
2158
2161
  }
2159
2162
  }
2163
+ :where(.og-root).border-og-border\/60,:where(.og-root) .border-og-border\/60 {
2164
+ border-color: var(--og-color-border);
2165
+ @supports (color: color-mix(in lab, red, red)) {
2166
+ border-color: color-mix(in oklab, var(--og-color-border) 60%, transparent);
2167
+ }
2168
+ }
2160
2169
  :where(.og-root).border-og-border\/70,:where(.og-root) .border-og-border\/70 {
2161
2170
  border-color: var(--og-color-border);
2162
2171
  @supports (color: color-mix(in lab, red, red)) {
@@ -2307,12 +2316,6 @@
2307
2316
  :where(.og-root).bg-black,:where(.og-root) .bg-black {
2308
2317
  background-color: var(--color-black);
2309
2318
  }
2310
- :where(.og-root).bg-black\/5,:where(.og-root) .bg-black\/5 {
2311
- background-color: color-mix(in srgb, #000 5%, transparent);
2312
- @supports (color: color-mix(in lab, red, red)) {
2313
- background-color: color-mix(in oklab, var(--color-black) 5%, transparent);
2314
- }
2315
- }
2316
2319
  :where(.og-root).bg-black\/45,:where(.og-root) .bg-black\/45 {
2317
2320
  background-color: color-mix(in srgb, #000 45%, transparent);
2318
2321
  @supports (color: color-mix(in lab, red, red)) {
@@ -2430,6 +2433,12 @@
2430
2433
  :where(.og-root).bg-og-fg-subtle,:where(.og-root) .bg-og-fg-subtle {
2431
2434
  background-color: var(--og-color-fg-subtle);
2432
2435
  }
2436
+ :where(.og-root).bg-og-fg\/5,:where(.og-root) .bg-og-fg\/5 {
2437
+ background-color: var(--og-color-fg);
2438
+ @supports (color: color-mix(in lab, red, red)) {
2439
+ background-color: color-mix(in oklab, var(--og-color-fg) 5%, transparent);
2440
+ }
2441
+ }
2433
2442
  :where(.og-root).bg-og-status-cancelled,:where(.og-root) .bg-og-status-cancelled {
2434
2443
  background-color: var(--og-color-status-cancelled);
2435
2444
  }
@@ -5096,12 +5105,14 @@
5096
5105
  grid-template-columns: repeat(3, minmax(0, 1fr));
5097
5106
  }
5098
5107
  }
5099
- :where(.og-root).dark\:bg-white\/5,:where(.og-root) .dark\:bg-white\/5 {
5100
- @media (prefers-color-scheme: dark) {
5101
- background-color: color-mix(in srgb, #fff 5%, transparent);
5102
- @supports (color: color-mix(in lab, red, red)) {
5103
- background-color: color-mix(in oklab, var(--color-white) 5%, transparent);
5104
- }
5108
+ :where(.og-root).\@max-\[20rem\]\/model-controls\:block,:where(.og-root) .\@max-\[20rem\]\/model-controls\:block {
5109
+ @container model-controls (width < 20rem) {
5110
+ display: block;
5111
+ }
5112
+ }
5113
+ :where(.og-root).\@max-\[20rem\]\/model-controls\:hidden,:where(.og-root) .\@max-\[20rem\]\/model-controls\:hidden {
5114
+ @container model-controls (width < 20rem) {
5115
+ display: none;
5105
5116
  }
5106
5117
  }
5107
5118
  :where(.og-root).dark\:data-\[variant\=destructive\]\:focus\:bg-destructive\/20,:where(.og-root) .dark\:data-\[variant\=destructive\]\:focus\:bg-destructive\/20 {
@@ -5475,7 +5486,7 @@
5475
5486
  }
5476
5487
  :where(.og-root).og-model-policy-menu,:where(.og-root) .og-model-policy-menu {
5477
5488
  box-sizing: border-box;
5478
- width: min( var(--og-model-picker-menu-width), calc(var(--og-portal-source-inline-size, 100vw) - 1rem), var(--radix-dropdown-menu-content-available-width, 100vw) );
5489
+ width: min( var(--og-model-picker-menu-width), calc(var(--og-portal-source-inline-size, 100vw) - 1rem), var(--radix-popover-content-available-width, 100vw) );
5479
5490
  max-width: calc(100vw - 1rem);
5480
5491
  }
5481
5492
  :where(.og-root).og-realtime-menu,:where(.og-root) .og-realtime-menu {