From d07f664450ddaaebb44127a4bd057763d13d3f82 Mon Sep 17 00:00:00 2001 From: Feuerfuchs Date: Sun, 1 Nov 2020 20:55:14 +0100 Subject: Init --- src/_props.scss | 281 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 281 insertions(+) create mode 100644 src/_props.scss (limited to 'src/_props.scss') diff --git a/src/_props.scss b/src/_props.scss new file mode 100644 index 0000000..7377c88 --- /dev/null +++ b/src/_props.scss @@ -0,0 +1,281 @@ +//// +/// Property trees. +/// +/// Property trees allow you to organize properties in a tree structure (internally nested maps). +/// The intended use is to store all your properties at the beginning and for the rest of the +/// stylesheet you just get them. +/// +/// @group Property trees +/// +/// @access public +//// + +/// +/// The maximum depth of resolved iro-prop-ref() references. +/// +/// @type number +/// +$iro-props-native-assing-max-depth: 2 !default; + +/// +/// Indicate if property names must start with two dashes (--). +/// This is required if property trees are also used for native CSS custom properties. +/// +/// @type bool +/// +$iro-props-enforce-double-dashes: true !default; + +/// +/// Default tree name to use if no name is specified. +/// +/// @type string +/// +$iro-props-default-tree: 'default' !default; + +/// +/// List of all created property trees. +/// +/// @type list +/// +/// @access private +/// +$iro-props-trees: (); + +/// +/// Save a property tree. If a tree with the sane name already exists, the trees +/// will be merged. +/// +/// @param {map} $map - Map containing properties +/// @param {string} $tree [$iro-props-default-tree] - ID the map is saved as +/// @param {bool} $merge [false] - If a tree named $tree already exists and this value is set to true, they will be merged. Otherwise an error will be emitted. +/// +@mixin iro-props-save($map, $tree: $iro-props-default-tree, $merge: false) { + $noop: iro-props-save($map, $tree, $merge); +} + +/// +/// Save a property tree. +/// +/// @param {map} $map - Map containing properties +/// @param {string} $tree [$iro-props-default-tree] - ID the map is saved as +/// @param {bool} $merge [false] - If a tree named $tree already exists and this value is set to true, they will be merged. Otherwise an error will be emitted. +/// +@function iro-props-save($map, $tree: $iro-props-default-tree, $merge: false) { + $prop-map: null; + + @if $iro-props-enforce-double-dashes { + @if not iro-props-validate($map) { + @error 'Property tree keys must start with two dashes (--). If you don\'t use property trees for native CSS custom properties, set $iro-props-enforce-double-dashes to false.'; + } + } + + @if map-has-key($iro-props-trees, $tree) { + @if $merge { + $map: iro-map-merge-recursive(map-get($iro-props-trees, $tree), $map); + } @else { + @error 'Property tree #{inspect($tree)} does already exist.'; + } + } + + $iro-props-trees: map-merge($iro-props-trees, ($tree: $map)) !global; + + @return null; +} + +/// +/// Delete a property tree. +/// +/// @param {string} $tree [$iro-props-default-tree] - ID of the tree to be deleted +/// +@mixin iro-props-delete($tree: $iro-props-default-tree) { + $noop: iro-props-delete($tree); +} + +/// +/// Unset a property tree. +/// +/// @param {string} $tree [$iro-props-default-tree] - ID of the tree to be deleted +/// +/// @throw If the property tree does not exist +/// +@function iro-props-delete($tree: $iro-props-default-tree) { + @if not map-has-key($iro-props-trees, $tree) { + @error 'Property tree "#{inspect($tree)}" does not exist.'; + } + + $iro-props-trees: map-remove($iro-props-trees, $tree) !global; + + @return null; +} + +/// +/// Access a whole property or a subsection (i.e. value) of it. +/// +/// @param {string | list} $key [null] - Key of the property to read. If this is a list of keys, the map will be traversed in that order. +/// @param {string} $tree [$iro-props-default-tree] - ID of the property tree to use +/// @param {any} $default [null] - Default value to return of no match was found. If null, this function will throw an error instead. +/// +/// @return {any} Value assigned to property or $default +/// +/// @throw If there was no match for $key and $default is null +/// +@function iro-props-get($key: (), $tree: $iro-props-default-tree, $default: null) { + @if not map-has-key($iro-props-trees, $tree) { + @error 'Unknown tree "#{$tree}".'; + } + + $result: map-get($iro-props-trees, $tree); + + @if type-of($key) == list { + $stop: false; + + @each $k in $key { + @if map-has-key($result, $k) and not $stop { + $result: map-get($result, $k); + + @if type-of($result) == list and nth($result, 1) == 'iro-prop-ref' { + @if length($result) == 2 { + $result: iro-props-get($tree: nth($result, 2)); + } @else { + $result: iro-props-get(nth($result, 3), nth($result, 2)); + } + } + } @else { + $stop: true; + } + } + + @if $stop { + $result: null; + } + } @else { + $result: map-get($result, $key); + + @if type-of($result) == list and nth($result, 1) == 'iro-prop-ref' { + @if length($result) == 2 { + $result: iro-props-get($tree: nth($result, 2)); + } @else { + $result: iro-props-get(nth($result, 3), nth($result, 2)); + } + } + } + + @if $result == null { + @if $default == null { + @error '"#{$key}" is null.'; + } @else { + @return $default; + } + } + + @return $result; +} + +/// +/// Generate a var() function call to get native CSS custom property. +/// +/// @param {string | list} $key - Key of the property to read. If this is a list of keys, the map will be traversed in that order. +/// @param {string | null} $tree [null] - Optional tree to check if the property actually exists. +/// @param {any} $default [null] - Default value to return of no match was found. +/// +/// @return {string} var() +/// +@function iro-props-get-native($key, $tree: null, $default: null) { + @if $tree != null { + $noop: iro-props-get($key, $tree, $default); + } + + $native-var: ''; + + @if type-of($key) == list { + @each $subkey in $key { + $native-var: $native-var + $subkey; + } + } @else { + $native-var: $key; + } + + @if $default == null { + @return var(#{$native-var}); + } @else { + @return var(#{$native-var}, #{$default}); + } +} + +/// +/// Generate assignments for native CSS custom properties with the values from the specified tree. +/// +/// @param {string} $tree [$iro-props-default-tree] - ID of the property tree to use +/// @param {string} $root [()] - Sub-tree to use for assignment +/// +@mixin iro-props-assign-native($tree: $iro-props-default-tree, $root: (), $skip: ()) { + $map: iro-props-get($root, $tree); + $map: map-remove($map, $skip...); + + @include iro-props-assign-native-internal($map); +} + +/// +/// @access private +/// +@mixin iro-props-assign-native-internal($map, $prefix: '', $ref-depth: $iro-props-native-assing-max-depth) { + @each $key, $value in $map { + $rd: $ref-depth; + @if type-of($value) == list and nth($value, 1) == 'iro-prop-ref' { + @if $ref-depth != 0 { + $rd: $rd - 1; + @if length($value) == 2 { + $value: iro-props-get($tree: nth($value, 2)); + } @else { + $value: iro-props-get(nth($value, 3), nth($value, 2)); + } + } @else { + $value: null; + } + } + @if type-of($value) != map { + #{$prefix + $key}: #{$value}; + } @else { + @include iro-props-assign-native-internal($value, $prefix + $key, $rd); + } + } +} + +/// +/// Validate property names. +/// +/// @access private +/// +@function iro-props-validate($map) { + @each $key, $value in $map { + @if str-index($key, '--') != 1 { + @return false; + } + + @if type-of($value) == map { + @if not iro-props-validate($value) { + @return false; + } + } + } + + @return true; +} + +/// +/// Generate a reference to another tree. Dereferencing is lazy, so you may specify a tree that hasn't been created yet. +/// +/// @param {string} $tree [$iro-props-default-tree] - ID of the property tree to use +/// @param {string | list} $key - Key of the property to read. If this is a list of keys, the map will be traversed in that order. +/// +/// @return {list} A special list that let's Ignis know that this is a lazy value. +/// +/// @throw If there was no match for $key and $default is null +/// +@function iro-props-ref($tree: $iro-props-default-tree, $key: null) { + @if $key == null { + @return ('iro-prop-ref' $tree); + } @else { + @return ('iro-prop-ref' $tree $key); + } +} -- cgit v1.2.3-70-g09d2