/* stylelint-disable no-descending-specificity */
// vendor.scss v1.0 | @ajlkn | MIT licensed */

// Vars.

/// Vendor prefixes.
/// @var {list}
$vendor-prefixes: (
    '-moz-',
    '-webkit-',
    '-ms-',
    ''
);

/// Properties that should be vendorized.
/// Data via caniuse.com, github.com/postcss/autoprefixer, and developer.mozilla.org
/// @var {list}
$vendor-properties: (
    // Animation.
    'animation',
    'animation-delay',
    'animation-direction',
    'animation-duration',
    'animation-fill-mode',
    'animation-iteration-count',
    'animation-name',
    'animation-play-state',
    'animation-timing-function',
        // Appearance.
    'appearance',
        // Backdrop filter.
    'backdrop-filter',
        // Background image options.
    'background-clip',
    'background-origin',
    'background-size',
        // Box sizing.
    'box-sizing',
        // Clip path.
    'clip-path',
        // Filter effects.
    'filter',
        // Flexbox.
    'align-content',
    'align-items',
    'align-self',
    'flex',
    'flex-basis',
    'flex-direction',
    'flex-flow',
    'flex-grow',
    'flex-shrink',
    'flex-wrap',
    'justify-content',
    'order',
        // Font feature.
    'font-feature-settings',
    'font-language-override',
    'font-variant-ligatures',
        // Font kerning.
    'font-kerning',
        // Fragmented borders and backgrounds.
    'box-decoration-break',
        // Grid layout.
    'grid-column',
    'grid-column-align',
    'grid-column-end',
    'grid-column-start',
    'grid-row',
    'grid-row-align',
    'grid-row-end',
    'grid-row-start',
    'grid-template-columns',
    'grid-template-rows',
        // Hyphens.
    'hyphens',
    'word-break',
        // Masks.
    'mask',
    'mask-border',
    'mask-border-outset',
    'mask-border-repeat',
    'mask-border-slice',
    'mask-border-source',
    'mask-border-width',
    'mask-clip',
    'mask-composite',
    'mask-image',
    'mask-origin',
    'mask-position',
    'mask-repeat',
    'mask-size',
        // Multicolumn.
    'break-after',
    'break-before',
    'break-inside',
    'column-count',
    'column-fill',
    'column-gap',
    'column-rule',
    'column-rule-color',
    'column-rule-style',
    'column-rule-width',
    'column-span',
    'column-width',
    'columns',
        // Object fit.
    'object-fit',
    'object-position',
        // Regions.
    'flow-from',
    'flow-into',
    'region-fragment',
        // Scroll snap points.
    'scroll-snap-coordinate',
    'scroll-snap-destination',
    'scroll-snap-points-x',
    'scroll-snap-points-y',
    'scroll-snap-type',
        // Shapes.
    'shape-image-threshold',
    'shape-margin',
    'shape-outside',
        // Tab size.
    'tab-size',
        // Text align last.
    'text-align-last',
        // Text decoration.
    'text-decoration-color',
    'text-decoration-line',
    'text-decoration-skip',
    'text-decoration-style',
        // Text emphasis.
    'text-emphasis',
    'text-emphasis-color',
    'text-emphasis-position',
    'text-emphasis-style',
        // Text size adjust.
    'text-size-adjust',
        // Text spacing.
    'text-spacing',
        // Transform.
    'transform',
    'transform-origin',
        // Transform 3D.
    'backface-visibility',
    'perspective',
    'perspective-origin',
    'transform-style',
        // Transition.
    'transition',
    'transition-delay',
    'transition-duration',
    'transition-property',
    'transition-timing-function',
        // Unicode bidi.
    'unicode-bidi',
        // User select.
    'user-select',
        // Writing mode.
    'writing-mode',
);

