import { clsx } from 'clsx';
import { useRef, useId, useState, useCallback } from 'react';
import { useIntl } from 'react-intl';
import Body from '../body/Body.mjs';
import '../common/theme.mjs';
import '../common/direction.mjs';
import '@transferwise/neptune-tokens';
import '../common/propsValues/control.mjs';
import '../common/propsValues/size.mjs';
import '../common/propsValues/typography.mjs';
import '../common/propsValues/width.mjs';
import '../common/propsValues/type.mjs';
import '../common/propsValues/dateMode.mjs';
import '../common/propsValues/monthFormat.mjs';
import '../common/propsValues/position.mjs';
import '../common/propsValues/layouts.mjs';
import '../common/propsValues/status.mjs';
import { Sentiment } from '../common/propsValues/sentiment.mjs';
import '../common/propsValues/profileType.mjs';
import '../common/propsValues/variant.mjs';
import '../common/propsValues/scroll.mjs';
import '../common/propsValues/markdownNodeType.mjs';
import '../common/fileType.mjs';
import '@transferwise/formatting';
import '@transferwise/icons';
import '../common/closeButton/CloseButton.messages.mjs';
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
import messages from './Field.messages.mjs';
import { InlinePrompt } from '../prompt/InlinePrompt/InlinePrompt.mjs';
import '../button/Button.resolver.mjs';
import '../prompt/PrimitivePrompt/PrimitivePrompt.mjs';
import '../badge/Badge.mjs';
import '@wise/art';
import '../statusIcon/StatusIcon.mjs';
import '@transferwise/neptune-validation';
import '../provider/direction/DirectionProvider.mjs';
import '../primitives/PrimitiveButton/PrimitiveButton.mjs';
import '../primitives/PrimitiveAnchor/PrimitiveAnchor.mjs';
import '../link/Link.messages.mjs';
import '../prompt/common/Expander/Expander.messages.mjs';
import { FieldLabelContextProvider, InputIdContextProvider, InputDescribedByProvider, InputInvalidProvider, TextareaCharacterCountProvider } from '../inputs/contexts.mjs';
import { Label as LabelNamespace } from '../label/Label.mjs';

const Field = ({
  id,
  label,
  required = true,
  message: propMessage,
  messageIconLabel,
  messageLoading,
  hint,
  description = hint,
  sentiment: propType = Sentiment.NEUTRAL,
  className,
  children,
  ...props
}) => {
  const {
    formatMessage
  } = useIntl();
  const labelRef = useRef(null);
  const sentiment = props.error ? Sentiment.NEGATIVE : propType;
  const message = propMessage || props.error;
  const hasError = sentiment === Sentiment.NEGATIVE;
  const labelId = useId();
  const fallbackInputId = useId();
  const inputId = id !== null ? id ?? fallbackInputId : undefined;
  const messageId = useId();
  const descriptionId = useId();
  const textareaCharCounterId = useId();
  const [textareaCharacterCount, setTextareaCharacterCount] = useState(null);
  const handleTextareaCharacterCount = useCallback(state => setTextareaCharacterCount(state), []);
  const isNearCharLimit = textareaCharacterCount != null && textareaCharacterCount.current >= textareaCharacterCount.max * 0.8;
  /**
   * form control can have multiple messages to describe it,
   * e.g the description underneath the label and inline alert
   */
  function ariaDescribedbyByIds() {
    const messageIds = [];
    if (description) {
      messageIds.push(descriptionId);
    }
    if (message) {
      messageIds.push(messageId);
    }
    if (textareaCharacterCount) {
      messageIds.push(textareaCharCounterId);
    }
    return messageIds.length > 0 ? messageIds.join(' ') : undefined;
  }
  return /*#__PURE__*/jsx(FieldLabelContextProvider, {
    value: {
      id: labelId,
      ref: labelRef
    },
    children: /*#__PURE__*/jsx(InputIdContextProvider, {
      value: inputId,
      children: /*#__PURE__*/jsx(InputDescribedByProvider, {
        value: ariaDescribedbyByIds(),
        children: /*#__PURE__*/jsx(InputInvalidProvider, {
          value: hasError,
          children: /*#__PURE__*/jsx(TextareaCharacterCountProvider, {
            value: handleTextareaCharacterCount,
            children: /*#__PURE__*/jsxs("div", {
              className: clsx('np-field form-group d-block', {
                'has-success': sentiment === Sentiment.POSITIVE,
                'has-warning': sentiment === Sentiment.WARNING,
                'has-error': hasError,
                'has-info': sentiment === Sentiment.NEUTRAL
              }, className),
              children: [label != null ? /*#__PURE__*/jsxs(Fragment, {
                children: [/*#__PURE__*/jsx(LabelNamespace, {
                  ref: labelRef,
                  id: labelId,
                  htmlFor: inputId,
                  children: required ? label : /*#__PURE__*/jsx(LabelNamespace.Optional, {
                    children: label
                  })
                }), /*#__PURE__*/jsx(LabelNamespace.Description, {
                  id: descriptionId,
                  children: description
                }), /*#__PURE__*/jsx("div", {
                  className: "np-field-control",
                  children: children
                })]
              }) : children, (message || textareaCharacterCount) && /*#__PURE__*/jsxs("div", {
                className: "np-field-validation",
                children: [message && /*#__PURE__*/jsx(InlinePrompt, {
                  sentiment: sentiment,
                  id: messageId,
                  mediaLabel: messageIconLabel,
                  className: "np-field__prompt",
                  loading: messageLoading,
                  width: "full",
                  children: message
                }), textareaCharacterCount && /*#__PURE__*/jsxs(Body, {
                  as: "span",
                  id: textareaCharCounterId,
                  ...(isNearCharLimit ? {
                    role: 'status',
                    'aria-live': 'polite',
                    'aria-atomic': 'true'
                  } : {}),
                  "aria-label": formatMessage(messages.characterCount, {
                    current: textareaCharacterCount.current,
                    max: textareaCharacterCount.max
                  }),
                  className: "np-field-textarea-char-counter",
                  children: [textareaCharacterCount.current, "/", textareaCharacterCount.max]
                })]
              })]
            })
          })
        })
      })
    })
  });
};

export { Field };
//# sourceMappingURL=Field.mjs.map
