@passui/react 0.1.45 → 0.1.47

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.
Files changed (141) hide show
  1. package/README.md +57 -46
  2. package/dist/types/src/components/accordion/accordion.d.ts +1 -1
  3. package/dist/types/src/components/breadcrumb/breadcrumb.d.ts +1 -1
  4. package/dist/types/src/components/inline-disclosure/inline-disclosure.d.ts +1 -1
  5. package/dist/types/src/components/popover/anchored-surface.d.ts +5 -1
  6. package/dist/types/src/components/popover/index.d.ts +41 -0
  7. package/dist/types/src/components/popover/popover-content.d.ts +38 -0
  8. package/dist/types/src/components/popover/popover-root.d.ts +22 -0
  9. package/dist/types/src/components/popover/popover-trigger.d.ts +23 -0
  10. package/dist/types/src/components/stepper/rolling-digit.d.ts +1 -1
  11. package/dist/types/src/components/table/table.d.ts +1 -1
  12. package/dist/types/src/components/view-controller/view-controller.d.ts +2 -2
  13. package/dist/types/src/index.d.ts +1 -1
  14. package/dist/types/src/machines/popover.machine.d.ts +30 -0
  15. package/package.json +307 -307
  16. package/src/appearance/index.ts +2 -2
  17. package/src/appearance/platform.tsx +76 -60
  18. package/src/appearance/theme.tsx +409 -377
  19. package/src/components/accordion/accordion.tsx +58 -49
  20. package/src/components/ambient/ambient.tsx +25 -25
  21. package/src/components/ambient/index.ts +1 -1
  22. package/src/components/aspect-ratio/aspect-ratio.tsx +21 -16
  23. package/src/components/breadcrumb/breadcrumb.tsx +63 -57
  24. package/src/components/button/button-styles.ts +39 -32
  25. package/src/components/button/button.tsx +91 -84
  26. package/src/components/button/icon-button.tsx +27 -25
  27. package/src/components/button/pending-spinner.tsx +8 -8
  28. package/src/components/button/use-pending-indicator.ts +11 -11
  29. package/src/components/chip/chip.tsx +35 -30
  30. package/src/components/code-block/code-block.tsx +40 -39
  31. package/src/components/combo-box/combo-box.tsx +5 -5
  32. package/src/components/command/command.tsx +124 -94
  33. package/src/components/compact-date-picker/calendar-month.ts +75 -53
  34. package/src/components/compact-date-picker/compact-date-picker.tsx +308 -289
  35. package/src/components/compact-time-picker/compact-time-picker.tsx +288 -281
  36. package/src/components/compact-time-picker/time-value.ts +32 -29
  37. package/src/components/content-unavailable-view/content-unavailable-view.tsx +64 -48
  38. package/src/components/content-view/content-view.tsx +168 -159
  39. package/src/components/content-view/index.ts +1 -1
  40. package/src/components/context-menu/conceal-menu-source.ts +25 -25
  41. package/src/components/context-menu/context-menu-host.tsx +439 -402
  42. package/src/components/context-menu/context-menu-store.ts +125 -123
  43. package/src/components/context-menu/menu-navigation.ts +25 -18
  44. package/src/components/context-menu/menu-position.ts +33 -29
  45. package/src/components/context-menu/menu-reveal.ts +32 -32
  46. package/src/components/context-menu/use-context-menu.ts +63 -56
  47. package/src/components/conversation/conversation.tsx +265 -263
  48. package/src/components/conversation/index.ts +1 -1
  49. package/src/components/date-picker/date-picker.tsx +95 -94
  50. package/src/components/date-picker/date-value.ts +20 -10
  51. package/src/components/dialog/dialog-host.tsx +105 -103
  52. package/src/components/dialog/dialog-store.ts +37 -36
  53. package/src/components/dialog/dialog.tsx +192 -179
  54. package/src/components/dialog/index.ts +1 -1
  55. package/src/components/disclosure-group/disclosure-group.tsx +93 -86
  56. package/src/components/divider/divider.tsx +24 -22
  57. package/src/components/inline-disclosure/inline-disclosure.tsx +40 -36
  58. package/src/components/keyboard-shortcut/keyboard-shortcut.tsx +23 -19
  59. package/src/components/labeled-content/labeled-content.tsx +68 -68
  60. package/src/components/locale-switcher/index.ts +1 -1
  61. package/src/components/locale-switcher/locale-switcher.tsx +278 -251
  62. package/src/components/menu/menu.tsx +75 -58
  63. package/src/components/morph/index.ts +2 -2
  64. package/src/components/morph/morph.tsx +227 -201
  65. package/src/components/morph/use-morph-disclosure.ts +19 -19
  66. package/src/components/one-time-code/one-time-code.tsx +216 -200
  67. package/src/components/picker/picker-trigger.ts +16 -13
  68. package/src/components/picker/picker.tsx +371 -345
  69. package/src/components/popover/anchored-surface.tsx +253 -229
  70. package/src/components/popover/index.ts +50 -0
  71. package/src/components/popover/popover-content.tsx +374 -0
  72. package/src/components/popover/popover-root.tsx +97 -0
  73. package/src/components/popover/popover-trigger.tsx +71 -0
  74. package/src/components/profile-image/profile-image.tsx +80 -64
  75. package/src/components/progress-view/progress-view.tsx +61 -59
  76. package/src/components/progress-view/use-liquid-progress.ts +38 -38
  77. package/src/components/radio-group/radio-group.tsx +71 -68
  78. package/src/components/search-field/expanding-search-field.tsx +191 -177
  79. package/src/components/search-field/search-field.tsx +59 -50
  80. package/src/components/search-list/search-list.tsx +246 -236
  81. package/src/components/section/section.tsx +58 -58
  82. package/src/components/secure-field/secure-field.tsx +3 -3
  83. package/src/components/segmented-control/segmented-control.tsx +136 -136
  84. package/src/components/sheet/modal-environment.ts +71 -64
  85. package/src/components/sheet/sheet-portal.tsx +58 -53
  86. package/src/components/sheet/sheet.tsx +146 -141
  87. package/src/components/sheet/use-sheet-focus.ts +97 -82
  88. package/src/components/sidebar/sidebar.tsx +78 -78
  89. package/src/components/skeleton/skeleton.tsx +30 -21
  90. package/src/components/slider/slider.tsx +113 -104
  91. package/src/components/slosh-slider/liquid-step.ts +32 -31
  92. package/src/components/slosh-slider/slosh-slider.tsx +265 -228
  93. package/src/components/stat-tile/index.ts +1 -1
  94. package/src/components/stat-tile/stat-tile.tsx +79 -68
  95. package/src/components/status-indicator/status-indicator.tsx +40 -37
  96. package/src/components/stepper/rolling-digit.tsx +82 -68
  97. package/src/components/stepper/stepper.tsx +122 -113
  98. package/src/components/swatch-picker/swatch-picker.tsx +120 -120
  99. package/src/components/tab-bar/tab-bar.tsx +149 -148
  100. package/src/components/tab-view/tab-view.tsx +140 -137
  101. package/src/components/table/table.tsx +117 -98
  102. package/src/components/text-editor/text-editor.tsx +34 -29
  103. package/src/components/text-field/text-field.tsx +182 -180
  104. package/src/components/toast/toast-store.ts +127 -115
  105. package/src/components/toast/toaster.tsx +361 -347
  106. package/src/components/toggle/toggle.tsx +297 -282
  107. package/src/components/tooltip/tooltip-host.tsx +157 -150
  108. package/src/components/view-controller/index.ts +1 -1
  109. package/src/components/view-controller/view-controller.tsx +64 -53
  110. package/src/components/wake-slider/wake-slider.tsx +220 -205
  111. package/src/hooks/scroll/minimize-decision.ts +11 -7
  112. package/src/hooks/use-anchored-disclosure.ts +19 -19
  113. package/src/hooks/use-anchored-placement.ts +29 -25
  114. package/src/hooks/use-dismiss.ts +33 -29
  115. package/src/hooks/use-floating-dismiss.ts +24 -22
  116. package/src/hooks/use-media-query.ts +67 -60
  117. package/src/hooks/use-minimize-on-scroll.ts +69 -60
  118. package/src/hooks/use-visual-viewport.ts +63 -63
  119. package/src/hooks/viewport/types.ts +16 -16
  120. package/src/hooks/viewport/viewport-metrics.ts +16 -10
  121. package/src/icons/icons.tsx +440 -328
  122. package/src/index.ts +91 -91
  123. package/src/lib/anchored-placement.ts +70 -65
  124. package/src/lib/class-names.ts +14 -13
  125. package/src/lib/clipboard.ts +8 -7
  126. package/src/lib/date.ts +61 -60
  127. package/src/lib/floating-layers.ts +39 -24
  128. package/src/lib/haptics.ts +10 -10
  129. package/src/lib/language.ts +9 -9
  130. package/src/lib/range-value.ts +27 -21
  131. package/src/lib/screen-edges.ts +33 -30
  132. package/src/lib/shapes.ts +38 -34
  133. package/src/machines/popover.machine.ts +51 -0
  134. package/src/motion/transitions.ts +46 -43
  135. package/src/styles/code-block.css +69 -43
  136. package/src/styles/motion-controls.css +393 -191
  137. package/src/tokens.ts +1 -1
  138. package/dist/types/src/components/popover/popover-fit.d.ts +0 -21
  139. package/dist/types/src/components/popover/popover.d.ts +0 -21
  140. package/src/components/popover/popover-fit.ts +0 -69
  141. package/src/components/popover/popover.tsx +0 -334
