aboutsummaryrefslogtreecommitdiffstats
path: root/src/_props.scss
diff options
context:
space:
mode:
Diffstat (limited to 'src/_props.scss')
-rw-r--r--src/_props.scss281
1 files changed, 281 insertions, 0 deletions
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 @@
1////
2/// Property trees.
3///
4/// Property trees allow you to organize properties in a tree structure (internally nested maps).
5/// The intended use is to store all your properties at the beginning and for the rest of the
6/// stylesheet you just get them.
7///
8/// @group Property trees
9///
10/// @access public
11////
12
13///
14/// The maximum depth of resolved iro-prop-ref() references.
15///
16/// @type number
17///
18$iro-props-native-assing-max-depth: 2 !default;
19
20///
21/// Indicate if property names must start with two dashes (--).
22/// This is required if property trees are also used for native CSS custom properties.
23///
24/// @type bool
25///
26$iro-props-enforce-double-dashes: true !default;
27
28///
29/// Default tree name to use if no name is specified.
30///
31/// @type string
32///
33$iro-props-default-tree: 'default' !default;
34
35///
36/// List of all created property trees.
37///
38/// @type list
39///
40/// @access private
41///
42$iro-props-trees: ();
43
44///
45/// Save a property tree. If a tree with the sane name already exists, the trees
46/// will be merged.
47///
48/// @param {map} $map - Map containing properties
49/// @param {string} $tree [$iro-props-default-tree] - ID the map is saved as
50/// @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.
51///
52@mixin iro-props-save($map, $tree: $iro-props-default-tree, $merge: false) {
53 $noop: iro-props-save($map, $tree, $merge);
54}
55
56///
57/// Save a property tree.
58///
59/// @param {map} $map - Map containing properties
60/// @param {string} $tree [$iro-props-default-tree] - ID the map is saved as
61/// @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.
62///
63@function iro-props-save($map, $tree: $iro-props-default-tree, $merge: false) {
64 $prop-map: null;
65
66 @if $iro-props-enforce-double-dashes {
67 @if not iro-props-validate($map) {
68 @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.';
69 }
70 }
71
72 @if map-has-key($iro-props-trees, $tree) {
73 @if $merge {
74 $map: iro-map-merge-recursive(map-get($iro-props-trees, $tree), $map);
75 } @else {
76 @error 'Property tree #{inspect($tree)} does already exist.';
77 }
78 }
79
80 $iro-props-trees: map-merge($iro-props-trees, ($tree: $map)) !global;
81
82 @return null;
83}
84
85///
86/// Delete a property tree.
87///
88/// @param {string} $tree [$iro-props-default-tree] - ID of the tree to be deleted
89///
90@mixin iro-props-delete($tree: $iro-props-default-tree) {
91 $noop: iro-props-delete($tree);
92}
93
94///
95/// Unset a property tree.
96///
97/// @param {string} $tree [$iro-props-default-tree] - ID of the tree to be deleted
98///
99/// @throw If the property tree does not exist
100///
101@function iro-props-delete($tree: $iro-props-default-tree) {
102 @if not map-has-key($iro-props-trees, $tree) {
103 @error 'Property tree "#{inspect($tree)}" does not exist.';
104 }
105
106 $iro-props-trees: map-remove($iro-props-trees, $tree) !global;
107
108 @return null;
109}
110
111///
112/// Access a whole property or a subsection (i.e. value) of it.
113///
114/// @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.
115/// @param {string} $tree [$iro-props-default-tree] - ID of the property tree to use
116/// @param {any} $default [null] - Default value to return of no match was found. If null, this function will throw an error instead.
117///
118/// @return {any} Value assigned to property or $default
119///
120/// @throw If there was no match for $key and $default is null
121///
122@function iro-props-get($key: (), $tree: $iro-props-default-tree, $default: null) {
123 @if not map-has-key($iro-props-trees, $tree) {
124 @error 'Unknown tree "#{$tree}".';
125 }
126
127 $result: map-get($iro-props-trees, $tree);
128
129 @if type-of($key) == list {
130 $stop: false;
131
132 @each $k in $key {
133 @if map-has-key($result, $k) and not $stop {
134 $result: map-get($result, $k);
135
136 @if type-of($result) == list and nth($result, 1) == 'iro-prop-ref' {
137 @if length($result) == 2 {
138 $result: iro-props-get($tree: nth($result, 2));
139 } @else {
140 $result: iro-props-get(nth($result, 3), nth($result, 2));
141 }
142 }
143 } @else {
144 $stop: true;
145 }
146 }
147
148 @if $stop {
149 $result: null;
150 }
151 } @else {
152 $result: map-get($result, $key);
153
154 @if type-of($result) == list and nth($result, 1) == 'iro-prop-ref' {
155 @if length($result) == 2 {
156 $result: iro-props-get($tree: nth($result, 2));
157 } @else {
158 $result: iro-props-get(nth($result, 3), nth($result, 2));
159 }
160 }
161 }
162
163 @if $result == null {
164 @if $default == null {
165 @error '"#{$key}" is null.';
166 } @else {
167 @return $default;
168 }
169 }
170
171 @return $result;
172}
173
174///
175/// Generate a var() function call to get native CSS custom property.
176///
177/// @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.
178/// @param {string | null} $tree [null] - Optional tree to check if the property actually exists.
179/// @param {any} $default [null] - Default value to return of no match was found.
180///
181/// @return {string} var()
182///
183@function iro-props-get-native($key, $tree: null, $default: null) {
184 @if $tree != null {
185 $noop: iro-props-get($key, $tree, $default);
186 }
187
188 $native-var: '';
189
190 @if type-of($key) == list {
191 @each $subkey in $key {
192 $native-var: $native-var + $subkey;
193 }
194 } @else {
195 $native-var: $key;
196 }
197
198 @if $default == null {
199 @return var(#{$native-var});
200 } @else {
201 @return var(#{$native-var}, #{$default});
202 }
203}
204
205///
206/// Generate assignments for native CSS custom properties with the values from the specified tree.
207///
208/// @param {string} $tree [$iro-props-default-tree] - ID of the property tree to use
209/// @param {string} $root [()] - Sub-tree to use for assignment
210///
211@mixin iro-props-assign-native($tree: $iro-props-default-tree, $root: (), $skip: ()) {
212 $map: iro-props-get($root, $tree);
213 $map: map-remove($map, $skip...);
214
215 @include iro-props-assign-native-internal($map);
216}
217
218///
219/// @access private
220///
221@mixin iro-props-assign-native-internal($map, $prefix: '', $ref-depth: $iro-props-native-assing-max-depth) {
222 @each $key, $value in $map {
223 $rd: $ref-depth;
224 @if type-of($value) == list and nth($value, 1) == 'iro-prop-ref' {
225 @if $ref-depth != 0 {
226 $rd: $rd - 1;
227 @if length($value) == 2 {
228 $value: iro-props-get($tree: nth($value, 2));
229 } @else {
230 $value: iro-props-get(nth($value, 3), nth($value, 2));
231 }
232 } @else {
233 $value: null;
234 }
235 }
236 @if type-of($value) != map {
237 #{$prefix + $key}: #{$value};
238 } @else {
239 @include iro-props-assign-native-internal($value, $prefix + $key, $rd);
240 }
241 }
242}
243
244///
245/// Validate property names.
246///
247/// @access private
248///
249@function iro-props-validate($map) {
250 @each $key, $value in $map {
251 @if str-index($key, '--') != 1 {
252 @return false;
253 }
254
255 @if type-of($value) == map {
256 @if not iro-props-validate($value) {
257 @return false;
258 }
259 }
260 }
261
262 @return true;
263}
264
265///
266/// Generate a reference to another tree. Dereferencing is lazy, so you may specify a tree that hasn't been created yet.
267///
268/// @param {string} $tree [$iro-props-default-tree] - ID of the property tree to use
269/// @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.
270///
271/// @return {list} A special list that let's Ignis know that this is a lazy value.
272///
273/// @throw If there was no match for $key and $default is null
274///
275@function iro-props-ref($tree: $iro-props-default-tree, $key: null) {
276 @if $key == null {
277 @return ('iro-prop-ref' $tree);
278 } @else {
279 @return ('iro-prop-ref' $tree $key);
280 }
281}