// Copyright (c) 2014, 2025, Oracle and/or its affiliates.  Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/


//------------------------------------------------------------------------------------------------
// Some mixins for *-label-inline and *-labels-inline
//------------------------------------------------------------------------------------------------
@import "../../utilities/oj.utilities";

// This inline label mixin is applied to the odd elements
@mixin oj-inline-label-support-odd($selectorPrefix, 
                               $labelInlineMarginTop: $formLayoutLabelInlineMarginTop, 
                               $labelInlineGutter: $formControlLabelInlineGutter, 
                               $labelInlineAlign: $formLayoutLabelInlineAlign, 
                               $fieldInlineAlign: $formLayoutFieldInlineAlign)
{
  // we're using width of 100% and so on for the case where 
  // the label-nowrap classes are used.
  // See the form layout demo titled "label wrapping" 
  // before checking the values in here
  width: 100%;
  box-sizing: border-box;
  overflow: hidden;
  text-overflow: ellipsis;



    @include oj-bidi-property($property: 'text-align', 
                              $startOrEnd: $labelInlineAlign);

}

// This inline label mixin is applied to the all elements
@mixin oj-inline-label-support-all($selectorPrefix, 
                               $labelInlineMarginTop: $formLayoutLabelInlineMarginTop, 
                               $labelInlineGutter: $formControlLabelInlineGutter, 
                               $labelInlineAlign: $formLayoutLabelInlineAlign, 
                               $fieldInlineAlign: $formLayoutFieldInlineAlign)
{
  display: inline-block;
  vertical-align: top;

    margin-top: $labelInlineMarginTop;

  // box sizing required for firefox or the
  // gutter padding  doesn't work
  box-sizing: border-box;



    @include oj-ltr {
      padding-right: $labelInlineGutter; 
    }

    @include oj-rtl(){
      padding-left: $labelInlineGutter;
    }

}

// when we don't float, then the order of the dom is the order of what
// you see, so we want spacing after the icons, not before.
@mixin oj-inline-label-support-non-float-spacing()
{

    @include oj-ltr {
      margin-left: 0;
      margin-right: 6px;
    }
    @include oj-rtl(){
      margin-right: 0;
      margin-left: 6px;
    }

}

// TODO: This function seems totally bogus.  How can stripping the units and checking the value
// be correct here?
@mixin oj-inline-label-support-radio-checkbox()
{

    @if (oj-strip-unit($radioCheckboxRowHeight) > 2.6) {
      // radioset/checkboxset are inline-top aligned, but they need to be
      // a couple pixels higher than other input components to have the label
      // line up with the first radio's label
      margin-top: $radioCheckboxRowHeight/5;
    } @else {
      // radioset/checkboxset's inline main label needs slightly different alignment
      // than the other form controls to line up with the first radio's label.
      // a couple pixels higher than other input components to have the label
      // line up with the first radio's label
      margin-top: $radioCheckboxRowHeight/10;
    }

  margin-bottom: 0;
}

// This is for cases where there are label modifiers (required, etc), in which case
// the properties below need to be inherited by oj-label-group
// otherwise the ellipsis doesn't show when the label-nowrap classes are used.
// See the form layout demo titled "label wrapping" 
// before checking the values in here
// line-height is needed so that the label has enough height to show borders.
// line-height on label itself has no effect.
@mixin oj-inline-label-support-with-modifiers()
{
  width: inherit;
  overflow: inherit;
  text-overflow: inherit;
  line-height: 1.6em;
}