@@ -1,31 +1,33 @@
1
- import { forwardRef } from "react"
2
- import { cn } from "../../lib/class-names"
3
- import { Button, type ButtonProps } from "./button"
4
- import type { ButtonVariant, IconButtonSize } from "./button-styles"
1
+ import { forwardRef } from "react";
2
+ import { cn } from "../../lib/class-names";
3
+ import { Button, type ButtonProps } from "./button";
4
+ import type { ButtonVariant, IconButtonSize } from "./button-styles";
5
5
 
6
- export type { ButtonVariant, IconButtonSize }
6
+ export type { ButtonVariant, IconButtonSize };
7
7
 
8
8
  export interface IconButtonProps extends Omit<ButtonProps, "size"> {
9
- /** Icon-only actions must have an accessible name. */
10
- label: string
11
- size?: IconButtonSize
9
+ /** Icon-only actions must have an accessible name. */
10
+ label: string;
11
+ size?: IconButtonSize;
12
12
  }
13
13
 
14
14
  /** An accessible icon-only presentation of Button, sharing its interaction behavior. */
15
- export const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(function IconButton(
16
- { label, size = "icon", className, children, ...props },
17
- ref
18
- ) {
19
- return (
20
- <Button
21
- ref={ref}
22
- size={size}
23
- aria-label={label}
24
- data-tooltip={label}
25
- className={cn("active:scale-[0.92]", className)}
26
- {...props}
27
- >
28
- {children}
29
- </Button>
30
- )
31
- })
15
+ export const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(
16
+ function IconButton(
17
+ { label, size = "icon", className, children, ...props },
18
+ ref,
19
+ ) {
20
+ return (
21
+ <Button
22
+ ref={ref}
23
+ size={size}
24
+ aria-label={label}
25
+ data-tooltip={label}
26
+ className={cn("active:scale-[0.92]", className)}
27
+ {...props}
28
+ >
29
+ {children}
30
+ </Button>
31
+ );
32
+ },
33
+ );
@@ -3,12 +3,12 @@
3
3
  * sized from the text so it suits every button size.
