react95
Version:
Refreshed Windows95 UI components for modern web apps - React95
93 lines (90 loc) • 4.68 kB
JavaScript
import React__default, { forwardRef, useRef, useImperativeHandle, useMemo, useCallback } from 'react';
import { useId } from '../common/hooks/useId.mjs';
import { StyledInner, StyledSelectContent, StyledDropdownMenu, StyledDropdownMenuItem } from './Select.styles.mjs';
import { useSelectCommon } from './useSelectCommon.mjs';
import { useSelectState } from './useSelectState.mjs';
export { SelectNative } from './SelectNative.mjs';
function SelectInnerOption({ activateOptionIndex, active, index, onClick, option, selected, setRef }) {
const handleOnMouseEnter = useCallback(() => {
activateOptionIndex(index);
}, [activateOptionIndex, index]);
const handleSetRef = useCallback((ref) => {
setRef(ref, index);
}, [index, setRef]);
const id = useId();
return React__default.createElement(StyledDropdownMenuItem, { active, "aria-selected": selected ? "true" : void 0, "data-value": option.value, id, onClick, onMouseEnter: handleOnMouseEnter, ref: handleSetRef, role: "option", tabIndex: 0 }, option.label);
}
function SelectInner({ "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, className, defaultValue, disabled = false, formatDisplay, inputProps, labelId, menuMaxHeight, name, onBlur, onChange, onClose, onFocus, onKeyDown, onMouseDown, onOpen, open: openProp, options: optionsProp, readOnly, shadow = true, style, variant = "default", value: valueProp, width = "auto", ...otherProps }, ref) {
const { isEnabled, options, setValue, value, wrapperProps, DropdownButton, Wrapper } = useSelectCommon({
className,
defaultValue,
disabled,
native: false,
onChange,
options: optionsProp,
style,
readOnly,
value: valueProp,
variant,
width
});
const inputRef = useRef(null);
const selectRef = useRef(null);
const wrapperRef = useRef(null);
const { activeOption, handleActivateOptionIndex, handleBlur, handleButtonKeyDown, handleDropdownKeyDown, handleFocus, handleMouseDown, handleOptionClick, handleSetDropdownRef, handleSetOptionRef, open, selectedOption } = useSelectState({
onBlur,
onChange,
onClose,
onFocus,
onKeyDown,
onMouseDown,
onOpen,
open: openProp,
options,
value,
selectRef,
setValue,
wrapperRef
});
useImperativeHandle(ref, () => ({
focus: (focusOptions) => {
var _a;
(_a = selectRef.current) === null || _a === void 0 ? void 0 : _a.focus(focusOptions);
},
node: inputRef.current,
value: String(value)
}), [value]);
const displayLabel = useMemo(() => !selectedOption ? "" : typeof formatDisplay === "function" ? formatDisplay(selectedOption) : selectedOption.label, [formatDisplay, selectedOption]);
const tabIndex = isEnabled ? 1 : void 0;
const dropdownMenuStyle = useMemo(() => menuMaxHeight ? { overflow: "auto", maxHeight: menuMaxHeight } : void 0, [menuMaxHeight]);
const dropdownMenuId = useId();
const optionsContent = useMemo(() => options.map((option, index) => {
const key = `${value}-${index}`;
const active = option === activeOption;
const selected = option === selectedOption;
return React__default.createElement(SelectInnerOption, { activateOptionIndex: handleActivateOptionIndex, active, index, key, onClick: handleOptionClick, option, selected, setRef: handleSetOptionRef });
}), [
activeOption,
handleActivateOptionIndex,
handleOptionClick,
handleSetOptionRef,
options,
selectedOption,
value
]);
return React__default.createElement(
Wrapper,
{ ...wrapperProps, "$disabled": disabled, ref: wrapperRef, shadow, style: { ...style, width } },
React__default.createElement("input", { name, ref: inputRef, type: "hidden", value: String(value), ...inputProps }),
React__default.createElement(
StyledInner,
{ "aria-disabled": disabled, "aria-expanded": open, "aria-haspopup": "listbox", "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy !== null && ariaLabelledBy !== void 0 ? ariaLabelledBy : labelId, "aria-owns": isEnabled && open ? dropdownMenuId : void 0, onBlur: handleBlur, onFocus: handleFocus, onKeyDown: handleButtonKeyDown, onMouseDown: isEnabled ? handleMouseDown : onMouseDown, ref: selectRef, role: "button", tabIndex, ...otherProps },
React__default.createElement(StyledSelectContent, null, displayLabel),
DropdownButton
),
isEnabled && open && React__default.createElement(StyledDropdownMenu, { id: dropdownMenuId, onKeyDown: handleDropdownKeyDown, ref: handleSetDropdownRef, role: "listbox", style: dropdownMenuStyle, tabIndex: 0, variant }, optionsContent)
);
}
const Select = forwardRef(SelectInner);
Select.displayName = "Select";
export { Select };