Repository: nextui-org/nextui
File: packages/components/input/src/use-input.ts (TypeScript)

Code before:

  const {focusProps: clearFocusProps, isFocusVisible: isClearButtonFocusVisible} = useFocusRing();

  const {focusWithinProps} = useFocusWithin({
    onFocusWithinChange: setFocusWithin,
  });

  const {pressProps: clearPressProps} = usePress({
    isDisabled: !!originalProps?.isDisabled || !!originalProps?.isReadOnly,
    onPress: handleClear,
  });

  const isInvalid = validationState === "invalid" || isAriaInvalid;

  /**
   * Following code is not used because adding 'outside-top' to
   * 'use-label-placement' hook breaks other component.
   *  Folowing code is replaced with the old way of computing
   * 'labelPlacement' for 'input' component.
   *
   *  const labelPlacement = useLabelPlacement({
   *       labelPlacement: originalProps.labelPlacement,
   *       label,
   *     });
   */

  const labelPlacement = useMemo<InputVariantProps["labelPlacement"]>(() => {
    if (isFileTypeInput) {
      // if `labelPlacement` is not defined, choose `outside` instead
      // since the default value `inside` is not supported in file input
      if (!originalProps.labelPlacement) return "outside";
      // throw a warning if `labelPlacement` is `inside`
      // and change it to `outside`
      if (originalProps.labelPlacement === "inside") {
        warn("Input with file type doesn't support inside label. Converting to outside ...");

        return "outside";
      }
    }
    if ((!originalProps.labelPlacement || originalProps.labelPlacement === "inside") && !label) {
      return "outside";
    }

    return originalProps.labelPlacement ?? "inside";
  }, [originalProps.labelPlacement, label]);

  const errorMessage =
    typeof props.errorMessage === "function"
      ? props.errorMessage({isInvalid, validationErrors, validationDetails})
      : props.errorMessage || validationErrors?.join(" ");
  const isClearable = !!onClear || originalProps.isClearable;

Review comment (suggestion):
```ts
// TODO: not using useLabelPlacement because `outside-top` doesn't support in other components.
```

Code after:
  const {isHovered, hoverProps} = useHover({isDisabled: !!originalProps?.isDisabled});

  const {isHovered: isLabelHovered, hoverProps: labelHoverProps} = useHover({
    isDisabled: !!originalProps?.isDisabled,
  });

  const {focusProps: clearFocusProps, isFocusVisible: isClearButtonFocusVisible} = useFocusRing();

  const {focusWithinProps} = useFocusWithin({
    onFocusWithinChange: setFocusWithin,
  });

  const {pressProps: clearPressProps} = usePress({
    isDisabled: !!originalProps?.isDisabled || !!originalProps?.isReadOnly,
    onPress: handleClear,
  });

  const isInvalid = validationState === "invalid" || isAriaInvalid;

  const labelPlacement = useInputLabelPlacement({
    labelPlacement: originalProps.labelPlacement,
    label,
  });

  const errorMessage =
    typeof props.errorMessage === "function"
      ? props.errorMessage({isInvalid, validationErrors, validationDetails})
      : props.errorMessage || validationErrors?.join(" ");
  const isClearable = !!onClear || originalProps.isClearable;
  const hasElements = !!label || !!description || !!errorMessage;
  const hasPlaceholder = !!props.placeholder;
  const hasLabel = !!label;
  const hasHelper = !!description || !!errorMessage;
  const isOutsideLeft = labelPlacement === "outside-left";
  const isOutsideTop = labelPlacement === "outside-top";

  const shouldLabelBeOutside =
    // label is outside only when some placeholder is there
    labelPlacement === "outside" ||
    // label is outside regardless of placeholder
    isOutsideLeft ||
    isOutsideTop;

  const shouldLabelBeInside = labelPlacement === "inside";
  const isPlaceholderShown = domRef.current
    ? (!domRef.current.value || domRef.current.value === "" || !inputValue || inputValue === "") &&
      hasPlaceholder
    : false;

  const hasStartContent = !!startContent;
  const isLabelOutside = shouldLabelBeOutside