4
4
  */
5
5
  export function PendingSpinner() {
6
- return (
7
- <span
8
- aria-hidden="true"
9
- className="absolute inset-0 flex animate-in items-center justify-center fade-in zoom-in-75 duration-200 motion-reduce:animate-none"
10
- >
11
- <span className="size-[1.1em] animate-spin rounded-full border-2 border-current/25 border-t-current motion-reduce:animate-none" />
12
- </span>
13
- )
6
+ return (
7
+ <span
8
+ aria-hidden="true"
9
+ className="animate-in fade-in zoom-in-75 absolute inset-0 flex items-center justify-center duration-200 motion-reduce:animate-none"
10
+ >
11
+ <span className="size-[1.1em] animate-spin rounded-full border-2 border-current/25 border-t-current motion-reduce:animate-none" />
12
+ </span>
13
+ );
14
14
  }
@@ -1,22 +1,22 @@
1
- import { useEffect, useState } from "react"
1
+ import { useEffect, useState } from "react";
2
2
 
3
- const PENDING_INDICATOR_DELAY = 300
3
+ const PENDING_INDICATOR_DELAY = 300;
4
4
 
5
5
  export function schedulePendingIndicator(onShow: () => void) {
6
- const timeout = setTimeout(onShow, PENDING_INDICATOR_DELAY)
7
- return () => clearTimeout(timeout)
6
+ const timeout = setTimeout(onShow, PENDING_INDICATOR_DELAY);
7
+ return () => clearTimeout(timeout);
8
8
  }
