// |------------------------------------------------------ // |------------------------------------------------------ // | Generate mixins // |------------------------------------------------------ // |------------------------------------------------------ /** * @name Generate mixins * This are all the mixins that you can use to generate classes to use inside your HTML codebase */ /** * Generate a custom class for all the states * @param {List} $pattern The name pattern of the class * @param {List} [$statesNames=null] The states names to generate. If null or all, will generate the class for all registered states * @example scss * \@include g-generate-custom-class(('my','-','cool','-','class','-','%state')) { * color: pink; * padding: g-get-state-var(gutter-left); * } * * @author Olivier Bossel */ @mixin g-custom-class( $pattern, $statesNames : null, $replacements... ) { // manage states to generate : $states : (); @if $statesNames == null or $statesNames == all { // loop on each states to generate names list : @each $stateName, $state in $_g-states { $states : append($states, $stateName); } } @else { $states : $statesNames; } // Get all pattern $unmatched_patterns : _g-unmatched-patterns($pattern); $matched_patterns : _g-matched-patterns($pattern); // Adjust the replacement list length to be the same as unmatched_patterns @while length( $unmatched_patterns ) != length( $replacements ) { @if length( $unmatched_patterns ) < length( $replacements ) { $replacements : list-pop($replacements); }@else{ $replacements : append($replacements, (null)); } } // for each valid pattern, get replacement list @each $index, $pattern in $matched_patterns { @if $pattern == "%state" { $matched_patterns : map-remove($matched_patterns, $index); }@else{ $replacements : append($replacements, _g-get-pattern-values(str-slice($pattern, 2))); } } $found_patterns : map-merge($unmatched_patterns, $matched_patterns); // loop on each states : @each $stateName in $states { // manage statename : @if type-of($stateName) != string { $stateName : map-get($stateName, name); } // classes : $classes : g-get-state-var(classes, $stateName); // genrate the classname : @if $classes { @include g-state($stateName, false) { $length_a:length($found_patterns); $length_b:length($replacements); @if $length_a > 0 and $length_a <= $length_b { $list_indexes : (); @for $i from 1 through $length_a { $list_indexes : append($list_indexes, 1); } @while nth($list_indexes, 1) <= length( nth($replacements, 1) ){ $g-scope : () !global; $replacement_pattern : $pattern; $replaced_count : 0; // Work the replacement @each $index, $flag in $found_patterns { $replaced_count : $replaced_count + 1; $current_replacement : nth( $replacements, $replaced_count ); $current_index : nth($list_indexes, $replaced_count); $replacement_pattern : set-nth( $replacement_pattern, $index, nth( $current_replacement, $current_index ) ); $var_name : str-slice($flag, 2); $g-scope : map-set( $g-scope, $var_name, nth( $current_replacement, $current_index ) ) !global; } #{_g-selector($replacement_pattern, $stateName)} { @content; } $g-scope : () !global; // Add 1 to indexes $break : false; $current_iteration_index : length( $list_indexes ); // The last index @while $break == false { $list_indexes : set-nth( $list_indexes, $current_iteration_index, nth( $list_indexes, $current_iteration_index ) + 1 ); @if nth( $list_indexes, $current_iteration_index ) > length( nth( $replacements, $current_iteration_index ) ) and $current_iteration_index != 1 { $list_indexes : set-nth( $list_indexes, $current_iteration_index, 1); $current_iteration_index : $current_iteration_index - 1; }@else{ $break : true; } } } }@else{ #{_g-selector($pattern, $stateName)} { @content; } } } } } } @mixin _g-generate-helper-classes ( $state : null, $package : null ) { // helpers : @if _g-need-to-generate(float, $package) { #{_g-selector(float, $state, left)} { @include g-float(left); } #{_g-selector(float, $state, right)} { @include g-float(right); } } @if _g-need-to-generate(clear, $package) { #{_g-selector(clear, $state)} { @include g-clear(both); } #{_g-selector(clear, $state, left)} { @include g-clear(left); } #{_g-selector(clear, $state, right)} { @include g-clear(right); } } @if _g-need-to-generate(auto-height, $package) { #{_g-selector(auto-height, $state)} { height:inherit; min-height:inherit; max-height:inherit; } } @if _g-need-to-generate(grid-centered, $package) { #{_g-selector(grid-centered, $state)} { @include g-grid-centered(); } } @if _g-need-to-generate(container, $package) { #{_g-selector(container, $state)} { @include g-container(); } } @if _g-need-to-generate(row, $package) { #{_g-selector(row, $state)} { @include g-row(false); } #{_g-selector(row, $state, reverse)} { @include g-row(true); } } @if _g-need-to-generate(row-full, $package) { #{_g-selector(row-full, $state)} { @include g-row-full(); } } @if _g-need-to-generate(col, $package) { #{_g-selector(col, $state)} { @include g-col(false); } #{_g-selector(col, $state, reverse)} { @include g-col(true); } } @if _g-need-to-generate(grid-table, $package) { #{_g-selector(grid-table, $state)} { @include g-grid-table(); } } @if _g-need-to-generate(grid-adapt, $package) { #{_g-selector(grid-adapt, $state)} { @include g-grid-adapt(); } } @if _g-need-to-generate(grid-grow, $package) { #{_g-selector(grid-grow, $state)} { @include g-grid-grow(); } } @if _g-need-to-generate(row-no-gutter, $package) { #{_g-selector(row-no-gutter, $state)} { @include g-row-no-gutter(); } #{_g-selector(row-no-gutter, $state, top)} { @include g-row-no-gutter(top); } #{_g-selector(row-no-gutter, $state, right)} { @include g-row-no-gutter(right); } #{_g-selector(row-no-gutter, $state, bottom)} { @include g-row-no-gutter(bottom); } #{_g-selector(row-no-gutter, $state, left)} { @include g-row-no-gutter(left); } } @if _g-need-to-generate(row-align, $package) { #{_g-selector(row-align, $state, left)} { @include g-row-align(left); } #{_g-selector(row-align, $state, center)} { @include g-row-align(center); } #{_g-selector(row-align, $state, right)} { @include g-row-align(right); } #{_g-selector(row-align, $state, middle)} { @include g-row-align(middle); } #{_g-selector(row-align, $state, top)} { @include g-row-align(top); } #{_g-selector(row-align, $state, bottom)} { @include g-row-align(bottom); } @if g-is-driver(flex) { #{_g-selector(row-align, $state, around)} { @include g-row-align(around); } #{_g-selector(row-align, $state, between)} { @include g-row-align(between); } } } // // Gutters // @if _g-need-to-generate(no-gutter, $package) { #{_g-selector(no-gutter, $state)} { @include g-no-gutter(); } #{_g-selector(no-gutter, $state, left)} { @include g-no-gutter(left); } #{_g-selector(no-gutter, $state, right)} { @include g-no-gutter(right); } #{_g-selector(no-gutter, $state, top)} { @include g-no-gutter(top); } #{_g-selector(no-gutter, $state, bottom)} { @include g-no-gutter(bottom); } } @if _g-need-to-generate(gutter, $package) { #{_g-selector(gutter, $state)} { @include g-gutter(top right bottom left); } #{_g-selector(gutter, $state, left)} { @include g-gutter(left); } #{_g-selector(gutter, $state, right)} { @include g-gutter(right); } #{_g-selector(gutter, $state, top)} { @include g-gutter(top); } #{_g-selector(gutter, $state, bottom)} { @include g-gutter(bottom); } } // // Wrapping // @if _g-need-to-generate(nowrap, $package) { #{_g-selector(nowrap, $state)} { @include g-nowrap(); } } @if _g-need-to-generate(wrap, $package) { #{_g-selector(wrap, $state)} { @include g-wrap(); } } // // Visible, hide, etc... // @if _g-need-to-generate(hide, $package) { #{_g-selector(hide, $state)} { @include g-hide(); } } @if _g-need-to-generate(not-visible, $package) { #{_g-selector(not-visible, $state)} { @include g-not-visible(); } } @if _g-need-to-generate(show, $package) { #{_g-selector(show, $state)} { @include g-show(); } } @if _g-need-to-generate(show-inline, $package) { #{_g-selector(show-inline, $state)} { @include g-show-inline(); } } @if _g-need-to-generate(visible, $package) { #{_g-selector(visible, $state)} { @include g-visible(); } } // // Clear each class : // @if _g-need-to-generate(clear-each, $package) { @each $clearName, $clearMap in $_g-clear-classes { // get count : $clearCount : map-get($clearMap, clearEach); // what to clear : $clearWhat : map-get($clearMap, clearWhat); // generate the class : #{_g-selector(clear-each, $state, $clearCount)} { @include g-clear-each($clearCount, $clearWhat); } } } // // debug // @if _g-need-to-generate(row-debug, $package) { #{_g-selector(row-debug, $state)} { @include g-row-debug(); } } } // // Generate json settings // @mixin g-generate-json-settings() { // settings content : $gridle-settings-states : "{"; // generate all classes for differents media queries : $statesCount : length($_g-states); $i : 0; @each $stateName, $state in $_g-states { $name : $stateName; $gridle-settings-states : "#{$gridle-settings-states} \"#{$name}\":{"; @each $varName, $var in $state { $value : null; @if $varName == "query" { $value : g-get-media-query($stateName); } @else { $value : map-get($state,$varName); } @if $value == null { $gridle-settings-states : "#{$gridle-settings-states} \"#{$varName}\" : null,"; } @elseif type-of($value) == bool { $gridle-settings-states : "#{$gridle-settings-states} \"#{$varName}\" : #{$value},"; } @elseif type-of($value) == map { $gridle-settings-states : "#{$gridle-settings-states} \"#{$varName}\" : {"; @each $vn, $vv in $value { $gridle-settings-states : "#{$gridle-settings-states} \"#{$vn}\" : \"#{$vv}\"," } $gridle-settings-states : "#{$gridle-settings-states} \"_\" : true"; $gridle-settings-states : "#{$gridle-settings-states} },"; } @else { $gridle-settings-states : "#{$gridle-settings-states} \"#{$varName}\" : \"#{$value}\","; } } $gridle-settings-states : "#{$gridle-settings-states} \"_\" : true"; @if $i >= $statesCount - 1 { $gridle-settings-states : "#{$gridle-settings-states} }"; } @else { $gridle-settings-states : "#{$gridle-settings-states} },"; } // update i : $i : $i + 1; } // generate settings json : $gridle-settings-states : "#{$gridle-settings-states}}"; $gridle-settings : "{"; $gridle-settings : "#{$gridle-settings} \"version\" : \"#{$_g-version}\""; // states : $gridle-settings : "#{$gridle-settings}, \"states\" : #{$gridle-settings-states}"; // settings : $gridle-settings : "#{$gridle-settings} }"; #gridle-settings { content : $gridle-settings; } } /** * Generate all the classes depending on the packages you have specified like: * - ```.container@{state}``` : default container * - ```.row@{state}``` : default row * - ```.row-align-{align}@{state}``` : default row-align * - ```.row-full@{state}``` : default row-full * - ```.row-debug@{state}``` : default row-debug * - ```.row-no-gutter@{state}``` : default row-no-gutter * - ```.nowrap@{state}``` : default nowrap * - ```.wrap@{state}``` : default wrap * - ```.col@{state}``` : default col * - ```.gr-{column}@{state}``` : default grid * - ```.gr-table@{state}``` : default gr-table * - ```.gr-grow@{state}``` : default gr-grow * - ```.gr-adapt@{state}``` : default gr-adapt * - ```.gr-centered@{state}``` : default gr-centered * - ```.push@{state}``` : default push * - ```.pull@{state}``` : default pull * - ```.prefix@{state}``` : default prefix * - ```.suffix@{state}``` : default suffix * - ```.hide@{state}``` : helpers hide * - ```.show@{state}``` : helpers show * - ```.show-inline@{state}``` : helpers show-inline * - ```.not-visible@{state}``` : helpers not-visible * - ```.visible@{state}``` : helpers visible * - ```.float-{%float}@{state}``` : helpers float * - ```.clear-{%float}@{state}``` : helpers clear * - ```.clear-each-{%count}@{state}``` : helpers clear-each * - ```.gutter-{%side}@{state}``` : helpers gutter * - ```.no-gutter-{%side}@{state}``` : helpers no-gutter * - ```.auto-height@{state}``` : helpers auto-height * - ```.order-{%column-count}@{state}``` : helpers order * * @param {String|List} [$states=all] The states to generate the classes for * @param {String|List} [$package=all] The packages to generate the classes for * @param {String} [$scope=null] A classname to scope the classes in * * @example scss * // generate all the classes * \@include g-classes(); * // generate only certain states * \@include g-classes(mobile tablet); * // generate only the helpers for all the states * \@include g-classes(all, helpers); * * @author Olivier Bossel */ @mixin g-classes( $states : all, $package : all, $scope : null ) { // init gridle @include g-init(); // check if a scope exist @if $scope { // wrapp grid into scope .#{$scope} { @include _g-classes($states, $package, true); } } @else { // generate classes @include _g-classes($states, $package, false); } } $_g-generateOnlyOnce : true !default; // keep track of generate once classes @mixin _g-classes( $states : all, $package : all, $has-parent : false ) { // set that we are in generate phase (that can be used anywhere) $_g-is-in-generate-phase : true !global; // get all the registered states that will be processed after // to determine which states to generate $generate-states : g-get-states-names(); // if we have provided some states to generate @if $states != null and $states != all { // check if we have only some - in the states list // mean that we want to only remove these specified states // from the all states list $onlyRemove : true; @each $stateName in $states { @if str-slice($stateName,1,1) != '-' { $onlyRemove : false; } } // if we want to only remove some states @if $onlyRemove { // loop on all the states to remove @each $stateName in $states { $sn : str-slice($stateName,2); $idx : index($generate-states, $sn); @if $idx != null { $generate-states : remove-nth($generate-states,$idx); } } } @else { $generate-states : $states; } } // generate these classes only once @if $_g-generateOnlyOnce { // update status $_g-generateOnlyOnce : false !global; // | ------------------------ // | Windows 8 fix // | ------------------------ // Windows 8 fix for snap mode @media screen and (max-width: 400px) { @-ms-viewport { width: device-width; } } // | ------------------------ // | JSON Settings // | ------------------------ // generate json settings @if $gridle-generate-json-settings { @include g-generate-json-settings(); } } // create the columns styleguide html $styleguideColumns : (); @each $columnName, $column in g-get-columns(default) { @if $columnName != '0' { $row : '
#{_g-selector(grid, default, $columnName)}
'; $styleguideColumns : append($styleguideColumns, $row); } } /** * @name Columns * Grid columns available * @styleguide Gridle / Columns * @example html * *
* #{$styleguideColumns} *
*/ // loop on each states to generate all the classes @each $stateName in $generate-states { // get the actual state $state : g-get-state($stateName); $classes : g-get-state-var(classes, $state); // stop here if no classes wanted @if $classes { // debug // @debug("Generate classes for state #{$stateName}"); // scope all the classes in a media query @include g-state($state, false) { // generate all classes for columns $i : 0; @each $columnName, $column in g-get-columns($state) { // variables $columnsCount : map-get($column, columns); $columnsContext : map-get($column, context); $columnsNameMultiplicator : map-get($column, name-multiplicator); // extend context in state (for columns) $extendedState : map-merge($state, ( context : $columnsContext, name-multiplicator : $columnsNameMultiplicator // inject the name multiplicator here getted from column to handle custom registered columns )); // classes @if _g-need-to-generate(grid, $package) { #{_g-selector(grid, $stateName, $columnName)} { @include g-grid($columnsCount, $columnsContext); } } @if _g-need-to-generate(push, $package) { #{_g-selector(push, $stateName, $columnName)} { @include g-push($columnsCount, $columnsContext); } } @if _g-need-to-generate(pull, $package) { #{_g-selector(pull, $stateName, $columnName)} { @include g-pull($columnsCount, $columnsContext); } } @if _g-need-to-generate(prefix, $package) { #{_g-selector(prefix, $stateName, $columnName)} { @include g-prefix($columnsCount, $columnsContext); } } @if _g-need-to-generate(suffix, $package) { #{_g-selector(suffix, $stateName, $columnName)} { @include g-suffix($columnsCount, $columnsContext); } } @if _g-need-to-generate(order, $package) { #{_g-selector(order, $stateName, first)} { @include g-order(-1); } #{_g-selector(order, $stateName, $i)} { @include g-order($i); } #{_g-selector(order, $stateName, last)} { @include g-order(9999); } } // up $i $i : $i + 1; } // handle direction on body body { direction: g-get-state-var(direction); } } } } // apply css for states of each elements @each $map in $_g-apply-css-for { @each $stateName, $fors in $map { @include _g-state($stateName, false) { @each $f, $rules in $fors { @if map-get($fors, $f) { @if _g-need-to-generate($f, $package) { @include g-selector($f, null) { @include _g-map-2-css($rules); } } } } } } } // loop on each states to generate all the classes @each $stateName in $generate-states { // get the actual state $state : g-get-state($stateName); $classes : g-get-state-var(classes, $state); // stop here if no classes wanted @if $classes { // debug // @debug("Generate classes for state #{$stateName}"); // scope all the classes in a media query @include g-state($state, false) { // media queries helpers classes @include _g-generate-helper-classes($stateName, $package); } } } // make nested grids working automatically @if _g-need-to-generate(col, $package) or _g-need-to-generate(row, $package) { @each $stateName, $state in g-get-states() { $classes : g-get-state-var(classes, $state); @if $classes { $gutter-left : g-get-state-var(gutter-left, $state); $gutter-right : g-get-state-var(gutter-right, $state); @include _g-state($stateName, false) { #{_g-get-generic-selector(grid)} > [class^="#{str-slice(_g-selector(row),2)}"], #{_g-get-generic-selector(grid)} > [class^="#{str-slice(_g-selector(col),2)}"] { margin-left: -#{$gutter-left}; margin-right: -#{$gutter-right}; } // [class*="#{str-slice(_g-selector(grid),2)}"] > [class^="#{str-slice(_g-selector(row),2)}"], // [class*="#{str-slice(_g-selector(grid),2)}"] > [class^="#{str-slice(_g-selector(col),2)}"] { // margin-left: -#{$gutter-left}; // margin-right: -#{$gutter-right}; // } } } } } // reset the variable that track if we are in generate phase or not $_g-is-in-generate-phase : false !global; }