@lisergia/styles 10.0.0 → 12.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lisergia/styles",
3
- "version": "10.0.0",
3
+ "version": "12.0.0",
4
4
  "files": [
5
5
  "scss"
6
6
  ],
@@ -8,8 +8,7 @@
8
8
  "lint": "stylelint \"**/*.scss\""
9
9
  },
10
10
  "dependencies": {
11
- "@lisergia/config-stylelint": "10.0.0",
12
- "include-media": "^2.0.0",
11
+ "@lisergia/config-stylelint": "12.0.0",
13
12
  "stylelint": "^16.19.1"
14
13
  }
15
14
  }
@@ -0,0 +1,589 @@
1
+ // _ _ _ _ _
2
+ // (_) | | | | | (_)
3
+ // _ _ __ ___| |_ _ __| | ___ _ __ ___ ___ __| |_ __ _
4
+ // | | '_ \ / __| | | | |/ _` |/ _ \ | '_ ` _ \ / _ \/ _` | |/ _` |
5
+ // | | | | | (__| | |_| | (_| | __/ | | | | | | __/ (_| | | (_| |
6
+ // |_|_| |_|\___|_|\__,_|\__,_|\___| |_| |_| |_|\___|\__,_|_|\__,_|
7
+ //
8
+ // Simple, elegant and maintainable media queries in Sass
9
+ // v2.0.0
10
+ //
11
+ // https://eduardoboucas.github.io/include-media
12
+ //
13
+ // Authors: Eduardo Boucas (@eduardoboucas)
14
+ // Kitty Giraudel (@kittygiraudel)
15
+ //
16
+ // This project is licensed under the terms of the MIT license
17
+ @charset "UTF-8";
18
+
19
+ ////
20
+ /// include-media library public configuration
21
+ /// @author Eduardo Boucas
22
+ /// @access public
23
+ ////
24
+ @use 'sass:math';
25
+ @use 'sass:map';
26
+ @use 'sass:list';
27
+ @use 'sass:string';
28
+ @use 'sass:meta';
29
+
30
+ ///
31
+ /// Creates a list of global breakpoints
32
+ ///
33
+ /// @example scss - Creates a single breakpoint with the label `phone`
34
+ /// $breakpoints: ('phone': 320px);
35
+ ///
36
+ $breakpoints: (
37
+ 'phone': 320px,
38
+ 'tablet': 768px,
39
+ 'desktop': 1024px,
40
+ ) !default;
41
+
42
+ ///
43
+ /// Creates a list of static expressions or media types
44
+ ///
45
+ /// @example scss - Creates a single media type (screen)
46
+ /// $media-expressions: ('screen': 'screen');
47
+ ///
48
+ /// @example scss - Creates a static expression with logical disjunction (OR operator)
49
+ /// $media-expressions: (
50
+ /// 'retina2x': '(-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi)'
51
+ /// );
52
+ ///
53
+ $media-expressions: (
54
+ 'screen': 'screen',
55
+ 'print': 'print',
56
+ 'handheld': 'handheld',
57
+ 'landscape': '(orientation: landscape)',
58
+ 'portrait': '(orientation: portrait)',
59
+ 'retina2x': '(-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi), (min-resolution: 2dppx)',
60
+ 'retina3x': '(-webkit-min-device-pixel-ratio: 3), (min-resolution: 350dpi), (min-resolution: 3dppx)',
61
+ ) !default;
62
+
63
+ ///
64
+ /// Defines a number to be added or subtracted from each unit when declaring breakpoints with exclusive intervals
65
+ ///
66
+ /// @example scss - Interval for pixels is defined as `1` by default
67
+ /// @include media('>128px') {}
68
+ ///
69
+ /// /* Generates: */
70
+ /// @media (min-width: 129px) {}
71
+ ///
72
+ /// @example scss - Interval for ems is defined as `0.01` by default
73
+ /// @include media('>20em') {}
74
+ ///
75
+ /// /* Generates: */
76
+ /// @media (min-width: 20.01em) {}
77
+ ///
78
+ /// @example scss - Interval for rems is defined as `0.1` by default, to be used with `font-size: 62.5%;`
79
+ /// @include media('>2.0rem') {}
80
+ ///
81
+ /// /* Generates: */
82
+ /// @media (min-width: 2.1rem) {}
83
+ ///
84
+ $unit-intervals: (
85
+ 'px': 1,
86
+ 'em': 0.01,
87
+ 'rem': 0.1,
88
+ '': 0,
89
+ ) !default;
90
+
91
+ ///
92
+ /// Defines whether support for media queries is available, useful for creating separate stylesheets
93
+ /// for browsers that don't support media queries.
94
+ ///
95
+ /// @example scss - Disables support for media queries
96
+ /// $im-media-support: false;
97
+ /// @include media('>=tablet') {
98
+ /// .foo {
99
+ /// color: tomato;
100
+ /// }
101
+ /// }
102
+ ///
103
+ /// /* Generates: */
104
+ /// .foo {
105
+ /// color: tomato;
106
+ /// }
107
+ ///
108
+ $im-media-support: true !default;
109
+
110
+ ///
111
+ /// Selects which breakpoint to emulate when support for media queries is disabled. Media queries that start at or
112
+ /// intercept the breakpoint will be displayed, any others will be ignored.
113
+ ///
114
+ /// @example scss - This media query will show because it intercepts the static breakpoint
115
+ /// $im-media-support: false;
116
+ /// $im-no-media-breakpoint: 'desktop';
117
+ /// @include media('>=tablet') {
118
+ /// .foo {
119
+ /// color: tomato;
120
+ /// }
121
+ /// }
122
+ ///
123
+ /// /* Generates: */
124
+ /// .foo {
125
+ /// color: tomato;
126
+ /// }
127
+ ///
128
+ /// @example scss - This media query will NOT show because it does not intercept the desktop breakpoint
129
+ /// $im-media-support: false;
130
+ /// $im-no-media-breakpoint: 'tablet';
131
+ /// @include media('>=desktop') {
132
+ /// .foo {
133
+ /// color: tomato;
134
+ /// }
135
+ /// }
136
+ ///
137
+ /// /* No output */
138
+ ///
139
+ $im-no-media-breakpoint: 'desktop' !default;
140
+
141
+ ///
142
+ /// Selects which media expressions are allowed in an expression for it to be used when media queries
143
+ /// are not supported.
144
+ ///
145
+ /// @example scss - This media query will show because it intercepts the static breakpoint and contains only accepted media expressions
146
+ /// $im-media-support: false;
147
+ /// $im-no-media-breakpoint: 'desktop';
148
+ /// $im-no-media-expressions: ('screen');
149
+ /// @include media('>=tablet', 'screen') {
150
+ /// .foo {
151
+ /// color: tomato;
152
+ /// }
153
+ /// }
154
+ ///
155
+ /// /* Generates: */
156
+ /// .foo {
157
+ /// color: tomato;
158
+ /// }
159
+ ///
160
+ /// @example scss - This media query will NOT show because it intercepts the static breakpoint but contains a media expression that is not accepted
161
+ /// $im-media-support: false;
162
+ /// $im-no-media-breakpoint: 'desktop';
163
+ /// $im-no-media-expressions: ('screen');
164
+ /// @include media('>=tablet', 'retina2x') {
165
+ /// .foo {
166
+ /// color: tomato;
167
+ /// }
168
+ /// }
169
+ ///
170
+ /// /* No output */
171
+ ///
172
+ $im-no-media-expressions: ('screen', 'portrait', 'landscape') !default;
173
+
174
+ ////
175
+ /// Cross-engine logging engine
176
+ /// @author Kitty Giraudel
177
+ /// @access private
178
+ ////
179
+
180
+ ///
181
+ /// Log a message either with `@error` if supported
182
+ /// else with `@warn`, using `feature-exists('at-error')`
183
+ /// to detect support.
184
+ ///
185
+ /// @param {String} $message - Message to log
186
+ ///
187
+ @function im-log($message) {
188
+ @if meta.feature-exists('at-error') {
189
+ @error $message;
190
+ } @else {
191
+ @warn $message;
192
+ $_: noop();
193
+ }
194
+
195
+ @return $message;
196
+ }
197
+
198
+ ///
199
+ /// Wrapper mixin for the log function so it can be used with a more friendly
200
+ /// API than `@if im-log('..') {}` or `$_: im-log('..')`. Basically, use the function
201
+ /// within functions because it is not possible to include a mixin in a function
202
+ /// and use the mixin everywhere else because it's much more elegant.
203
+ ///
204
+ /// @param {String} $message - Message to log
205
+ ///
206
+ @mixin log($message) {
207
+ @if im-log($message) {
208
+ }
209
+ }
210
+
211
+ ///
212
+ /// Function with no `@return` called next to `@warn` in Sass 3.3
213
+ /// to trigger a compiling error and stop the process.
214
+ ///
215
+ @function noop() {
216
+ }
217
+
218
+ ///
219
+ /// Determines whether a list of conditions is intercepted by the static breakpoint.
220
+ ///
221
+ /// @param {Arglist} $conditions - Media query conditions
222
+ ///
223
+ /// @return {Boolean} - Returns true if the conditions are intercepted by the static breakpoint
224
+ ///
225
+ @function im-intercepts-static-breakpoint($conditions...) {
226
+ $no-media-breakpoint-value: map.get($breakpoints, $im-no-media-breakpoint);
227
+
228
+ @if not $no-media-breakpoint-value {
229
+ @if im-log('`#{$im-no-media-breakpoint}` is not a valid breakpoint.') {
230
+ }
231
+ }
232
+
233
+ @each $condition in $conditions {
234
+ @if not map.has-key($media-expressions, $condition) {
235
+ $operator: get-expression-operator($condition);
236
+ $prefix: get-expression-prefix($operator);
237
+ $value: get-expression-value($condition, $operator);
238
+
239
+ @if ($prefix == 'max' and $value <= $no-media-breakpoint-value) or
240
+ ($prefix == 'min' and $value > $no-media-breakpoint-value)
241
+ {
242
+ @return false;
243
+ }
244
+ } @else if not list.index($im-no-media-expressions, $condition) {
245
+ @return false;
246
+ }
247
+ }
248
+
249
+ @return true;
250
+ }
251
+
252
+ ////
253
+ /// Parsing engine
254
+ /// @author Kitty Giraudel
255
+ /// @access private
256
+ ////
257
+
258
+ ///
259
+ /// Get operator of an expression
260
+ ///
261
+ /// @param {String} $expression - Expression to extract operator from
262
+ ///
263
+ /// @return {String} - Any of `>=`, `>`, `<=`, `<`, `≥`, `≤`
264
+ ///
265
+ @function get-expression-operator($expression) {
266
+ @each $operator in ('>=', '>', '<=', '<', '≥', '≤') {
267
+ @if string.index($expression, $operator) {
268
+ @return $operator;
269
+ }
270
+ }
271
+
272
+ // It is not possible to include a mixin inside a function, so we have to
273
+ // rely on the `im-log(..)` function rather than the `log(..)` mixin. Because
274
+ // functions cannot be called anywhere in Sass, we need to hack the call in
275
+ // a dummy variable, such as `$_`. If anybody ever raise a scoping issue with
276
+ // Sass 3.3, change this line in `@if im-log(..) {}` instead.
277
+ $_: im-log('No operator found in `#{$expression}`.');
278
+ }
279
+
280
+ ///
281
+ /// Get dimension of an expression, based on a found operator
282
+ ///
283
+ /// @param {String} $expression - Expression to extract dimension from
284
+ /// @param {String} $operator - Operator from `$expression`
285
+ ///
286
+ /// @return {String} - `width` or `height` (or potentially anything else)
287
+ ///
288
+ @function get-expression-dimension($expression, $operator) {
289
+ $operator-index: string.index($expression, $operator);
290
+ $parsed-dimension: string.slice($expression, 0, $operator-index - 1);
291
+ $dimension: 'width';
292
+
293
+ @if string.length($parsed-dimension) > 0 {
294
+ $dimension: $parsed-dimension;
295
+ }
296
+
297
+ @return $dimension;
298
+ }
299
+
300
+ ///
301
+ /// Get dimension prefix based on an operator
302
+ ///
303
+ /// @param {String} $operator - Operator
304
+ ///
305
+ /// @return {String} - `min` or `max`
306
+ ///
307
+ @function get-expression-prefix($operator) {
308
+ @return if(list.index(('<', '<=', '≤'), $operator), 'max', 'min');
309
+ }
310
+
311
+ ///
312
+ /// Get value of an expression, based on a found operator
313
+ ///
314
+ /// @param {String} $expression - Expression to extract value from
315
+ /// @param {String} $operator - Operator from `$expression`
316
+ ///
317
+ /// @return {Number} - A numeric value
318
+ ///
319
+ @function get-expression-value($expression, $operator) {
320
+ $operator-index: string.index($expression, $operator);
321
+ $value: string.slice($expression, $operator-index + string.length($operator));
322
+
323
+ @if map.has-key($breakpoints, $value) {
324
+ $value: map.get($breakpoints, $value);
325
+ } @else {
326
+ $value: to-number($value);
327
+ }
328
+
329
+ $interval: map.get($unit-intervals, math.unit($value));
330
+
331
+ @if not $interval {
332
+ // It is not possible to include a mixin inside a function, so we have to
333
+ // rely on the `im-log(..)` function rather than the `log(..)` mixin. Because
334
+ // functions cannot be called anywhere in Sass, we need to hack the call in
335
+ // a dummy variable, such as `$_`. If anybody ever raise a scoping issue with
336
+ // Sass 3.3, change this line in `@if im-log(..) {}` instead.
337
+ $_: im-log('Unknown unit `#{math.unit($value)}`.');
338
+ }
339
+
340
+ @if $operator == '>' {
341
+ $value: $value + $interval;
342
+ } @else if $operator == '<' {
343
+ $value: $value - $interval;
344
+ }
345
+
346
+ @return $value;
347
+ }
348
+
349
+ ///
350
+ /// Parse an expression to return a valid media-query expression
351
+ ///
352
+ /// @param {String} $expression - Expression to parse
353
+ ///
354
+ /// @return {String} - Valid media query
355
+ ///
356
+ @function parse-expression($expression) {
357
+ // If it is part of $media-expressions, it has no operator
358
+ // then there is no need to go any further, just return the value
359
+ @if map.has-key($media-expressions, $expression) {
360
+ @return map.get($media-expressions, $expression);
361
+ }
362
+
363
+ $operator: get-expression-operator($expression);
364
+ $dimension: get-expression-dimension($expression, $operator);
365
+ $prefix: get-expression-prefix($operator);
366
+ $value: get-expression-value($expression, $operator);
367
+
368
+ @return '(#{$prefix}-#{$dimension}: #{$value})';
369
+ }
370
+
371
+ ///
372
+ /// Slice `$list` between `$start` and `$end` indexes
373
+ ///
374
+ /// @access private
375
+ ///
376
+ /// @param {List} $list - List to slice
377
+ /// @param {Number} $start [1] - Start index
378
+ /// @param {Number} $end [length($list)] - End index
379
+ ///
380
+ /// @return {List} Sliced list
381
+ ///
382
+ @function slice($list, $start: 1, $end: list.length($list)) {
383
+ @if list.length($list) < 1 or $start > $end {
384
+ @return ();
385
+ }
386
+
387
+ $result: ();
388
+
389
+ @for $i from $start through $end {
390
+ $result: list.append($result, list.nth($list, $i), comma);
391
+ }
392
+
393
+ @return $result;
394
+ }
395
+
396
+ ////
397
+ /// String to number converter
398
+ /// @author Kitty Giraudel
399
+ /// @access private
400
+ ////
401
+
402
+ ///
403
+ /// Casts a string into a number
404
+ ///
405
+ /// @param {String | Number} $value - Value to be parsed
406
+ ///
407
+ /// @return {Number}
408
+ ///
409
+
410
+ @function to-number($value) {
411
+ @if meta.type-of($value) == 'number' {
412
+ @return $value;
413
+ } @else if meta.type-of($value) != 'string' {
414
+ $_: im-log('Value for `to-number` should be a number or a string.');
415
+ }
416
+
417
+ $first-character: string.slice($value, 1, 1);
418
+ $result: 0;
419
+ $digits: 0;
420
+ $minus: ($first-character == '-');
421
+ $numbers: (
422
+ '0': 0,
423
+ '1': 1,
424
+ '2': 2,
425
+ '3': 3,
426
+ '4': 4,
427
+ '5': 5,
428
+ '6': 6,
429
+ '7': 7,
430
+ '8': 8,
431
+ '9': 9,
432
+ );
433
+
434
+ // Remove +/- sign if present at first character
435
+ @if ($first-character == '+' or $first-character == '-') {
436
+ $value: string.slice($value, 2);
437
+ }
438
+
439
+ @for $i from 1 through string.length($value) {
440
+ $character: string.slice($value, $i, $i);
441
+
442
+ @if not(list.index(map.keys($numbers), $character) or $character == '.') {
443
+ @return to-length(if($minus, -$result, $result), string.slice($value, $i));
444
+ }
445
+
446
+ @if $character == '.' {
447
+ $digits: 1;
448
+ } @else if $digits == 0 {
449
+ $result: $result * 10 + map.get($numbers, $character);
450
+ } @else {
451
+ $digits: $digits * 10;
452
+ $result: $result + math.div(map.get($numbers, $character), $digits);
453
+ }
454
+ }
455
+
456
+ @return if($minus, -$result, $result);
457
+ }
458
+
459
+ ///
460
+ /// Add `$unit` to `$value`
461
+ ///
462
+ /// @param {Number} $value - Value to add unit to
463
+ /// @param {String} $unit - String representation of the unit
464
+ ///
465
+ /// @return {Number} - `$value` expressed in `$unit`
466
+ ///
467
+ @function to-length($value, $unit) {
468
+ $units: (
469
+ 'px': 1px,
470
+ 'cm': 1cm,
471
+ 'mm': 1mm,
472
+ '%': 1%,
473
+ 'ch': 1ch,
474
+ 'pc': 1pc,
475
+ 'in': 1in,
476
+ 'em': 1em,
477
+ 'rem': 1rem,
478
+ 'pt': 1pt,
479
+ 'ex': 1ex,
480
+ 'vw': 1vw,
481
+ 'vh': 1vh,
482
+ 'vmin': 1vmin,
483
+ 'vmax': 1vmax,
484
+ );
485
+
486
+ @if not list.index(map.keys($units), $unit) {
487
+ $_: im-log('Invalid unit `#{$unit}`.');
488
+ }
489
+
490
+ @return $value * map.get($units, $unit);
491
+ }
492
+
493
+ ///
494
+ /// This mixin aims at redefining the configuration just for the scope of
495
+ /// the call. It is helpful when having a component needing an extended
496
+ /// configuration such as custom breakpoints (referred to as tweakpoints)
497
+ /// for instance.
498
+ ///
499
+ /// @author Kitty Giraudel
500
+ ///
501
+ /// @param {Map} $tweakpoints [()] - Map of tweakpoints to be merged with `$breakpoints`
502
+ /// @param {Map} $tweak-media-expressions [()] - Map of tweaked media expressions to be merged with `$media-expression`
503
+ ///
504
+ /// @example scss - Extend the global breakpoints with a tweakpoint
505
+ /// @include media-context(('custom': 678px)) {
506
+ /// .foo {
507
+ /// @include media('>phone', '<=custom') {
508
+ /// // ...
509
+ /// }
510
+ /// }
511
+ /// }
512
+ ///
513
+ /// @example scss - Extend the global media expressions with a custom one
514
+ /// @include media-context($tweak-media-expressions: ('all': 'all')) {
515
+ /// .foo {
516
+ /// @include media('all', '>phone') {
517
+ /// // ...
518
+ /// }
519
+ /// }
520
+ /// }
521
+ ///
522
+ /// @example scss - Extend both configuration maps
523
+ /// @include media-context(('custom': 678px), ('all': 'all')) {
524
+ /// .foo {
525
+ /// @include media('all', '>phone', '<=custom') {
526
+ /// // ...
527
+ /// }
528
+ /// }
529
+ /// }
530
+ ///
531
+ @mixin media-context($tweakpoints: (), $tweak-media-expressions: ()) {
532
+ // Save global configuration
533
+ $global-breakpoints: $breakpoints;
534
+ $global-media-expressions: $media-expressions;
535
+
536
+ // Update global configuration
537
+ $breakpoints: map.merge($breakpoints, $tweakpoints) !global;
538
+ $media-expressions: map.merge($media-expressions, $tweak-media-expressions) !global;
539
+
540
+ @content;
541
+
542
+ // Restore global configuration
543
+ $breakpoints: $global-breakpoints !global;
544
+ $media-expressions: $global-media-expressions !global;
545
+ }
546
+
547
+ ////
548
+ /// include-media public exposed API
549
+ /// @author Eduardo Boucas
550
+ /// @access public
551
+ ////
552
+
553
+ ///
554
+ /// Generates a media query based on a list of conditions
555
+ ///
556
+ /// @param {Arglist} $conditions - Media query conditions
557
+ ///
558
+ /// @example scss - With a single set breakpoint
559
+ /// @include media('>phone') { }
560
+ ///
561
+ /// @example scss - With two set breakpoints
562
+ /// @include media('>phone', '<=tablet') { }
563
+ ///
564
+ /// @example scss - With custom values
565
+ /// @include media('>=358px', '<850px') { }
566
+ ///
567
+ /// @example scss - With set breakpoints with custom values
568
+ /// @include media('>desktop', '<=1350px') { }
569
+ ///
570
+ /// @example scss - With a static expression
571
+ /// @include media('retina2x') { }
572
+ ///
573
+ /// @example scss - Mixing everything
574
+ /// @include media('>=350px', '<tablet', 'retina3x') { }
575
+ ///
576
+ @mixin media($conditions...) {
577
+ @if ($im-media-support and list.length($conditions) == 0) or
578
+ (not $im-media-support and im-intercepts-static-breakpoint($conditions...))
579
+ {
580
+ @content;
581
+ } @else if ($im-media-support and list.length($conditions) > 0) {
582
+ @media #{string.unquote(parse-expression(list.nth($conditions, 1)))} {
583
+ // Recursive call
584
+ @include media(slice($conditions, 2)...) {
585
+ @content;
586
+ }
587
+ }
588
+ }
589
+ }
@@ -4,4 +4,4 @@ $breakpoints: (
4
4
  'desktop': 1920px,
5
5
  ) !default;
6
6
 
7
- @import 'include-media/dist/include-media';
7
+ @import './include-media-library';