@use '../core/tokens/token-utils';
@use '../core/style/vendor-prefixes';
@use './m3-form-field';
@use './form-field-subscript';
@use './form-field-focus-overlay';
@use './form-field-high-contrast';
@use './form-field-native-select';
@use './user-agent-overrides';
@use './mdc-text-field-structure';
@use './mdc-text-field-textarea-overrides';
@use './mdc-text-field-structure-overrides';
@use './mdc-text-field-density-overrides';

$fallbacks: m3-form-field.get-tokens();

// Base styles for MDC text-field, notched-outline, floating label and line-ripple.
@include mdc-text-field-structure.private-text-field-structure();

// MDC text-field overwrites.
@include mdc-text-field-textarea-overrides.private-text-field-textarea-overrides();
@include mdc-text-field-structure-overrides.private-text-field-structure-overrides();
@include mdc-text-field-density-overrides.private-text-field-density-overrides();

// Include the subscript, focus-overlay, native select and high-contrast styles.
@include form-field-subscript.private-form-field-subscript();
@include form-field-focus-overlay.private-form-field-focus-overlay();
@include form-field-native-select.private-form-field-native-select();
@include form-field-high-contrast.private-form-field-high-contrast();
@include user-agent-overrides.private-form-field-user-agent-overrides();

// The amount of padding between the icon prefix/suffix and the infix.
// This assumes that the icon will be a 24px square with 12px padding.
$_icon-prefix-infix-padding: 4px;