/// Values that should be vendorized.
/// Data via caniuse.com, github.com/postcss/autoprefixer, and developer.mozilla.org
/// @var {list}
$vendor-values: (
    // Cross fade.
    'cross-fade',
        // Element function.
    'element',
        // Filter function.
    'filter',
        // Flexbox.
    'flex',
    'inline-flex',
        // Grab cursors.
    'grab',
    'grabbing',
        // Gradients.
    'linear-gradient',
    'repeating-linear-gradient',
    'radial-gradient',
    'repeating-radial-gradient',
        // Grid layout.
    'grid',
    'inline-grid',
        // Image set.
    'image-set',
        // Intrinsic width.
    'max-content',
    'min-content',
    'fit-content',
    'fill',
    'fill-available',
    'stretch',
        // Sticky position.
    'sticky',
        // Transform.
    'transform',
        // Zoom cursors.
    'zoom-in',
    'zoom-out',
);

// Functions.

/// Removes a specific item from a list.
/// @author Hugo Giraudel
/// @param {list} $list List.
/// @param {integer} $index Index.
/// @return {list} Updated list.
@function remove-nth($list, $index) {

    $result: null;

    @if type-of($index) != number {
        @warn "$index: #{quote($index)} is not a number for `remove-nth`.";
    } @else if $index == 0 {
        @warn "List index 0 must be a non-zero integer for `remove-nth`.";
    } @else if abs($index) > length($list) {
        @warn "List index is #{$index} but list is only #{length($list)} item long for `remove-nth`.";
    } @else {

        $result: ();
        $index: if($index < 0, length($list) + $index + 1, $index);

        @for $i from 1 through length($list) {

            @if $i != $index {
                $result: append($result, nth($list, $i));
            }

        }

    }

    @return $result;

}

/// Replaces a substring within another string.
/// @author Hugo Giraudel
/// @param {string} $string String.
/// @param {string} $search Substring.
/// @param {string} $replace Replacement.
/// @return {string} Updated string.
@function str-replace($string, $search, $replace: '') {

    $index: str-index($string, $search);

    @if $index {
        @return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
    }

    @return $string;

}

/// Replaces a substring within each string in a list.
/// @param {list} $strings List of strings.
/// @param {string} $search Substring.
/// @param {string} $replace Replacement.
/// @return {list} Updated list of strings.
@function str-replace-all($strings, $search, $replace: '') {

    @each $string in $strings {
        $strings: set-nth($strings, index($strings, $string), str-replace($string, $search, $replace));
    }

    @return $strings;

}

// Mixins.

/// Wraps @content in vendorized keyframe blocks.
/// @param {string} $name Name.
@mixin keyframes($name) {

    @-moz-keyframes #{$name} {
        @content;
    }
    @-webkit-keyframes #{$name} {
        @content;
    }
    @-ms-keyframes #{$name} {
        @content;
    }
    @keyframes #{$name} {
        @content;
    }

}

/// Vendorizes a declaration's property and/or value(s).
/// @param {string} $property Property.
/// @param {mixed} $value String/list of value(s).
@mixin vendor($property, $value) {

    // Determine if property should expand.
    $expandProperty: index($vendor-properties, $property);

    // Determine if value should expand (and if so, add '-prefix-' placeholder).
    $expandValue: false;

    @each $x in $value {
        @each $y in $vendor-values {
            @if $y == str-slice($x, 1, str-length($y)) {

                $value: set-nth($value, index($value, $x), '-prefix-' + $x);
                $expandValue: true;

            }
        }
    }

    // Expand property?
    @if $expandProperty {
        @each $vendor in $vendor-prefixes {
            #{$vendor}#{$property}: #{str-replace-all($value, '-prefix-', $vendor)};
        }
    }

        // Expand just the value?
    @else if $expandValue {
        @each $vendor in $vendor-prefixes {
            #{$property}: #{str-replace-all($value, '-prefix-', $vendor)};
        }
    }

        // Neither? Treat them as a normal declaration.
    @else {
        #{$property}: #{$value};
    }

}