//-------------------------------------------------------------------------------------------------
// Create common form layout classes that are used by css and element form layout
//
//-------------------------------------------------------------------------------------------------
@mixin oj-form-layout-common($selectorPrefix, 
                             $labelInlineMarginTop: $formLayoutLabelInlineMarginTop, 
                             $labelInlineGutter: $formControlLabelInlineGutter, 
                             $labelInlineAlign: $formLayoutLabelInlineAlign, 
                             $fieldInlineAlign: $formLayoutFieldInlineAlign)
{
  // nowrap label support
  .oj-form > .oj-flex > .oj-flex-item > .#{$selectorPrefix}-label-nowrap,
  .#{$selectorPrefix}-labels-nowrap > .oj-flex > .oj-flex-item > .oj-label,
  .#{$selectorPrefix}-labels-nowrap > .oj-flex > .oj-flex-item > .oj-formlayout-inline-label > .oj-label,
  .#{$selectorPrefix}-labels-nowrap > .oj-flex > .oj-flex-item > .oj-label-nocomp,
  .#{$selectorPrefix}-labels-nowrap > .oj-flex > .oj-flex-item > .oj-label-value .oj-label {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  // inline label suport
  .#{$selectorPrefix}-labels-inline > .oj-flex > .oj-flex-item > .oj-label,
  .oj-formlayout-inline-label > .oj-label,
  .#{$selectorPrefix}-labels-inline > .oj-flex > .oj-flex-item > .oj-label-nocomp,
  .oj-formlayout-inline-label > .oj-label-nocomp {
    @include oj-inline-label-support-odd($selectorPrefix, 
                                         $labelInlineMarginTop, 
                                         $labelInlineGutter, 
                                         $labelInlineAlign, 
                                         $fieldInlineAlign);
  }

  // inline field suport
  .oj-formlayout-inline-value {

      @include oj-bidi-property($property: 'text-align', 
                                $startOrEnd: $fieldInlineAlign);

  }

  // without this, the required icon is chopped off at top in Chrome.
  .#{$selectorPrefix}-labels-inline > .oj-flex > .oj-flex-item:nth-child(odd) .oj-label-required-icon,
  .#{$selectorPrefix}-labels-inline > .oj-form > .oj-flex > .oj-flex-item:nth-child(odd) .oj-label-required-icon {
    margin-top: 1px;
  }

  // when labels are inline we don't float. 
  .#{$selectorPrefix}-labels-inline > .oj-flex > .oj-flex-item:nth-child(odd) .oj-label-required-icon,
  .#{$selectorPrefix}-labels-inline > .oj-form > .oj-flex > .oj-flex-item:nth-child(odd) .oj-label-required-icon,
  .#{$selectorPrefix}-labels-inline > .oj-flex > .oj-flex-item:nth-child(odd) .oj-label-help-icon,
  .#{$selectorPrefix}-labels-inline > .oj-form > .oj-flex > .oj-flex-item:nth-child(odd) .oj-label-help-icon,
  .#{$selectorPrefix}-labels-inline > .oj-flex > .oj-flex-item:nth-child(odd) label,
  .#{$selectorPrefix}-labels-inline > .oj-form > .oj-flex > .oj-flex-item:nth-child(odd) label,
  .#{$selectorPrefix}-labels-inline > .oj-flex > .oj-flex-item:nth-child(odd) .oj-label-help-icon-anchor,
  .#{$selectorPrefix}-labels-inline > .oj-form > .oj-flex > .oj-flex-item:nth-child(odd) .oj-label-help-icon-anchor {
     float:none; 
  }
  
  // when labels are inline we don't float so we need to add spacing. 
  .#{$selectorPrefix}-labels-inline > .oj-flex > .oj-flex-item:nth-child(odd) .oj-label-required-icon,
  .#{$selectorPrefix}-labels-inline > .oj-form > .oj-flex > .oj-flex-item:nth-child(odd) .oj-label-required-icon,
  .#{$selectorPrefix}-labels-inline > .oj-flex > .oj-flex-item:nth-child(odd) .oj-label-help-icon,
  .#{$selectorPrefix}-labels-inline > .oj-form > .oj-flex > .oj-flex-item:nth-child(odd) .oj-label-help-icon {
    @include oj-inline-label-support-non-float-spacing();
  }
  
  .#{$selectorPrefix}-labels-inline > .oj-flex > .oj-flex-item > .oj-label,
  .oj-formlayout-inline-label > .oj-label,
  .#{$selectorPrefix}-labels-inline > .oj-flex > .oj-flex-item > .oj-label-nocomp,
  .oj-formlayout-inline-label > .oj-label-nocomp {
    @include oj-inline-label-support-all($selectorPrefix, 
                                         $labelInlineMarginTop, 
                                         $labelInlineGutter, 
                                         $labelInlineAlign, 
                                         $fieldInlineAlign);
  }
  
  // when the label should be top aligned
  .#{$selectorPrefix}-labels-inline > .oj-flex > .oj-flex-item > .oj-label-inline-top,
  .oj-formlayout-inline-label > .oj-label-inline-top,
  .#{$selectorPrefix}-labels-inline > .oj-flex > .oj-flex-item > .oj-label-nocomp.oj-label-for-non-control,
  .oj-formlayout-inline-label > .oj-label-nocomp.oj-label-for-non-control {
    margin-top: 0;
  }

  .#{$selectorPrefix}-labels-inline > .oj-flex > .oj-flex-item > .oj-radioset-label,
  .oj-formlayout-inline-label > .oj-radioset-label,
  .#{$selectorPrefix}-labels-inline > .oj-flex > .oj-flex-item > .oj-checkboxset-label,
  .oj-flformlayoutex-inline-label > .oj-checkboxset-label {
    @include oj-inline-label-support-radio-checkbox();
  }
  
  // This is for cases where there are label modifiers (required, etc), in which case
  // the properties below need to be inherited by oj-label-group
  // otherwise the ellipsis doesn't show when the label-nowrap classes are used.
  // See the form layout demo titled "label wrapping" 
  // before checking the values in here
  // line-height is needed so that the label has enough height to show borders.
  // line-height on label itself has no effect.
  .oj-form > .oj-flex > .oj-flex-item > .#{$selectorPrefix}-label-nowrap  .oj-label-group,
  .#{$selectorPrefix}-labels-nowrap > .oj-flex > .oj-flex-item > .oj-label  .oj-label-group,
  .#{$selectorPrefix}-labels-nowrap > .oj-flex > .oj-flex-item > .oj-formlayout-inline-label > .oj-label  .oj-label-group {
    width: inherit;
    overflow: inherit;
    text-overflow: inherit;
  }
  
  .#{$selectorPrefix}-labels-inline > .oj-flex > .oj-flex-item > .oj-label .oj-label-group,
  .oj-formlayout-inline-label > .oj-label .oj-label-group {
    @include oj-inline-label-support-with-modifiers();
  }

  // if it's a no component label and it's for a form control* set the line height so things
  // match exactly. we put line-height on component labels to line things up and to give room
  // for the required and help icons.
  // *(inline label in a oj-flex > .oj-flex-item; we do not float, thus we need line-height
  // to maintain label's height.
  .#{$selectorPrefix}-labels-inline > .oj-flex > .oj-flex-item:nth-child(odd) > 
    .oj-label-nocomp:not(.oj-label-for-non-control) {
    line-height: 1.6em;
  }

  // For alta/redwood
  .#{$selectorPrefix}-form-across > .oj-flex > .oj-flex-item:first-child {

    @include oj-ltr {
      padding-left: 0;
    }
    @include oj-rtl(){
      padding-right: 0;
    }

  }

  .#{$selectorPrefix}-form-across > .oj-flex > .oj-flex-item:last-child {

    @include oj-ltr {
      padding-right: 0;
    }
    @include oj-rtl(){
      padding-left: 0;
    }

  }
  // For the form across, we need to remove the left/right padding from the .oj-flex div as the padding is
  // on the even/odd .oj-flex-item divs (see above)
  .oj-form.#{$selectorPrefix}-form-across > .oj-flex {
    padding-left: 0;
    padding-right: 0;
  }
  // For some reason, iOS theme applies padding to the .oj-form, so we need to undo that for the across case
  // here so that we can specify the .#{$selectorPrefix}-form-across class
  .oj-form.#{$selectorPrefix}-form-across {
    @include oj-ltr()
    {
      padding-left: 0;
    }
    @include oj-rtl()
    {
      padding-right: 0;
    }
  }
  .oj-form.#{$selectorPrefix}-form-across > .oj-flex {
    @include oj-ltr()
    {
      padding-right: 0;
    }
    @include oj-rtl()
    {
      padding-left: 0;
    }
  }

}