9
9
 
10
10
  export function usePendingIndicator(isPending: boolean) {
11
- const [isVisible, setIsVisible] = useState(false)
11
+ const [isVisible, setIsVisible] = useState(false);
12
12
 
13
- useEffect(() => {
14
- setIsVisible(false)
13
+ useEffect(() => {
14
+ setIsVisible(false);
15
15
 
16
- if (!isPending) return
16
+ if (!isPending) return;
17
17
 
18
- return schedulePendingIndicator(() => setIsVisible(true))
19
- }, [isPending])
18
+ return schedulePendingIndicator(() => setIsVisible(true));
19
+ }, [isPending]);
20
20
 
21
- return isPending && isVisible
21
+ return isPending && isVisible;
22
22
  }
@@ -1,40 +1,45 @@
1
- import type { HTMLAttributes } from "react"
2
- import { cn } from "../../lib/class-names"
1
+ import type { HTMLAttributes } from "react";
2
+ import { cn } from "../../lib/class-names";
3
3
 
4
- export type ChipTone = "neutral" | "accent" | "public" | "family" | "friends"
5
- export type ChipSize = "xs" | "sm" | "md"
4
+ export type ChipTone = "neutral" | "accent" | "public" | "family" | "friends";
5
+ export type ChipSize = "xs" | "sm" | "md";
6
6
 
7
7
  const tones: Record<ChipTone, string> = {
8
- neutral: "bg-fill text-label-secondary",
9
- accent: "bg-elevated text-accent-text",
10
- public: "bg-[#e8efff] text-[#2c55b8] dark:bg-[#1c2740] dark:text-[#a9c1ff]",
11
- family: "bg-[#e3f3eb] text-[#24704f] dark:bg-[#15302a] dark:text-[#8fd6b6]",
12
- friends: "bg-[#ede8ff] text-[#5a3fc0] dark:bg-[#26203f] dark:text-[#c3b5ff]",
13
- }
8
+ neutral: "bg-fill text-label-secondary",
9
+ accent: "bg-elevated text-accent-text",
10
+ public: "bg-[#e8efff] text-[#2c55b8] dark:bg-[#1c2740] dark:text-[#a9c1ff]",
11
+ family: "bg-[#e3f3eb] text-[#24704f] dark:bg-[#15302a] dark:text-[#8fd6b6]",
12
+ friends: "bg-[#ede8ff] text-[#5a3fc0] dark:bg-[#26203f] dark:text-[#c3b5ff]",
13
+ };
14
14
 
15
15
  const sizes: Record<ChipSize, string> = {
16
- xs: "px-1 py-0 text-caption2",
17
- sm: "px-1.5 py-0.5 text-caption2",
18
- md: "px-2 py-0.5 text-caption",
19
- }
16
+ xs: "px-1 py-0 text-caption2",
17
+ sm: "px-1.5 py-0.5 text-caption2",
18
+ md: "px-2 py-0.5 text-caption",
19
+ };
20
20
 
21
21
  export interface ChipProps extends HTMLAttributes<HTMLSpanElement> {
22
- /** `neutral`, `accent`, `public`, `family`, or `friends`. @default "neutral" */
23
- tone?: ChipTone
24
- /** `xs`, `sm`, or `md`. @default "sm" */
25
- size?: ChipSize
22
+ /** `neutral`, `accent`, `public`, `family`, or `friends`. @default "neutral" */
23
+ tone?: ChipTone;
24
+ /** `xs`, `sm`, or `md`. @default "sm" */
25
+ size?: ChipSize;
26
26
  }
27
27
 
