@omnisass/library 0.2.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.
Files changed (93) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/LICENSE +21 -0
  3. package/README.md +2 -0
  4. package/_configs.scss +68 -0
  5. package/index.scss +95 -0
  6. package/modules/utilities/converters/_convert-camel2kebab.scss +186 -0
  7. package/modules/utilities/converters/_convert-em2px.scss +239 -0
  8. package/modules/utilities/converters/_convert-hex2rgb.scss +97 -0
  9. package/modules/utilities/converters/_convert-hex2rgba.scss +124 -0
  10. package/modules/utilities/converters/_convert-kebab2camel.scss +232 -0
  11. package/modules/utilities/converters/_convert-kebab2snake.scss +118 -0
  12. package/modules/utilities/converters/_convert-px2em.scss +236 -0
  13. package/modules/utilities/converters/_convert-px2rem.scss +180 -0
  14. package/modules/utilities/converters/_convert-rem2px.scss +207 -0
  15. package/modules/utilities/converters/_convert-snake2kebab.scss +173 -0
  16. package/modules/utilities/getters/color/_get-color-brightness.scss +138 -0
  17. package/modules/utilities/getters/color/_get-color-darkest.scss +178 -0
  18. package/modules/utilities/getters/list/_get-list-item-end.scss +114 -0
  19. package/modules/utilities/getters/list/_get-list-item-start.scss +109 -0
  20. package/modules/utilities/getters/list/_get-list-item.scss +179 -0
  21. package/modules/utilities/getters/number/_get-number-from-percent.scss +139 -0
  22. package/modules/utilities/getters/number/_get-number-height-by-ratio.scss +199 -0
  23. package/modules/utilities/getters/number/_get-number-max.scss +168 -0
  24. package/modules/utilities/getters/number/_get-number-min.scss +162 -0
  25. package/modules/utilities/getters/number/_get-number-percentage-of.scss +149 -0
  26. package/modules/utilities/getters/number/_get-number-unit.scss +111 -0
  27. package/modules/utilities/getters/number/_get-number-width-by-ratio.scss +223 -0
  28. package/modules/utilities/helpers/color/_color-blend-steps.scss +210 -0
  29. package/modules/utilities/helpers/color/_color-blend.scss +183 -0
  30. package/modules/utilities/helpers/color/_color-hue-shift.scss +148 -0
  31. package/modules/utilities/helpers/color/_color-scale.scss +208 -0
  32. package/modules/utilities/helpers/color/_color-shade.scss +113 -0
  33. package/modules/utilities/helpers/color/_color-tint.scss +118 -0
  34. package/modules/utilities/helpers/color/_color-triad.scss +141 -0
  35. package/modules/utilities/helpers/list/_list-dedupe.scss +146 -0
  36. package/modules/utilities/helpers/list/_list-insert-at.scss +166 -0
  37. package/modules/utilities/helpers/list/_list-merge.scss +86 -0
  38. package/modules/utilities/helpers/list/_list-remove-at.scss +160 -0
  39. package/modules/utilities/helpers/list/_list-sum-numbers-safe.scss +175 -0
  40. package/modules/utilities/helpers/list/_list-sum-numbers.scss +128 -0
  41. package/modules/utilities/helpers/misc/_url-encode.configs.scss +64 -0
  42. package/modules/utilities/helpers/misc/_url-encode.scss +148 -0
  43. package/modules/utilities/helpers/number/_number-ceil-to.scss +111 -0
  44. package/modules/utilities/helpers/number/_number-clamp-max.scss +92 -0
  45. package/modules/utilities/helpers/number/_number-clamp-min.scss +100 -0
  46. package/modules/utilities/helpers/number/_number-clamp.scss +109 -0
  47. package/modules/utilities/helpers/number/_number-denormalize.scss +172 -0
  48. package/modules/utilities/helpers/number/_number-fibonacci.scss +235 -0
  49. package/modules/utilities/helpers/number/_number-floor-to.scss +114 -0
  50. package/modules/utilities/helpers/number/_number-format-with-separator.scss +122 -0
  51. package/modules/utilities/helpers/number/_number-normalize.scss +160 -0
  52. package/modules/utilities/helpers/number/_number-random-between-int.scss +84 -0
  53. package/modules/utilities/helpers/number/_number-random-between.scss +120 -0
  54. package/modules/utilities/helpers/number/_number-range.scss +268 -0
  55. package/modules/utilities/helpers/number/_number-round-to-nearest.scss +131 -0
  56. package/modules/utilities/helpers/number/_number-round-to.scss +118 -0
  57. package/modules/utilities/helpers/number/_number-strip-unit.scss +97 -0
  58. package/modules/utilities/helpers/string/_string-capitalize.scss +84 -0
  59. package/modules/utilities/helpers/string/_string-replace.scss +69 -0
  60. package/modules/utilities/helpers/string/_string-trim-end.scss +62 -0
  61. package/modules/utilities/helpers/string/_string-trim-start.scss +62 -0
  62. package/modules/utilities/helpers/string/_string-trim.scss +69 -0
  63. package/modules/utilities/loggers/_log-invalid-type.scss +151 -0
  64. package/modules/utilities/loggers/_log-invalid-value.scss +151 -0
  65. package/modules/utilities/setters/_index.scss +3 -0
  66. package/modules/utilities/validators/color/_is-color-light.scss +132 -0
  67. package/modules/utilities/validators/color/_is-color-list.scss +124 -0
  68. package/modules/utilities/validators/list/_is-list-contained.scss +65 -0
  69. package/modules/utilities/validators/misc/_is-time.scss +115 -0
  70. package/modules/utilities/validators/number/_is-int-even.scss +69 -0
  71. package/modules/utilities/validators/number/_is-int-odd.scss +70 -0
  72. package/modules/utilities/validators/number/_is-int.scss +124 -0
  73. package/modules/utilities/validators/number/_is-number-has-unit.scss +85 -0
  74. package/modules/utilities/validators/number/_is-number-negative.scss +76 -0
  75. package/modules/utilities/validators/number/_is-number-positive.scss +74 -0
  76. package/modules/utilities/validators/number/_is-number-unitless.scss +88 -0
  77. package/modules/utilities/validators/number/_is-number-zero.scss +75 -0
  78. package/modules/utilities/validators/string/_is-string-contained.scss +108 -0
  79. package/modules/utilities/validators/string/_is-string-empty.scss +56 -0
  80. package/modules/utilities/validators/string/_is-string-ending-with.scss +66 -0
  81. package/modules/utilities/validators/string/_is-string-starting-with.scss +66 -0
  82. package/modules/utilities/validators/type-of/_is-boolean.scss +92 -0
  83. package/modules/utilities/validators/type-of/_is-color.scss +96 -0
  84. package/modules/utilities/validators/type-of/_is-list.scss +105 -0
  85. package/modules/utilities/validators/type-of/_is-map.scss +105 -0
  86. package/modules/utilities/validators/type-of/_is-number.scss +103 -0
  87. package/modules/utilities/validators/type-of/_is-string.scss +110 -0
  88. package/modules/utilities/validators/type-of/_is-type.scss +77 -0
  89. package/package.json +54 -0
  90. package/package.scss +156 -0
  91. package/test.md +168 -0
  92. package/test.scss +405 -0
  93. package/test.sh +149 -0
