Files
Basilosaurusrex f027651f9b main repo
2025-11-24 18:09:40 +01:00

1217 lines
53 KiB
JavaScript

"use strict";
"use client";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// packages/react/select/src/index.ts
var src_exports = {};
__export(src_exports, {
Arrow: () => Arrow2,
Content: () => Content2,
Group: () => Group,
Icon: () => Icon,
Item: () => Item,
ItemIndicator: () => ItemIndicator,
ItemText: () => ItemText,
Label: () => Label,
Portal: () => Portal,
Root: () => Root2,
ScrollDownButton: () => ScrollDownButton,
ScrollUpButton: () => ScrollUpButton,
Select: () => Select,
SelectArrow: () => SelectArrow,
SelectContent: () => SelectContent,
SelectGroup: () => SelectGroup,
SelectIcon: () => SelectIcon,
SelectItem: () => SelectItem,
SelectItemIndicator: () => SelectItemIndicator,
SelectItemText: () => SelectItemText,
SelectLabel: () => SelectLabel,
SelectPortal: () => SelectPortal,
SelectScrollDownButton: () => SelectScrollDownButton,
SelectScrollUpButton: () => SelectScrollUpButton,
SelectSeparator: () => SelectSeparator,
SelectTrigger: () => SelectTrigger,
SelectValue: () => SelectValue,
SelectViewport: () => SelectViewport,
Separator: () => Separator,
Trigger: () => Trigger,
Value: () => Value,
Viewport: () => Viewport,
createSelectScope: () => createSelectScope
});
module.exports = __toCommonJS(src_exports);
// packages/react/select/src/Select.tsx
var React = __toESM(require("react"));
var ReactDOM = __toESM(require("react-dom"));
var import_number = require("@radix-ui/number");
var import_primitive = require("@radix-ui/primitive");
var import_react_collection = require("@radix-ui/react-collection");
var import_react_compose_refs = require("@radix-ui/react-compose-refs");
var import_react_context = require("@radix-ui/react-context");
var import_react_direction = require("@radix-ui/react-direction");
var import_react_dismissable_layer = require("@radix-ui/react-dismissable-layer");
var import_react_focus_guards = require("@radix-ui/react-focus-guards");
var import_react_focus_scope = require("@radix-ui/react-focus-scope");
var import_react_id = require("@radix-ui/react-id");
var PopperPrimitive = __toESM(require("@radix-ui/react-popper"));
var import_react_popper = require("@radix-ui/react-popper");
var import_react_portal = require("@radix-ui/react-portal");
var import_react_primitive = require("@radix-ui/react-primitive");
var import_react_slot = require("@radix-ui/react-slot");
var import_react_use_callback_ref = require("@radix-ui/react-use-callback-ref");
var import_react_use_controllable_state = require("@radix-ui/react-use-controllable-state");
var import_react_use_layout_effect = require("@radix-ui/react-use-layout-effect");
var import_react_use_previous = require("@radix-ui/react-use-previous");
var import_react_visually_hidden = require("@radix-ui/react-visually-hidden");
var import_aria_hidden = require("aria-hidden");
var import_react_remove_scroll = require("react-remove-scroll");
var import_jsx_runtime = require("react/jsx-runtime");
var OPEN_KEYS = [" ", "Enter", "ArrowUp", "ArrowDown"];
var SELECTION_KEYS = [" ", "Enter"];
var SELECT_NAME = "Select";
var [Collection, useCollection, createCollectionScope] = (0, import_react_collection.createCollection)(SELECT_NAME);
var [createSelectContext, createSelectScope] = (0, import_react_context.createContextScope)(SELECT_NAME, [
createCollectionScope,
import_react_popper.createPopperScope
]);
var usePopperScope = (0, import_react_popper.createPopperScope)();
var [SelectProvider, useSelectContext] = createSelectContext(SELECT_NAME);
var [SelectNativeOptionsProvider, useSelectNativeOptionsContext] = createSelectContext(SELECT_NAME);
var Select = (props) => {
const {
__scopeSelect,
children,
open: openProp,
defaultOpen,
onOpenChange,
value: valueProp,
defaultValue,
onValueChange,
dir,
name,
autoComplete,
disabled,
required,
form
} = props;
const popperScope = usePopperScope(__scopeSelect);
const [trigger, setTrigger] = React.useState(null);
const [valueNode, setValueNode] = React.useState(null);
const [valueNodeHasChildren, setValueNodeHasChildren] = React.useState(false);
const direction = (0, import_react_direction.useDirection)(dir);
const [open = false, setOpen] = (0, import_react_use_controllable_state.useControllableState)({
prop: openProp,
defaultProp: defaultOpen,
onChange: onOpenChange
});
const [value, setValue] = (0, import_react_use_controllable_state.useControllableState)({
prop: valueProp,
defaultProp: defaultValue,
onChange: onValueChange
});
const triggerPointerDownPosRef = React.useRef(null);
const isFormControl = trigger ? form || !!trigger.closest("form") : true;
const [nativeOptionsSet, setNativeOptionsSet] = React.useState(/* @__PURE__ */ new Set());
const nativeSelectKey = Array.from(nativeOptionsSet).map((option) => option.props.value).join(";");
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PopperPrimitive.Root, { ...popperScope, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
SelectProvider,
{
required,
scope: __scopeSelect,
trigger,
onTriggerChange: setTrigger,
valueNode,
onValueNodeChange: setValueNode,
valueNodeHasChildren,
onValueNodeHasChildrenChange: setValueNodeHasChildren,
contentId: (0, import_react_id.useId)(),
value,
onValueChange: setValue,
open,
onOpenChange: setOpen,
dir: direction,
triggerPointerDownPosRef,
disabled,
children: [
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Collection.Provider, { scope: __scopeSelect, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
SelectNativeOptionsProvider,
{
scope: props.__scopeSelect,
onNativeOptionAdd: React.useCallback((option) => {
setNativeOptionsSet((prev) => new Set(prev).add(option));
}, []),
onNativeOptionRemove: React.useCallback((option) => {
setNativeOptionsSet((prev) => {
const optionsSet = new Set(prev);
optionsSet.delete(option);
return optionsSet;
});
}, []),
children
}
) }),
isFormControl ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
BubbleSelect,
{
"aria-hidden": true,
required,
tabIndex: -1,
name,
autoComplete,
value,
onChange: (event) => setValue(event.target.value),
disabled,
form,
children: [
value === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "" }) : null,
Array.from(nativeOptionsSet)
]
},
nativeSelectKey
) : null
]
}
) });
};
Select.displayName = SELECT_NAME;
var TRIGGER_NAME = "SelectTrigger";
var SelectTrigger = React.forwardRef(
(props, forwardedRef) => {
const { __scopeSelect, disabled = false, ...triggerProps } = props;
const popperScope = usePopperScope(__scopeSelect);
const context = useSelectContext(TRIGGER_NAME, __scopeSelect);
const isDisabled = context.disabled || disabled;
const composedRefs = (0, import_react_compose_refs.useComposedRefs)(forwardedRef, context.onTriggerChange);
const getItems = useCollection(__scopeSelect);
const pointerTypeRef = React.useRef("touch");
const [searchRef, handleTypeaheadSearch, resetTypeahead] = useTypeaheadSearch((search) => {
const enabledItems = getItems().filter((item) => !item.disabled);
const currentItem = enabledItems.find((item) => item.value === context.value);
const nextItem = findNextItem(enabledItems, search, currentItem);
if (nextItem !== void 0) {
context.onValueChange(nextItem.value);
}
});
const handleOpen = (pointerEvent) => {
if (!isDisabled) {
context.onOpenChange(true);
resetTypeahead();
}
if (pointerEvent) {
context.triggerPointerDownPosRef.current = {
x: Math.round(pointerEvent.pageX),
y: Math.round(pointerEvent.pageY)
};
}
};
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PopperPrimitive.Anchor, { asChild: true, ...popperScope, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_react_primitive.Primitive.button,
{
type: "button",
role: "combobox",
"aria-controls": context.contentId,
"aria-expanded": context.open,
"aria-required": context.required,
"aria-autocomplete": "none",
dir: context.dir,
"data-state": context.open ? "open" : "closed",
disabled: isDisabled,
"data-disabled": isDisabled ? "" : void 0,
"data-placeholder": shouldShowPlaceholder(context.value) ? "" : void 0,
...triggerProps,
ref: composedRefs,
onClick: (0, import_primitive.composeEventHandlers)(triggerProps.onClick, (event) => {
event.currentTarget.focus();
if (pointerTypeRef.current !== "mouse") {
handleOpen(event);
}
}),
onPointerDown: (0, import_primitive.composeEventHandlers)(triggerProps.onPointerDown, (event) => {
pointerTypeRef.current = event.pointerType;
const target = event.target;
if (target.hasPointerCapture(event.pointerId)) {
target.releasePointerCapture(event.pointerId);
}
if (event.button === 0 && event.ctrlKey === false && event.pointerType === "mouse") {
handleOpen(event);
event.preventDefault();
}
}),
onKeyDown: (0, import_primitive.composeEventHandlers)(triggerProps.onKeyDown, (event) => {
const isTypingAhead = searchRef.current !== "";
const isModifierKey = event.ctrlKey || event.altKey || event.metaKey;
if (!isModifierKey && event.key.length === 1) handleTypeaheadSearch(event.key);
if (isTypingAhead && event.key === " ") return;
if (OPEN_KEYS.includes(event.key)) {
handleOpen();
event.preventDefault();
}
})
}
) });
}
);
SelectTrigger.displayName = TRIGGER_NAME;
var VALUE_NAME = "SelectValue";
var SelectValue = React.forwardRef(
(props, forwardedRef) => {
const { __scopeSelect, className, style, children, placeholder = "", ...valueProps } = props;
const context = useSelectContext(VALUE_NAME, __scopeSelect);
const { onValueNodeHasChildrenChange } = context;
const hasChildren = children !== void 0;
const composedRefs = (0, import_react_compose_refs.useComposedRefs)(forwardedRef, context.onValueNodeChange);
(0, import_react_use_layout_effect.useLayoutEffect)(() => {
onValueNodeHasChildrenChange(hasChildren);
}, [onValueNodeHasChildrenChange, hasChildren]);
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_react_primitive.Primitive.span,
{
...valueProps,
ref: composedRefs,
style: { pointerEvents: "none" },
children: shouldShowPlaceholder(context.value) ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: placeholder }) : children
}
);
}
);
SelectValue.displayName = VALUE_NAME;
var ICON_NAME = "SelectIcon";
var SelectIcon = React.forwardRef(
(props, forwardedRef) => {
const { __scopeSelect, children, ...iconProps } = props;
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_primitive.Primitive.span, { "aria-hidden": true, ...iconProps, ref: forwardedRef, children: children || "\u25BC" });
}
);
SelectIcon.displayName = ICON_NAME;
var PORTAL_NAME = "SelectPortal";
var SelectPortal = (props) => {
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_portal.Portal, { asChild: true, ...props });
};
SelectPortal.displayName = PORTAL_NAME;
var CONTENT_NAME = "SelectContent";
var SelectContent = React.forwardRef(
(props, forwardedRef) => {
const context = useSelectContext(CONTENT_NAME, props.__scopeSelect);
const [fragment, setFragment] = React.useState();
(0, import_react_use_layout_effect.useLayoutEffect)(() => {
setFragment(new DocumentFragment());
}, []);
if (!context.open) {
const frag = fragment;
return frag ? ReactDOM.createPortal(
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectContentProvider, { scope: props.__scopeSelect, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Collection.Slot, { scope: props.__scopeSelect, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: props.children }) }) }),
frag
) : null;
}
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectContentImpl, { ...props, ref: forwardedRef });
}
);
SelectContent.displayName = CONTENT_NAME;
var CONTENT_MARGIN = 10;
var [SelectContentProvider, useSelectContentContext] = createSelectContext(CONTENT_NAME);
var CONTENT_IMPL_NAME = "SelectContentImpl";
var SelectContentImpl = React.forwardRef(
(props, forwardedRef) => {
const {
__scopeSelect,
position = "item-aligned",
onCloseAutoFocus,
onEscapeKeyDown,
onPointerDownOutside,
//
// PopperContent props
side,
sideOffset,
align,
alignOffset,
arrowPadding,
collisionBoundary,
collisionPadding,
sticky,
hideWhenDetached,
avoidCollisions,
//
...contentProps
} = props;
const context = useSelectContext(CONTENT_NAME, __scopeSelect);
const [content, setContent] = React.useState(null);
const [viewport, setViewport] = React.useState(null);
const composedRefs = (0, import_react_compose_refs.useComposedRefs)(forwardedRef, (node) => setContent(node));
const [selectedItem, setSelectedItem] = React.useState(null);
const [selectedItemText, setSelectedItemText] = React.useState(
null
);
const getItems = useCollection(__scopeSelect);
const [isPositioned, setIsPositioned] = React.useState(false);
const firstValidItemFoundRef = React.useRef(false);
React.useEffect(() => {
if (content) return (0, import_aria_hidden.hideOthers)(content);
}, [content]);
(0, import_react_focus_guards.useFocusGuards)();
const focusFirst = React.useCallback(
(candidates) => {
const [firstItem, ...restItems] = getItems().map((item) => item.ref.current);
const [lastItem] = restItems.slice(-1);
const PREVIOUSLY_FOCUSED_ELEMENT = document.activeElement;
for (const candidate of candidates) {
if (candidate === PREVIOUSLY_FOCUSED_ELEMENT) return;
candidate?.scrollIntoView({ block: "nearest" });
if (candidate === firstItem && viewport) viewport.scrollTop = 0;
if (candidate === lastItem && viewport) viewport.scrollTop = viewport.scrollHeight;
candidate?.focus();
if (document.activeElement !== PREVIOUSLY_FOCUSED_ELEMENT) return;
}
},
[getItems, viewport]
);
const focusSelectedItem = React.useCallback(
() => focusFirst([selectedItem, content]),
[focusFirst, selectedItem, content]
);
React.useEffect(() => {
if (isPositioned) {
focusSelectedItem();
}
}, [isPositioned, focusSelectedItem]);
const { onOpenChange, triggerPointerDownPosRef } = context;
React.useEffect(() => {
if (content) {
let pointerMoveDelta = { x: 0, y: 0 };
const handlePointerMove = (event) => {
pointerMoveDelta = {
x: Math.abs(Math.round(event.pageX) - (triggerPointerDownPosRef.current?.x ?? 0)),
y: Math.abs(Math.round(event.pageY) - (triggerPointerDownPosRef.current?.y ?? 0))
};
};
const handlePointerUp = (event) => {
if (pointerMoveDelta.x <= 10 && pointerMoveDelta.y <= 10) {
event.preventDefault();
} else {
if (!content.contains(event.target)) {
onOpenChange(false);
}
}
document.removeEventListener("pointermove", handlePointerMove);
triggerPointerDownPosRef.current = null;
};
if (triggerPointerDownPosRef.current !== null) {
document.addEventListener("pointermove", handlePointerMove);
document.addEventListener("pointerup", handlePointerUp, { capture: true, once: true });
}
return () => {
document.removeEventListener("pointermove", handlePointerMove);
document.removeEventListener("pointerup", handlePointerUp, { capture: true });
};
}
}, [content, onOpenChange, triggerPointerDownPosRef]);
React.useEffect(() => {
const close = () => onOpenChange(false);
window.addEventListener("blur", close);
window.addEventListener("resize", close);
return () => {
window.removeEventListener("blur", close);
window.removeEventListener("resize", close);
};
}, [onOpenChange]);
const [searchRef, handleTypeaheadSearch] = useTypeaheadSearch((search) => {
const enabledItems = getItems().filter((item) => !item.disabled);
const currentItem = enabledItems.find((item) => item.ref.current === document.activeElement);
const nextItem = findNextItem(enabledItems, search, currentItem);
if (nextItem) {
setTimeout(() => nextItem.ref.current.focus());
}
});
const itemRefCallback = React.useCallback(
(node, value, disabled) => {
const isFirstValidItem = !firstValidItemFoundRef.current && !disabled;
const isSelectedItem = context.value !== void 0 && context.value === value;
if (isSelectedItem || isFirstValidItem) {
setSelectedItem(node);
if (isFirstValidItem) firstValidItemFoundRef.current = true;
}
},
[context.value]
);
const handleItemLeave = React.useCallback(() => content?.focus(), [content]);
const itemTextRefCallback = React.useCallback(
(node, value, disabled) => {
const isFirstValidItem = !firstValidItemFoundRef.current && !disabled;
const isSelectedItem = context.value !== void 0 && context.value === value;
if (isSelectedItem || isFirstValidItem) {
setSelectedItemText(node);
}
},
[context.value]
);
const SelectPosition = position === "popper" ? SelectPopperPosition : SelectItemAlignedPosition;
const popperContentProps = SelectPosition === SelectPopperPosition ? {
side,
sideOffset,
align,
alignOffset,
arrowPadding,
collisionBoundary,
collisionPadding,
sticky,
hideWhenDetached,
avoidCollisions
} : {};
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
SelectContentProvider,
{
scope: __scopeSelect,
content,
viewport,
onViewportChange: setViewport,
itemRefCallback,
selectedItem,
onItemLeave: handleItemLeave,
itemTextRefCallback,
focusSelectedItem,
selectedItemText,
position,
isPositioned,
searchRef,
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_remove_scroll.RemoveScroll, { as: import_react_slot.Slot, allowPinchZoom: true, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_react_focus_scope.FocusScope,
{
asChild: true,
trapped: context.open,
onMountAutoFocus: (event) => {
event.preventDefault();
},
onUnmountAutoFocus: (0, import_primitive.composeEventHandlers)(onCloseAutoFocus, (event) => {
context.trigger?.focus({ preventScroll: true });
event.preventDefault();
}),
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_react_dismissable_layer.DismissableLayer,
{
asChild: true,
disableOutsidePointerEvents: true,
onEscapeKeyDown,
onPointerDownOutside,
onFocusOutside: (event) => event.preventDefault(),
onDismiss: () => context.onOpenChange(false),
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
SelectPosition,
{
role: "listbox",
id: context.contentId,
"data-state": context.open ? "open" : "closed",
dir: context.dir,
onContextMenu: (event) => event.preventDefault(),
...contentProps,
...popperContentProps,
onPlaced: () => setIsPositioned(true),
ref: composedRefs,
style: {
// flex layout so we can place the scroll buttons properly
display: "flex",
flexDirection: "column",
// reset the outline by default as the content MAY get focused
outline: "none",
...contentProps.style
},
onKeyDown: (0, import_primitive.composeEventHandlers)(contentProps.onKeyDown, (event) => {
const isModifierKey = event.ctrlKey || event.altKey || event.metaKey;
if (event.key === "Tab") event.preventDefault();
if (!isModifierKey && event.key.length === 1) handleTypeaheadSearch(event.key);
if (["ArrowUp", "ArrowDown", "Home", "End"].includes(event.key)) {
const items = getItems().filter((item) => !item.disabled);
let candidateNodes = items.map((item) => item.ref.current);
if (["ArrowUp", "End"].includes(event.key)) {
candidateNodes = candidateNodes.slice().reverse();
}
if (["ArrowUp", "ArrowDown"].includes(event.key)) {
const currentElement = event.target;
const currentIndex = candidateNodes.indexOf(currentElement);
candidateNodes = candidateNodes.slice(currentIndex + 1);
}
setTimeout(() => focusFirst(candidateNodes));
event.preventDefault();
}
})
}
)
}
)
}
) })
}
);
}
);
SelectContentImpl.displayName = CONTENT_IMPL_NAME;
var ITEM_ALIGNED_POSITION_NAME = "SelectItemAlignedPosition";
var SelectItemAlignedPosition = React.forwardRef((props, forwardedRef) => {
const { __scopeSelect, onPlaced, ...popperProps } = props;
const context = useSelectContext(CONTENT_NAME, __scopeSelect);
const contentContext = useSelectContentContext(CONTENT_NAME, __scopeSelect);
const [contentWrapper, setContentWrapper] = React.useState(null);
const [content, setContent] = React.useState(null);
const composedRefs = (0, import_react_compose_refs.useComposedRefs)(forwardedRef, (node) => setContent(node));
const getItems = useCollection(__scopeSelect);
const shouldExpandOnScrollRef = React.useRef(false);
const shouldRepositionRef = React.useRef(true);
const { viewport, selectedItem, selectedItemText, focusSelectedItem } = contentContext;
const position = React.useCallback(() => {
if (context.trigger && context.valueNode && contentWrapper && content && viewport && selectedItem && selectedItemText) {
const triggerRect = context.trigger.getBoundingClientRect();
const contentRect = content.getBoundingClientRect();
const valueNodeRect = context.valueNode.getBoundingClientRect();
const itemTextRect = selectedItemText.getBoundingClientRect();
if (context.dir !== "rtl") {
const itemTextOffset = itemTextRect.left - contentRect.left;
const left = valueNodeRect.left - itemTextOffset;
const leftDelta = triggerRect.left - left;
const minContentWidth = triggerRect.width + leftDelta;
const contentWidth = Math.max(minContentWidth, contentRect.width);
const rightEdge = window.innerWidth - CONTENT_MARGIN;
const clampedLeft = (0, import_number.clamp)(left, [
CONTENT_MARGIN,
// Prevents the content from going off the starting edge of the
// viewport. It may still go off the ending edge, but this can be
// controlled by the user since they may want to manage overflow in a
// specific way.
// https://github.com/radix-ui/primitives/issues/2049
Math.max(CONTENT_MARGIN, rightEdge - contentWidth)
]);
contentWrapper.style.minWidth = minContentWidth + "px";
contentWrapper.style.left = clampedLeft + "px";
} else {
const itemTextOffset = contentRect.right - itemTextRect.right;
const right = window.innerWidth - valueNodeRect.right - itemTextOffset;
const rightDelta = window.innerWidth - triggerRect.right - right;
const minContentWidth = triggerRect.width + rightDelta;
const contentWidth = Math.max(minContentWidth, contentRect.width);
const leftEdge = window.innerWidth - CONTENT_MARGIN;
const clampedRight = (0, import_number.clamp)(right, [
CONTENT_MARGIN,
Math.max(CONTENT_MARGIN, leftEdge - contentWidth)
]);
contentWrapper.style.minWidth = minContentWidth + "px";
contentWrapper.style.right = clampedRight + "px";
}
const items = getItems();
const availableHeight = window.innerHeight - CONTENT_MARGIN * 2;
const itemsHeight = viewport.scrollHeight;
const contentStyles = window.getComputedStyle(content);
const contentBorderTopWidth = parseInt(contentStyles.borderTopWidth, 10);
const contentPaddingTop = parseInt(contentStyles.paddingTop, 10);
const contentBorderBottomWidth = parseInt(contentStyles.borderBottomWidth, 10);
const contentPaddingBottom = parseInt(contentStyles.paddingBottom, 10);
const fullContentHeight = contentBorderTopWidth + contentPaddingTop + itemsHeight + contentPaddingBottom + contentBorderBottomWidth;
const minContentHeight = Math.min(selectedItem.offsetHeight * 5, fullContentHeight);
const viewportStyles = window.getComputedStyle(viewport);
const viewportPaddingTop = parseInt(viewportStyles.paddingTop, 10);
const viewportPaddingBottom = parseInt(viewportStyles.paddingBottom, 10);
const topEdgeToTriggerMiddle = triggerRect.top + triggerRect.height / 2 - CONTENT_MARGIN;
const triggerMiddleToBottomEdge = availableHeight - topEdgeToTriggerMiddle;
const selectedItemHalfHeight = selectedItem.offsetHeight / 2;
const itemOffsetMiddle = selectedItem.offsetTop + selectedItemHalfHeight;
const contentTopToItemMiddle = contentBorderTopWidth + contentPaddingTop + itemOffsetMiddle;
const itemMiddleToContentBottom = fullContentHeight - contentTopToItemMiddle;
const willAlignWithoutTopOverflow = contentTopToItemMiddle <= topEdgeToTriggerMiddle;
if (willAlignWithoutTopOverflow) {
const isLastItem = items.length > 0 && selectedItem === items[items.length - 1].ref.current;
contentWrapper.style.bottom = "0px";
const viewportOffsetBottom = content.clientHeight - viewport.offsetTop - viewport.offsetHeight;
const clampedTriggerMiddleToBottomEdge = Math.max(
triggerMiddleToBottomEdge,
selectedItemHalfHeight + // viewport might have padding bottom, include it to avoid a scrollable viewport
(isLastItem ? viewportPaddingBottom : 0) + viewportOffsetBottom + contentBorderBottomWidth
);
const height = contentTopToItemMiddle + clampedTriggerMiddleToBottomEdge;
contentWrapper.style.height = height + "px";
} else {
const isFirstItem = items.length > 0 && selectedItem === items[0].ref.current;
contentWrapper.style.top = "0px";
const clampedTopEdgeToTriggerMiddle = Math.max(
topEdgeToTriggerMiddle,
contentBorderTopWidth + viewport.offsetTop + // viewport might have padding top, include it to avoid a scrollable viewport
(isFirstItem ? viewportPaddingTop : 0) + selectedItemHalfHeight
);
const height = clampedTopEdgeToTriggerMiddle + itemMiddleToContentBottom;
contentWrapper.style.height = height + "px";
viewport.scrollTop = contentTopToItemMiddle - topEdgeToTriggerMiddle + viewport.offsetTop;
}
contentWrapper.style.margin = `${CONTENT_MARGIN}px 0`;
contentWrapper.style.minHeight = minContentHeight + "px";
contentWrapper.style.maxHeight = availableHeight + "px";
onPlaced?.();
requestAnimationFrame(() => shouldExpandOnScrollRef.current = true);
}
}, [
getItems,
context.trigger,
context.valueNode,
contentWrapper,
content,
viewport,
selectedItem,
selectedItemText,
context.dir,
onPlaced
]);
(0, import_react_use_layout_effect.useLayoutEffect)(() => position(), [position]);
const [contentZIndex, setContentZIndex] = React.useState();
(0, import_react_use_layout_effect.useLayoutEffect)(() => {
if (content) setContentZIndex(window.getComputedStyle(content).zIndex);
}, [content]);
const handleScrollButtonChange = React.useCallback(
(node) => {
if (node && shouldRepositionRef.current === true) {
position();
focusSelectedItem?.();
shouldRepositionRef.current = false;
}
},
[position, focusSelectedItem]
);
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
SelectViewportProvider,
{
scope: __scopeSelect,
contentWrapper,
shouldExpandOnScrollRef,
onScrollButtonChange: handleScrollButtonChange,
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"div",
{
ref: setContentWrapper,
style: {
display: "flex",
flexDirection: "column",
position: "fixed",
zIndex: contentZIndex
},
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_react_primitive.Primitive.div,
{
...popperProps,
ref: composedRefs,
style: {
// When we get the height of the content, it includes borders. If we were to set
// the height without having `boxSizing: 'border-box'` it would be too big.
boxSizing: "border-box",
// We need to ensure the content doesn't get taller than the wrapper
maxHeight: "100%",
...popperProps.style
}
}
)
}
)
}
);
});
SelectItemAlignedPosition.displayName = ITEM_ALIGNED_POSITION_NAME;
var POPPER_POSITION_NAME = "SelectPopperPosition";
var SelectPopperPosition = React.forwardRef((props, forwardedRef) => {
const {
__scopeSelect,
align = "start",
collisionPadding = CONTENT_MARGIN,
...popperProps
} = props;
const popperScope = usePopperScope(__scopeSelect);
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
PopperPrimitive.Content,
{
...popperScope,
...popperProps,
ref: forwardedRef,
align,
collisionPadding,
style: {
// Ensure border-box for floating-ui calculations
boxSizing: "border-box",
...popperProps.style,
// re-namespace exposed content custom properties
...{
"--radix-select-content-transform-origin": "var(--radix-popper-transform-origin)",
"--radix-select-content-available-width": "var(--radix-popper-available-width)",
"--radix-select-content-available-height": "var(--radix-popper-available-height)",
"--radix-select-trigger-width": "var(--radix-popper-anchor-width)",
"--radix-select-trigger-height": "var(--radix-popper-anchor-height)"
}
}
}
);
});
SelectPopperPosition.displayName = POPPER_POSITION_NAME;
var [SelectViewportProvider, useSelectViewportContext] = createSelectContext(CONTENT_NAME, {});
var VIEWPORT_NAME = "SelectViewport";
var SelectViewport = React.forwardRef(
(props, forwardedRef) => {
const { __scopeSelect, nonce, ...viewportProps } = props;
const contentContext = useSelectContentContext(VIEWPORT_NAME, __scopeSelect);
const viewportContext = useSelectViewportContext(VIEWPORT_NAME, __scopeSelect);
const composedRefs = (0, import_react_compose_refs.useComposedRefs)(forwardedRef, contentContext.onViewportChange);
const prevScrollTopRef = React.useRef(0);
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"style",
{
dangerouslySetInnerHTML: {
__html: `[data-radix-select-viewport]{scrollbar-width:none;-ms-overflow-style:none;-webkit-overflow-scrolling:touch;}[data-radix-select-viewport]::-webkit-scrollbar{display:none}`
},
nonce
}
),
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Collection.Slot, { scope: __scopeSelect, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_react_primitive.Primitive.div,
{
"data-radix-select-viewport": "",
role: "presentation",
...viewportProps,
ref: composedRefs,
style: {
// we use position: 'relative' here on the `viewport` so that when we call
// `selectedItem.offsetTop` in calculations, the offset is relative to the viewport
// (independent of the scrollUpButton).
position: "relative",
flex: 1,
// Viewport should only be scrollable in the vertical direction.
// This won't work in vertical writing modes, so we'll need to
// revisit this if/when that is supported
// https://developer.chrome.com/blog/vertical-form-controls
overflow: "hidden auto",
...viewportProps.style
},
onScroll: (0, import_primitive.composeEventHandlers)(viewportProps.onScroll, (event) => {
const viewport = event.currentTarget;
const { contentWrapper, shouldExpandOnScrollRef } = viewportContext;
if (shouldExpandOnScrollRef?.current && contentWrapper) {
const scrolledBy = Math.abs(prevScrollTopRef.current - viewport.scrollTop);
if (scrolledBy > 0) {
const availableHeight = window.innerHeight - CONTENT_MARGIN * 2;
const cssMinHeight = parseFloat(contentWrapper.style.minHeight);
const cssHeight = parseFloat(contentWrapper.style.height);
const prevHeight = Math.max(cssMinHeight, cssHeight);
if (prevHeight < availableHeight) {
const nextHeight = prevHeight + scrolledBy;
const clampedNextHeight = Math.min(availableHeight, nextHeight);
const heightDiff = nextHeight - clampedNextHeight;
contentWrapper.style.height = clampedNextHeight + "px";
if (contentWrapper.style.bottom === "0px") {
viewport.scrollTop = heightDiff > 0 ? heightDiff : 0;
contentWrapper.style.justifyContent = "flex-end";
}
}
}
}
prevScrollTopRef.current = viewport.scrollTop;
})
}
) })
] });
}
);
SelectViewport.displayName = VIEWPORT_NAME;
var GROUP_NAME = "SelectGroup";
var [SelectGroupContextProvider, useSelectGroupContext] = createSelectContext(GROUP_NAME);
var SelectGroup = React.forwardRef(
(props, forwardedRef) => {
const { __scopeSelect, ...groupProps } = props;
const groupId = (0, import_react_id.useId)();
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectGroupContextProvider, { scope: __scopeSelect, id: groupId, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_primitive.Primitive.div, { role: "group", "aria-labelledby": groupId, ...groupProps, ref: forwardedRef }) });
}
);
SelectGroup.displayName = GROUP_NAME;
var LABEL_NAME = "SelectLabel";
var SelectLabel = React.forwardRef(
(props, forwardedRef) => {
const { __scopeSelect, ...labelProps } = props;
const groupContext = useSelectGroupContext(LABEL_NAME, __scopeSelect);
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_primitive.Primitive.div, { id: groupContext.id, ...labelProps, ref: forwardedRef });
}
);
SelectLabel.displayName = LABEL_NAME;
var ITEM_NAME = "SelectItem";
var [SelectItemContextProvider, useSelectItemContext] = createSelectContext(ITEM_NAME);
var SelectItem = React.forwardRef(
(props, forwardedRef) => {
const {
__scopeSelect,
value,
disabled = false,
textValue: textValueProp,
...itemProps
} = props;
const context = useSelectContext(ITEM_NAME, __scopeSelect);
const contentContext = useSelectContentContext(ITEM_NAME, __scopeSelect);
const isSelected = context.value === value;
const [textValue, setTextValue] = React.useState(textValueProp ?? "");
const [isFocused, setIsFocused] = React.useState(false);
const composedRefs = (0, import_react_compose_refs.useComposedRefs)(
forwardedRef,
(node) => contentContext.itemRefCallback?.(node, value, disabled)
);
const textId = (0, import_react_id.useId)();
const pointerTypeRef = React.useRef("touch");
const handleSelect = () => {
if (!disabled) {
context.onValueChange(value);
context.onOpenChange(false);
}
};
if (value === "") {
throw new Error(
"A <Select.Item /> must have a value prop that is not an empty string. This is because the Select value can be set to an empty string to clear the selection and show the placeholder."
);
}
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
SelectItemContextProvider,
{
scope: __scopeSelect,
value,
disabled,
textId,
isSelected,
onItemTextChange: React.useCallback((node) => {
setTextValue((prevTextValue) => prevTextValue || (node?.textContent ?? "").trim());
}, []),
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
Collection.ItemSlot,
{
scope: __scopeSelect,
value,
disabled,
textValue,
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_react_primitive.Primitive.div,
{
role: "option",
"aria-labelledby": textId,
"data-highlighted": isFocused ? "" : void 0,
"aria-selected": isSelected && isFocused,
"data-state": isSelected ? "checked" : "unchecked",
"aria-disabled": disabled || void 0,
"data-disabled": disabled ? "" : void 0,
tabIndex: disabled ? void 0 : -1,
...itemProps,
ref: composedRefs,
onFocus: (0, import_primitive.composeEventHandlers)(itemProps.onFocus, () => setIsFocused(true)),
onBlur: (0, import_primitive.composeEventHandlers)(itemProps.onBlur, () => setIsFocused(false)),
onClick: (0, import_primitive.composeEventHandlers)(itemProps.onClick, () => {
if (pointerTypeRef.current !== "mouse") handleSelect();
}),
onPointerUp: (0, import_primitive.composeEventHandlers)(itemProps.onPointerUp, () => {
if (pointerTypeRef.current === "mouse") handleSelect();
}),
onPointerDown: (0, import_primitive.composeEventHandlers)(itemProps.onPointerDown, (event) => {
pointerTypeRef.current = event.pointerType;
}),
onPointerMove: (0, import_primitive.composeEventHandlers)(itemProps.onPointerMove, (event) => {
pointerTypeRef.current = event.pointerType;
if (disabled) {
contentContext.onItemLeave?.();
} else if (pointerTypeRef.current === "mouse") {
event.currentTarget.focus({ preventScroll: true });
}
}),
onPointerLeave: (0, import_primitive.composeEventHandlers)(itemProps.onPointerLeave, (event) => {
if (event.currentTarget === document.activeElement) {
contentContext.onItemLeave?.();
}
}),
onKeyDown: (0, import_primitive.composeEventHandlers)(itemProps.onKeyDown, (event) => {
const isTypingAhead = contentContext.searchRef?.current !== "";
if (isTypingAhead && event.key === " ") return;
if (SELECTION_KEYS.includes(event.key)) handleSelect();
if (event.key === " ") event.preventDefault();
})
}
)
}
)
}
);
}
);
SelectItem.displayName = ITEM_NAME;
var ITEM_TEXT_NAME = "SelectItemText";
var SelectItemText = React.forwardRef(
(props, forwardedRef) => {
const { __scopeSelect, className, style, ...itemTextProps } = props;
const context = useSelectContext(ITEM_TEXT_NAME, __scopeSelect);
const contentContext = useSelectContentContext(ITEM_TEXT_NAME, __scopeSelect);
const itemContext = useSelectItemContext(ITEM_TEXT_NAME, __scopeSelect);
const nativeOptionsContext = useSelectNativeOptionsContext(ITEM_TEXT_NAME, __scopeSelect);
const [itemTextNode, setItemTextNode] = React.useState(null);
const composedRefs = (0, import_react_compose_refs.useComposedRefs)(
forwardedRef,
(node) => setItemTextNode(node),
itemContext.onItemTextChange,
(node) => contentContext.itemTextRefCallback?.(node, itemContext.value, itemContext.disabled)
);
const textContent = itemTextNode?.textContent;
const nativeOption = React.useMemo(
() => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: itemContext.value, disabled: itemContext.disabled, children: textContent }, itemContext.value),
[itemContext.disabled, itemContext.value, textContent]
);
const { onNativeOptionAdd, onNativeOptionRemove } = nativeOptionsContext;
(0, import_react_use_layout_effect.useLayoutEffect)(() => {
onNativeOptionAdd(nativeOption);
return () => onNativeOptionRemove(nativeOption);
}, [onNativeOptionAdd, onNativeOptionRemove, nativeOption]);
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_primitive.Primitive.span, { id: itemContext.textId, ...itemTextProps, ref: composedRefs }),
itemContext.isSelected && context.valueNode && !context.valueNodeHasChildren ? ReactDOM.createPortal(itemTextProps.children, context.valueNode) : null
] });
}
);
SelectItemText.displayName = ITEM_TEXT_NAME;
var ITEM_INDICATOR_NAME = "SelectItemIndicator";
var SelectItemIndicator = React.forwardRef(
(props, forwardedRef) => {
const { __scopeSelect, ...itemIndicatorProps } = props;
const itemContext = useSelectItemContext(ITEM_INDICATOR_NAME, __scopeSelect);
return itemContext.isSelected ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_primitive.Primitive.span, { "aria-hidden": true, ...itemIndicatorProps, ref: forwardedRef }) : null;
}
);
SelectItemIndicator.displayName = ITEM_INDICATOR_NAME;
var SCROLL_UP_BUTTON_NAME = "SelectScrollUpButton";
var SelectScrollUpButton = React.forwardRef((props, forwardedRef) => {
const contentContext = useSelectContentContext(SCROLL_UP_BUTTON_NAME, props.__scopeSelect);
const viewportContext = useSelectViewportContext(SCROLL_UP_BUTTON_NAME, props.__scopeSelect);
const [canScrollUp, setCanScrollUp] = React.useState(false);
const composedRefs = (0, import_react_compose_refs.useComposedRefs)(forwardedRef, viewportContext.onScrollButtonChange);
(0, import_react_use_layout_effect.useLayoutEffect)(() => {
if (contentContext.viewport && contentContext.isPositioned) {
let handleScroll2 = function() {
const canScrollUp2 = viewport.scrollTop > 0;
setCanScrollUp(canScrollUp2);
};
var handleScroll = handleScroll2;
const viewport = contentContext.viewport;
handleScroll2();
viewport.addEventListener("scroll", handleScroll2);
return () => viewport.removeEventListener("scroll", handleScroll2);
}
}, [contentContext.viewport, contentContext.isPositioned]);
return canScrollUp ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
SelectScrollButtonImpl,
{
...props,
ref: composedRefs,
onAutoScroll: () => {
const { viewport, selectedItem } = contentContext;
if (viewport && selectedItem) {
viewport.scrollTop = viewport.scrollTop - selectedItem.offsetHeight;
}
}
}
) : null;
});
SelectScrollUpButton.displayName = SCROLL_UP_BUTTON_NAME;
var SCROLL_DOWN_BUTTON_NAME = "SelectScrollDownButton";
var SelectScrollDownButton = React.forwardRef((props, forwardedRef) => {
const contentContext = useSelectContentContext(SCROLL_DOWN_BUTTON_NAME, props.__scopeSelect);
const viewportContext = useSelectViewportContext(SCROLL_DOWN_BUTTON_NAME, props.__scopeSelect);
const [canScrollDown, setCanScrollDown] = React.useState(false);
const composedRefs = (0, import_react_compose_refs.useComposedRefs)(forwardedRef, viewportContext.onScrollButtonChange);
(0, import_react_use_layout_effect.useLayoutEffect)(() => {
if (contentContext.viewport && contentContext.isPositioned) {
let handleScroll2 = function() {
const maxScroll = viewport.scrollHeight - viewport.clientHeight;
const canScrollDown2 = Math.ceil(viewport.scrollTop) < maxScroll;
setCanScrollDown(canScrollDown2);
};
var handleScroll = handleScroll2;
const viewport = contentContext.viewport;
handleScroll2();
viewport.addEventListener("scroll", handleScroll2);
return () => viewport.removeEventListener("scroll", handleScroll2);
}
}, [contentContext.viewport, contentContext.isPositioned]);
return canScrollDown ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
SelectScrollButtonImpl,
{
...props,
ref: composedRefs,
onAutoScroll: () => {
const { viewport, selectedItem } = contentContext;
if (viewport && selectedItem) {
viewport.scrollTop = viewport.scrollTop + selectedItem.offsetHeight;
}
}
}
) : null;
});
SelectScrollDownButton.displayName = SCROLL_DOWN_BUTTON_NAME;
var SelectScrollButtonImpl = React.forwardRef((props, forwardedRef) => {
const { __scopeSelect, onAutoScroll, ...scrollIndicatorProps } = props;
const contentContext = useSelectContentContext("SelectScrollButton", __scopeSelect);
const autoScrollTimerRef = React.useRef(null);
const getItems = useCollection(__scopeSelect);
const clearAutoScrollTimer = React.useCallback(() => {
if (autoScrollTimerRef.current !== null) {
window.clearInterval(autoScrollTimerRef.current);
autoScrollTimerRef.current = null;
}
}, []);
React.useEffect(() => {
return () => clearAutoScrollTimer();
}, [clearAutoScrollTimer]);
(0, import_react_use_layout_effect.useLayoutEffect)(() => {
const activeItem = getItems().find((item) => item.ref.current === document.activeElement);
activeItem?.ref.current?.scrollIntoView({ block: "nearest" });
}, [getItems]);
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_react_primitive.Primitive.div,
{
"aria-hidden": true,
...scrollIndicatorProps,
ref: forwardedRef,
style: { flexShrink: 0, ...scrollIndicatorProps.style },
onPointerDown: (0, import_primitive.composeEventHandlers)(scrollIndicatorProps.onPointerDown, () => {
if (autoScrollTimerRef.current === null) {
autoScrollTimerRef.current = window.setInterval(onAutoScroll, 50);
}
}),
onPointerMove: (0, import_primitive.composeEventHandlers)(scrollIndicatorProps.onPointerMove, () => {
contentContext.onItemLeave?.();
if (autoScrollTimerRef.current === null) {
autoScrollTimerRef.current = window.setInterval(onAutoScroll, 50);
}
}),
onPointerLeave: (0, import_primitive.composeEventHandlers)(scrollIndicatorProps.onPointerLeave, () => {
clearAutoScrollTimer();
})
}
);
});
var SEPARATOR_NAME = "SelectSeparator";
var SelectSeparator = React.forwardRef(
(props, forwardedRef) => {
const { __scopeSelect, ...separatorProps } = props;
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_primitive.Primitive.div, { "aria-hidden": true, ...separatorProps, ref: forwardedRef });
}
);
SelectSeparator.displayName = SEPARATOR_NAME;
var ARROW_NAME = "SelectArrow";
var SelectArrow = React.forwardRef(
(props, forwardedRef) => {
const { __scopeSelect, ...arrowProps } = props;
const popperScope = usePopperScope(__scopeSelect);
const context = useSelectContext(ARROW_NAME, __scopeSelect);
const contentContext = useSelectContentContext(ARROW_NAME, __scopeSelect);
return context.open && contentContext.position === "popper" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PopperPrimitive.Arrow, { ...popperScope, ...arrowProps, ref: forwardedRef }) : null;
}
);
SelectArrow.displayName = ARROW_NAME;
function shouldShowPlaceholder(value) {
return value === "" || value === void 0;
}
var BubbleSelect = React.forwardRef(
(props, forwardedRef) => {
const { value, ...selectProps } = props;
const ref = React.useRef(null);
const composedRefs = (0, import_react_compose_refs.useComposedRefs)(forwardedRef, ref);
const prevValue = (0, import_react_use_previous.usePrevious)(value);
React.useEffect(() => {
const select = ref.current;
const selectProto = window.HTMLSelectElement.prototype;
const descriptor = Object.getOwnPropertyDescriptor(
selectProto,
"value"
);
const setValue = descriptor.set;
if (prevValue !== value && setValue) {
const event = new Event("change", { bubbles: true });
setValue.call(select, value);
select.dispatchEvent(event);
}
}, [prevValue, value]);
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_visually_hidden.VisuallyHidden, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("select", { ...selectProps, ref: composedRefs, defaultValue: value }) });
}
);
BubbleSelect.displayName = "BubbleSelect";
function useTypeaheadSearch(onSearchChange) {
const handleSearchChange = (0, import_react_use_callback_ref.useCallbackRef)(onSearchChange);
const searchRef = React.useRef("");
const timerRef = React.useRef(0);
const handleTypeaheadSearch = React.useCallback(
(key) => {
const search = searchRef.current + key;
handleSearchChange(search);
(function updateSearch(value) {
searchRef.current = value;
window.clearTimeout(timerRef.current);
if (value !== "") timerRef.current = window.setTimeout(() => updateSearch(""), 1e3);
})(search);
},
[handleSearchChange]
);
const resetTypeahead = React.useCallback(() => {
searchRef.current = "";
window.clearTimeout(timerRef.current);
}, []);
React.useEffect(() => {
return () => window.clearTimeout(timerRef.current);
}, []);
return [searchRef, handleTypeaheadSearch, resetTypeahead];
}
function findNextItem(items, search, currentItem) {
const isRepeated = search.length > 1 && Array.from(search).every((char) => char === search[0]);
const normalizedSearch = isRepeated ? search[0] : search;
const currentItemIndex = currentItem ? items.indexOf(currentItem) : -1;
let wrappedItems = wrapArray(items, Math.max(currentItemIndex, 0));
const excludeCurrentItem = normalizedSearch.length === 1;
if (excludeCurrentItem) wrappedItems = wrappedItems.filter((v) => v !== currentItem);
const nextItem = wrappedItems.find(
(item) => item.textValue.toLowerCase().startsWith(normalizedSearch.toLowerCase())
);
return nextItem !== currentItem ? nextItem : void 0;
}
function wrapArray(array, startIndex) {
return array.map((_, index) => array[(startIndex + index) % array.length]);
}
var Root2 = Select;
var Trigger = SelectTrigger;
var Value = SelectValue;
var Icon = SelectIcon;
var Portal = SelectPortal;
var Content2 = SelectContent;
var Viewport = SelectViewport;
var Group = SelectGroup;
var Label = SelectLabel;
var Item = SelectItem;
var ItemText = SelectItemText;
var ItemIndicator = SelectItemIndicator;
var ScrollUpButton = SelectScrollUpButton;
var ScrollDownButton = SelectScrollDownButton;
var Separator = SelectSeparator;
var Arrow2 = SelectArrow;
//# sourceMappingURL=index.js.map