28
- export function Chip({ tone = "neutral", size = "sm", className, ...props }: ChipProps) {
29
- return (
30
- <span
31
- className={cn(
32
- "inline-flex items-center gap-1 rounded-full font-semibold",
33
- tones[tone],
34
- sizes[size],
35
- className
36
- )}
37
- {...props}
38
- />
39
- )
28
+ export function Chip({
29
+ tone = "neutral",
30
+ size = "sm",
31
+ className,
32
+ ...props
33
+ }: ChipProps) {
34
+ return (
35
+ <span
36
+ className={cn(
37
+ "inline-flex items-center gap-1 rounded-full font-semibold",
38
+ tones[tone],
39
+ sizes[size],
40
+ className,
41
+ )}
42
+ {...props}
43
+ />
44
+ );
40
45
  }
@@ -1,47 +1,48 @@
1
- import { Fragment, type ComponentProps, type ReactNode } from "react"
2
- import { cn } from "../../lib/class-names"
1
+ import { Fragment, type ComponentProps, type ReactNode } from "react";
2
+ import { cn } from "../../lib/class-names";
3
3
 
4
- export type CodeBlockSize = "sm" | "md" | "lg"
4
+ export type CodeBlockSize = "sm" | "md" | "lg";
5
5
 
6
- export interface CodeBlockProps extends Omit<ComponentProps<"div">, "children" | "size"> {
7
- code: string
8
- /** Supply a highlighter's rendered pre/code element; source remains the fallback. */
9
- children?: ReactNode
10
- /** Show a nonselectable line gutter. @default true */
11
- lineNumbers?: boolean
12
- /** Code font size, padding and line gutter scale. @default "md" */
13
- size?: CodeBlockSize
6
+ export interface CodeBlockProps
7
+ extends Omit<ComponentProps<"div">, "children" | "size"> {
8
+ code: string;
9
+ /** Supply a highlighter's rendered pre/code element; source remains the fallback. */
10
+ children?: ReactNode;
11
+ /** Show a nonselectable line gutter. @default true */
12
+ lineNumbers?: boolean;
13
+ /** Code font size, padding and line gutter scale. @default "md" */
14
+ size?: CodeBlockSize;
14
15
  }
15
16
 
16
17
  /** Code presentation without shipping a highlighter or formatter to consumers. */
17
18
  export function CodeBlock({
18
- code,
19
- children,
20
- lineNumbers = true,
21
- size = "md",
22
- className,
23
- ...props
19
+ code,
20
+ children,
21
+ lineNumbers = true,
22
+ size = "md",
23
+ className,
24
+ ...props
24
25
  }: CodeBlockProps) {
25
- const lines = code.split("\n")
26
- return (
27
- <div
28
- {...props}
29
- className={cn("passui-code-block", className)}
30
- data-line-numbers={lineNumbers || undefined}
31
- data-size={size}
32
- >
33
- {children ?? (
34
- <pre>
35
- <code>
36
- {lines.map((line, index) => (
37
- <Fragment key={`${index}-${line}`}>
38
- <span className="line">{line || " "}</span>
39
- {index < lines.length - 1 ? "\n" : null}
40
- </Fragment>
41
- ))}
42
- </code>
43
- </pre>
44
- )}
45
- </div>
46
- )
26
+ const lines = code.split("\n");
27
+ return (
28
+ <div
29
+ {...props}
30
+ className={cn("passui-code-block", className)}
31
+ data-line-numbers={lineNumbers || undefined}
32
+ data-size={size}
33
+ >
34
+ {children ?? (
35
+ <pre>
36
+ <code>
37
+ {lines.map((line, index) => (
38
+ <Fragment key={line || index}>
39
+ <span className="line">{line || " "}</span>
40
+ {index < lines.length - 1 ? "\n" : null}
41
+ </Fragment>
42
+ ))}
43
+ </code>
44
+ </pre>
45
+ )}
46
+ </div>
47
+ );
47
48
  }
@@ -1,13 +1,13 @@
1
- import { Picker, type PickerOption, type PickerProps } from "../picker/picker"
1
+ import { Picker, type PickerOption, type PickerProps } from "../picker/picker";
2
2
 
3
3
  export interface ComboBoxOption<T extends string> extends PickerOption<T> {}
4
4
  export interface ComboBoxProps<T extends string>
5
- extends Omit<PickerProps<T>, "searchable" | "options"> {
6
- options: readonly ComboBoxOption<T>[]
7
- emptyLabel: string
5
+ extends Omit<PickerProps<T>, "searchable" | "options"> {
6
+ options: readonly ComboBoxOption<T>[];
7
+ emptyLabel: string;
8
8
  }
9
9
 
10
10
  /** A searchable Picker, with optional creation from the person's typed query. */
11
11
  export function ComboBox<T extends string>(props: ComboBoxProps<T>) {
12
- return <Picker {...props} searchable />
12
+ return <Picker {...props} searchable />;
13
13
  }
@@ -1,119 +1,149 @@
1
- import { type ComponentProps, useEffect, useRef } from "react"
2
- import { SearchIcon } from "../../icons/icons"
3
- import { cn } from "../../lib/class-names"
4
- import { KeyboardShortcut } from "../keyboard-shortcut/keyboard-shortcut"
1
+ import { type ComponentProps, useEffect, useRef } from "react";
2
+ import { SearchIcon } from "../../icons/icons";
3
+ import { cn } from "../../lib/class-names";
4
+ import { KeyboardShortcut } from "../keyboard-shortcut/keyboard-shortcut";
5
5
  import {
6
- SearchList,
7
- SearchListField,
8
- SearchListResults,
9
- SearchListEmpty,
10
- SearchListGroup,
11
- SearchListItem,
12
- } from "../search-list/search-list"
13
- import { Sheet, type SheetProps } from "../sheet/sheet"
6
+ SearchList,
7
+ SearchListField,
8
+ SearchListResults,
9
+ SearchListEmpty,
10
+ SearchListGroup,
11
+ SearchListItem,
12
+ } from "../search-list/search-list";
13
+ import { Sheet, type SheetProps } from "../sheet/sheet";
14
14
 
15
15
  export interface CommandProps extends ComponentProps<typeof SearchList> {}
16
16
  export interface CommandDialogProps extends Omit<SheetProps, "placement"> {}
17
17
 
18
18
  /** An inline command palette. SearchList owns filtering and keyboard selection. */
19
19
  export function Command({ className, ...props }: CommandProps) {
20
- return (
21
- <SearchList
22
- {...props}
23
- className={cn(
24
- "not-typeset glass-menu flex min-h-0 w-full flex-col overflow-hidden rounded-3xl",
25
- className
26
- )}
27
- />
28
- )
20
+ return (
21
+ <SearchList
22
+ {...props}
23
+ className={cn(
24
+ "not-typeset glass-menu flex min-h-0 w-full flex-col overflow-hidden rounded-3xl",
25
+ className,
26
+ )}
27
+ />
28
+ );
29
29
  }
30
30
 
31
31
  /** A modal command palette with Sheet's focus isolation and restoration. */
32
- export function CommandDialog({ children, className, ...props }: CommandDialogProps) {
33
- return (
34
- <Sheet
35
- {...props}
36
- placement="center"
37
- className={cn("max-w-lg rounded-3xl outline-none", className)}
38
- >
39
- <SearchList className="not-typeset flex min-h-0 flex-col">{children}</SearchList>
40
- </Sheet>
41
- )
32
+ export function CommandDialog({
33
+ children,
34
+ className,
35
+ ...props
36
+ }: CommandDialogProps) {
37
+ return (
38
+ <Sheet
39
+ {...props}
40
+ placement="center"
41
+ className={cn("max-w-lg rounded-3xl outline-none", className)}
42
+ >
43
+ <SearchList className="not-typeset flex min-h-0 flex-col">
44
+ {children}
45
+ </SearchList>
46
+ </Sheet>
47
+ );
42
48
  }
43
49
 
44
50
  export function CommandInput({
45
- className,
46
- autoFocus,
47
- ref: forwardedRef,
48
- ...props
51
+ className,
52
+ autoFocus,
53
+ ref: forwardedRef,
54
+ ...props
49
55
  }: ComponentProps<typeof SearchListField>) {
50
- const input = useRef<HTMLInputElement>(null)
51
- useEffect(() => {
52
- if (autoFocus) input.current?.focus({ preventScroll: true })
53
- }, [autoFocus])
54
- return (
55
- <div className="flex shrink-0 items-center gap-2 border-b border-separator/50 px-4">
56
- <SearchIcon size={17} className="shrink-0 text-label-tertiary" />
57
- <SearchListField
58
- {...props}
59
- ref={(node) => {
60
- input.current = node
61
- if (typeof forwardedRef === "function") forwardedRef(node)
62
- else if (forwardedRef) forwardedRef.current = node
63
- }}
64
- className={cn(
65
- "min-h-12 rounded-none border-0 bg-transparent px-0 focus-visible:ring-0",
66
- className
67
- )}
68
- />
69
- </div>
70
- )
56
+ const input = useRef<HTMLInputElement>(null);
57
+ useEffect(() => {
58
+ if (autoFocus) input.current?.focus({ preventScroll: true });
59
+ }, [autoFocus]);
60
+ return (
61
+ <div className="border-separator/50 flex shrink-0 items-center gap-2 border-b px-4">
62
+ <SearchIcon size={17} className="text-label-tertiary shrink-0" />
63
+ <SearchListField
64
+ {...props}
65
+ ref={(node) => {
66
+ input.current = node;
67
+ if (typeof forwardedRef === "function") forwardedRef(node);
68
+ else if (forwardedRef) forwardedRef.current = node;
69
+ }}
70
+ className={cn(
71
+ "min-h-12 rounded-none border-0 bg-transparent px-0 focus-visible:ring-0",
72
+ className,
73
+ )}
74
+ />
75
+ </div>
76
+ );
71
77
  }
72
78
 
73
- export function CommandList({ className, ...props }: ComponentProps<typeof SearchListResults>) {
74
- return (
75
- <SearchListResults {...props} className={cn("max-h-[min(60svh,24rem)] p-1.5", className)} />
76
- )
79
+ export function CommandList({
80
+ className,
81
+ ...props
82
+ }: ComponentProps<typeof SearchListResults>) {
83
+ return (
84
+ <SearchListResults
85
+ {...props}
86
+ className={cn("max-h-[min(60svh,24rem)] p-1.5", className)}
87
+ />
88
+ );
77
89
  }
78
90
 
79
- export function CommandEmpty({ className, ...props }: ComponentProps<typeof SearchListEmpty>) {
80
- return (
81
- <SearchListEmpty
82
- {...props}
83
- className={cn("px-3 py-8 text-center text-footnote text-label-secondary", className)}
84
- />
85
- )
91
+ export function CommandEmpty({
92
+ className,
93
+ ...props
94
+ }: ComponentProps<typeof SearchListEmpty>) {
95
+ return (
96
+ <SearchListEmpty
97
+ {...props}
98
+ className={cn(
99
+ "text-footnote text-label-secondary px-3 py-8 text-center",
100
+ className,
101
+ )}
102
+ />
103
+ );
86
104
  }
87
105
 
88
- export function CommandShortcut({ className, ...props }: ComponentProps<typeof KeyboardShortcut>) {
89
- return (
90
- <KeyboardShortcut
91
- {...props}
92
- className={cn("ms-auto border-0 bg-transparent text-label-tertiary", className)}
93
- />
94
- )
106
+ export function CommandShortcut({
107
+ className,
108
+ ...props
109
+ }: ComponentProps<typeof KeyboardShortcut>) {
110
+ return (
111
+ <KeyboardShortcut
112
+ {...props}
113
+ className={cn(
114
+ "text-label-tertiary ms-auto border-0 bg-transparent",
115
+ className,
116
+ )}
117
+ />
118
+ );
95
119
  }
96
120
 
97
- export function CommandGroup({ className, ...props }: ComponentProps<typeof SearchListGroup>) {
98
- return (
99
- <SearchListGroup
100
- {...props}
101
- className={cn(
102
- "border-separator/50 not-first:mt-1 not-first:border-t not-first:pt-1",
103
- className
104
- )}
105
- />
106
- )
121
+ export function CommandGroup({
122
+ className,
123
+ ...props
124
+ }: ComponentProps<typeof SearchListGroup>) {
125
+ return (
126
+ <SearchListGroup
127
+ {...props}
128
+ className={cn(
129
+ "border-separator/50 not-first:mt-1 not-first:border-t not-first:pt-1",
130
+ className,
131
+ )}
132
+ />
133
+ );
107
134
  }
108
135
 
109
- export function CommandItem({ className, ...props }: ComponentProps<typeof SearchListItem>) {
110
- return (
111
- <SearchListItem
112
- {...props}
113
- className={cn(
114
- "[&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-label-secondary",
115
- className
116
- )}
117
- />
118
- )
136
+ export function CommandItem({
137
+ className,
138
+ ...props
139
+ }: ComponentProps<typeof SearchListItem>) {
140
+ return (
141
+ <SearchListItem
142
+ {...props}
143
+ className={cn(
144
+ "[&>svg]:text-label-secondary [&>svg]:size-4 [&>svg]:shrink-0",
145
+ className,
146
+ )}
147
+ />
148
+ );
119
149
  }