//-------------------------------------------------------------------------------------------------
// Create css only form layout classes, example call is 
//      @include oj-form-responsive("oj-sm");
// 
// $selectorPrefix: prefix to use for label classes, for example "oj-sm"
//-------------------------------------------------------------------------------------------------
@mixin oj-form-responsive($selectorPrefix, 
                          $labelInlineMarginTop: $formLayoutLabelInlineMarginTop, 
                          $labelInlineGutter: $formControlLabelInlineGutter, 
                          $labelInlineAlign: $formLayoutLabelInlineAlign, 
                          $fieldInlineAlign: $formLayoutFieldInlineAlign)
{
  // include the common mixins that are shared between the css and element approaches
  @include oj-form-layout-common($selectorPrefix, $labelInlineMarginTop, 
                                 $labelInlineGutter, $labelInlineAlign,
                                 $fieldInlineAlign);

  // when there are multiple columns put a gutter between the columns
  .oj-form-layout:not(.#{$selectorPrefix}-only-flex-direction-column) > .oj-flex-item:not(:first-child) {
     // todo: temporarily using $labelInlineGutter

      @include oj-ltr {
        margin-left: $labelInlineGutter;
      }
      @include oj-rtl(){
        margin-right: $labelInlineGutter;
      }

  }

  // declare the *-label-inline selector for inline label support
  .oj-form > .oj-flex > .oj-flex-item:nth-child(odd) > .#{$selectorPrefix}-label-inline {
    @include oj-inline-label-support-odd($selectorPrefix, 
                                         $labelInlineMarginTop, 
                                         $labelInlineGutter, 
                                         $labelInlineAlign, 
                                         $fieldInlineAlign)
  }

  // without this, the required icon is chopped off at top in Chrome. 
  .#{$selectorPrefix}-label-inline .oj-label-required-icon {
     margin-top: 1px;
  }

  // when labels are inline we don't float. 
  .#{$selectorPrefix}-label-inline .oj-label-required-icon,
  .#{$selectorPrefix}-label-inline .oj-label-help-icon,
  .#{$selectorPrefix}-label-inline.oj-label label,
  .#{$selectorPrefix}-label-inline .oj-label-help-icon-anchor {
     float:none; 
  }
  
  // when labels are inline we don't float so we need to add spacing. 
  .#{$selectorPrefix}-label-inline .oj-label-required-icon,
  .#{$selectorPrefix}-label-inline .oj-label-help-icon {
     @include oj-inline-label-support-non-float-spacing();
  }

  .#{$selectorPrefix}-label-inline.oj-label {
    @include oj-inline-label-support-all($selectorPrefix, 
                                         $labelInlineMarginTop, 
                                         $labelInlineGutter, 
                                         $labelInlineAlign, 
                                         $fieldInlineAlign);
  }

  // when the label should be top aligned
  .#{$selectorPrefix}-label-inline.oj-label-inline-top,
  .#{$selectorPrefix}-label-inline.oj-label-nocomp.oj-label-for-non-control {
    margin-top: 0;
  }

  .#{$selectorPrefix}-label-inline.oj-radioset-label,
  .#{$selectorPrefix}-label-inline.oj-checkboxset-label {
    @include oj-inline-label-support-radio-checkbox();
  }
  
  .oj-form > .oj-flex > .oj-flex-item:nth-child(odd) > .#{$selectorPrefix}-label-inline .oj-label-group {
    @include oj-inline-label-support-with-modifiers();
  }

  // when labels are inline we don't float. we need this selector to be more specific than the
  // .oj-label label selector in common.formcontrol.label.scss which has rtl/ltr, otherwise
  // we get that float:right if we have .oj-md-labels-inline on the label in rtl mode.
  .#{$selectorPrefix}-label-inline.oj-label label {

      @include oj-ltr {
        float: none;
      }
      @include oj-rtl(){
        float: none;
      }

  }
}