// Host element of the form-field. It contains the mdc-text-field wrapper
// and the subscript wrapper.
.mat-mdc-form-field {
  // The scale to use for the form-field's label when its in the floating position.
  --mat-mdc-form-field-floating-label-scale: 0.75;

  display: inline-flex;
  // This container contains the text-field and the subscript. The subscript
  // should be displayed below the text-field. Hence the column direction.
  flex-direction: column;
  // This allows the form-field to shrink down when used inside flex or grid layouts.
  min-width: 0;
  // To avoid problems with text-align.
  text-align: left;

  @include vendor-prefixes.smooth-font();
  font-family: token-utils.slot(form-field-container-text-font, $fallbacks);
  line-height: token-utils.slot(form-field-container-text-line-height, $fallbacks);
  font-size: token-utils.slot(form-field-container-text-size, $fallbacks);
  letter-spacing: token-utils.slot(form-field-container-text-tracking, $fallbacks);
  font-weight: token-utils.slot(form-field-container-text-weight, $fallbacks);

  .mdc-text-field--outlined {
    $token-value: token-utils.slot(form-field-outlined-label-text-populated-size, $fallbacks);

    // For the non-upgraded notch label (i.e. when rendered on the server), also
    // use the correct typography.
    .mdc-floating-label--float-above {
      font-size: calc(#{$token-value} * var(--mat-mdc-form-field-floating-label-scale));
    }

    .mdc-notched-outline--upgraded .mdc-floating-label--float-above {
      font-size: $token-value;
    }
  }

  [dir='rtl'] & {
    text-align: right;
  }
}

// Container that contains the prefixes, infix and suffixes. These elements should
// be aligned vertically in the baseline and in a single row.
.mat-mdc-form-field-flex {
  display: inline-flex;
  align-items: baseline;
  box-sizing: border-box;
  width: 100%;
}

.mat-mdc-text-field-wrapper {
  // The MDC text-field should stretch to the width of the host `<mat-form-field>` element.
  // This allows developers to control the width without needing custom CSS overrides.
  width: 100%;
  // Avoids stacking issues due to the absolutely-positioned
  // descendants of the form field (see #28708)
  z-index: 0;
}

.mat-mdc-form-field-icon-prefix,
.mat-mdc-form-field-icon-suffix {
  // Vertically center icons.
  align-self: center;
  // The line-height can cause the prefix/suffix container to be taller than the actual icons,
  // breaking the vertical centering. To prevent this we set the line-height to 0.
  line-height: 0;
  // MDC applies `pointer-events: none` to the `.mdc-text-field--disabled`. This breaks clicking on
  // prefix and suffix buttons, so we override `pointer-events` to always allow clicking.
  pointer-events: auto;
  // Needs a z-index to ensure it's on top of other clickable content. See #27043.
  position: relative;
  z-index: 1;

  & > .mat-icon {
    padding: 0 12px;
    // It's common for apps to apply `box-sizing: border-box`
    // globally which will break the alignment.
    box-sizing: content-box;
  }
}

.mat-mdc-form-field-icon-prefix {
  color: token-utils.slot(form-field-leading-icon-color, $fallbacks);

  .mat-form-field-disabled & {
    color: token-utils.slot(form-field-disabled-leading-icon-color, $fallbacks);
  }
}

.mat-mdc-form-field-icon-suffix {
  color: token-utils.slot(form-field-trailing-icon-color, $fallbacks);

  .mat-form-field-disabled & {
    color: token-utils.slot(form-field-disabled-trailing-icon-color, $fallbacks);
  }

  .mat-form-field-invalid & {
    color: token-utils.slot(form-field-error-trailing-icon-color, $fallbacks);
  }

  .mat-form-field-invalid:not(.mat-focused):not(.mat-form-field-disabled)
    .mat-mdc-text-field-wrapper:hover & {
    color: token-utils.slot(form-field-error-hover-trailing-icon-color, $fallbacks);
  }

  .mat-form-field-invalid.mat-focused .mat-mdc-text-field-wrapper & {
    color: token-utils.slot(form-field-error-focus-trailing-icon-color, $fallbacks);
  }
}

// The prefix/suffix needs a little extra padding between the icon and the infix. Because we need to
// support arbitrary height input elements, we use a different DOM structure for prefix and suffix
// icons, and therefore can't rely on MDC for these styles.
.mat-mdc-form-field-icon-prefix,
[dir='rtl'] .mat-mdc-form-field-icon-suffix {
  padding: 0 $_icon-prefix-infix-padding 0 0;
}
.mat-mdc-form-field-icon-suffix,
[dir='rtl'] .mat-mdc-form-field-icon-prefix {
  padding: 0 0 0 $_icon-prefix-infix-padding;
}

// Scale down icons in the subscript and floating label to be the same size
// as the text.
.mat-mdc-form-field-subscript-wrapper,
.mat-mdc-form-field label {
  .mat-icon {
    width: 1em;
    height: 1em;
    font-size: inherit;
  }
}

// Infix that contains the projected content (usually an input or a textarea). We ensure
// that the projected form-field control and content can stretch as needed, but we also
// apply a default infix width to make the form-field's look natural.
.mat-mdc-form-field-infix {
  flex: auto;
  min-width: 0;

  // Infix stretches to fit the container, but naturally wants to be this wide. We set
  // this in order to have a consistent natural size for the various types of controls
  // that can go in a form field.
  width: 180px;

  // Needed so that the floating label does not overlap with prefixes or suffixes.
  position: relative;
  box-sizing: border-box;

  // We do not want to set fixed width on textarea with cols attribute as it makes different
  // columns look same width.
  &:has(textarea[cols]) {
    width: auto;
  }
}

// In the form-field theme, we add a 1px left margin to the notch to fix a rendering bug in Chrome.
// Here we apply negative margin to offset the effect on the layout and a clip-path to ensure the
// left border is completely hidden. (Though the border is transparent, it still creates a triangle
// shaped artifact where it meets the top and bottom borders.)
.mat-mdc-form-field .mdc-notched-outline__notch {
  margin-left: -1px;
  @include vendor-prefixes.clip-path(inset(-9em -999em -9em 1px));

  [dir='rtl'] & {
    margin-left: 0;
    margin-right: -1px;
    @include vendor-prefixes.clip-path(inset(-9em 1px -9em -999em));
  }
}

// In order to make it possible for developers to disable animations for form-fields,
// we only activate the animation styles if animations are not explicitly disabled.
.mat-mdc-form-field.mat-form-field-animations-enabled {
  @include mdc-text-field-structure.private-text-field-animations;
}

// Allow the label to grow 1px bigger than the notch.
// If we see this actually happen we know we need to resize the notch.
.mdc-notched-outline .mdc-floating-label {
  max-width: calc(100% + 1px);
}
.mdc-notched-outline--upgraded .mdc-floating-label--float-above {
  max-width: calc(100% * 4 / 3 + 1px);
}
