| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357 |
- //
- // Copyright 2017 Google Inc.
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to deal
- // in the Software without restriction, including without limitation the rights
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- // copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- // THE SOFTWARE.
- //
- @use 'sass:list';
- @use 'sass:meta';
- @use 'sass:selector';
- @use '@material/theme/gss';
- @use '@material/theme/selector-ext';
- @use '@material/theme/theme';
- $include: true !default;
- /// Creates a rule that will be applied when a component is within the context
- /// of an RTL layout.
- ///
- /// @example - scss
- /// .mdc-foo {
- /// padding-left: 4px;
- ///
- /// @include rtl {
- /// padding-left: auto;
- /// padding-right: 4px;
- /// }
- /// }
- ///
- /// @example - css
- /// .mdc-foo {
- /// padding-left: 4px;
- /// }
- ///
- /// [dir="rtl"] .mdc-foo,
- /// .mdc-foo[dir="rtl"] {
- /// padding-left: auto;
- /// padding-right: 4px;
- /// }
- ///
- /// Note that this mixin works by checking for an ancestor element with
- /// `[dir="rtl"]`. As a result, nested `dir` values are not supported:
- ///
- /// @example - html
- /// <html dir="rtl">
- /// <!-- ... -->
- /// <div dir="ltr">
- /// <div class="mdc-foo">Styled incorrectly as RTL!</div>
- /// </div>
- /// </html>
- ///
- /// In the future, selectors such as the `:dir` pseudo-class
- /// (http://mdn.io/css/:dir) will help us mitigate this.
- ///
- /// @content Content to be styled in an RTL context.
- @mixin rtl() {
- @if ($include) {
- $dir-rtl: '[dir=rtl]';
- $rtl-selectors: list.join(
- selector.nest($dir-rtl, &),
- selector-ext.append-strict(&, $dir-rtl)
- );
- @at-root {
- #{$rtl-selectors} {
- /*rtl:begin:ignore*/
- @content;
- /*rtl:end:ignore*/
- }
- }
- }
- }
- // Takes a base box-model property name (`margin`, `border`, `padding`, etc.) along with a
- // default direction (`left` or `right`) and value, and emits rules which apply the given value to the
- // specified direction by default and the opposite direction in RTL.
- //
- // For example:
- //
- // ```scss
- // .mdc-foo {
- // @include rtl-reflexive-box(margin, left, 8px);
- // }
- // ```
- //
- // is equivalent to:
- //
- // ```scss
- // .mdc-foo {
- // margin-left: 8px;
- // margin-right: 0;
- //
- // @include rtl {
- // margin-left: 0;
- // margin-right: 8px;
- // }
- // }
- // ```
- //
- // whereas:
- //
- // ```scss
- // .mdc-foo {
- // @include rtl-reflexive-box(margin, right, 8px);
- // }
- // ```
- //
- // is equivalent to:
- //
- // ```scss
- // .mdc-foo {
- // margin-left: 0;
- // margin-right: 8px;
- //
- // @include rtl {
- // margin-left: 8px;
- // margin-right: 0;
- // }
- // }
- // ```
- //
- // You can also pass an optional 4th `$root-selector` argument which will be forwarded to `mdc-rtl`,
- // e.g. `@include rtl-reflexive-box(margin, left, 8px, '.mdc-component')`.
- //
- // Note that this function will always zero out the original value in an RTL context.
- // If you're trying to flip the values, use `mdc-rtl-reflexive-property()` instead.
- @mixin reflexive-box(
- $base-property,
- $default-direction,
- $value,
- $replace: null
- ) {
- @if (list.index((right, left), $default-direction) == null) {
- @error "Invalid default direction: '#{$default-direction}'. Please specifiy either 'right' or 'left'.";
- }
- $left-value: $value;
- $right-value: 0;
- @if ($default-direction == right) {
- $left-value: 0;
- $right-value: $value;
- }
- @include reflexive-property(
- $base-property,
- $left-value,
- $right-value,
- $replace: $replace
- );
- }
- // Takes a base property and emits rules that assign <base-property>-left to <left-value> and
- // <base-property>-right to <right-value> in a LTR context, and vice versa in a RTL context.
- // For example:
- //
- // ```scss
- // .mdc-foo {
- // @include rtl-reflexive-property(margin, auto, 12px);
- // }
- // ```
- //
- // is equivalent to:
- //
- // ```scss
- // .mdc-foo {
- // margin-left: auto;
- // margin-right: 12px;
- //
- // @include rtl {
- // margin-left: 12px;
- // margin-right: auto;
- // }
- // }
- // ```
- //
- // An optional 4th `$root-selector` argument can be given, which will be passed to `mdc-rtl`.
- @mixin reflexive-property(
- $base-property,
- $left-value,
- $right-value,
- $replace: null
- ) {
- $prop-left: #{$base-property}-left;
- $prop-right: #{$base-property}-right;
- @include reflexive(
- $prop-left,
- $left-value,
- $prop-right,
- $right-value,
- $replace: $replace
- );
- }
- // Takes an argument specifying a horizontal position property (either 'left' or 'right') as well
- // as a value, and applies that value to the specified position in a LTR context, and flips it in a
- // RTL context. For example:
- //
- // ```scss
- // .mdc-foo {
- // @include rtl-reflexive-position(left, 0);
- // }
- // ```
- //
- // is equivalent to:
- //
- // ```scss
- // .mdc-foo {
- // left: 0;
- // right: initial;
- //
- // @include rtl {
- // left: initial;
- // right: 0;
- // }
- // }
- // ```
- //
- // An optional third $root-selector argument may also be given, which is passed to `mdc-rtl`.
- @mixin reflexive-position($position-property, $value, $replace: null) {
- @if (list.index((right, left), $position-property) == null) {
- @error "Invalid position #{position-property}. Please specifiy either right or left";
- }
- // TODO: 'initial' is not supported in IE 11. https://caniuse.com/#feat=css-initial-value
- $left-value: $value;
- $right-value: initial;
- @if ($position-property == right) {
- $right-value: $value;
- $left-value: initial;
- }
- @include reflexive(
- left,
- $left-value,
- right,
- $right-value,
- $replace: $replace
- );
- }
- // Takes pair of properties with values as arguments and flips it in RTL context.
- // For example:
- //
- // ```scss
- // .mdc-foo {
- // @include rtl-reflexive(left, 2px, right, 5px);
- // }
- // ```
- //
- // is equivalent to:
- //
- // ```scss
- // .mdc-foo {
- // left: 2px;
- // right: 5px;
- //
- // @include rtl {
- // right: 2px;
- // left: 5px;
- // }
- // }
- // ```
- //
- // An optional fifth `$root-selector` argument may also be given, which is passed to `mdc-rtl`.
- @mixin reflexive(
- $left-property,
- $left-value,
- $right-property,
- $right-value,
- $replace: null
- ) {
- $left-replace: null;
- $right-replace: null;
- @if $replace {
- @if meta.type-of($left-value) == 'string' {
- $left-replace: $replace;
- }
- @if meta.type-of($right-value) == 'string' {
- $right-replace: $replace;
- }
- @if $left-replace == null and $right-replace == null {
- @error 'mdc-rtl: $replace may only be used with strings but neither left nor right values are strings.';
- }
- // If any replacements are null, treat the entire value as null (do not
- // emit anything).
- @each $name, $replacement in $replace {
- @if $replacement == null {
- $left-value: null;
- $right-value: null;
- }
- }
- }
- // Do not emit if either value are null
- @if $left-value and $right-value {
- @include _property($left-property, $left-value, $replace: $left-replace);
- @include _property($right-property, $right-value, $replace: $right-replace);
- @include rtl {
- @include _property(
- $left-property,
- $right-value,
- $replace: $right-replace
- );
- @include _property($right-property, $left-value, $replace: $left-replace);
- }
- }
- }
- ///
- /// Adds RTL ignore annotation when `$mdc-rtl-include` is true.
- ///
- @mixin ignore-next-line() {
- @include gss.annotate(
- (
- noflip: $include,
- )
- );
- }
- ///
- /// Adds `@noflip` annotation when `$mdc-rtl-include` is true.
- ///
- /// @param {String} $property
- /// @param {String} $value
- /// @param {Map} $replace
- ///
- @mixin _property($property, $value, $replace: null) {
- @include theme.property(
- $property,
- $value,
- $replace: $replace,
- $gss: (noflip: $include)
- );
- }
|