@@ -0,0 +1,223 @@
1
+ @use 'sass:math';
2
+ @use '../../loggers/log-invalid-type' as *;
3
+ @use '../../validators/type-of/is-number' as *;
4
+
5
+ /// Вычисляет ширину на основе высоты и соотношения сторон.
6
+ ///
7
+ /// Функция рассчитывает ширину элемента по заданной высоте и
8
+ /// соотношению сторон (aspect ratio). Соотношение сторон
9
+ /// определяется как `ширина / высота`. Эта функция является
10
+ /// обратной к `get-number-height-by-ratio()` и используется в
11
+ /// тех же сценариях адаптивного веб-дизайна, когда известна
12
+ /// высота, но нужно вычислить соответствующую ширину для
13
+ /// сохранения пропорций.
14
+ ///
15
+ /// Математическая формула:
16
+ /// - `width = height × ratio` (где `ratio = width / height`)
17
+ ///
18
+ /// Свойства результата:
19
+ /// - При `ratio = 1` (квадрат) → ширина равна высоте
20
+ /// - При `ratio > 1` (альбомная ориентация) → ширина больше
21
+ /// высоты
22
+ /// - При `ratio < 1` (портретная ориентация) → ширина меньше
23
+ /// высоты
24
+ /// - Результат имеет те же единицы измерения, что и `$height`
25
+ /// - Функция сохраняет пропорции исходного соотношения сторон
26
+ ///
27
+ /// Важные особенности функции:
28
+ /// - Вычисляет ширину по высоте и соотношению сторон
29
+ /// - Использует умножение вместо деления (более эффективно)
30
+ /// - Сохраняет единицы измерения высоты (px, rem, em, %, и т.д.)
31
+ /// - Поддерживает дробные значения соотношения сторон
32
+ /// - Идеально подходит для вертикально-ориентированных
33
+ /// интерфейсов
34
+ /// - Является парной функцией к `get-number-height-by-ratio()`
35
+ ///
36
+ /// > Вычисление ширины по соотношению сторон особенно полезно
37
+ /// > в мобильных интерфейсах и вертикальных макетах, где высота
38
+ /// > может быть фиксированной или известной заранее. Этот подход
39
+ /// > позволяет создавать адаптивные элементы, которые сохраняют
40
+ /// > пропорции независимо от ориентации устройства.
41
+ /// >
42
+ /// > Пример: для отображения изображения 4:3 с высотой 300px,
43
+ /// > ширина будет вычислена как 300 × (4/3) = 400px.
44
+ /// ---
45
+ /// @name get-number-width-by-ratio
46
+ /// @group utilities-getters
47
+ /// @since 2025.12.27
48
+ /// @access public
49
+ /// @author Murad Rustamov (therteenten)
50
+ /// @link https://sourcecraft.dev/users/therteenten/overview SourceCraft - therteenten
51
+ /// @link https://sourcecraft.dev/omnisass/library SourceCraft - OmniSass
52
+ /// @link https://sass-lang.com/documentation/values/numbers См. также: Официальная документация Sass - Тип данных "Числа"
53
+ /// @link https://sass-lang.com/documentation/modules/math См. также: Официальная документация Sass - Модуль math
54
+ /// @link https://developer.mozilla.org/en-US/docs/Web/CSS/aspect-ratio См. также: MDN Web Docs - CSS свойство aspect-ratio
55
+ /// @link https://css-tricks.com/aspect-ratio-boxes/ См. также: CSS-Tricks - Блоки с фиксированным соотношением сторон
56
+ /// @link https://www.w3schools.com/howto/howto_css_aspect_ratio.asp См. также: W3Schools - Как создавать блоки с фиксированным соотношением сторон
57
+ /// @example scss - Стандартные соотношения сторон видео
58
+ /// @debug get-number-width-by-ratio(450px, math.div(16, 9)); // 800px
59
+ /// @debug get-number-width-by-ratio(450px, 1.7777777778); // 800.00000001px
60
+ /// @debug get-number-width-by-ratio(600px, math.div(4, 3)); // 800px
61
+ /// @debug get-number-width-by-ratio(600px, 1.3333333333); // 799.99999998px
62
+ /// @debug get-number-width-by-ratio(342.8571428571px, math.div(21, 9)); // 799.9999999999px
63
+ /// @debug get-number-width-by-ratio(342.8571428571px, 2.3333333333); // 799.9999999884714px
64
+ /// @example scss - Квадратные и прямоугольные элементы
65
+ /// @debug get-number-width-by-ratio(400px, 1); // 400px (квадрат)
66
+ /// @debug get-number-width-by-ratio(300px, 2); // 600px (горизонтальный прямоугольник 2:1)
67
+ /// @debug get-number-width-by-ratio(1200px, 0.5); // 600px (вертикальный прямоугольник 1:2)
68
+ /// @debug get-number-width-by-ratio(200px, math.div(3, 2)); // 300px (3:2)
69
+ /// @debug get-number-width-by-ratio(450px, math.div(2, 3)); // 300px (2:3)
70
+ /// @example scss - Разные единицы измерения
71
+ /// @debug get-number-width-by-ratio(56.25%, math.div(16, 9)); // 100%
72
+ /// @debug get-number-width-by-ratio(28.125rem, math.div(16, 9)); // 50rem
73
+ /// @debug get-number-width-by-ratio(45vw, math.div(16, 9)); // 80vw
74
+ /// @debug get-number-width-by-ratio(675px, math.div(16, 9)); // 1200px
75
+ /// @debug get-number-width-by-ratio(48em, math.div(4, 3)); // 64em
76
+ /// @example scss - Дробные значения высоты
77
+ /// @debug get-number-width-by-ratio(422.15625px, math.div(16, 9)); // 750.5px
78
+ /// @debug get-number-width-by-ratio(683.1666666667px, 1.5); // 1024.75000000005px
79
+ /// @debug get-number-width-by-ratio(205rem, math.div(5, 4)); // 256.25rem
80
+ /// @debug get-number-width-by-ratio(61.7435117429%, 1.618); // 99.9010020000122% (золотое сечение)
81
+ /// @example scss - Популярные соотношения сторон (обратные вычисления)
82
+ /// // 1:1 - Квадрат, Instagram фото
83
+ /// @debug get-number-width-by-ratio(500px, 1); // 500px
84
+ ///
85
+ /// // 4:3 - Стандартный монитор, некоторые планшеты
86
+ /// @debug get-number-width-by-ratio(768px, math.div(4, 3)); // 1024px
87
+ ///
88
+ /// // 16:9 - Современное видео, Full HD
89
+ /// @debug get-number-width-by-ratio(1080px, math.div(16, 9)); // 1920px
90
+ ///
91
+ /// // 21:9 - Ультраширокий монитор, кинематографичный формат
92
+ /// @debug get-number-width-by-ratio(1097.1428571429px, math.div(21, 9)); // 2560.0000000001005px
93
+ ///
94
+ /// // 3:2 - Некоторые фотоаппараты, MacBook
95
+ /// @debug get-number-width-by-ratio(1200px, math.div(3, 2)); // 1800px
96
+ ///
97
+ /// // 1.618:1 - Золотое сечение
98
+ /// @debug get-number-width-by-ratio(618.0463572312px, 1.618); // 999.9990060000816px
99
+ /// @example scss - Для вертикальных адаптивных контейнеров
100
+ /// .vertical-video-container {
101
+ /// height: 100vh;
102
+ /// width: get-number-width-by-ratio(100vh, math.div(9, 16));
103
+ /// }
104
+ ///
105
+ /// .portrait-image {
106
+ /// height: 500px;
107
+ /// width: get-number-width-by-ratio(500px, math.div(3, 4));
108
+ /// }
109
+ ///
110
+ /// .mobile-card {
111
+ /// height: 200px;
112
+ /// width: get-number-width-by-ratio(200px, math.div(4, 5));
113
+ /// }
114
+ /// @example css - Результат
115
+ /// .vertical-video-container {
116
+ /// height: 100vh;
117
+ /// width: 56.25vh;
118
+ /// }
119
+ ///
120
+ /// .portrait-image {
121
+ /// height: 500px;
122
+ /// width: 375px;
123
+ /// }
124
+ ///
125
+ /// .mobile-card {
126
+ /// height: 200px;
127
+ /// width: 160px;
128
+ /// }
129
+ /// @example scss - Динамические вычисления для известной высоты
130
+ /// $container-height: 675px;
131
+ /// $aspect-ratio: math.div(16, 9);
132
+ /// @debug get-number-width-by-ratio($container-height, $aspect-ratio); // 1200px
133
+ ///
134
+ /// $mobile-height: 210.9375px;
135
+ /// @debug get-number-width-by-ratio($mobile-height, $aspect-ratio); // 375px
136
+ /// @example scss - Проверка граничных значений
137
+ /// @debug get-number-width-by-ratio(0px, math.div(16, 9)); // 0px
138
+ /// @debug get-number-width-by-ratio(1000px, 0); // 0px (соотношение 0 означает нулевую ширину)
139
+ /// // @debug get-number-width-by-ratio(1000px, math.infinity()); // infinity (теоретически), а так Error
140
+ /// @example scss - Очень большие и малые соотношения
141
+ /// @debug get-number-width-by-ratio(100px, 10); // 1000px (очень широкий)
142
+ /// @debug get-number-width-by-ratio(10000px, 0.1); // 1000px (очень узкий)
143
+ /// @debug get-number-width-by-ratio(5px, 100); // 500px
144
+ /// @debug get-number-width-by-ratio(50000px, 0.01); // 500px
145
+ /// @param {Number} $height - Высота элемента. Может быть
146
+ /// любым числом с единицами измерения (`px`, `rem`, `em`,
147
+ /// `%`, `vh`, и т.д.)
148
+ /// или без них.
149
+ /// @param {Number} $ratio - Соотношение сторон, вычисляемое
150
+ /// как `ширина / высота`. Например:
151
+ /// - 1.7777777778 для 16:9
152
+ /// - 1.3333333333 для 4:3
153
+ /// - 1 для квадрата
154
+ /// - 0.75 для портретного формата 3:4
155
+ /// @return {Number} - Ширина элемента, рассчитанная по формуле
156
+ /// `width = height × ratio`. Сохраняет единицы измерения
157
+ /// параметра `$height`.
158
+ @function get-number-width-by-ratio($height, $ratio) {
159
+
160
+ @if not is-number($height) {
161
+
162
+ // Валидация первого параметра: высота.
163
+ // Функция ожидает числовое значение, которое может содержать
164
+ // единицы измерения (px, rem, em, %, и т.д.).
165
+ //
166
+ // Если $height не является числом (например, строка, булево
167
+ // значение), вызываем стандартизированную функцию
168
+ // логирования ошибок.
169
+ @return log-invalid-type(
170
+ 'get-number-width-by-ratio',
171
+ $height,
172
+ '$height',
173
+ 'number'
174
+ );
175
+
176
+ }
177
+
178
+ @else if not is-number($ratio) {
179
+
180
+ // Валидация второго параметра: соотношение сторон.
181
+ // Соотношение должно быть числом (чаще всего безразмерным).
182
+ //
183
+ // Проверка выполняется только если $height прошел валидацию.
184
+ // Это последовательный подход fail-fast (быстрая остановка
185
+ // при ошибке).
186
+ @return log-invalid-type(
187
+ 'get-number-width-by-ratio',
188
+ $ratio,
189
+ '$ratio',
190
+ 'number'
191
+ );
192
+
193
+ }
194
+
195
+ @else {
196
+
197
+ // Оба параметра валидны - выполняем вычисление.
198
+ //
199
+ // Формула: ширина = высота × соотношение.
200
+ //
201
+ // Важные аспекты:
202
+ // 1. Умножение $height (с единицами) на $ratio (безразмерное)
203
+ // сохраняет единицы измерения из $height
204
+ // 2. Если $ratio также имеет единицы, Sass попытается их
205
+ // перемножить, что может привести к неожиданным результатам
206
+ // 3. Рекомендуется передавать $ratio как безразмерное число
207
+ @return $height * $ratio;
208
+
209
+ }
210
+
211
+ }
212
+
213
+ /// @name get-width-by-ratio
214
+ /// @alias get-number-width-by-ratio
215
+ /// @group utilities-aliases
216
+ /// @since 2025.12.27
217
+ /// @access public
218
+ /// @author Murad Rustamov (therteenten)
219
+ /// @link https://sourcecraft.dev/users/therteenten/overview SourceCraft - therteenten
220
+ /// @link https://sourcecraft.dev/omnisass/library SourceCraft - OmniSass
221
+ @function get-width-by-ratio($height, $ratio) {
222
+ @return get-number-width-by-ratio($height, $ratio);
223
+ }
@@ -0,0 +1,210 @@
1
+ @use 'sass:math';
2
+ @use 'sass:list';
3
+ @use 'sass:color';
4
+ @use '../../loggers/log-invalid-type' as *;
5
+ @use '../../validators/type-of/is-color' as *;
6
+ @use '../../validators/type-of/is-number' as *;
7
+
8
+ /// Создает последовательность равномерно распределенных
9
+ /// цветов между двумя точками.
10
+ ///
11
+ /// Функция `color-blend-steps()` генерирует список
12
+ /// промежуточных цветов, равномерно распределенных между
13
+ /// начальным и конечным цветами.
14
+ ///
15
+ /// Каждый цвет в последовательности представляет собой
16
+ /// линейную интерполяцию между `$color-start` и `$color-end` с
17
+ /// определенным процентом смешивания. Полезно для создания
18
+ /// цветовых градиентов с дискретными остановками, генерации
19
+ /// палитр или построения систем цветовых переходов с
20
+ /// контролируемым количеством шагов.
21
+ ///
22
+ /// > Все шаги равномерно распределены математически, но визуально
23
+ /// > могут восприниматься неравномерно в зависимости от цветового
24
+ /// > пространства.
25
+ /// ---
26
+ /// @name color-blend-steps
27
+ /// @group utilities-helpers
28
+ /// @since 2025.12.27
29
+ /// @access public
30
+ /// @author Murad Rustamov (therteenten)
31
+ /// @link https://sourcecraft.dev/users/therteenten/overview SourceCraft - therteenten
32
+ /// @link https://sourcecraft.dev/omnisass/library SourceCraft - OmniSass
33
+ /// @link https://sass-lang.com/documentation/modules/color#mix См. также: Sass - Функция color.mix()
34
+ /// @link https://developer.mozilla.org/en-US/docs/Web/CSS/gradient/linear-gradient См. также: MDN - Линейные градиенты
35
+ /// @link https://www.w3.org/TR/css-color-5/#color-mix См. также: W3C - Спецификация color-mix
36
+ /// @link https://css-tricks.com/striped-css-gradients/ См. также: CSS-Tricks - Полосатые CSS-градиенты
37
+ /// @example scss - Использование для CSS-переменных
38
+ /// @use 'sass:list';
39
+ ///
40
+ /// :root {
41
+ ///
42
+ /// $transition: color-blend-steps(#3498db, #2c3e50, 4);
43
+ ///
44
+ /// @for $i from 1 through list.length($transition) {
45
+ /// --color-step-#{$i}: #{list.nth($transition, $i)};
46
+ /// }
47
+ ///
48
+ /// }
49
+ /// @example css - Результат
50
+ /// :root {
51
+ /// --color-step-1: #3498db;
52
+ /// --color-step-2: rgb(50, 129.5, 184.25);
53
+ /// --color-step-3: rgb(48, 107, 149.5);
54
+ /// --color-step-4: rgb(46, 84.5, 114.75);
55
+ /// --color-step-5: #2c3e50;
56
+ /// }
57
+ /// @example scss - Создание плавного hover-эффекта с шагами
58
+ /// @use 'sass:list';
59
+ ///
60
+ /// .progress-bar {
61
+ /// $colors: color-blend-steps(#2ecc71, #e74c3c, 5);
62
+ ///
63
+ /// @for $i from 1 through list.length($colors) {
64
+ /// &--step-#{$i} {
65
+ /// background-color: list.nth($colors, $i);
66
+ /// }
67
+ /// }
68
+ ///
69
+ /// }
70
+ /// @example css - Результат
71
+ /// .progress-bar--step-1 {
72
+ /// background-color: #2ecc71;
73
+ /// }
74
+ /// .progress-bar--step-2 {
75
+ /// background-color: rgb(83, 178.4, 102.4);
76
+ /// }
77
+ /// .progress-bar--step-3 {
78
+ /// background-color: rgb(120, 152.8, 91.8);
79
+ /// }
80
+ /// .progress-bar--step-4 {
81
+ /// background-color: rgb(157, 127.2, 81.2);
82
+ /// }
83
+ /// .progress-bar--step-5 {
84
+ /// background-color: rgb(194, 101.6, 70.6);
85
+ /// }
86
+ /// .progress-bar--step-6 {
87
+ /// background-color: #e74c3c;
88
+ /// }
89
+ /// @example scss - Генерация градиента с дискретными остановками
90
+ /// @use 'sass:list';
91
+ ///
92
+ /// .gradient-stripes {
93
+ /// background: linear-gradient(
94
+ /// to right,
95
+ /// #{list.nth(color-blend-steps(#ff0000, #00ff00, 5), 1)},
96
+ /// #{list.nth(color-blend-steps(#ff0000, #00ff00, 5), 3)},
97
+ /// #{list.nth(color-blend-steps(#ff0000, #00ff00, 5), 5)},
98
+ /// #{list.nth(color-blend-steps(#ff0000, #00ff00, 5), 6)},
99
+ /// );
100
+ /// }
101
+ /// @example css - Результат
102
+ /// gradient-stripes {
103
+ /// background: linear-gradient(to right, red, #996600, #33cc00, lime);
104
+ /// }
105
+ /// @param {Color} $color-start - Начальный цвет последовательности.
106
+ /// Может быть в любом формате, поддерживаемом Sass (HEX, RGB,
107
+ /// HSL и т.д.).
108
+ /// @param {Color} $color-end - Конечный цвет последовательности.
109
+ /// Должен быть совместим по цветовому пространству с `$color-start`.
110
+ /// @param {Number} $steps [5] - Количество промежуточных шагов
111
+ /// между цветами. Определяет, сколько цветов будет сгенерировано
112
+ /// между начальным и конечным. Фактическое количество цветов в
113
+ /// результате = `$steps + 2`. Минимальное значение - `0` (вернет
114
+ /// только начальный и конечный цвета).
115
+ /// @return {List} - Упорядоченный список (list) цветов, где:
116
+ /// - Первый элемент: чистый `$color-start` (0% смешивания)
117
+ /// - Последний элемент: чистый `$color-end` (100% смешивания)
118
+ /// - Промежуточные элементы: равномерно распределенные смеси
119
+ /// - Всего элементов: `$steps + 2`
120
+ @function color-blend-steps($color-start, $color-end, $steps: 5) {
121
+
122
+ // Инициализация списка для хранения промежуточных цветов.
123
+ // Результатом функции будет список (массив) цветов,
124
+ // представляющих градиентный переход от начального цвета
125
+ // к конечному.
126
+ $-colors: ();
127
+
128
+ // Проверка типа первого параметра: ожидается начальный цвет.
129
+ // Функция is-color() проверяет, является ли $color-start
130
+ // валидным цветом CSS.
131
+ @if not is-color($color-start) {
132
+
133
+ // Если $color-start не является цветом, возвращаем ошибку через
134
+ // стандартную функцию логирования. Это предотвращает
135
+ // некорректные вычисления с нецветовыми данными.
136
+ @return log-invalid-type(
137
+ 'color-blend-steps',
138
+ $color-start,
139
+ '$color-start',
140
+ 'color'
141
+ );
142
+
143
+ }
144
+
145
+ // Проверка типа второго параметра: ожидается конечный цвет.
146
+ // Проверка выполняется только если $color-start прошел валидацию.
147
+ @else if not is-color($color-end) {
148
+
149
+ // Если $color-end не является цветом, возвращаем ошибку.
150
+ @return log-invalid-type(
151
+ 'color-blend-steps',
152
+ $color-end,
153
+ '$color-end',
154
+ 'color'
155
+ );
156
+
157
+ }
158
+
159
+ // Проверка типа третьего параметра: ожидается количество шагов.
160
+ // $steps определяет, сколько промежуточных цветов будет сгенерировано
161
+ // между начальным и конечным цветом.
162
+ @else if not is-number($steps) {
163
+
164
+ // Если $steps не является числом, возвращаем ошибку.
165
+ @return log-invalid-type(
166
+ 'color-blend-steps',
167
+ $steps,
168
+ '$steps',
169
+ 'number'
170
+ );
171
+
172
+ }
173
+
174
+ // Все параметры прошли валидацию - выполняем генерацию цветов.
175
+ @else {
176
+
177
+ // Цикл генерации промежуточных цветов.
178
+ // Переменная $i принимает значения от 0 до $steps включительно.
179
+ // Это создает $steps + 1 цвет в итоговом списке
180
+ // (включая начальный и конечный цвета).
181
+ @for $i from 0 through $steps {
182
+
183
+ // Вычисление процентного соотношения для текущего шага.
184
+ // Формула: (текущий шаг) × (100% / общее количество шагов)
185
+ // Пример для 5 шагов: шаги будут на 0%, 20%, 40%, 60%, 80%, 100%
186
+ $-percentage: $i * math.div(100, $steps);
187
+
188
+ // Создание промежуточного цвета с помощью функции color.mix()
189
+ // color.mix() смешивает два цвета в указанной пропорции.
190
+ // Параметры:
191
+ // - $color-end: первый цвет для смешивания
192
+ // - $color-start: второй цвет для смешивания
193
+ // - $-percentage * 1%: процентное соотношение
194
+ // (сколько процентов $color-start в смеси)
195
+ //
196
+ // Примечание: порядок параметров в color.mix() важен:
197
+ // - При $-percentage = 0% → 100% $color-end, 0% $color-start
198
+ // - При $-percentage = 100% → 0% $color-end, 100% $color-start
199
+ $-colors: list.append($-colors, color.mix($color-end, $color-start, $-percentage * 1%));
200
+
201
+ }
202
+
203
+ // Возвращаем список сгенерированных цветов.
204
+ // Список содержит $steps + 1 элементов, равномерно распределенных
205
+ // между начальным и конечным цветом.
206
+ @return $-colors;
207
+
208
+ }
209
+
210
+ }
@@ -0,0 +1,183 @@
1
+ @use 'sass:color';
2
+ @use '../../loggers/log-invalid-type' as *;
3
+ @use '../../validators/type-of/is-color' as *;
4
+ @use '../../validators/type-of/is-number' as *;
5
+
6
+ /// Линейная интерполяция (смешивание) между двумя цветами.
7
+ ///
8
+ /// Функция `color-blend()` создает промежуточный цвет между
9
+ /// двумя заданными точками, используя линейную интерполяцию.
10
+ ///
11
+ /// Это упрощенная обертка над встроенной функцией
12
+ /// `color.mix()` с автоматическим преобразованием процента.
13
+ /// Полезно для создания плавных переходов, градиентов,
14
+ /// оттенков или любого промежуточного состояния между двумя
15
+ /// цветами.
16
+ ///
17
+ /// > Функция автоматически добавляет единицы % к
18
+ /// > параметру `$percentage`.
19
+ ///
20
+ /// > Для сложных градиентов или смешивания в специфических
21
+ /// > пространствах используйте встроенную функцию
22
+ /// > `color.mix()` напрямую.
23
+ ///
24
+ /// > Результат зависит от цветового пространства смешивания
25
+ /// > по умолчанию. Для контроля пространства используйте
26
+ /// > `color.mix()` с параметром `$space`.
27
+ /// ---
28
+ /// @name color-blend
29
+ /// @group utilities-helpers
30
+ /// @since 2025.12.27
31
+ /// @access public
32
+ /// @author Murad Rustamov (therteenten)
33
+ /// @link https://sourcecraft.dev/users/therteenten/overview SourceCraft - therteenten
34
+ /// @link https://sourcecraft.dev/omnisass/library SourceCraft - OmniSass
35
+ /// @link https://sass-lang.com/documentation/modules/color#mix См. также: Sass - Функция color.mix()
36
+ /// @link https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/color-mix См. также: MDN - CSS функция color-mix()
37
+ /// @link https://www.w3.org/TR/css-color-5/#color-mix См. также: W3C - Спецификация color-mix
38
+ /// @link https://css-tricks.com/color-mix-function/ См. также: CSS-Tricks - Функция color-mix()
39
+ /// @example scss - Создание промежуточного оттенка
40
+ /// $mid-color: color-blend(#ff0000, #0000ff, 50);
41
+ ///
42
+ /// // Результат: #800080 (фиолетовый)
43
+ /// .element {
44
+ /// color: $mid-color;
45
+ /// }
46
+ /// @example css - Результат
47
+ /// .element {
48
+ /// color: rgb(127.5, 0, 127.5);
49
+ /// }
50
+ /// @example scss - Плавный hover-эффект
51
+ /// .button {
52
+ /// background-color: #3498db;
53
+ ///
54
+ /// &:hover {
55
+ /// // Плавное затемнение при наведении
56
+ /// background-color: color-blend(#3498db, #2c3e50, 70);
57
+ /// }
58
+ ///
59
+ /// }
60
+ /// @example css - Результат
61
+ /// .button {
62
+ /// background-color: #3498db;
63
+ /// }
64
+ ///
65
+ /// .button:hover {
66
+ /// background-color: rgb(46.4, 89, 121.7);
67
+ /// }
68
+ /// @example scss - Создание градиента с несколькими остановками
69
+ /// .gradient-box {
70
+ ///
71
+ /// background: linear-gradient(
72
+ /// to right,
73
+ /// color-blend(#ff0000, #00ff00, 0),
74
+ /// color-blend(#ff0000, #00ff00, 25),
75
+ /// color-blend(#ff0000, #00ff00, 50),
76
+ /// color-blend(#ff0000, #00ff00, 75),
77
+ /// color-blend(#ff0000, #00ff00, 100)
78
+ /// );
79
+ ///
80
+ /// }
81
+ /// @example css - Результат
82
+ /// .gradient-box {
83
+ /// background: linear-gradient(to right, red, rgb(191.25, 63.75, 0), rgb(127.5, 127.5, 0), rgb(63.75, 191.25, 0), lime);
84
+ /// }
85
+ /// @example scss - Осветление и затемнение через смешивание
86
+ /// // Лучше использовать функции color-shade и color-tint
87
+ /// // из набора OmniSass.
88
+ ///
89
+ /// $base-color: #9b59b6;
90
+ /// $lightened: color-blend($base-color, white, 30); // Осветление на 30%
91
+ /// $darkened: color-blend($base-color, black, 30); // Затемнение на 30%
92
+ /// @see color-shade
93
+ /// @see color-tint
94
+ /// @param {Color} $color-from - Исходный (начальный) цвет. Может
95
+ /// быть в любом формате, поддерживаемом Sass (HEX, RGB,
96
+ /// HSL и т.д.).
97
+ /// @param {Color} $color-to - Целевой (конечный) цвет. Автоматически
98
+ /// приводится к тому же цветовому пространству, что и
99
+ /// `$color-from`.
100
+ /// @param {Number} $percentage - Процент смешивания от
101
+ /// `$color-from` к `$color-to` (0-100). Значение автоматически
102
+ /// конвертируется в проценты с помощью умножения на 1%.
103
+ /// - 0: возвращает чистый цвет `$color-from`
104
+ /// - 100: возвращает чистый цвет `$color-to`
105
+ /// - 50: возвращает ровную смесь `50/50`
106
+ /// @return {Color} - Промежуточный цвет, полученный линейной
107
+ /// интерполяцией между `$color-from` и `$color-to` в указанной пропорции.
108
+ /// Использует цветовое пространство по умолчанию для
109
+ /// смешивания (обычно sRGB).
110
+ @function color-blend($color-from, $color-to, $percentage) {
111
+
112
+ // Проверка типа первого параметра: ожидается начальный цвет.
113
+ // Функция is-color() проверяет, является ли $color-from
114
+ // валидным цветом CSS.
115
+ @if not is-color($color-from) {
116
+
117
+ // Если $color-from не является цветом, возвращаем ошибку через
118
+ // стандартную функцию логирования. Это предотвращает
119
+ // некорректные вычисления с нецветовыми данными.
120
+ @return log-invalid-type(
121
+ 'color-blend',
122
+ $color-from,
123
+ '$color-from',
124
+ 'color'
125
+ );
126
+
127
+ }
128
+
129
+ // Проверка типа второго параметра: ожидается конечный цвет.
130
+ // Проверка выполняется только если $color-from прошел валидацию.
131
+ @else if not is-color($color-to) {
132
+
133
+ // Если $color-to не является цветом, возвращаем ошибку.
134
+ @return log-invalid-type(
135
+ 'color-blend',
136
+ $color-to,
137
+ '$color-to',
138
+ 'color'
139
+ );
140
+
141
+ }
142
+
143
+ // Проверка типа третьего параметра: ожидается процент смешивания.
144
+ // $percentage определяет, сколько процентов начального цвета
145
+ // будет в итоговой смеси (от 0 до 100).
146
+ @else if not is-number($percentage) {
147
+
148
+ // Если $percentage не является числом, возвращаем ошибку.
149
+ @return log-invalid-type(
150
+ 'color-blend',
151
+ $percentage,
152
+ '$percentage',
153
+ 'number'
154
+ );
155
+
156
+ }
157
+
158
+ // Все параметры прошли валидацию - выполняем смешивание цветов.
159
+ @else {
160
+
161
+ // Формула смешивания: создаем промежуточный цвет между
162
+ // $color-from и $color-to с указанным процентным соотношением.
163
+ //
164
+ // Используем встроенную функцию color.mix():
165
+ // Параметры:
166
+ // - $color-to: первый цвет для смешивания
167
+ // - $color-from: второй цвет для смешивания
168
+ // - $percentage * 1%: процентное соотношение
169
+ // (сколько процентов $color-from в смеси)
170
+ //
171
+ // Математика смешивания:
172
+ // - При $percentage = 0% → 100% $color-to, 0% $color-from
173
+ // - При $percentage = 50% → 50% $color-to, 50% $color-from
174
+ // - При $percentage = 100% → 0% $color-to, 100% $color-from
175
+ //
176
+ // Ключевая особенность: функция является оберткой над
177
+ // color.mix() с добавлением валидации параметров и
178
+ // преобразованием процентов в правильный формат.
179
+ @return color.mix($color-to, $color-from, $percentage * 1%);
180
+
181
+ }
182
+
183
+ }