@shipfox/react-ui 0.18.0 → 0.19.0

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.
@@ -5,34 +5,34 @@ import { cn } from '../../utils/cn.js';
5
5
  export function Calendar({ className, classNames, showOutsideDays = true, ...props }) {
6
6
  return /*#__PURE__*/ _jsx(DayPicker, {
7
7
  showOutsideDays: showOutsideDays,
8
- className: cn('p-16 transition-colors', className),
8
+ className: cn('transition-colors', className),
9
9
  classNames: {
10
- months: 'flex flex-col sm:flex-row gap-24',
11
- month: 'space-y-16 relative',
12
- month_caption: 'flex items-center justify-center mb-8 px-4 relative h-32',
10
+ months: 'flex flex-col sm:flex-row gap-0',
11
+ month: 'space-y-16 relative p-16 border-r border-border-neutral-base-component last:border-r-0',
12
+ month_caption: 'flex items-center justify-center mb-8 px-4 relative h-32 bg-background-field-base rounded-8 shadow-tooltip',
13
13
  caption_label: 'text-sm font-medium text-foreground-neutral-base',
14
14
  nav: 'flex items-center gap-4 fixed left-0 top-16 w-full z-10',
15
- button_previous: cn('size-32 bg-transparent p-0 absolute left-16 top-0', 'inline-flex items-center justify-center rounded-6', 'text-foreground-neutral-base', 'hover:bg-background-button-transparent-hover', 'active:bg-background-button-transparent-pressed', 'transition-colors outline-none', 'focus-visible:shadow-border-interactive-with-active', 'disabled:pointer-events-none disabled:opacity-50'),
16
- button_next: cn('size-32 bg-transparent p-0 absolute right-16 top-0', 'inline-flex items-center justify-center rounded-6', 'text-foreground-neutral-base', 'hover:bg-background-button-transparent-hover', 'active:bg-background-button-transparent-pressed', 'transition-colors outline-none', 'focus-visible:shadow-border-interactive-with-active', 'disabled:pointer-events-none disabled:opacity-50'),
15
+ button_previous: cn('size-32 bg-transparent p-0 absolute left-16 top-0 cursor-pointer', 'inline-flex items-center justify-center rounded-6', 'text-foreground-neutral-muted', 'hover:bg-transparent hover:text-foreground-neutral-subtle', 'active:bg-transparent', 'transition-colors outline-none', 'focus-visible:shadow-border-interactive-with-active', 'disabled:pointer-events-none disabled:opacity-50'),
16
+ button_next: cn('size-32 bg-transparent p-0 absolute right-16 top-0 cursor-pointer', 'inline-flex items-center justify-center rounded-6', 'text-foreground-neutral-muted', 'hover:bg-transparent hover:text-foreground-neutral-subtle', 'active:bg-transparent', 'transition-colors outline-none', 'focus-visible:shadow-border-interactive-with-active', 'disabled:pointer-events-none disabled:opacity-50'),
17
17
  month_grid: 'w-full border-collapse mt-8',
18
- weekdays: 'flex mb-8',
18
+ weekdays: 'flex gap-8',
19
19
  weekday: 'text-foreground-neutral-subtle text-xs font-medium w-36 h-32 flex items-center justify-center',
20
- week: 'flex mt-4',
20
+ week: 'flex mt-8 gap-8',
21
21
  day: cn('relative text-center size-36 p-0 text-sm font-normal [&:last-child[data-selected=true]_button]:rounded-r-md group/day aspect-square select-none', '[&:last-child[data-selected=true]_button]:rounded-r-6', props.showWeekNumber ? '[&:nth-child(2)[data-selected=true]_button]:rounded-l-6' : '[&:first-child[data-selected=true]_button]:rounded-l-6'),
22
22
  day_button: cn('size-36 p-0 text-sm font-normal rounded-6', 'inline-flex items-center justify-center', 'hover:bg-background-button-transparent-hover', 'focus-visible:shadow-border-interactive-with-active', 'transition-colors outline-none', 'aria-selected:opacity-100'),
23
23
  range_start: 'day-range-start rounded-6',
24
24
  range_end: 'day-range-end rounded-6',
25
- selected: cn('bg-foreground-highlight-interactive/80 !text-foreground-neutral-base font-medium rounded-6', 'hover:bg-foreground-highlight-interactive-hover/80', 'focus:bg-foreground-highlight-interactive/80'),
26
- today: cn('bg-background-field-base text-foreground-neutral-base font-medium rounded-6', 'border border-border-neutral-base'),
25
+ selected: cn('bg-foreground-highlight-interactive/80 !text-foreground-neutral-on-inverted font-medium rounded-6', 'hover:bg-foreground-highlight-interactive-hover/80', 'focus:bg-foreground-highlight-interactive/80'),
26
+ today: cn('relative font-medium rounded-6', 'after:absolute after:bottom-[6px] after:left-1/2 after:-translate-x-1/2', 'after:size-[3px] after:rounded-full after:bg-[var(--color-primary-400)]'),
27
27
  outside: 'day-outside text-foreground-neutral-muted',
28
28
  disabled: 'text-foreground-neutral-disabled opacity-30 cursor-not-allowed',
29
- range_middle: cn('aria-selected:bg-foreground-highlight-interactive/10 aria-selected:text-foreground-neutral-base', 'rounded-none', 'first:rounded-l-6 first:rounded-r-none', 'last:rounded-r-6 last:rounded-l-none'),
29
+ range_middle: cn('aria-selected:bg-background-highlight-base aria-selected:!text-foreground-highlight-interactive'),
30
30
  hidden: 'invisible',
31
31
  ...classNames
32
32
  },
33
33
  components: {
34
34
  Chevron: ({ orientation })=>{
35
- const iconName = orientation === 'left' ? 'arrowLeftSLine' : 'arrowRightSLine';
35
+ const iconName = orientation === 'left' ? 'arrowLeftSFill' : 'arrowRightSFill';
36
36
  return /*#__PURE__*/ _jsx(Icon, {
37
37
  name: iconName,
38
38
  className: "size-20"
@@ -29,10 +29,13 @@ export function KpiCard({ label, value, variant = 'neutral', isLoading, classNam
29
29
  }),
30
30
  isLoading ? /*#__PURE__*/ _jsx(Skeleton, {
31
31
  className: "w-48 h-20 rounded-4"
32
- }) : /*#__PURE__*/ _jsx(Text, {
32
+ }) : typeof value === 'string' || typeof value === 'number' ? /*#__PURE__*/ _jsx(Text, {
33
33
  size: "sm",
34
34
  className: "font-medium text-foreground-neutral-base",
35
35
  children: value
36
+ }) : /*#__PURE__*/ _jsx("div", {
37
+ className: "text-sm font-medium text-foreground-neutral-base",
38
+ children: value
36
39
  })
37
40
  ]
38
41
  })
@@ -14,6 +14,7 @@ export type DatePickerProps = Omit<ComponentProps<'input'>, 'size' | 'type'> & V
14
14
  rightIcon?: ReactNode;
15
15
  onClear?: () => void;
16
16
  closeOnSelect?: boolean;
17
+ maxDisabledOffsetDays?: number;
17
18
  };
18
19
  export declare const DatePicker: import("react").ForwardRefExoticComponent<Omit<DatePickerProps, "ref"> & import("react").RefAttributes<HTMLInputElement>>;
19
20
  //# sourceMappingURL=date-picker.d.ts.map
@@ -3,8 +3,8 @@ import { cva } from 'class-variance-authority';
3
3
  import { Calendar } from '../../components/calendar/index.js';
4
4
  import { Icon } from '../../components/icon/index.js';
5
5
  import { Popover, PopoverContent, PopoverTrigger } from '../../components/popover/index.js';
6
- import { format } from 'date-fns';
7
- import { forwardRef, useState } from 'react';
6
+ import { addDays, format, subDays } from 'date-fns';
7
+ import { forwardRef, useMemo, useState } from 'react';
8
8
  import { cn } from '../../utils/cn.js';
9
9
  export const datePickerVariants = cva('relative flex items-center rounded-6 shadow-button-neutral transition-[background-color,box-shadow] outline-none', {
10
10
  variants: {
@@ -28,10 +28,22 @@ export const datePickerVariants = cva('relative flex items-center rounded-6 shad
28
28
  state: 'default'
29
29
  }
30
30
  });
31
- export const DatePicker = /*#__PURE__*/ forwardRef(({ className, variant, size, state, date, onDateSelect, placeholder = 'DD/MM/YYYY', dateFormat = 'dd/MM/yyyy', leftIcon, rightIcon, onClear, disabled, closeOnSelect = false, ...props }, ref)=>{
31
+ export const DatePicker = /*#__PURE__*/ forwardRef(({ className, variant, size, state, date, onDateSelect, placeholder = 'DD/MM/YYYY', dateFormat = 'dd/MM/yyyy', leftIcon, rightIcon, onClear, disabled, closeOnSelect = false, maxDisabledOffsetDays, ...props }, ref)=>{
32
32
  const [open, setOpen] = useState(false);
33
33
  const isDisabled = disabled || state === 'disabled';
34
34
  const displayValue = date ? format(date, dateFormat) : '';
35
+ // Disable dates beyond maxDisabledDays before and after today
36
+ const disabledDates = useMemo(()=>{
37
+ if (!maxDisabledOffsetDays) return undefined;
38
+ const today = new Date();
39
+ const minDate = subDays(today, maxDisabledOffsetDays);
40
+ const maxDate = addDays(today, maxDisabledOffsetDays);
41
+ return (date)=>{
42
+ return date < minDate || date > maxDate;
43
+ };
44
+ }, [
45
+ maxDisabledOffsetDays
46
+ ]);
35
47
  const handleSelect = (selectedDate)=>{
36
48
  onDateSelect?.(selectedDate);
37
49
  if (closeOnSelect) {
@@ -103,7 +115,11 @@ export const DatePicker = /*#__PURE__*/ forwardRef(({ className, variant, size,
103
115
  children: /*#__PURE__*/ _jsx(Calendar, {
104
116
  mode: "single",
105
117
  selected: date,
106
- onSelect: handleSelect
118
+ onSelect: handleSelect,
119
+ disabled: disabledDates,
120
+ formatters: {
121
+ formatWeekdayName: (date)=>format(date, 'EEEEE')
122
+ }
107
123
  })
108
124
  })
109
125
  ]
@@ -51,6 +51,22 @@ export const DatePickerStory = {
51
51
  });
52
52
  }
53
53
  };
54
+ export const DatePickerWithThresholdStory = {
55
+ play: (ctx)=>openCalendarAndScreenshot(ctx, 'DatePicker With Threshold Calendar Open'),
56
+ render: ()=>{
57
+ const [date, setDate] = useState(new Date());
58
+ return /*#__PURE__*/ _jsx("div", {
59
+ className: "relative flex h-600 w-500 items-center justify-center rounded-16 bg-background-subtle-base shadow-tooltip overflow-visible",
60
+ children: /*#__PURE__*/ _jsx(DatePicker, {
61
+ date: date,
62
+ onDateSelect: setDate,
63
+ onClear: ()=>setDate(undefined),
64
+ placeholder: "DD/MM/YYYY",
65
+ maxDisabledOffsetDays: 30
66
+ })
67
+ });
68
+ }
69
+ };
54
70
  export const DateRangePickerStory = {
55
71
  play: (ctx)=>openCalendarAndScreenshot(ctx, 'DateRangePicker Calendar Open'),
56
72
  render: ()=>{
@@ -19,6 +19,7 @@ export type DateTimeRangePickerProps = Omit<ComponentProps<'input'>, 'size' | 't
19
19
  onClear?: () => void;
20
20
  numberOfMonths?: number;
21
21
  closeOnSelect?: boolean;
22
+ maxRangeDays?: number;
22
23
  };
23
24
  export declare const DateTimeRangePicker: import("react").ForwardRefExoticComponent<Omit<DateTimeRangePickerProps, "ref"> & import("react").RefAttributes<HTMLInputElement>>;
24
25
  //# sourceMappingURL=date-time-range-picker.d.ts.map
@@ -3,8 +3,8 @@ import { cva } from 'class-variance-authority';
3
3
  import { Calendar } from '../../components/calendar/index.js';
4
4
  import { Icon } from '../../components/icon/index.js';
5
5
  import { Popover, PopoverContent, PopoverTrigger } from '../../components/popover/index.js';
6
- import { format } from 'date-fns';
7
- import { forwardRef, useState } from 'react';
6
+ import { addDays, differenceInDays, format } from 'date-fns';
7
+ import { forwardRef, useMemo, useState } from 'react';
8
8
  import { cn } from '../../utils/cn.js';
9
9
  export const dateTimeRangePickerVariants = cva('min-w-240 relative flex items-center rounded-6 shadow-button-neutral transition-[background-color,box-shadow] outline-none', {
10
10
  variants: {
@@ -28,28 +28,52 @@ export const dateTimeRangePickerVariants = cva('min-w-240 relative flex items-ce
28
28
  state: 'default'
29
29
  }
30
30
  });
31
- export const DateTimeRangePicker = /*#__PURE__*/ forwardRef(({ className, variant, size, state, dateRange, onDateRangeSelect, placeholder = 'DD/MM/YYYY - DD/MM/YYYY', dateFormat = 'dd/MM/yyyy', leftIcon, rightIcon, onClear, disabled, numberOfMonths = 2, closeOnSelect = false, ...props }, ref)=>{
31
+ export const DateTimeRangePicker = /*#__PURE__*/ forwardRef(({ className, variant, size, state, dateRange, onDateRangeSelect, placeholder = 'DD/MM/YYYY - DD/MM/YYYY', dateFormat = 'dd/MM/yyyy', leftIcon, rightIcon, onClear, disabled, numberOfMonths = 2, closeOnSelect = false, maxRangeDays, ...props }, ref)=>{
32
32
  const [open, setOpen] = useState(false);
33
33
  const isDisabled = disabled || state === 'disabled';
34
- const hasRange = dateRange?.start && dateRange?.end;
35
- const displayValue = hasRange && dateRange.start && dateRange.end ? `${format(dateRange.start, dateFormat)} - ${format(dateRange.end, dateFormat)}` : '';
36
- // Convert our DateRange to react-day-picker's DateRange format
37
- const dayPickerRange = dateRange?.start || dateRange?.end ? {
38
- from: dateRange?.start,
39
- to: dateRange?.end
34
+ const startDate = dateRange?.start;
35
+ const endDate = dateRange?.end;
36
+ const hasRange = Boolean(startDate && endDate);
37
+ // Format display value
38
+ const displayValue = hasRange && startDate && endDate ? `${format(startDate, dateFormat)} - ${format(endDate, dateFormat)}` : '';
39
+ // Convert to react-day-picker format
40
+ const dayPickerRange = startDate || endDate ? {
41
+ from: startDate,
42
+ to: endDate
40
43
  } : undefined;
44
+ // Get default month for calendar (prioritize selected start date, then today)
45
+ const defaultMonth = startDate ?? new Date();
46
+ // Disable dates beyond maxRangeDays (only if maxRangeDays is provided)
47
+ const disabledDates = useMemo(()=>{
48
+ if (!startDate || maxRangeDays === undefined) return undefined;
49
+ return (date)=>{
50
+ const daysFromStart = differenceInDays(date, startDate);
51
+ return daysFromStart > maxRangeDays;
52
+ };
53
+ }, [
54
+ startDate,
55
+ maxRangeDays
56
+ ]);
41
57
  const handleSelect = (selectedRange)=>{
42
- if (selectedRange) {
43
- onDateRangeSelect?.({
44
- start: selectedRange.from,
45
- end: selectedRange.to
46
- });
47
- // Only close if both dates are selected and closeOnSelect is true
48
- if (closeOnSelect && selectedRange.from && selectedRange.to) {
49
- setOpen(false);
50
- }
51
- } else {
58
+ if (!selectedRange) {
52
59
  onDateRangeSelect?.(undefined);
60
+ return;
61
+ }
62
+ const { from, to } = selectedRange;
63
+ let finalEndDate = to;
64
+ // Cap end date to maxRangeDays if both dates are selected and maxRangeDays is provided
65
+ if (from && to && maxRangeDays !== undefined) {
66
+ const daysFromStart = differenceInDays(to, from);
67
+ if (daysFromStart > maxRangeDays) {
68
+ finalEndDate = addDays(from, maxRangeDays);
69
+ }
70
+ }
71
+ onDateRangeSelect?.({
72
+ start: from,
73
+ end: finalEndDate
74
+ });
75
+ if (closeOnSelect && from && finalEndDate) {
76
+ setOpen(false);
53
77
  }
54
78
  };
55
79
  const handleClear = (e)=>{
@@ -98,11 +122,11 @@ export const DateTimeRangePicker = /*#__PURE__*/ forwardRef(({ className, varian
98
122
  /*#__PURE__*/ _jsx("button", {
99
123
  type: "button",
100
124
  onClick: handleClear,
101
- className: cn('flex items-center justify-center shrink-0 transition-colors hover:text-foreground-neutral-base', size === 'small' ? 'size-28' : 'size-32', hasRange && onClear && !isDisabled ? 'visible' : 'invisible'),
125
+ className: cn('flex items-center justify-center shrink-0 transition-colors hover:text-foreground-neutral-base cursor-pointer', size === 'small' ? 'size-28' : 'size-32', hasRange && onClear && !isDisabled ? 'visible' : 'invisible'),
102
126
  "aria-label": "Clear date range",
103
127
  children: /*#__PURE__*/ _jsx(Icon, {
104
128
  name: "closeLine",
105
- className: "size-16 text-foreground-neutral-muted"
129
+ className: "size-16 text-foreground-neutral-muted hover:text-foreground-neutral-subtle transition-colors"
106
130
  })
107
131
  }),
108
132
  rightIcon && !hasRange && /*#__PURE__*/ _jsx("div", {
@@ -116,10 +140,14 @@ export const DateTimeRangePicker = /*#__PURE__*/ forwardRef(({ className, varian
116
140
  align: "start",
117
141
  children: /*#__PURE__*/ _jsx(Calendar, {
118
142
  mode: "range",
119
- defaultMonth: dayPickerRange?.from,
143
+ defaultMonth: defaultMonth,
120
144
  selected: dayPickerRange,
121
145
  onSelect: handleSelect,
122
- numberOfMonths: numberOfMonths
146
+ numberOfMonths: numberOfMonths,
147
+ disabled: disabledDates,
148
+ formatters: {
149
+ formatWeekdayName: (date)=>format(date, 'EEEEE')
150
+ }
123
151
  })
124
152
  })
125
153
  ]
@@ -0,0 +1,25 @@
1
+ import { Input } from '../../components/input';
2
+ import type { ComponentProps } from 'react';
3
+ import { type ReactNode } from 'react';
4
+ export type DropdownInputItem<T = unknown> = {
5
+ id: string | number;
6
+ label: string;
7
+ value: T;
8
+ };
9
+ type InputBaseProps = Omit<ComponentProps<typeof Input>, 'value' | 'onChange' | 'onSelect'>;
10
+ export type DropdownInputProps<T = unknown> = InputBaseProps & {
11
+ value: string;
12
+ onValueChange: (value: string) => void;
13
+ onSelect?: (item: DropdownInputItem<T>) => void;
14
+ items: DropdownInputItem<T>[];
15
+ emptyPlaceholder?: string | ReactNode;
16
+ open: boolean;
17
+ onOpenChange: (open: boolean) => void;
18
+ focusedIndex: number;
19
+ onFocusedIndexChange: (index: number) => void;
20
+ selectedItem?: DropdownInputItem<T> | null;
21
+ dropdownClassName?: string;
22
+ };
23
+ export declare function DropdownInput<T = unknown>({ value, onValueChange, onSelect, items, emptyPlaceholder, open, onOpenChange, focusedIndex, onFocusedIndexChange, selectedItem, dropdownClassName, className, ...inputProps }: DropdownInputProps<T>): import("react/jsx-runtime").JSX.Element;
24
+ export {};
25
+ //# sourceMappingURL=dropdown-input.d.ts.map
@@ -0,0 +1,188 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Button } from '../../components/button/index.js';
3
+ import { Input } from '../../components/input/index.js';
4
+ import { Popover, PopoverContent, PopoverTrigger } from '../../components/popover/index.js';
5
+ import { useCallback, useEffect, useRef } from 'react';
6
+ import { cn } from '../../utils/cn.js';
7
+ export function DropdownInput({ value, onValueChange, onSelect, items = [], emptyPlaceholder, open, onOpenChange, focusedIndex, onFocusedIndexChange, selectedItem, dropdownClassName, className, ...inputProps }) {
8
+ const inputRef = useRef(null);
9
+ const blurTimeoutRef = useRef(null);
10
+ const popoverContentRef = useRef(null);
11
+ const itemRefs = useRef([]);
12
+ const isDisabled = Boolean(inputProps.disabled);
13
+ const hasResults = items.length > 0;
14
+ const shouldShowDropdown = open && !isDisabled;
15
+ const handleOpenChange = useCallback((nextOpen)=>{
16
+ if (isDisabled) {
17
+ if (!nextOpen) onOpenChange(false);
18
+ return;
19
+ }
20
+ onOpenChange(nextOpen);
21
+ }, [
22
+ isDisabled,
23
+ onOpenChange
24
+ ]);
25
+ const handleSelect = useCallback((item)=>{
26
+ onValueChange(item.label);
27
+ onSelect?.(item);
28
+ onOpenChange(false);
29
+ inputRef.current?.blur();
30
+ }, [
31
+ onValueChange,
32
+ onOpenChange,
33
+ onSelect
34
+ ]);
35
+ const handleInputChange = useCallback((e)=>{
36
+ onValueChange(e.target.value);
37
+ onFocusedIndexChange(-1);
38
+ if (!open && !isDisabled) {
39
+ onOpenChange(true);
40
+ }
41
+ }, [
42
+ onValueChange,
43
+ onFocusedIndexChange,
44
+ open,
45
+ isDisabled,
46
+ onOpenChange
47
+ ]);
48
+ const handleInputKeyDown = useCallback((e)=>{
49
+ if (!shouldShowDropdown || items.length === 0) return;
50
+ if (e.key === 'ArrowDown') {
51
+ e.preventDefault();
52
+ onFocusedIndexChange(focusedIndex < items.length - 1 ? focusedIndex + 1 : 0);
53
+ } else if (e.key === 'ArrowUp') {
54
+ e.preventDefault();
55
+ onFocusedIndexChange(focusedIndex > 0 ? focusedIndex - 1 : items.length - 1);
56
+ } else if (e.key === 'Enter' && focusedIndex >= 0) {
57
+ e.preventDefault();
58
+ const item = items[focusedIndex];
59
+ if (item) {
60
+ handleSelect(item);
61
+ }
62
+ } else if (e.key === 'Escape') {
63
+ e.preventDefault();
64
+ onOpenChange(false);
65
+ }
66
+ }, [
67
+ shouldShowDropdown,
68
+ items,
69
+ focusedIndex,
70
+ onFocusedIndexChange,
71
+ handleSelect,
72
+ onOpenChange
73
+ ]);
74
+ const handleInputBlur = useCallback(()=>{
75
+ if (blurTimeoutRef.current) {
76
+ clearTimeout(blurTimeoutRef.current);
77
+ }
78
+ blurTimeoutRef.current = setTimeout(()=>{
79
+ const activeElement = document.activeElement;
80
+ const popoverContent = activeElement?.closest('[data-radix-popper-content-wrapper]');
81
+ if (!popoverContent) {
82
+ onOpenChange(false);
83
+ }
84
+ }, 200);
85
+ }, [
86
+ onOpenChange
87
+ ]);
88
+ useEffect(()=>{
89
+ return ()=>{
90
+ if (blurTimeoutRef.current) {
91
+ clearTimeout(blurTimeoutRef.current);
92
+ }
93
+ };
94
+ }, []);
95
+ useEffect(()=>{
96
+ if (focusedIndex >= 0 && itemRefs.current[focusedIndex]) {
97
+ itemRefs.current[focusedIndex]?.scrollIntoView({
98
+ block: 'nearest'
99
+ });
100
+ }
101
+ }, [
102
+ focusedIndex
103
+ ]);
104
+ const handlePointerDownOutside = useCallback((e)=>{
105
+ const target = e.target;
106
+ if (target && popoverContentRef.current?.contains(target)) {
107
+ e.preventDefault();
108
+ }
109
+ }, []);
110
+ return /*#__PURE__*/ _jsxs(Popover, {
111
+ open: shouldShowDropdown,
112
+ onOpenChange: handleOpenChange,
113
+ children: [
114
+ /*#__PURE__*/ _jsx(PopoverTrigger, {
115
+ asChild: true,
116
+ children: /*#__PURE__*/ _jsx("div", {
117
+ className: "w-full",
118
+ children: /*#__PURE__*/ _jsx(Input, {
119
+ ref: inputRef,
120
+ value: value,
121
+ onChange: handleInputChange,
122
+ onKeyDown: handleInputKeyDown,
123
+ onBlur: handleInputBlur,
124
+ onFocus: ()=>{
125
+ if (blurTimeoutRef.current) {
126
+ clearTimeout(blurTimeoutRef.current);
127
+ blurTimeoutRef.current = null;
128
+ }
129
+ if (!open && !isDisabled && value.length > 0 && hasResults) {
130
+ onOpenChange(true);
131
+ }
132
+ },
133
+ className: className,
134
+ ...inputProps
135
+ })
136
+ })
137
+ }),
138
+ /*#__PURE__*/ _jsx(PopoverContent, {
139
+ align: "start",
140
+ sideOffset: 8,
141
+ className: cn('w-(--radix-popover-trigger-width) rounded-8 bg-background-components-base p-4 shadow-tooltip', dropdownClassName),
142
+ onOpenAutoFocus: (e)=>e.preventDefault(),
143
+ onPointerDownOutside: handlePointerDownOutside,
144
+ onInteractOutside: handlePointerDownOutside,
145
+ children: /*#__PURE__*/ _jsx("div", {
146
+ ref: popoverContentRef,
147
+ className: "max-h-200 overflow-y-auto overscroll-contain scrollbar",
148
+ onWheel: (e)=>e.stopPropagation(),
149
+ onTouchStart: (e)=>e.stopPropagation(),
150
+ onTouchMove: (e)=>e.stopPropagation(),
151
+ children: hasResults ? /*#__PURE__*/ _jsxs("div", {
152
+ className: "flex flex-col gap-4 p-4",
153
+ children: [
154
+ /*#__PURE__*/ _jsx("div", {
155
+ className: "p-4 text-xs leading-20 text-foreground-neutral-muted",
156
+ children: "Select a repository"
157
+ }),
158
+ items.map((item, index)=>{
159
+ const isSelected = selectedItem?.id === item.id;
160
+ const isFocused = focusedIndex === index;
161
+ return /*#__PURE__*/ _jsx(Button, {
162
+ type: "button",
163
+ variant: "transparent",
164
+ ref: (el)=>{
165
+ itemRefs.current[index] = el;
166
+ },
167
+ onClick: ()=>handleSelect(item),
168
+ onMouseDown: (e)=>e.preventDefault(),
169
+ onMouseEnter: ()=>onFocusedIndexChange(index),
170
+ className: cn('!px-8 w-full text-left text-foreground-neutral-subtle', (isSelected || isFocused) && 'bg-background-components-hover text-foreground-neutral-base'),
171
+ children: /*#__PURE__*/ _jsx("span", {
172
+ className: "flex-1 truncate",
173
+ children: item.label
174
+ })
175
+ }, item.id);
176
+ })
177
+ ]
178
+ }) : /*#__PURE__*/ _jsx("div", {
179
+ className: "p-4 text-xs leading-20 text-foreground-neutral-muted",
180
+ children: emptyPlaceholder ? emptyPlaceholder : null
181
+ })
182
+ })
183
+ })
184
+ ]
185
+ });
186
+ }
187
+
188
+ //# sourceMappingURL=dropdown-input.js.map