UNPKG

@1771technologies/lytenyte-pro

Version:

2,257 lines 76.3 kB
import { jsx, jsxs } from "react/jsx-runtime";
import { clsx } from "@1771technologies/js-utils";
import { A as ArrowDownIcon } from "./arrow-down-icon-B-3ldODD.js";
import { c as CheckMark } from "./drag-store-BF4ad65L.js";
import "@1771technologies/react-sizer";
import "@1771technologies/react-utils";
import "@1771technologies/grid-provider";
import * as React from "react";
import "@1771technologies/react-dragon";
import "@1771technologies/grid-core";
import { j as useEventCallback, m as mergeProps, d as useEnhancedEffect, n as useOpenChangeComplete, p as useFloatingRootContext, v as useClick, w as useDismiss, x as useRole, y as useListNavigation, z as useTypeahead, A as useInteractions, P as PropTypes, E as contains, F as FloatingPortal, H as HTMLElementType, r as refType, D as FloatingFocusManager, u as useLatestRef } from "./proptypes-BjYr2nFr.js";
import { b as useBaseUiId, u as useForkRef, c as pressableTriggerOpenStateMapping, a as useComponentRenderer, p as popupStateMapping, I as InternalBackdrop, t as transitionStatusMapping } from "./InternalBackdrop-C4RACVzs.js";
import { u as useControlled, a as useTransitionStatus, o as ownerDocument, b as useScrollLock, d as ownerWindow, i as isWebKit } from "./useScrollLock-D4UY33Sb.js";
import { w as warn, u as useButton } from "./useButton-DWXzFgcr.js";
import { g as getPseudoElementBounds } from "./getPseudoElementBounds-BSHt6WYm.js";
import { C as CompositeList, u as useCompositeListItem } from "./CompositeList-CGRaS6LQ.js";
import { u as useAnchorPositioning } from "./useAnchorPositioning-52zK7jlD.js";
let FieldControlDataAttributes = /* @__PURE__ */ function(FieldControlDataAttributes2) {
  FieldControlDataAttributes2["disabled"] = "data-disabled";
  FieldControlDataAttributes2["valid"] = "data-valid";
  FieldControlDataAttributes2["invalid"] = "data-invalid";
  FieldControlDataAttributes2["touched"] = "data-touched";
  FieldControlDataAttributes2["dirty"] = "data-dirty";
  FieldControlDataAttributes2["filled"] = "data-filled";
  FieldControlDataAttributes2["focused"] = "data-focused";
  return FieldControlDataAttributes2;
}({});
const DEFAULT_VALIDITY_STATE = {
  badInput: false,
  customError: false,
  patternMismatch: false,
  rangeOverflow: false,
  rangeUnderflow: false,
  stepMismatch: false,
  tooLong: false,
  tooShort: false,
  typeMismatch: false,
  valid: null,
  valueMissing: false
};
const fieldValidityMapping = {
  valid(value) {
    if (value === null) {
      return null;
    }
    if (value) {
      return {
        [FieldControlDataAttributes.valid]: ""
      };
    }
    return {
      [FieldControlDataAttributes.invalid]: ""
    };
  }
};
const NOOP = () => {
};
const FieldRootContext = /* @__PURE__ */ React.createContext({
  invalid: void 0,
  controlId: void 0,
  setControlId: NOOP,
  labelId: void 0,
  setLabelId: NOOP,
  messageIds: [],
  setMessageIds: NOOP,
  name: void 0,
  validityData: {
    state: DEFAULT_VALIDITY_STATE,
    errors: [],
    error: "",
    value: "",
    initialValue: null
  },
  setValidityData: NOOP,
  disabled: void 0,
  touched: false,
  setTouched: NOOP,
  dirty: false,
  setDirty: NOOP,
  filled: false,
  setFilled: NOOP,
  focused: false,
  setFocused: NOOP,
  validate: () => null,
  validationMode: "onBlur",
  validationDebounceTime: 0,
  state: {
    disabled: false,
    valid: null,
    touched: false,
    dirty: false,
    filled: false,
    focused: false
  },
  markedDirtyRef: {
    current: false
  }
});
if (process.env.NODE_ENV !== "production") {
  FieldRootContext.displayName = "FieldRootContext";
}
function useFieldRootContext(optional = true) {
  const context = React.useContext(FieldRootContext);
  if (context.setControlId === NOOP && !optional) {
    throw new Error("Base UI: FieldRootContext is missing. Field parts must be placed within <Field.Root>.");
  }
  return context;
}
const FormContext = /* @__PURE__ */ React.createContext({
  formRef: {
    current: {
      fields: /* @__PURE__ */ new Map()
    }
  },
  errors: {},
  onClearErrors: () => {
  }
});
if (process.env.NODE_ENV !== "production") {
  FormContext.displayName = "FormContext";
}
function useFormContext() {
  return React.useContext(FormContext);
}
function getCombinedFieldValidityData(validityData, invalid) {
  return {
    ...validityData,
    state: {
      ...validityData.state,
      valid: !invalid && validityData.state.valid
    }
  };
}
const validityKeys = Object.keys(DEFAULT_VALIDITY_STATE);
function useFieldControlValidation() {
  const {
    setValidityData,
    validate,
    messageIds,
    validityData,
    validationMode,
    validationDebounceTime,
    invalid,
    markedDirtyRef,
    controlId,
    state
  } = useFieldRootContext();
  const {
    formRef
  } = useFormContext();
  const timeoutRef = React.useRef(-1);
  const inputRef = React.useRef(null);
  React.useEffect(() => {
    return () => {
      window.clearTimeout(timeoutRef.current);
    };
  }, []);
  const commitValidation = useEventCallback(async (value) => {
    const element = inputRef.current;
    if (!element) {
      return;
    }
    function getState(el) {
      return validityKeys.reduce((acc, key) => {
        acc[key] = el.validity[key];
        if (!el.validity.customError && !markedDirtyRef.current) {
          acc[key] = key === "valid";
        }
        return acc;
      }, {});
    }
    window.clearTimeout(timeoutRef.current);
    const resultOrPromise = validate(value);
    let result = null;
    if (typeof resultOrPromise === "object" && resultOrPromise !== null && "then" in resultOrPromise) {
      result = await resultOrPromise;
    } else {
      result = resultOrPromise;
    }
    let errorMessage = "";
    if (result !== null) {
      errorMessage = Array.isArray(result) ? result.join("\n") : result;
    }
    element.setCustomValidity(errorMessage);
    const nextState = getState(element);
    let validationErrors = [];
    if (Array.isArray(result)) {
      validationErrors = result;
    } else if (result) {
      validationErrors = [result];
    } else if (element.validationMessage) {
      validationErrors = [element.validationMessage];
    }
    const nextValidityData = {
      value,
      state: nextState,
      error: Array.isArray(result) ? result[0] : result ?? element.validationMessage,
      errors: validationErrors,
      initialValue: validityData.initialValue
    };
    if (controlId) {
      const currentFieldData = formRef.current.fields.get(controlId);
      if (currentFieldData) {
        formRef.current.fields.set(controlId, {
          ...currentFieldData,
          ...getCombinedFieldValidityData(nextValidityData, invalid)
        });
      }
    }
    setValidityData(nextValidityData);
  });
  const getValidationProps = React.useCallback((externalProps = {}) => mergeProps({
    ...messageIds.length && {
      "aria-describedby": messageIds.join(" ")
    },
    ...state.valid === false && {
      "aria-invalid": true
    }
  }, externalProps), [messageIds, state.valid]);
  const getInputValidationProps = React.useCallback((externalProps = {}) => mergeProps({
    onChange(event) {
      if (event.nativeEvent.defaultPrevented) {
        return;
      }
      if (invalid || validationMode !== "onChange") {
        return;
      }
      const element = event.currentTarget;
      if (element.value === "") {
        commitValidation(element.value);
        return;
      }
      window.clearTimeout(timeoutRef.current);
      if (validationDebounceTime) {
        timeoutRef.current = window.setTimeout(() => {
          commitValidation(element.value);
        }, validationDebounceTime);
      } else {
        commitValidation(element.value);
      }
    }
  }, getValidationProps(externalProps)), [getValidationProps, invalid, validationMode, validationDebounceTime, commitValidation]);
  return React.useMemo(() => ({
    getValidationProps,
    getInputValidationProps,
    inputRef,
    commitValidation
  }), [getValidationProps, getInputValidationProps, commitValidation]);
}
const visuallyHidden = {
  clip: "rect(0 0 0 0)",
  overflow: "hidden",
  whiteSpace: "nowrap",
  position: "fixed",
  top: 0,
  left: 0,
  border: 0,
  padding: 0,
  width: 1,
  height: 1,
  margin: -1
};
const EMPTY_ARRAY = [];
function useSelectRoot(params) {
  const {
    id: idProp,
    disabled = false,
    readOnly = false,
    required = false,
    alignItemToTrigger: alignItemToTriggerParam = true,
    modal = false,
    onOpenChangeComplete
  } = params;
  const {
    setDirty,
    validityData,
    validationMode,
    setControlId,
    setFilled
  } = useFieldRootContext();
  const fieldControlValidation = useFieldControlValidation();
  const id = useBaseUiId(idProp);
  useEnhancedEffect(() => {
    setControlId(id);
    return () => {
      setControlId(void 0);
    };
  }, [id, setControlId]);
  const [value, setValueUnwrapped] = useControlled({
    controlled: params.value,
    default: params.defaultValue,
    name: "Select",
    state: "value"
  });
  const [open, setOpenUnwrapped] = useControlled({
    controlled: params.open,
    default: params.defaultOpen,
    name: "Select",
    state: "open"
  });
  useEnhancedEffect(() => {
    setFilled(value !== null);
  }, [setFilled, value]);
  const [controlledAlignItemToTrigger, setControlledAlignItemToTrigger] = React.useState(alignItemToTriggerParam);
  const listRef = React.useRef([]);
  const labelsRef = React.useRef([]);
  const popupRef = React.useRef(null);
  const valueRef = React.useRef(null);
  const valuesRef = React.useRef([]);
  const typingRef = React.useRef(false);
  const keyboardActiveRef = React.useRef(false);
  const selectedItemTextRef = React.useRef(null);
  const selectionRef = React.useRef({
    allowSelectedMouseUp: false,
    allowUnselectedMouseUp: false,
    allowSelect: false
  });
  const [triggerElement, setTriggerElement] = React.useState(null);
  const [positionerElement, setPositionerElement] = React.useState(null);
  const [activeIndex, setActiveIndex] = React.useState(null);
  const [selectedIndex, setSelectedIndex] = React.useState(null);
  const [label, setLabel] = React.useState("");
  const [touchModality, setTouchModality] = React.useState(false);
  const [scrollUpArrowVisible, setScrollUpArrowVisible] = React.useState(false);
  const [scrollDownArrowVisible, setScrollDownArrowVisible] = React.useState(false);
  const {
    mounted,
    setMounted,
    transitionStatus
  } = useTransitionStatus(open);
  const alignItemToTrigger = Boolean(mounted && controlledAlignItemToTrigger && !touchModality);
  if (!mounted && controlledAlignItemToTrigger !== alignItemToTriggerParam) {
    setControlledAlignItemToTrigger(alignItemToTriggerParam);
  }
  if (!alignItemToTriggerParam || !mounted) {
    if (scrollUpArrowVisible) {
      setScrollUpArrowVisible(false);
    }
    if (scrollDownArrowVisible) {
      setScrollDownArrowVisible(false);
    }
  }
  const setOpen = useEventCallback((nextOpen, event) => {
    params.onOpenChange?.(nextOpen, event);
    setOpenUnwrapped(nextOpen);
    if (!nextOpen && activeIndex !== null) {
      const activeOption = listRef.current[activeIndex];
      queueMicrotask(() => {
        activeOption?.setAttribute("tabindex", "-1");
      });
    }
  });
  const handleUnmount = useEventCallback(() => {
    setMounted(false);
    setActiveIndex(null);
    onOpenChangeComplete?.(false);
  });
  useOpenChangeComplete({
    enabled: !params.actionsRef,
    open,
    ref: popupRef,
    onComplete() {
      if (!open) {
        handleUnmount();
      }
    }
  });
  React.useImperativeHandle(params.actionsRef, () => ({
    unmount: handleUnmount
  }), [handleUnmount]);
  const setValue = useEventCallback((nextValue, event) => {
    params.onValueChange?.(nextValue, event);
    setValueUnwrapped(nextValue);
    setDirty(nextValue !== validityData.initialValue);
    if (validationMode === "onChange") {
      fieldControlValidation.commitValidation(nextValue);
    }
    const index = valuesRef.current.indexOf(nextValue);
    setSelectedIndex(index);
    setLabel(labelsRef.current[index] ?? "");
  });
  const hasRegisteredRef = React.useRef(false);
  const registerSelectedItem = useEventCallback((suppliedIndex) => {
    if (suppliedIndex !== void 0) {
      hasRegisteredRef.current = true;
    }
    const stringValue = typeof value === "string" || value === null ? value : JSON.stringify(value);
    const index = suppliedIndex ?? valuesRef.current.indexOf(stringValue);
    const hasIndex = index !== -1;
    if (hasIndex || value === null) {
      if (hasIndex) {
        setSelectedIndex(index);
      }
      setLabel(hasIndex ? labelsRef.current[index] ?? "" : "");
    } else if (value) {
      warn(`The value \`${stringValue}\` is not present in the select items.`);
    }
  });
  useEnhancedEffect(() => {
    if (!hasRegisteredRef.current) {
      return;
    }
    registerSelectedItem(void 0);
  }, [value, registerSelectedItem]);
  const floatingRootContext = useFloatingRootContext({
    open,
    onOpenChange: setOpen,
    elements: {
      reference: triggerElement,
      floating: positionerElement
    }
  });
  const click = useClick(floatingRootContext, {
    enabled: !readOnly && !disabled,
    event: "mousedown"
  });
  const dismiss = useDismiss(floatingRootContext, {
    bubbles: false,
    outsidePressEvent: "mousedown"
  });
  const role = useRole(floatingRootContext, {
    role: "select"
  });
  const listNavigation = useListNavigation(floatingRootContext, {
    enabled: !readOnly && !disabled,
    listRef,
    activeIndex,
    selectedIndex,
    disabledIndices: EMPTY_ARRAY,
    onNavigate(nextActiveIndex) {
      if (nextActiveIndex === null && !open) {
        return;
      }
      setActiveIndex(nextActiveIndex);
    },
    // Implement our own listeners since `onPointerLeave` on each option fires while scrolling with
    // the `alignItemToTrigger` prop enabled, causing a performance issue on Chrome.
    focusItemOnHover: false
  });
  const typeahead = useTypeahead(floatingRootContext, {
    enabled: !readOnly && !disabled,
    listRef: labelsRef,
    activeIndex,
    selectedIndex,
    onMatch(index) {
      if (open) {
        setActiveIndex(index);
      } else {
        setValue(valuesRef.current[index]);
      }
    },
    onTypingChange(typing) {
      typingRef.current = typing;
    }
  });
  const {
    getReferenceProps: getRootTriggerProps,
    getFloatingProps: getRootPositionerProps,
    getItemProps
  } = useInteractions([click, dismiss, role, listNavigation, typeahead]);
  const rootContext = React.useMemo(() => ({
    id,
    name: params.name,
    required,
    disabled,
    readOnly,
    triggerElement,
    setTriggerElement,
    positionerElement,
    setPositionerElement,
    scrollUpArrowVisible,
    setScrollUpArrowVisible,
    scrollDownArrowVisible,
    setScrollDownArrowVisible,
    setControlledAlignItemToTrigger,
    value,
    setValue,
    open,
    setOpen,
    mounted,
    setMounted,
    label,
    setLabel,
    valueRef,
    valuesRef,
    labelsRef,
    typingRef,
    selectionRef,
    getRootPositionerProps,
    getRootTriggerProps,
    getItemProps,
    listRef,
    popupRef,
    selectedItemTextRef,
    floatingRootContext,
    touchModality,
    setTouchModality,
    alignItemToTrigger,
    transitionStatus,
    fieldControlValidation,
    modal,
    registerSelectedItem,
    onOpenChangeComplete,
    keyboardActiveRef
  }), [id, params.name, required, disabled, readOnly, triggerElement, positionerElement, scrollUpArrowVisible, scrollDownArrowVisible, value, setValue, open, setOpen, mounted, setMounted, label, getRootPositionerProps, getRootTriggerProps, getItemProps, floatingRootContext, touchModality, alignItemToTrigger, transitionStatus, fieldControlValidation, modal, registerSelectedItem, onOpenChangeComplete, keyboardActiveRef]);
  const indexContext = React.useMemo(() => ({
    activeIndex,
    setActiveIndex,
    selectedIndex,
    setSelectedIndex
  }), [activeIndex, selectedIndex, setActiveIndex]);
  return React.useMemo(() => ({
    rootContext,
    indexContext
  }), [rootContext, indexContext]);
}
const SelectRootContext = /* @__PURE__ */ React.createContext(null);
function useSelectRootContext() {
  const context = React.useContext(SelectRootContext);
  if (context === null) {
    throw new Error("useSelectRootContext must be used within a SelectRoot");
  }
  return context;
}
const SelectIndexContext = /* @__PURE__ */ React.createContext(void 0);
function useSelectIndexContext() {
  const context = React.useContext(SelectIndexContext);
  if (context === void 0) {
    throw new Error("Base UI: SelectIndexContext is missing. Select parts must be placed within <Select.Root>.");
  }
  return context;
}
const SelectRoot = function SelectRoot2(props) {
  const {
    value: valueProp,
    defaultValue = null,
    onValueChange,
    open,
    defaultOpen = false,
    onOpenChange,
    alignItemToTrigger = true,
    name,
    disabled = false,
    readOnly = false,
    required = false,
    modal = true,
    actionsRef,
    onOpenChangeComplete
  } = props;
  const selectRoot = useSelectRoot({
    value: valueProp,
    defaultValue,
    onValueChange,
    open,
    defaultOpen,
    onOpenChange,
    alignItemToTrigger,
    name,
    disabled,
    readOnly,
    required,
    modal,
    actionsRef,
    onOpenChangeComplete
  });
  const {
    setDirty,
    validityData,
    validationMode
  } = useFieldRootContext();
  const {
    rootContext
  } = selectRoot;
  const value = rootContext.value;
  const serializedValue = React.useMemo(() => {
    if (value == null) {
      return "";
    }
    if (typeof value === "string") {
      return value;
    }
    return JSON.stringify(value);
  }, [value]);
  return /* @__PURE__ */ jsx(SelectRootContext.Provider, {
    value: selectRoot.rootContext,
    children: /* @__PURE__ */ jsxs(SelectIndexContext.Provider, {
      value: selectRoot.indexContext,
      children: [props.children, /* @__PURE__ */ jsx("input", {
        ...rootContext.fieldControlValidation.getInputValidationProps({
          onFocus() {
            rootContext.triggerElement?.focus();
          },
          // Handle browser autofill.
          onChange(event) {
            if (event.nativeEvent.defaultPrevented) {
              return;
            }
            const nextValue = event.target.value;
            const exactValue = rootContext.valuesRef.current.find((v) => v === nextValue || typeof value === "string" && nextValue.toLowerCase() === v.toLowerCase());
            if (exactValue != null) {
              setDirty(exactValue !== validityData.initialValue);
              rootContext.setValue?.(exactValue, event.nativeEvent);
              if (validationMode === "onChange") {
                selectRoot.rootContext.fieldControlValidation.commitValidation(exactValue);
              }
            }
          },
          id: rootContext.id,
          name: rootContext.name,
          disabled: rootContext.disabled,
          required: rootContext.required,
          readOnly: rootContext.readOnly,
          value: serializedValue,
          ref: rootContext.fieldControlValidation.inputRef,
          style: visuallyHidden,
          tabIndex: -1,
          "aria-hidden": true
        })
      })]
    })
  });
};
process.env.NODE_ENV !== "production" ? SelectRoot.propTypes = {
  // ┌────────────────────────────── Warning ──────────────────────────────┐
  // │ These PropTypes are generated from the TypeScript type definitions. │
  // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │
  // └─────────────────────────────────────────────────────────────────────┘
  /**
   * A ref to imperative actions.
   */
  actionsRef: PropTypes.shape({
    current: PropTypes.shape({
      unmount: PropTypes.func.isRequired
    }).isRequired
  }),
  /**
   * Determines if the selected item inside the popup should align to the trigger element.
   * @default true
   */
  alignItemToTrigger: PropTypes.bool,
  /**
   * @ignore
   */
  children: PropTypes.node,
  /**
   * Whether the select menu is initially open.
   *
   * To render a controlled select menu, use the `open` prop instead.
   * @default false
   */
  defaultOpen: PropTypes.bool,
  /**
   * The uncontrolled value of the select when it’s initially rendered.
   *
   * To render a controlled select, use the `value` prop instead.
   * @default null
   */
  defaultValue: PropTypes.any,
  /**
   * Whether the component should ignore user interaction.
   * @default false
   */
  disabled: PropTypes.bool,
  /**
   * Whether the select should prevent outside clicks and lock page scroll when open.
   * @default true
   */
  modal: PropTypes.bool,
  /**
   * Identifies the field when a form is submitted.
   */
  name: PropTypes.string,
  /**
   * Event handler called when the select menu is opened or closed.
   */
  onOpenChange: PropTypes.func,
  /**
   * Event handler called after any animations complete when the select menu is opened or closed.
   */
  onOpenChangeComplete: PropTypes.func,
  /**
   * Callback fired when the value of the select changes. Use when controlled.
   */
  onValueChange: PropTypes.func,
  /**
   * Whether the select menu is currently open.
   */
  open: PropTypes.bool,
  /**
   * Whether the user should be unable to choose a different option from the select menu.
   * @default false
   */
  readOnly: PropTypes.bool,
  /**
   * Whether the user must choose a value before submitting a form.
   * @default false
   */
  required: PropTypes.bool,
  /**
   * The value of the select.
   */
  value: PropTypes.any
} : void 0;
function useSelectTrigger(parameters) {
  const BOUNDARY_OFFSET = 2;
  const {
    disabled = false,
    rootRef: externalRef
  } = parameters;
  const {
    open,
    setOpen,
    setTriggerElement,
    selectionRef,
    value,
    fieldControlValidation,
    setTouchModality,
    positionerElement,
    alignItemToTrigger,
    readOnly
  } = useSelectRootContext();
  const {
    labelId,
    setTouched,
    setFocused,
    validationMode
  } = useFieldRootContext();
  const triggerRef = React.useRef(null);
  const timeoutRef = React.useRef(-1);
  const mergedRef = useForkRef(externalRef, triggerRef);
  const {
    getButtonProps,
    buttonRef
  } = useButton({
    disabled,
    buttonRef: mergedRef
  });
  const handleRef = useForkRef(buttonRef, setTriggerElement);
  React.useEffect(() => {
    if (open) {
      const timeoutId1 = window.setTimeout(() => {
        selectionRef.current.allowSelectedMouseUp = true;
      }, 400);
      const timeoutId2 = window.setTimeout(() => {
        selectionRef.current.allowUnselectedMouseUp = true;
      }, 200);
      return () => {
        clearTimeout(timeoutId1);
        clearTimeout(timeoutId2);
      };
    }
    selectionRef.current = {
      allowSelectedMouseUp: false,
      allowUnselectedMouseUp: false,
      allowSelect: true
    };
    clearTimeout(timeoutRef.current);
    return void 0;
  }, [open, selectionRef]);
  const getTriggerProps = React.useCallback((externalProps) => {
    return mergeProps(
      {
        "aria-labelledby": labelId,
        "aria-readonly": readOnly || void 0,
        tabIndex: disabled ? -1 : 0,
        // this is needed to make the button focused after click in Safari
        ref: handleRef,
        onFocus() {
          setFocused(true);
          if (open && alignItemToTrigger) {
            setOpen(false);
          }
        },
        onBlur() {
          setTouched(true);
          setFocused(false);
          if (validationMode === "onBlur") {
            fieldControlValidation.commitValidation(value);
          }
        },
        onPointerMove({
          pointerType
        }) {
          setTouchModality(pointerType === "touch");
        },
        onPointerDown({
          pointerType
        }) {
          setTouchModality(pointerType === "touch");
        },
        onMouseDown(event) {
          if (open) {
            return;
          }
          const doc = ownerDocument(event.currentTarget);
          function handleMouseUp(mouseEvent) {
            if (!triggerRef.current) {
              return;
            }
            const mouseUpTarget = mouseEvent.target;
            if (contains(triggerRef.current, mouseUpTarget) || contains(positionerElement, mouseUpTarget) || mouseUpTarget === triggerRef.current) {
              return;
            }
            const bounds = getPseudoElementBounds(triggerRef.current);
            if (mouseEvent.clientX >= bounds.left - BOUNDARY_OFFSET && mouseEvent.clientX <= bounds.right + BOUNDARY_OFFSET && mouseEvent.clientY >= bounds.top - BOUNDARY_OFFSET && mouseEvent.clientY <= bounds.bottom + BOUNDARY_OFFSET) {
              return;
            }
            setOpen(false, mouseEvent);
          }
          timeoutRef.current = window.setTimeout(() => {
            doc.addEventListener("mouseup", handleMouseUp, {
              once: true
            });
          });
        }
      },
      fieldControlValidation.getValidationProps(externalProps),
      getButtonProps,
      // ensure nested useButton does not overwrite the combobox role:
      // <Toolbar.Button render={<Select.Trigger />} />
      {
        role: "combobox"
      }
    );
  }, [getButtonProps, fieldControlValidation, labelId, readOnly, disabled, handleRef, setFocused, open, alignItemToTrigger, setOpen, setTouched, setTouchModality, validationMode, value, positionerElement]);
  return React.useMemo(() => ({
    getTriggerProps,
    rootRef: handleRef
  }), [getTriggerProps, handleRef]);
}
const SelectTrigger = /* @__PURE__ */ React.forwardRef(function SelectTrigger2(props, forwardedRef) {
  const {
    render,
    className,
    disabled: disabledProp = false,
    ...otherProps
  } = props;
  const {
    state: fieldState,
    disabled: fieldDisabled
  } = useFieldRootContext();
  const {
    getRootTriggerProps,
    disabled: selectDisabled,
    mounted
  } = useSelectRootContext();
  const disabled = fieldDisabled || selectDisabled || disabledProp;
  const {
    getTriggerProps
  } = useSelectTrigger({
    disabled,
    rootRef: forwardedRef
  });
  const state = React.useMemo(() => ({
    ...fieldState,
    open: mounted,
    disabled
  }), [fieldState, mounted, disabled]);
  const styleHookMapping = React.useMemo(() => ({
    ...pressableTriggerOpenStateMapping,
    ...fieldValidityMapping
  }), []);
  const {
    renderElement
  } = useComponentRenderer({
    render: render ?? "div",
    className,
    state,
    propGetter: (externalProps) => getTriggerProps(getRootTriggerProps(externalProps)),
    customStyleHookMapping: styleHookMapping,
    extraProps: otherProps
  });
  return renderElement();
});
process.env.NODE_ENV !== "production" ? SelectTrigger.propTypes = {
  // ┌────────────────────────────── Warning ──────────────────────────────┐
  // │ These PropTypes are generated from the TypeScript type definitions. │
  // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │
  // └─────────────────────────────────────────────────────────────────────┘
  /**
   * @ignore
   */
  children: PropTypes.node,
  /**
   * CSS class applied to the element, or a function that
   * returns a class based on the component’s state.
   */
  className: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
  /**
   * Whether the component should ignore user interaction.
   * @default false
   */
  disabled: PropTypes.bool,
  /**
   * Allows you to replace the component’s HTML element
   * with a different tag, or compose it with another component.
   *
   * Accepts a `ReactElement` or a function that returns the element to render.
   */
  render: PropTypes.oneOfType([PropTypes.element, PropTypes.func])
} : void 0;
const SelectValue = /* @__PURE__ */ React.forwardRef(function SelectValue2(props, forwardedRef) {
  const {
    className,
    render,
    children,
    placeholder,
    ...otherProps
  } = props;
  const {
    value,
    label,
    valueRef
  } = useSelectRootContext();
  const mergedRef = useForkRef(forwardedRef, valueRef);
  const state = React.useMemo(() => ({}), []);
  const getValueProps = React.useCallback((externalProps = {}) => mergeProps({
    children: typeof children === "function" ? children(!label && placeholder ? placeholder : label, value) : label || placeholder
  }, externalProps), [children, label, placeholder, value]);
  const {
    renderElement
  } = useComponentRenderer({
    propGetter: getValueProps,
    render: render ?? "span",
    className,
    state,
    ref: mergedRef,
    extraProps: otherProps
  });
  return renderElement();
});
process.env.NODE_ENV !== "production" ? SelectValue.propTypes = {
  // ┌────────────────────────────── Warning ──────────────────────────────┐
  // │ These PropTypes are generated from the TypeScript type definitions. │
  // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │
  // └─────────────────────────────────────────────────────────────────────┘
  /**
   * @ignore
   */
  children: PropTypes.func,
  /**
   * CSS class applied to the element, or a function that
   * returns a class based on the component’s state.
   */
  className: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
  /**
   * A placeholder value to display when no value is selected.
   *
   * You can use this prop to pre-render the displayed text
   * during SSR in order to avoid the hydration flash.
   */
  placeholder: PropTypes.string,
  /**
   * Allows you to replace the component’s HTML element
   * with a different tag, or compose it with another component.
   *
   * Accepts a `ReactElement` or a function that returns the element to render.
   */
  render: PropTypes.oneOfType([PropTypes.element, PropTypes.func])
} : void 0;
const SelectIcon = /* @__PURE__ */ React.forwardRef(function SelectIcon2(props, forwardedRef) {
  const {
    className,
    render,
    ...otherProps
  } = props;
  const state = React.useMemo(() => ({}), []);
  const getIconProps = React.useCallback((externalProps) => {
    return mergeProps({
      "aria-hidden": true,
      children: "▼"
    }, externalProps);
  }, []);
  const {
    renderElement
  } = useComponentRenderer({
    propGetter: getIconProps,
    render: render ?? "span",
    ref: forwardedRef,
    className,
    state,
    extraProps: otherProps
  });
  return renderElement();
});
process.env.NODE_ENV !== "production" ? SelectIcon.propTypes = {
  // ┌────────────────────────────── Warning ──────────────────────────────┐
  // │ These PropTypes are generated from the TypeScript type definitions. │
  // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │
  // └─────────────────────────────────────────────────────────────────────┘
  /**
   * @ignore
   */
  children: PropTypes.node,
  /**
   * CSS class applied to the element, or a function that
   * returns a class based on the component’s state.
   */
  className: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
  /**
   * Allows you to replace the component’s HTML element
   * with a different tag, or compose it with another component.
   *
   * Accepts a `ReactElement` or a function that returns the element to render.
   */
  render: PropTypes.oneOfType([PropTypes.element, PropTypes.func])
} : void 0;
const SelectPortalContext = /* @__PURE__ */ React.createContext(void 0);
function SelectPortal(props) {
  const {
    children,
    container
  } = props;
  return /* @__PURE__ */ jsx(SelectPortalContext.Provider, {
    value: true,
    children: /* @__PURE__ */ jsx(FloatingPortal, {
      root: container,
      children
    })
  });
}
process.env.NODE_ENV !== "production" ? SelectPortal.propTypes = {
  // ┌────────────────────────────── Warning ──────────────────────────────┐
  // │ These PropTypes are generated from the TypeScript type definitions. │
  // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │
  // └─────────────────────────────────────────────────────────────────────┘
  /**
   * @ignore
   */
  children: PropTypes.node,
  /**
   * A parent element to render the portal element into.
   */
  container: PropTypes.oneOfType([HTMLElementType, refType])
} : void 0;
function useSelectPositioner(params) {
  const {
    open,
    alignItemToTrigger,
    mounted,
    triggerElement,
    modal
  } = useSelectRootContext();
  useScrollLock((alignItemToTrigger || modal) && open, triggerElement);
  const positioning = useAnchorPositioning({
    ...params,
    trackAnchor: params.trackAnchor ?? !alignItemToTrigger
  });
  const positionerStyles = React.useMemo(() => alignItemToTrigger ? {
    position: "fixed"
  } : positioning.positionerStyles, [alignItemToTrigger, positioning.positionerStyles]);
  const getPositionerProps = React.useCallback((externalProps = {}) => {
    const hiddenStyles = {};
    if (!open) {
      hiddenStyles.pointerEvents = "none";
    }
    return mergeProps({
      role: "presentation",
      hidden: !mounted,
      style: {
        ...positionerStyles,
        ...hiddenStyles
      }
    }, externalProps);
  }, [open, mounted, positionerStyles]);
  return React.useMemo(() => ({
    ...positioning,
    side: alignItemToTrigger ? "none" : positioning.side,
    getPositionerProps
  }), [alignItemToTrigger, getPositionerProps, positioning]);
}
const SelectPositionerContext = /* @__PURE__ */ React.createContext(null);
function useSelectPositionerContext() {
  const context = React.useContext(SelectPositionerContext);
  if (context === null) {
    throw new Error("Base UI: SelectPositionerContext is missing. SelectPositioner parts must be placed within <Select.Positioner>.");
  }
  return context;
}
var _InternalBackdrop;
const SelectPositioner = /* @__PURE__ */ React.forwardRef(function SelectPositioner2(props, ref) {
  const {
    anchor,
    positionMethod = "absolute",
    className,
    render,
    side = "bottom",
    align = "center",
    sideOffset = 0,
    alignOffset = 0,
    collisionBoundary = "clipping-ancestors",
    collisionPadding,
    arrowPadding = 5,
    sticky = false,
    trackAnchor = true,
    ...otherProps
  } = props;
  const {
    open,
    mounted,
    setPositionerElement,
    listRef,
    labelsRef,
    floatingRootContext,
    modal
  } = useSelectRootContext();
  const positioner = useSelectPositioner({
    anchor,
    floatingRootContext,
    positionMethod,
    mounted,
    side,
    sideOffset,
    align,
    alignOffset,
    arrowPadding,
    collisionBoundary,
    collisionPadding,
    sticky,
    trackAnchor,
    keepMounted: true
  });
  const mergedRef = useForkRef(ref, setPositionerElement);
  const state = React.useMemo(() => ({
    open,
    side: positioner.side,
    align: positioner.align,
    anchorHidden: positioner.anchorHidden
  }), [open, positioner.side, positioner.align, positioner.anchorHidden]);
  const {
    renderElement
  } = useComponentRenderer({
    propGetter: positioner.getPositionerProps,
    render: render ?? "div",
    ref: mergedRef,
    className,
    state,
    customStyleHookMapping: popupStateMapping,
    extraProps: otherProps
  });
  return /* @__PURE__ */ jsx(CompositeList, {
    elementsRef: listRef,
    labelsRef,
    children: /* @__PURE__ */ jsxs(SelectPositionerContext.Provider, {
      value: positioner,
      children: [mounted && modal && (_InternalBackdrop || (_InternalBackdrop = /* @__PURE__ */ jsx(InternalBackdrop, {}))), renderElement()]
    })
  });
});
process.env.NODE_ENV !== "production" ? SelectPositioner.propTypes = {
  // ┌────────────────────────────── Warning ──────────────────────────────┐
  // │ These PropTypes are generated from the TypeScript type definitions. │
  // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │
  // └─────────────────────────────────────────────────────────────────────┘
  /**
   * How to align the popup relative to the specified side.
   * @default 'center'
   */
  align: PropTypes.oneOf(["center", "end", "start"]),
  /**
   * Additional offset along the alignment axis in pixels.
   * Also accepts a function that returns the offset to read the dimensions of the anchor
   * and positioner elements, along with its side and alignment.
   *
   * - `data.anchor`: the dimensions of the anchor element with properties `width` and `height`.
   * - `data.positioner`: the dimensions of the positioner element with properties `width` and `height`.
   * - `data.side`: which side of the anchor element the positioner is aligned against.
   * - `data.align`: how the positioner is aligned relative to the specified side.
   * @default 0
   */
  alignOffset: PropTypes.oneOfType([PropTypes.func, PropTypes.number]),
  /**
   * An element to position the popup against.
   * By default, the popup will be positioned against the trigger.
   */
  anchor: PropTypes.oneOfType([HTMLElementType, refType, PropTypes.object, PropTypes.func]),
  /**
   * Minimum distance to maintain between the arrow and the edges of the popup.
   *
   * Use it to prevent the arrow element from hanging out of the rounded corners of a popup.
   * @default 5
   */
  arrowPadding: PropTypes.number,
  /**
   * @ignore
   */
  children: PropTypes.node,
  /**
   * CSS class applied to the element, or a function that
   * returns a class based on the component’s state.
   */
  className: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
  /**
   * An element or a rectangle that delimits the area that the popup is confined to.
   * @default 'clipping-ancestors'
   */
  collisionBoundary: PropTypes.oneOfType([HTMLElementType, PropTypes.arrayOf(HTMLElementType), PropTypes.string, PropTypes.shape({
    height: PropTypes.number,
    width: PropTypes.number,
    x: PropTypes.number,
    y: PropTypes.number
  })]),
  /**
   * Additional space to maintain from the edge of the collision boundary.
   * @default 5
   */
  collisionPadding: PropTypes.oneOfType([PropTypes.number, PropTypes.shape({
    bottom: PropTypes.number,
    left: PropTypes.number,
    right: PropTypes.number,
    top: PropTypes.number
  })]),
  /**
   * Determines which CSS `position` property to use.
   * @default 'absolute'
   */
  positionMethod: PropTypes.oneOf(["absolute", "fixed"]),
  /**
   * Allows you to replace the component’s HTML element
   * with a different tag, or compose it with another component.
   *
   * Accepts a `ReactElement` or a function that returns the element to render.
   */
  render: PropTypes.oneOfType([PropTypes.element, PropTypes.func]),
  /**
   * Which side of the anchor element to align the popup against.
   * May automatically change to avoid collisions.
   * @default 'bottom'
   */
  side: PropTypes.oneOf(["bottom", "inline-end", "inline-start", "left", "right", "top"]),
  /**
   * Distance between the anchor and the popup in pixels.
   * Also accepts a function that returns the distance to read the dimensions of the anchor
   * and positioner elements, along with its side and alignment.
   *
   * - `data.anchor`: the dimensions of the anchor element with properties `width` and `height`.
   * - `data.positioner`: the dimensions of the positioner element with properties `width` and `height`.
   * - `data.side`: which side of the anchor element the positioner is aligned against.
   * - `data.align`: how the positioner is aligned relative to the specified side.
   * @default 0
   */
  sideOffset: PropTypes.oneOfType([PropTypes.func, PropTypes.number]),
  /**
   * Whether to maintain the popup in the viewport after
   * the anchor element was scrolled out of view.
   * @default false
   */
  sticky: PropTypes.bool,
  /**
   * Whether the popup tracks any layout shift of its positioning anchor.
   * @default true
   */
  trackAnchor: PropTypes.bool
} : void 0;
function clearPositionerStyles(positionerElement, originalPositionerStyles) {
  Object.assign(positionerElement.style, originalPositionerStyles);
}
function useSelectPopup() {
  const {
    mounted,
    id,
    setOpen,
    getRootPositionerProps,
    alignItemToTrigger,
    triggerElement,
    positionerElement,
    valueRef,
    selectedItemTextRef,
    popupRef,
    scrollUpArrowVisible,
    scrollDownArrowVisible,
    setScrollUpArrowVisible,
    setScrollDownArrowVisible,
    setControlledAlignItemToTrigger,
    keyboardActiveRef
  } = useSelectRootContext();
  const initialHeightRef = React.useRef(0);
  const reachedMaxHeightRef = React.useRef(false);
  const maxHeightRef = React.useRef(0);
  const initialPlacedRef = React.useRef(false);
  const originalPositionerStylesRef = React.useRef({});
  const handleScrollArrowVisibility = useEventCallback(() => {
    if (!alignItemToTrigger || !popupRef.current) {
      return;
    }
    const isScrolledToTop = popupRef.current.scrollTop < 1;
    const isScrolledToBottom = popupRef.current.scrollTop + popupRef.current.clientHeight >= popupRef.current.scrollHeight - 1;
    if (scrollUpArrowVisible !== !isScrolledToTop) {
      setScrollUpArrowVisible(!isScrolledToTop);
    }
    if (scrollDownArrowVisible !== !isScrolledToBottom) {
      setScrollDownArrowVisible(!isScrolledToBottom);
    }
  });
  useEnhancedEffect(() => {
    if (alignItemToTrigger || !positionerElement || Object.keys(originalPositionerStylesRef.current).length) {
      return;
    }
    originalPositionerStylesRef.current = {
      top: positionerElement.style.top || "0",
      left: positionerElement.style.left || "0",
      right: positionerElement.style.right,
      height: positionerElement.style.height,
      bottom: positionerElement.style.bottom,
      minHeight: positionerElement.style.minHeight,
      maxHeight: positionerElement.style.maxHeight,
      marginTop: positionerElement.style.marginTop,
      marginBottom: positionerElement.style.marginBottom
    };
  }, [alignItemToTrigger, positionerElement]);
  useEnhancedEffect(() => {
    if (mounted || alignItemToTrigger) {
      return;
    }
    initialPlacedRef.current = false;
    reachedMaxHeightRef.current = false;
    initialHeightRef.current = 0;
    maxHeightRef.current = 0;
    if (positionerElement) {
      clearPositionerStyles(positionerElement, originalPositionerStylesRef.current);
    }
  }, [mounted, alignItemToTrigger, positionerElement]);
  useEnhancedEffect(() => {
    if (!mounted || !alignItemToTrigger || !triggerElement || !positionerElement || !popupRef.current) {
      return;
    }
    const positionerStyles = getComputedStyle(positionerElement);
    const popupStyles = getComputedStyle(popupRef.current);
    const doc = ownerDocument(triggerElement);
    const win = ownerWindow(positionerElement);
    const triggerRect = triggerElement.getBoundingClientRect();
    const positionerRect = positionerElement.getBoundingClientRect();
    const triggerX = triggerRect.left;
    const triggerHeight = triggerRect.height;
    const scrollHeight = popupRef.current.scrollHeight;
    const borderBottom = parseFloat(popupStyles.borderBottomWidth);
    const marginTop = parseFloat(positionerStyles.marginTop) || 10;
    const marginBottom = parseFloat(positionerStyles.marginBottom) || 10;
    const minHeight = parseFloat(positionerStyles.minHeight) || 100;
    const paddingLeft = 5;
    const paddingRight = 5;
    const triggerCollisionThreshold = 20;
    const viewportHeight = doc.documentElement.clientHeight - marginTop - marginBottom;
    const viewportWidth = doc.documentElement.clientWidth;
    const availableSpaceBeneathTrigger = viewportHeight - triggerRect.bottom + triggerHeight;
    const textElement = selectedItemTextRef.current;
    const valueElement = valueRef.current;
    let offsetX = 0;
    let offsetY = 0;
    if (textElement && valueElement) {
      const valueRect = valueElement.getBoundingClientRect();
      const textRect = textElement.getBoundingClientRect();
      const valueLeftFromTriggerLeft = valueRect.left - triggerX;
      const textLeftFromPositionerLeft = textRect.left - positionerRect.left;
      const valueCenterFromPositionerTop = valueRect.top - triggerRect.top + valueRect.height / 2;
      const textCenterFromTriggerTop = textRect.top - positionerRect.top + textRect.height / 2;
      offsetX = valueLeftFromTriggerLeft - textLeftFromPositionerLeft;
      offsetY = textCenterFromTriggerTop - valueCenterFromPositionerTop;
    }
    const idealHeight = availableSpaceBeneathTrigger + offsetY + marginBottom + borderBottom;
    let height = Math.min(viewportHeight, idealHeight);
    const maxHeight = viewportHeight - marginTop - marginBottom;
    const scrollTop = idealHeight - height;
    const left = Math.max(paddingLeft, triggerX + offsetX);
    const maxRight = viewportWidth - paddingRight;
    const rightOverflow = Math.max(0, left + positionerRect.width - maxRight);
    positionerElement.style.left = `${left - rightOverflow}px`;
    positionerElement.style.height = `${height}px`;
    positionerElement.style.maxHeight = "auto";
    positionerElement.style.marginTop = `${marginTop}px`;
    positionerElement.style.marginBottom = `${marginBottom}px`;
    const maxScrollTop = popupRef.current.scrollHeight - popupRef.current.clientHeight;
    const isTopPositioned = scrollTop >= maxScrollTop;
    if (isTopPositioned) {
      height = Math.min(viewportHeight, positionerRect.height) - (scrollTop - maxScrollTop);
    }
    const fallbackToAlignPopupToTrigger = triggerRect.top < triggerCollisionThreshold || triggerRect.bottom > viewportHeight - triggerCollisionThreshold || height < Math.min(scrollHeight, minHeight);
    const isPinchZoomed = (win.visualViewport?.scale ?? 1) !== 1 && isWebKit();
    if (fallbackToAlignPopupToTrigger || isPinchZoomed) {
      initialPlacedRef.current = true;
      clearPositionerStyles(positionerElement, originalPositionerStylesRef.current);
      setControlledAlignItemToTrigger(false);
      return;
    }
    if (isTopPositioned) {
      const topOffset = Math.max(0, viewportHeight - idealHeight);
      positionerElement.style.top = positionerRect.height >= maxHeight ? "0" : `${topOffset}px`;
      positionerElement.style.height = `${height}px`;
      popupRef.current.scrollTop = popupRef.current.scrollHeight - popupRef.current.clientHeight;
      initialHeightRef.current = Math.max(minHeight, height);
    } else {
      positionerElement.style.bottom = "0";
      initialHeightRef.current = Math.max(minHeight, height);
      popupRef.current.scrollTop = scrollTop;
    }
    if (initialHeightRef.current === viewportHeight) {
      reachedMaxHeightRef.current = true;
    }
    handleScrollArrowVisibility();
    setTimeout(() => {
      initialPlacedRef.current = true;
    });
  }, [mounted, alignItemToTrigger, positionerElement, triggerElement, valueRef, selectedItemTextRef, popupRef, setScrollUpArrowVisible, setScrollDownArrowVisible, handleScrollArrowVisibility, setControlledAlignItemToTrigger]);
  React.useEffect(() => {
    if (!alignItemToTrigger || !positionerElement || !mounted) {
      return void 0;
    }
    const win = ownerWindow(positionerElement);
    function handleResize() {
      setOpen(false);
    }
    win.addEventListener("resize", handleResize);
    return () => {
      win.removeEventListener("resize", handleResize);
    };
  }, [setOpen, alignItemToTrigger, positionerElement, mounted]);
  const getPopupProps = React.useCallback((externalProps = {}) => {
    return mergeProps({
      ["data-id"]: `${id}-popup`,
      onKeyDown() {
        keyboardActiveRef.current = true;
      },
      onMouseMove() {
        keyboardActiveRef.current = false;
      },
      onScroll(event) {
        if (!alignItemToTrigger || !positionerElement || !popupRef.current || !initialPlacedRef.current) {
          return;
        }
        if (reachedMaxHeightRef.current || !alignItemToTrigger) {
          handleScrollArrowVisibility();
          return;
        }
        const isTopPositioned = positionerElement.style.top === "0px";
        const isBottomPositioned = positionerElement.style.bottom === "0px";
        const currentHeight = positionerElement.getBoundingClientRect().height;
        const doc = ownerDocument(positionerElement);
        const positionerStyles = getComputedStyle(positionerElement);
        const marginTop = parseFloat(positionerStyles.marginTop);
        const marginBottom = parseFloat(positionerStyles.marginBottom);
        const viewportHeight = doc.documentElement.clientHeight - marginTop - marginBottom;
        if (isTopPositioned) {
          const scrollTop = event.currentTarget.scrollTop;
          const maxScrollTop = event.currentTarget.scrollHeight - event.currentTarget.clientHeight;
          const diff = maxScrollTop - scrollTop;
          const nextHeight = Math.min(currentHeight + diff, viewportHeight);
          positionerElement.style.height = `${Math.min(currentHeight + diff, viewportHeight)}px`;
          if (nextHeight !== viewportHeight) {
            event.currentTarget.scrollTop = maxScrollTop;
          } else {
            reachedMaxHeightRef.current = true;
          }
        } else if (isBottomPositioned) {
          const scrollTop = event.currentTarget.scrollTop;
          const minScrollTop = 0;
          const diff = scrollTop - minScrollTop;
          const nextHeight = Math.min(currentHeight + diff, viewportHeight);
          const idealHeight = currentHeight + diff;
          const overshoot = idealHeight - viewportHeight;
          positionerElement.style.height = `${Math.min(idealHeight, viewportHeight)}px`;
          if (nextHeight !== viewportHeight) {
            event.currentTarget.scrollTop = 0;
          } else {
            reachedMaxHeightRef.current = true;
            if (event.currentTarget.scrollTop < event.currentTarget.scrollHeight - event.currentTarget.clientHeight) {
              event.currentTarget.scrollTop -= diff - overshoot;
            }
          }
        }
        handleScrollArrowVisibility();
      },
      ...alignItemToTrigger && {
        style: {
          position: "relative",
          maxHeight: "100%",
          overflowX: "hidden",
          overflowY: "auto"
        }
      }
    }, getRootPositionerProps(externalProps));
  }, [id, alignItemToTrigger, getRootPositionerProps, keyboardActiveRef, positionerElement, popupRef, handleScrollArrowVisibility]);
  return React.useMemo(() => ({
    getPopupProps
  }), [getPopupProps]);
}
const customStyleHookMapping = {
  ...popupStateMapping,
  ...transitionStatusMapping
};
const SelectPopup = /* @__PURE__ */ React.forwardRef(function SelectPopup2(props, forwardedRef) {
  const {
    render,
    className,
    ...otherProps
  } = props;
  const {
    id,
    open,
    popupRef,
    transitionStatus,
    alignItemToTrigger,
    mounted,
    modal,
    onOpenChangeComplete
  } = useSelectRootContext();
  const positioner = useSelectPositionerContext();
  useOpenChangeComplete({
    open,
    ref: popupRef,
    onComplete() {
      if (open) {
        onOpenChangeComplete?.(true);
      }
    }
  });
  const {
    getPopupProps
  } = useSelectPopup();
  const mergedRef = useForkRef(forwardedRef, popupRef);
  const state = React.useMemo(() => ({
    open,
    transitionStatus,
    side: positioner.side,
    align: positioner.align
  }), [open, transitionStatus, positioner]);
  const {
    renderElement
  } = useComponentRenderer({
    propGetter: getPopupProps,
    render: render ?? "div",
    ref: mergedRef,
    className,
    state,
    customStyleHookMapping,
    extraProps: transitionStatus === "starting" ? mergeProps({
      style: {
        transition: "none"
      }
    }, otherProps) : otherProps
  });
  const popupSelector = `[data-id="${id}-popup"]`;
  const html = React.useMemo(() => ({
    __html: `${popupSelector}{scrollbar-width:none}${popupSelector}::-webkit-scrollbar{display:none}`
  }), [popupSelector]);
  return /* @__PURE__ */ jsxs(React.Fragment, {
    children: [id && alignItemToTrigger && /* @__PURE__ */ jsx("style", {
      // eslint-disable-next-line react/no-danger
      dangerouslySetInnerHTML: html
    }), /* @__PURE__ */ jsx(FloatingFocusManager, {
      context: positioner.context,
      modal: false,
      disabled: !mounted,
      visuallyHiddenDismiss: modal ? "Dismiss popup" : void 0,
      children: renderElement()
    })]
  });
});
process.env.NODE_ENV !== "production" ? SelectPopup.propTypes = {
  // ┌────────────────────────────── Warning ──────────────────────────────┐
  // │ These PropTypes are generated from the TypeScript type definitions. │
  // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │
  // └─────────────────────────────────────────────────────────────────────┘
  /**
   * @ignore
   */
  children: PropTypes.node,
  /**
   * CSS class applied to the element, or a function that
   * returns a class based on the component’s state.
   */
  className: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
  /**
   * @ignore
   */
  id: PropTypes.string,
  /**
   * Allows you to replace the component’s HTML element
   * with a different tag, or compose it with another component.
   *
   * Accepts a `ReactElement` or a function that returns the element to render.
   */
  render: PropTypes.oneOfType([PropTypes.element, PropTypes.func])
} : void 0;
function useSelectItem(params) {
  const {
    open,
    disabled = false,
    highlighted,
    selected,
    ref: externalRef,
    setOpen,
    typingRef,
    handleSelect,
    selectionRef,
    indexRef,
    setActiveIndex,
    popupRef,
    keyboardActiveRef
  } = params;
  const ref = React.useRef(null);
  const mergedRef = useForkRef(externalRef, ref);
  const {
    getButtonProps,
    buttonRef
  } = useButton({
    disabled,
    focusableWhenDisabled: true,
    buttonRef: mergedRef
  });
  const commitSelection = useEventCallback((event) => {
    handleSelect();
    setOpen(false, event);
  });
  const lastKeyRef = React.useRef(null);
  const pointerTypeRef = React.useRef("mouse");
  const prevPopupHeightRef = React.useRef(0);
  const allowFocusSyncRef = React.useRef(true);
  const getItemProps = React.useCallback((externalProps) => {
    return mergeProps({
      "aria-disabled": disabled || void 0,
      tabIndex: highlighted ? 0 : -1,
      onFocus() {
        if (allowFocusSyncRef.current) {
          setActiveIndex(indexRef.current);
        }
      },
      onMouseMove() {
        setActiveIndex(indexRef.current);
        if (popupRef.current) {
          prevPopupHeightRef.current = popupRef.current.offsetHeight;
        }
      },
      onMouseLeave(event) {
        const popup = popupRef.current;
        if (!popup || !open || keyboardActiveRef.current) {
          return;
        }
        const targetRect = event.currentTarget.getBoundingClientRect();
        const isWithinBounds = targetRect.top + 1 <= event.clientY && event.clientY <= targetRect.bottom - 1 && targetRect.left + 1 <= event.clientX && event.clientX <= targetRect.right - 1;
        if (isWithinBounds) {
          return;
        }
        if (popup.offsetHeight === prevPopupHeightRef.current) {
          allowFocusSyncRef.current = false;
          setActiveIndex(null);
          requestAnimationFrame(() => {
            popup.focus({
              preventScroll: true
            });
            allowFocusSyncRef.current = true;
          });
        }
      },
      onTouchStart() {
        selectionRef.current = {
          allowSelectedMouseUp: false,
          allowUnselectedMouseUp: false,
          allowSelect: true
        };
      },
      onKeyDown(event) {
        selectionRef.current.allowSelect = true;
        lastKeyRef.current = event.key;
      },
      onClick(event) {
        if (disabled || lastKeyRef.current === " " && typingRef.current || pointerTypeRef.current !== "touch" && !highlighted) {
          return;
        }
        if (selectionRef.current.allowSelect) {
          lastKeyRef.current = null;
          commitSelection(event.nativeEvent);
        }
      },
      onPointerEnter(event) {
        pointerTypeRef.current = event.pointerType;
      },
      onPointerDown(event) {
        pointerTypeRef.current = event.pointerType;
      },
      onMouseUp(event) {
        if (disabled) {
          return;
        }
        const disallowSelectedMouseUp = !selectionRef.current.allowSelectedMouseUp && selected;
        const disallowUnselectedMouseUp = !selectionRef.current.allowUnselectedMouseUp && !selected;
        if (disallowSelectedMouseUp || disallowUnselectedMouseUp || pointerTypeRef.current !== "touch" && !highlighted) {
          return;
        }
        if (selectionRef.current.allowSelect || !selected) {
          commitSelection(event.nativeEvent);
        }
        selectionRef.current.allowSelect = true;
      }
    }, externalProps, getButtonProps);
  }, [commitSelection, disabled, getButtonProps, highlighted, indexRef, keyboardActiveRef, open, popupRef, selected, selectionRef, setActiveIndex, typingRef]);
  return React.useMemo(() => ({
    getItemProps,
    rootRef: buttonRef
  }), [getItemProps, buttonRef]);
}
const SelectItemContext = /* @__PURE__ */ React.createContext(void 0);
function useSelectItemContext() {
  const context = React.useContext(SelectItemContext);
  if (context === void 0) {
    throw new Error("Base UI: SelectItemContext is missing. SelectItem parts must be placed within <Select.Item>.");
  }
  return context;
}
const InnerSelectItem = /* @__PURE__ */ React.forwardRef(function InnerSelectItem2(props, forwardedRef) {
  const {
    className,
    disabled = false,
    highlighted,
    selected,
    getRootItemProps,
    render,
    setOpen,
    typingRef,
    selectionRef,
    open,
    value,
    setValue,
    selectedIndexRef,
    indexRef,
    setActiveIndex,
    popupRef,
    keyboardActiveRef,
    ...otherProps
  } = props;
  const state = React.useMemo(() => ({
    disabled,
    open,
    highlighted,
    selected
  }), [disabled, open, highlighted, selected]);
  const {
    getItemProps,
    rootRef
  } = useSelectItem({
    open,
    setOpen,
    disabled,
    highlighted,
    selected,
    ref: forwardedRef,
    typingRef,
    handleSelect: () => setValue(value),
    selectionRef,
    selectedIndexRef,
    indexRef,
    setActiveIndex,
    popupRef,
    keyboardActiveRef
  });
  const mergedRef = useForkRef(rootRef, forwardedRef);
  const {
    renderElement
  } = useComponentRenderer({
    propGetter(externalProps = {}) {
      const rootProps = getRootItemProps({
        ...externalProps,
        active: highlighted,
        selected
      });
      delete rootProps.onFocus;
      return getItemProps(rootProps);
    },
    render: render ?? "div",
    ref: mergedRef,
    className,
    state,
    extraProps: otherProps
  });
  const contextValue = React.useMemo(() => ({
    selected,
    indexRef
  }), [selected, indexRef]);
  return /* @__PURE__ */ jsx(SelectItemContext.Provider, {
    value: contextValue,
    children: renderElement()
  });
});
process.env.NODE_ENV !== "production" ? InnerSelectItem.propTypes = {
  // ┌────────────────────────────── Warning ──────────────────────────────┐
  // │ These PropTypes are generated from the TypeScript type definitions. │
  // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │
  // └─────────────────────────────────────────────────────────────────────┘
  /**
   * @ignore
   */
  children: PropTypes.node,
  /**
   * CSS class applied to the element, or a function that
   * returns a class based on the component’s state.
   */
  className: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
  /**
   * Whether the component should ignore user interaction.
   * @default false
   */
  disabled: PropTypes.bool,
  /**
   * @ignore
   */
  getRootItemProps: PropTypes.func.isRequired,
  /**
   * @ignore
   */
  highlighted: PropTypes.bool.isRequired,
  /**
   * @ignore
   */
  indexRef: PropTypes.shape({
    current: PropTypes.number.isRequired
  }).isRequired,
  /**
   * @ignore
   */
  keyboardActiveRef: PropTypes.shape({
    current: PropTypes.bool.isRequired
  }).isRequired,
  /**
   * Overrides the text label to use on the trigger when this item is selected
   * and when the item is matched during keyboard text navigation.
   */
  label: PropTypes.string,
  /**
   * @ignore
   */
  open: PropTypes.bool.isRequired,
  /**
   * @ignore
   */
  popupRef: PropTypes.shape({
    current: PropTypes.object
  }).isRequired,
  /**
   * Allows you to replace the component’s HTML element
   * with a different tag, or compose it with another component.
   *
   * Accepts a `ReactElement` or a function that returns the element to render.
   */
  render: PropTypes.oneOfType([PropTypes.element, PropTypes.func]),
  /**
   * @ignore
   */
  selected: PropTypes.bool.isRequired,
  /**
   * @ignore
   */
  selectedIndexRef: PropTypes.shape({
    current: PropTypes.number
  }).isRequired,
  /**
   * @ignore
   */
  selectionRef: PropTypes.shape({
    current: PropTypes.shape({
      allowSelect: PropTypes.bool.isRequired,
      allowSelectedMouseUp: PropTypes.bool.isRequired,
      allowUnselectedMouseUp: PropTypes.bool.isRequired
    }).isRequired
  }).isRequired,
  /**
   * @ignore
   */
  setActiveIndex: PropTypes.func.isRequired,
  /**
   * @ignore
   */
  setOpen: PropTypes.func.isRequired,
  /**
   * @ignore
   */
  setValue: PropTypes.func.isRequired,
  /**
   * @ignore
   */
  typingRef: PropTypes.shape({
    current: PropTypes.bool.isRequired
  }).isRequired,
  /**
   * @ignore
   */
  value: PropTypes.any.isRequired
} : void 0;
const MemoizedInnerSelectItem = /* @__PURE__ */ React.memo(InnerSelectItem);
const SelectItem = /* @__PURE__ */ React.forwardRef(function SelectItem2(props, forwardedRef) {
  const {
    value: valueProp = null,
    label,
    ...otherProps
  } = props;
  const listItem = useCompositeListItem({
    label
  });
  const {
    activeIndex,
    selectedIndex,
    setActiveIndex
  } = useSelectIndexContext();
  const {
    getItemProps,
    setOpen,
    setValue,
    open,
    selectionRef,
    typingRef,
    valuesRef,
    popupRef,
    registerSelectedItem,
    value,
    keyboardActiveRef
  } = useSelectRootContext();
  const itemRef = React.useRef(null);
  const selectedIndexRef = useLatestRef(selectedIndex);
  const indexRef = useLatestRef(listItem.index);
  const mergedRef = useForkRef(listItem.ref, forwardedRef, itemRef);
  const hasRegistered = listItem.index !== -1;
  useEnhancedEffect(() => {
    if (!hasRegistered) {
      return void 0;
    }
    const values = valuesRef.current;
    values[listItem.index] = valueProp;
    return () => {
      delete values[listItem.index];
    };
  }, [hasRegistered, listItem.index, valueProp, valuesRef]);
  useEnhancedEffect(() => {
    if (hasRegistered && valueProp === value) {
      registerSelectedItem(listItem.index);
    }
  }, [hasRegistered, listItem.index, registerSelectedItem, valueProp, value]);
  const highlighted = activeIndex === listItem.index;
  const selected = selectedIndex === listItem.index;
  return /* @__PURE__ */ jsx(MemoizedInnerSelectItem, {
    ref: mergedRef,
    highlighted,
    selected,
    getRootItemProps: getItemProps,
    setOpen,
    open,
    selectionRef,
    typingRef,
    value: valueProp,
    setValue,
    selectedIndexRef,
    indexRef,
    setActiveIndex,
    popupRef,
    keyboardActiveRef,
    ...otherProps
  });
});
process.env.NODE_ENV !== "production" ? SelectItem.propTypes = {
  // ┌────────────────────────────── Warning ──────────────────────────────┐
  // │ These PropTypes are generated from the TypeScript type definitions. │
  // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │
  // └─────────────────────────────────────────────────────────────────────┘
  /**
   * @ignore
   */
  children: PropTypes.node,
  /**
   * CSS class applied to the element, or a function that
   * returns a class based on the component’s state.
   */
  className: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
  /**
   * Whether the component should ignore user interaction.
   * @default false
   */
  disabled: PropTypes.bool,
  /**
   * Overrides the text label to use on the trigger when this item is selected
   * and when the item is matched during keyboard text navigation.
   */
  label: PropTypes.string,
  /**
   * Allows you to replace the component’s HTML element
   * with a different tag, or compose it with another component.
   *
   * Accepts a `ReactElement` or a function that returns the element to render.
   */
  render: PropTypes.oneOfType([PropTypes.element, PropTypes.func]),
  /**
   * A unique value that identifies this select item.
   * @default null
   */
  value: PropTypes.any
} : void 0;
const SelectItemIndicator = /* @__PURE__ */ React.forwardRef(function SelectItemIndicator2(props, forwardedRef) {
  const {
    render,
    className,
    keepMounted = false,
    ...otherProps
  } = props;
  const {
    selected
  } = useSelectItemContext();
  const indicatorRef = React.useRef(null);
  const mergedRef = useForkRef(forwardedRef, indicatorRef);
  const {
    mounted,
    transitionStatus,
    setMounted
  } = useTransitionStatus(selected);
  const getItemProps = React.useCallback((externalProps = {}) => mergeProps({
    "aria-hidden": true,
    children: "✔️"
  }, externalProps), []);
  const state = React.useMemo(() => ({
    selected,
    transitionStatus
  }), [selected, transitionStatus]);
  const {
    renderElement
  } = useComponentRenderer({
    propGetter: getItemProps,
    render: render ?? "span",
    ref: mergedRef,
    className,
    state,
    extraProps: {
      hidden: !mounted,
      ...otherProps
    }
  });
  useOpenChangeComplete({
    open: selected,
    ref: indicatorRef,
    onComplete() {
      if (!selected) {
        setMounted(false);
      }
    }
  });
  const shouldRender = keepMounted || selected;
  if (!shouldRender) {
    return null;
  }
  return renderElement();
});
process.env.NODE_ENV !== "production" ? SelectItemIndicator.propTypes = {
  // ┌────────────────────────────── Warning ──────────────────────────────┐
  // │ These PropTypes are generated from the TypeScript type definitions. │
  // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │
  // └─────────────────────────────────────────────────────────────────────┘
  /**
   * @ignore
   */
  children: PropTypes.node,
  /**
   * CSS class applied to the element, or a function that
   * returns a class based on the component’s state.
   */
  className: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
  /**
   * Whether to keep the HTML element in the DOM when the item is not selected.
   * @default false
   */
  keepMounted: PropTypes.bool,
  /**
   * Allows you to replace the component’s HTML element
   * with a different tag, or compose it with another component.
   *
   * Accepts a `ReactElement` or a function that returns the element to render.
   */
  render: PropTypes.oneOfType([PropTypes.element, PropTypes.func])
} : void 0;
const InnerSelectItemText = /* @__PURE__ */ React.forwardRef(function InnerSelectItemText2(props, forwardedRef) {
  const {
    className,
    render,
    selected,
    selectedItemTextRef,
    indexRef,
    ...otherProps
  } = props;
  const mergedRef = useForkRef(forwardedRef);
  const state = React.useMemo(() => ({}), []);
  const ref = React.useCallback((node) => {
    if (mergedRef) {
      mergedRef(node);
    }
    queueMicrotask(() => {
      if (selected || selectedItemTextRef.current === null && indexRef.current === 0) {
        selectedItemTextRef.current = node;
      }
    });
  }, [mergedRef, selected, selectedItemTextRef, indexRef]);
  const {
    renderElement
  } = useComponentRenderer({
    ref,
    render: render ?? "div",
    className,
    state,
    extraProps: otherProps
  });
  return renderElement();
});
process.env.NODE_ENV !== "production" ? InnerSelectItemText.propTypes = {
  // ┌────────────────────────────── Warning ──────────────────────────────┐
  // │ These PropTypes are generated from the TypeScript type definitions. │
  // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │
  // └─────────────────────────────────────────────────────────────────────┘
  /**
   * @ignore
   */
  children: PropTypes.node,
  /**
   * CSS class applied to the element, or a function that
   * returns a class based on the component’s state.
   */
  className: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
  /**
   * @ignore
   */
  indexRef: PropTypes.shape({
    current: PropTypes.number.isRequired
  }).isRequired,
  /**
   * Allows you to replace the component’s HTML element
   * with a different tag, or compose it with another component.
   *
   * Accepts a `ReactElement` or a function that returns the element to render.
   */
  render: PropTypes.oneOfType([PropTypes.element, PropTypes.func]),
  /**
   * @ignore
   */
  selected: PropTypes.bool.isRequired,
  /**
   * @ignore
   */
  selectedItemTextRef: PropTypes.shape({
    current: (props, propName) => {
      if (props[propName] == null) {
        return null;
      }
      if (typeof props[propName] !== "object" || props[propName].nodeType !== 1) {
        return new Error(`Expected prop '${propName}' to be of type Element`);
      }
      return null;
    }
  }).isRequired
} : void 0;
const MemoizedInnerSelectItemText = /* @__PURE__ */ React.memo(InnerSelectItemText);
const SelectItemText = /* @__PURE__ */ React.forwardRef(function SelectItemText2(props, forwardedRef) {
  const {
    selected,
    indexRef
  } = useSelectItemContext();
  const {
    selectedItemTextRef
  } = useSelectRootContext();
  const mergedRef = useForkRef(forwardedRef);
  return /* @__PURE__ */ jsx(MemoizedInnerSelectItemText, {
    ref: mergedRef,
    selected,
    selectedItemTextRef,
    indexRef,
    ...props
  });
});
process.env.NODE_ENV !== "production" ? SelectItemText.propTypes = {
  // ┌────────────────────────────── Warning ──────────────────────────────┐
  // │ These PropTypes are generated from the TypeScript type definitions. │
  // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │
  // └─────────────────────────────────────────────────────────────────────┘
  /**
   * @ignore
   */
  children: PropTypes.node,
  /**
   * CSS class applied to the element, or a function that
   * returns a class based on the component’s state.
   */
  className: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
  /**
   * Allows you to replace the component’s HTML element
   * with a different tag, or compose it with another component.
   *
   * Accepts a `ReactElement` or a function that returns the element to render.
   */
  render: PropTypes.oneOfType([PropTypes.element, PropTypes.func])
} : void 0;
function Select({
  selected,
  onSelect,
  options,
  placeholder,
  triggerClassName,
  triggerValueClassName,
  triggerIconClassName,
  popupClassName,
  itemClassName,
  itemIndicatorClassName,
  itemTextClassName,
  ...props
}) {
  return /* @__PURE__ */ jsxs(
    SelectRoot,
    {
      value: selected?.value ?? null,
      onValueChange: (v) => {
        const opt = options.find((c) => c.value === v);
        if (!opt) return;
        onSelect(opt);
      },
      alignItemToTrigger: false,
      children: [
        /* @__PURE__ */ jsxs(SelectTrigger, { ...props, className: clsx("lng1771-select", triggerClassName), children: [
          /* @__PURE__ */ jsx(
            SelectValue,
            {
              className: clsx(
                "lng1771-select__value",
                !selected && "lng1771-select__value--no-value",
                triggerValueClassName
              ),
              placeholder
            }
          ),
          /* @__PURE__ */ jsx(SelectIcon, { className: clsx("lng1771-select__trigger", triggerIconClassName), children: /* @__PURE__ */ jsx(ArrowDownIcon, {}) })
        ] }),
        /* @__PURE__ */ jsx(SelectPortal, { children: /* @__PURE__ */ jsx(SelectPositioner, { sideOffset: 8, className: "lng1771-select__positioner", children: /* @__PURE__ */ jsx(SelectPopup, { className: clsx("lng1771-select__popup", popupClassName), children: options.map((c) => {
          return /* @__PURE__ */ jsxs(
            SelectItem,
            {
              value: c.value,
              className: clsx("lng1771-select__item", itemClassName),
              children: [
                /* @__PURE__ */ jsx(SelectItemText, { className: clsx("lng1771-select__item-text", itemIndicatorClassName), children: c.label }),
                /* @__PURE__ */ jsx(
                  SelectItemIndicator,
                  {
                    className: clsx("lng1771-select__item-indicator", itemTextClassName),
                    children: /* @__PURE__ */ jsx(CheckMark, {})
                  }
                )
              ]
            },
            c.value
          );
        }) }) }) })
      ]
    }
  );
}
export {
  Select as S
};