// changes for when the column drops to one column
@mixin oj-form-columns($selectorPrefix, 
                       $labelInlineGutter: $formControlLabelInlineGutter)
{
  .oj-form-layout.#{$selectorPrefix}-flex-direction-column > .oj-flex-item:not(:last-child) > .oj-form > .oj-flex:last-child {

    // when there is only one column add back the divider except on the last form
      @if $formLayoutDividerColor != null and $formLayoutDividerColor != transparent {
        border-width: 0 0 1px 0;
      }
      @else {
        border-width: 0 0 0 0;
      }

  }
}

// Css FormLayout utility selectors
@mixin common-formlayout-selectors() {
  // Since these are actual selectors in this mixin, we only want to add them once
  @include module-include-once("common.formlayout.selectors") {
    // The technique used in these column classes use css multi column layout.
    // http://dev.w3.org/csswg/css-multicol/ 
    // With this layout the columns should automatically be 
    // approximately the same heights.
    .oj-form-cols-labels-inline { 

        column-width: $formLayoutLabelsInlineColumnWidth;
        column-gap: $formLayoutLabelsInlineColumnGap;

    }

    .oj-form-cols { 

        column-width: $formLayoutColumnWidth;
        column-gap: $formLayoutColumnGap;

    }

    // if columns attribute is specified, we want the exact number of columns specified
    // so we need to remove the minimum column width setting.
    .oj-form-layout-no-min-column-width .oj-form-cols,
    .oj-form-layout-no-min-column-width .oj-form-cols-labels-inline {
      column-width: auto;
    }

    // set the max number of columns to 2
    .oj-form-cols-max2 { 
      column-count: 2;
    } 

    // without controlling breaking then in some cases a label will 
    // show up in the first column but its associated field will show 
    // up in the second column.
    .oj-form-cols > .oj-flex,
    .oj-form-cols-labels-inline > .oj-flex,
    .oj-form-cols > .oj-flex > .oj-flex-item,
    .oj-form-cols-labels-inline > .oj-flex > .oj-flex-item { 

     // -moz-column-break-inside doesn't work on FF 24 on windows
     // try adding page-break-inside as well
     -moz-column-break-inside: avoid;
      -ms-column-break-inside: avoid;
                 break-inside: avoid;
      page-break-inside: avoid; 
    } 

    // Due to a difference of implementation with Safari and how they deal with
    // fragmentainers that aren't direct children of the multi-column layout element,
    // this work around was found to work with Safari and not cause any issues with
    // other browsers. See JET-42692
    // I'm limiting this to direction="column" and column="1" to minimize any
    // potential regression, but I think it is very unlikely to cause any issues.
    // Due to a change in Chrome 98 (see bug JET-49143), we need to make these specific only to
    // the affected browsers.  Firefox needs both work arounds, Safari just needs this one.
   .oj-agent-browser-safari .oj-formlayout-max-cols-1 > .oj-form:not(.oj-formlayout-form-across),
    .oj-agent-browser-firefox .oj-formlayout-max-cols-1 > .oj-form:not(.oj-formlayout-form-across) {
      display: inline;
    }
    // Unfortunately, the safari work around does nothing to help Firefox and this fix
    // can't be limited to one column but is limited to direction="column". See JET-42692
    .oj-agent-browser-firefox .oj-form-layout > .oj-form:not(.oj-formlayout-form-across) > .oj-flex {
      display: inline;
    }

    // headers inside a form layout have different margins than regular headers
    .oj-form > hr,
    .oj-form > h1,
    .oj-form > h2,
    .oj-form > h3,
    .oj-form > h4 {
      // the margins above and below are 15px, but there's
      // already the formlayout margin bottom above, so subtract that
      // from the top

        margin: calc(15px - #{$formLayoutMarginBottom}) 0 15px 0;

    }


    //
    // Stacked (non-responsive) form layout
    //

    .oj-form > .oj-form-control,
    .oj-form > .oj-form-non-control {

        margin-bottom: $formLayoutMarginBottom;

    }

    // when a form is nested reset the text align to start, otherwise the field's
    // text-align property will be inherited
    .oj-form > .oj-flex > .oj-flex-item > .oj-form{

        @include oj-bidi-property(
           $property: 'text-align', 
           $startOrEnd: start);

    }


    // Originally the margin was on .oj-form .oj-flex. However there was a problem. 
    // In the "across" form layout there's 4 grid cells in a row. 
    // On large screens these 4 cells are all on one line. 
    // But on medium screens the first 2 cells stay on the 
    // first line and the second 2 cells wrap to a new line 
    // to create a second "row". However there's no actual row 
    // class in this case, so the margins need to be on the field columns.
    //
    // The :last-child is to handle cases where there is a colspan
    // across all the cells.
    //
    // See the form layout demo titled "inline responsive across" 
    // before checking in any changes to where the margin is placed.
    //
    // For the nested form layout case, the padding is coming from the form layout and is not
    // possible to remove due to column direction case, so we don't want the margin applied here
    // for that case.
    .oj-form > .oj-flex > .oj-flex-item:not(.oj-formlayout-nested-formlayout):not(.oj-formlayout-nested-labelvalue) {
      padding: 0 0 calc(#{$formLayoutMarginBottom} - #{$wrappableMarginBottom}) 0;
    }

    // oj-label-value still has an oj-label in its own div, which should never have a margin bottom
    // For oj-label-value, the first-child is the label and the last-child is the value
    .oj-form.oj-label-value>.oj-flex>.oj-flex-item:first-child {
      margin: 0;
    }

    .oj-form > .oj-flex > .oj-flex-item > .oj-form-non-control {
        margin-bottom: $wrappableMarginBottom;
    }



    // borders around the form

      @if $formLayoutBorderColor != null and $formLayoutBorderColor != transparent {
        .oj-form-layout {
          border-color: $formLayoutBorderColor;
          border-style: solid;
          border-width: 1px 0 0;
        }

        // we really don't want nested form layouts to have a border as it looks funky
        .oj-flex-item.oj-formlayout-nested-formlayout > .oj-form-layout {
          border-width: 0;
        }

        .oj-form-layout-inset {
          // todo: use vars from Amy's padding classes?
          margin: 12px;
          border-width: 1px;
        }
      }
      @else {
        .oj-form-layout {
          border-color: transparent;
          border-style: solid;
          border-width: 0 0 0;
        }

        .oj-form-layout-inset {
          // todo: use vars from Amy's padding classes?
          margin: 0;
          border-width: 0;
        }
      }


    // dividers between rows
  
      @if  $formLayoutDividerColor != null and $formLayoutDividerColor != transparent {
        .oj-form > .oj-flex {
          border-style: solid;
          border-color: $formLayoutDividerColor;
          border-width: 0 0 1px 0;
          padding: $formLayoutMarginBottom 0 0;
        }

        // for nested form-layout, we don't want the margin onthe first .oj-flex
        .oj-flex-item.oj-formlayout-nested-formlayout > .oj-form-layout > .oj-form > .oj-flex {
          padding: 0;
        }

        // Ideally when you have multiple columns there wouldn't be 
        // divider under the last item in each column. However
        // on layouts using the css multi column layout we don't know
        // when there's multiple columns, so we need to put a border
        // on the last item, otherwise when there's multiple columns the 
        // first column has a divider on the bottom, but the second column doesn't.
        .oj-form-layout > .oj-form[class*="oj-form-cols-"] > .oj-flex:last-child {
          border-width: 0 0 1px 0;
        }
      }
      @else {
        .oj-form > .oj-flex {
          border-style: solid;
          border-color: transparent;
          border-width: 0 0 0 0;
          padding: 0 0 0;
        }

        .oj-form-layout > .oj-form[class*="oj-form-cols-"] > .oj-flex:last-child {
          border-width: 0 0 0 0;
        }
      }


    // no border on the last row
    .oj-form > .oj-flex:last-child{
      border-width: 0;
    }
  }
}