@rotcetihra/c2c 1.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/LICENSE +21 -0
- package/README.md +1309 -0
- package/package.json +28 -0
- package/src/_error.scss +18 -0
- package/src/_generate.scss +659 -0
- package/src/_index.scss +1 -0
- package/src/_render.scss +70 -0
- package/src/_utility.scss +171 -0
- package/src/_validate.scss +46 -0
- package/src/_var.scss +386 -0
package/README.md
ADDED
|
@@ -0,0 +1,1309 @@
|
|
|
1
|
+
# C2C — Config-to-CSS Compiler
|
|
2
|
+
|
|
3
|
+
[](https://sass-lang.com/)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
|
|
6
|
+
**C2C (Config-to-CSS)** — это декларативный AOT (Ahead-Of-Time) компилятор и движок генерации
|
|
7
|
+
атомарных CSS-утилит, написанный на современном Dart Sass.
|
|
8
|
+
|
|
9
|
+
Проект вдохновлен философией Tailwind CSS, но переносит логику сборки дизайн-системы непосредственно
|
|
10
|
+
на уровень препроцессора. Вместо написания шаблонного CSS-кода вручную, вы описываете структуру
|
|
11
|
+
вашей дизайн-системы в виде Sass-карт (`Maps`), а движок автоматически разворачивает их в
|
|
12
|
+
структурированные атомарные классы, включая адаптивные брейкпоинты, интерактивные состояния и их
|
|
13
|
+
пересечения.
|
|
14
|
+
|
|
15
|
+
## 🚀 Главные особенности
|
|
16
|
+
|
|
17
|
+
- **Декларативность:** Полное разделение данных (вашей конфигурации) и логики рендеринга.
|
|
18
|
+
- **Продвинутый полиморфизм:** Генераторы компилятора автоматически адаптируются под тип переданных
|
|
19
|
+
данных (обработка плоских строк, списков и комплексных карт-шаблонов).
|
|
20
|
+
- **Комбинаторика вариантов:** Автоматическая генерация модификаторов состояний (`h:`, `f:`, `a:`) и
|
|
21
|
+
адаптивных медиа-запросов (`md:`, `lg:`) для любого модуля одной строчкой в конфиге.
|
|
22
|
+
- **Строгая валидация:** Встроенная система контроля типов и обязательных полей верхнего и
|
|
23
|
+
вложенного уровней — понятные сообщения об ошибках в консоли компилятора при сборке.
|
|
24
|
+
- **Готов к Production:** Спроектирован с учетом обязательной фильтрации через **PurgeCSS /
|
|
25
|
+
PostCSS**, что позволяет генерировать любые объемы утилит на этапе разработки без раздувания
|
|
26
|
+
финального бандла.
|
|
27
|
+
|
|
28
|
+
> 💡 **Обратите внимание:** Это статический AOT-компилятор (генерация до сборки), а не JIT-движок.
|
|
29
|
+
> Он компилирует конфигурационные матрицы в статический CSS-файл, из которого сборщик затем вычищает
|
|
30
|
+
> неиспользуемые классы.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## 📦 Установка
|
|
35
|
+
|
|
36
|
+
Вы можете установить компилятор **C2C** как стандартную зависимость через ваш любимый пакетный
|
|
37
|
+
менеджер.
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# Через npm
|
|
41
|
+
npm install @rotcetihra/c2c
|
|
42
|
+
|
|
43
|
+
# Через yarn
|
|
44
|
+
yarn add c2c
|
|
45
|
+
|
|
46
|
+
# Через pnpm
|
|
47
|
+
pnpm add c2c
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 🔌 Базовое подключение
|
|
51
|
+
|
|
52
|
+
Чтобы начать работу, достаточно импортировать компилятор в ваш главный файл стилей и передать
|
|
53
|
+
конфигурационную карту в метод-оркестратор. Благодаря встроенной системе модулей Dart Sass (`@use`),
|
|
54
|
+
все внутренние механизмы компилятора доступны через единую точку входа.
|
|
55
|
+
|
|
56
|
+
```scss
|
|
57
|
+
// main.scss проекта
|
|
58
|
+
@use "pkg:@rotcetihra/c2c" as c2c;
|
|
59
|
+
|
|
60
|
+
// 1. Описываем конфигурацию вашего модуля
|
|
61
|
+
$display-config: (
|
|
62
|
+
// Имя модуля (Используется для отладки).
|
|
63
|
+
"name": "layout",
|
|
64
|
+
|
|
65
|
+
// Блок с описанием утилит по их свойствам.
|
|
66
|
+
"properties": (
|
|
67
|
+
(
|
|
68
|
+
"use": (
|
|
69
|
+
// Сгенерировать точки останова (`sm:`, `md:`, `lg:` и др.).
|
|
70
|
+
"breakpoints": true,
|
|
71
|
+
// Сгенерировать только перечисленные состояния.
|
|
72
|
+
"states": (
|
|
73
|
+
"h",
|
|
74
|
+
// :hover
|
|
75
|
+
"f",
|
|
76
|
+
// :focus
|
|
77
|
+
"a" // :active
|
|
78
|
+
),
|
|
79
|
+
),
|
|
80
|
+
"values": (
|
|
81
|
+
// Свойство, на основе которого будут генерироваться утилиты.
|
|
82
|
+
"display": (
|
|
83
|
+
// "Имя утилиты": "Значение утилиты"
|
|
84
|
+
"block": "block",
|
|
85
|
+
"inline": "inline",
|
|
86
|
+
"flex": "flex",
|
|
87
|
+
"hidden": "none"
|
|
88
|
+
),
|
|
89
|
+
),
|
|
90
|
+
)
|
|
91
|
+
)
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
// 2. Запускаем компиляцию
|
|
95
|
+
@include c2c.by($display-config);
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
> 📌 **Примечание к импорту:** Префикс `pkg:` поддерживается современным Dart Sass и большинством
|
|
99
|
+
> популярных сборщиков (Vite, Webpack с `sass-loader`, Rspack). Если ваш сборщик использует
|
|
100
|
+
> устаревшие настройки разрешения путей, импорт может выглядеть как `@use "~c2c" as c2c;` или
|
|
101
|
+
> требовать прямого указания пути к `node_modules`.
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## 📐 Архитектура конфигурации (Configuration Matrix)
|
|
106
|
+
|
|
107
|
+
В основе **C2C** лежит концепция **конфигурационной матрицы модуля**. Каждый модуль (например,
|
|
108
|
+
`display`, `spacing`, `colors`) описывается в виде единой многомерной карты Sass (`Map`).
|
|
109
|
+
|
|
110
|
+
Движок устроен ортогонально: свойства отображения (брейкпоинты, ховеры) отделены от самих
|
|
111
|
+
генерируемых данных. Вы можете комбинировать разные типы генераторов внутри одной конфигурации.
|
|
112
|
+
|
|
113
|
+
### Полный каркас конфигурации модуля
|
|
114
|
+
|
|
115
|
+
Ниже представлена полная структура карты, которую принимает оркестратор `c2c.by()`. Каждая секция
|
|
116
|
+
является опциональной и запускает соответствующий метод компиляции:
|
|
117
|
+
|
|
118
|
+
```scss
|
|
119
|
+
$module-config: (
|
|
120
|
+
// 1. Идентификатор модуля
|
|
121
|
+
"name": "module-name",
|
|
122
|
+
|
|
123
|
+
// 2. Статические утилиты (Один класс = Одно свойство = Одно значение)
|
|
124
|
+
"properties": (/* ... */),
|
|
125
|
+
// 3. Динамические числовые диапазоны
|
|
126
|
+
"steps": (/* ... */),
|
|
127
|
+
// 4. Дробные и сеточные утилиты
|
|
128
|
+
"fractions": (/* ... */),
|
|
129
|
+
// 5. Цветовые утилиты
|
|
130
|
+
"palettes": (/* ... */),
|
|
131
|
+
// 6. Комплексные составные классы (Один класс = Пачка CSS-свойств)
|
|
132
|
+
"classes": (/* ... */),
|
|
133
|
+
// 7. Глобальные именованные CSS-блоки (На данный момент поддерживается только @keyframes)
|
|
134
|
+
"blocks": (/* ... */)
|
|
135
|
+
);
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Общая анатомия внутренних блоков
|
|
139
|
+
|
|
140
|
+
Каждый генератор (`properties`, `steps` и т.д.) внутри конфигурации ожидает карту, состоящую из двух
|
|
141
|
+
ключевых частей:
|
|
142
|
+
|
|
143
|
+
1. **`"use"` (Настройки вариантов):** Управляет генерацией модификаторов. Здесь вы указываете, нужно
|
|
144
|
+
ли генерировать для этого конкретного блока адаптивные брейкпоинты (`"breakpoints": true`) или
|
|
145
|
+
интерактивные состояния (`"states": ("h", "f")`).
|
|
146
|
+
2. **`"values"` (Данные для компиляции):** Карта, структура которой специфична для каждого
|
|
147
|
+
конкретного метода (строки, списки или вложенные карты).
|
|
148
|
+
|
|
149
|
+
#### Абстрактный пример структуры генератора:
|
|
150
|
+
|
|
151
|
+
```scss
|
|
152
|
+
"properties":(("use":("breakpoints":true,"states": ("h"),
|
|
153
|
+
),
|
|
154
|
+
"values": (
|
|
155
|
+
// Данные, которые будут прогнаны через циклы модификаторов
|
|
156
|
+
)
|
|
157
|
+
)
|
|
158
|
+
);
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Такой подход позволяет гибко настраивать генерацию кода: например, для модуля `display` вам могут
|
|
162
|
+
быть жизненно необходимы брейкпоинты (`md:block`), но абсолютно не нужны ховеры, в то время как для
|
|
163
|
+
модуля `palettes` (цветовых схем) вам понадобятся и брейкпоинты, и ховеры одновременно.
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## 🛠 Руководство по методам компиляции
|
|
168
|
+
|
|
169
|
+
В этом разделе подробно описаны все доступные миксины-генераторы компилятора **C2C**. Каждый метод
|
|
170
|
+
спроектирован как изолированный математический движок, который принимает очищенные данные из вашей
|
|
171
|
+
конфигурации и разворачивает их в валидный CSS-код.
|
|
172
|
+
|
|
173
|
+
### 🧩 Главный принцип: Полиморфизм данных
|
|
174
|
+
|
|
175
|
+
Ключевая особенность компилятора **C2C** — его «всеядность» и гибкость к типам данных во входных
|
|
176
|
+
параметрах (`values`). Движок под капотом использует инспекцию типов (мета-проверки на строки,
|
|
177
|
+
списки и карты).
|
|
178
|
+
|
|
179
|
+
Это означает, что один и тот же метод компиляции может вести себя абсолютно по-разному в зависимости
|
|
180
|
+
от того, как вы описали целевое CSS-свойство:
|
|
181
|
+
|
|
182
|
+
- **Плоская строка (`String`):** Запускает классический атомарный рендеринг (одно свойство = одно
|
|
183
|
+
динамическое значение).
|
|
184
|
+
- **Список (`List`):** Позволяет генерировать комбинированные классы, где одно динамическое значение
|
|
185
|
+
одновременно присваивается массиву свойств (например, `inset-x` сразу для `left` и `right`).
|
|
186
|
+
- **Карта-шаблон (`Map`):** Включает продвинутый режим шаблонизации. Движок ищет внутри
|
|
187
|
+
строки-значения специальный знак плейсхолдера (`*`) и подставляет вычисленный шаг или цвет прямо
|
|
188
|
+
внутрь сложных CSS-функций (например, `rgba(*, var(--opacity))` или `translateX(*)`).
|
|
189
|
+
|
|
190
|
+
Ниже приведены подробные спецификации для каждого метода компиляции с примерами входных конфигураций
|
|
191
|
+
(`Map`) и результатом их компиляции в CSS-код.
|
|
192
|
+
|
|
193
|
+
### 4.1. Оркестратор `by($config)`
|
|
194
|
+
|
|
195
|
+
Миксин `by()` является главной входной точкой (оркестратором) конвейера **C2C**. Он инкапсулирует
|
|
196
|
+
логику верхнего уровня: принимает сырую конфигурационную карту модуля, проверяет её целостность,
|
|
197
|
+
извлекает метаданные (имя модуля, глобальные флаги) и автоматически распределяет блоки данных по
|
|
198
|
+
соответствующим генераторам нижнего уровня с помощью динамического вызова миксинов
|
|
199
|
+
(`meta.get-mixin`).
|
|
200
|
+
|
|
201
|
+
Вам не нужно вручную вызывать `properties`, `steps` или `palettes` — оркестратор сделает это сам на
|
|
202
|
+
основе ключей вашей конфигурации.
|
|
203
|
+
|
|
204
|
+
#### 📝 Пример конфигурации модуля
|
|
205
|
+
|
|
206
|
+
Передаем карту модуля в миксин `c2c.by()`. В данном примере мы объединяем статические свойства и
|
|
207
|
+
динамические шаги в рамках одного модуля `spacing`:
|
|
208
|
+
|
|
209
|
+
```scss
|
|
210
|
+
@use "pkg:@rotcetihra/c2c" as c2c;
|
|
211
|
+
|
|
212
|
+
$spacing-module: (
|
|
213
|
+
"name": "spacing",
|
|
214
|
+
|
|
215
|
+
// Статический блок (вызовет метод properties)
|
|
216
|
+
"properties": (
|
|
217
|
+
(
|
|
218
|
+
"use": (
|
|
219
|
+
"breakpoints": true,
|
|
220
|
+
),
|
|
221
|
+
"values": (
|
|
222
|
+
"box-sizing": (
|
|
223
|
+
"box-border": "border-box",
|
|
224
|
+
"box-content": "content-box",
|
|
225
|
+
),
|
|
226
|
+
),
|
|
227
|
+
),
|
|
228
|
+
),
|
|
229
|
+
|
|
230
|
+
// Динамический блок (вызовет метод steps)
|
|
231
|
+
"steps": (
|
|
232
|
+
(
|
|
233
|
+
"use": (
|
|
234
|
+
"breakpoints": true,
|
|
235
|
+
),
|
|
236
|
+
"meta": (
|
|
237
|
+
"from": 0,
|
|
238
|
+
"to": 2,
|
|
239
|
+
"step": 1,
|
|
240
|
+
"unit": "rem",
|
|
241
|
+
),
|
|
242
|
+
"values": (
|
|
243
|
+
"p": "padding",
|
|
244
|
+
),
|
|
245
|
+
),
|
|
246
|
+
),
|
|
247
|
+
);
|
|
248
|
+
|
|
249
|
+
// Запуск глобального конвейера сборки модуля
|
|
250
|
+
@include c2c.by($spacing-module);
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
#### 📄 Результат компиляции в CSS
|
|
254
|
+
|
|
255
|
+
Оркестратор самостоятельно распознал типы блоков, прогнал их через внутренний цикл брейкпоинтов (для
|
|
256
|
+
тех блоков, где был флаг `breakpoints: true`) и сгенерировал плоский CSS-код:
|
|
257
|
+
|
|
258
|
+
```css
|
|
259
|
+
/* Базовые статические утилиты */
|
|
260
|
+
.box-border {
|
|
261
|
+
box-sizing: border-box;
|
|
262
|
+
}
|
|
263
|
+
.box-content {
|
|
264
|
+
box-sizing: content-box;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/* Базовые динамические шаги */
|
|
268
|
+
.p-0 {
|
|
269
|
+
padding: 0rem;
|
|
270
|
+
}
|
|
271
|
+
.p-1 {
|
|
272
|
+
padding: 1rem;
|
|
273
|
+
}
|
|
274
|
+
.p-2 {
|
|
275
|
+
padding: 2rem;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/* Адаптивные модификаторы (внутри медиа-запросов) */
|
|
279
|
+
@media (min-width: 768px) {
|
|
280
|
+
.md\:box-border {
|
|
281
|
+
box-sizing: border-box;
|
|
282
|
+
}
|
|
283
|
+
.md\:box-content {
|
|
284
|
+
box-sizing: content-box;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
.md\:p-0 {
|
|
288
|
+
padding: 0rem;
|
|
289
|
+
}
|
|
290
|
+
.md\:p-1 {
|
|
291
|
+
padding: 1rem;
|
|
292
|
+
}
|
|
293
|
+
.md\:p-2 {
|
|
294
|
+
padding: 2rem;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### 4.2. Метод `properties` (Статические утилиты)
|
|
300
|
+
|
|
301
|
+
Метод `properties` предназначен для generation традиционных статических утилит, где имя класса,
|
|
302
|
+
целевое CSS-свойство и его значение жестко зафиксированы в конфигурации. Этот генератор идеально
|
|
303
|
+
подходит для таких модулей, как `display`, `position`, `overflow`, `text-align`, `font-weight` и
|
|
304
|
+
других нечисловых CSS-свойств.
|
|
305
|
+
|
|
306
|
+
Генератор ожидает строгую двумерную карту (`2D Map`) в ключе `values`, которая раскладывается по
|
|
307
|
+
следующему принципу: `CSS-Свойство -> ( Желаемый CSS-Класс: Итоговое CSS-Значение )`
|
|
308
|
+
|
|
309
|
+
#### 📝 Пример конфигурации модуля
|
|
310
|
+
|
|
311
|
+
В данном примере настраивается генерация утилит для управления позиционированием и отображением
|
|
312
|
+
элементов с поддержкой адаптивных брейкпоинтов и ховер-состояний:
|
|
313
|
+
|
|
314
|
+
```scss
|
|
315
|
+
@use "pkg:@rotcetihra/c2c" as c2c;
|
|
316
|
+
|
|
317
|
+
$layout-module: (
|
|
318
|
+
"name": "layout",
|
|
319
|
+
"properties": (
|
|
320
|
+
(
|
|
321
|
+
// Настройки вариантов (модификаторов)
|
|
322
|
+
"use": (
|
|
323
|
+
"breakpoints": true,
|
|
324
|
+
"states": (
|
|
325
|
+
"h",
|
|
326
|
+
),
|
|
327
|
+
),
|
|
328
|
+
// Матрица статических значений
|
|
329
|
+
"values": (
|
|
330
|
+
"position": (
|
|
331
|
+
"absolute": "absolute",
|
|
332
|
+
"relative": "relative",
|
|
333
|
+
"fixed": "fixed",
|
|
334
|
+
),
|
|
335
|
+
"pointer-events": (
|
|
336
|
+
"click-allow": "auto",
|
|
337
|
+
"click-none": "none",
|
|
338
|
+
),
|
|
339
|
+
)
|
|
340
|
+
),
|
|
341
|
+
),
|
|
342
|
+
);
|
|
343
|
+
|
|
344
|
+
@include c2c.by($layout-module);
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
#### 📄 Результат компиляции в CSS
|
|
348
|
+
|
|
349
|
+
Благодаря встроенной в метод безопасной интерполяции строк, пустые модификаторы контекста бесследно
|
|
350
|
+
исчезают в базовых классах, но автоматически разворачиваются при генерации вариантов:
|
|
351
|
+
|
|
352
|
+
```css
|
|
353
|
+
/* Базовые утилиты */
|
|
354
|
+
.absolute {
|
|
355
|
+
position: absolute;
|
|
356
|
+
}
|
|
357
|
+
.relative {
|
|
358
|
+
position: relative;
|
|
359
|
+
}
|
|
360
|
+
.fixed {
|
|
361
|
+
position: fixed;
|
|
362
|
+
}
|
|
363
|
+
.click-allow {
|
|
364
|
+
pointer-events: auto;
|
|
365
|
+
}
|
|
366
|
+
.click-none {
|
|
367
|
+
pointer-events: none;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/* Модификаторы состояний (Глобальные) */
|
|
371
|
+
.h\:absolute:hover {
|
|
372
|
+
position: absolute;
|
|
373
|
+
}
|
|
374
|
+
.h\:relative:hover {
|
|
375
|
+
position: relative;
|
|
376
|
+
}
|
|
377
|
+
.h\:fixed:hover {
|
|
378
|
+
position: fixed;
|
|
379
|
+
}
|
|
380
|
+
.h\:click-allow:hover {
|
|
381
|
+
pointer-events: auto;
|
|
382
|
+
}
|
|
383
|
+
.h\:click-none:hover {
|
|
384
|
+
pointer-events: none;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/* Адаптивные модификаторы (внутри медиа-запросов) */
|
|
388
|
+
@media (min-width: 768px) {
|
|
389
|
+
.md\:absolute {
|
|
390
|
+
position: absolute;
|
|
391
|
+
}
|
|
392
|
+
.md\:relative {
|
|
393
|
+
position: relative;
|
|
394
|
+
}
|
|
395
|
+
.md\:fixed {
|
|
396
|
+
position: fixed;
|
|
397
|
+
}
|
|
398
|
+
.md\:click-allow {
|
|
399
|
+
pointer-events: auto;
|
|
400
|
+
}
|
|
401
|
+
.md\:click-none {
|
|
402
|
+
pointer-events: none;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/* Адаптивные модификаторы состояний */
|
|
406
|
+
.md\:h\:absolute:hover {
|
|
407
|
+
position: absolute;
|
|
408
|
+
}
|
|
409
|
+
.md\:h\:relative:hover {
|
|
410
|
+
position: relative;
|
|
411
|
+
}
|
|
412
|
+
.md\:h\:fixed:hover {
|
|
413
|
+
position: fixed;
|
|
414
|
+
}
|
|
415
|
+
.md\:h\:click-allow:hover {
|
|
416
|
+
pointer-events: auto;
|
|
417
|
+
}
|
|
418
|
+
.md\:h\:click-none:hover {
|
|
419
|
+
pointer-events: none;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
### 4.3. Метод `steps` (Динамические числовые диапазоны)
|
|
425
|
+
|
|
426
|
+
Метод `steps` — это мощный математический генератор, который избавляет от ручного описания
|
|
427
|
+
однотипных числовых классов (отступы, размеры, углы поворота, индексы слоев). Вместо перечисления
|
|
428
|
+
каждого значения, вы задаете диапазон и шаг в блоке `"meta"`, а движок сам рассчитывает итерации
|
|
429
|
+
цикла.
|
|
430
|
+
|
|
431
|
+
Генератор ожидает обязательную карту конфигурации `"meta"` со следующими ключами:
|
|
432
|
+
|
|
433
|
+
- `from` (Number) — стартовое значение диапазона.
|
|
434
|
+
- `to` (Number) — конечное значение диапазона.
|
|
435
|
+
- `step` (Number) — шаг инкремента.
|
|
436
|
+
- `unit` (String | Null) — единица измерения (например, `px`, `rem`, `%`, `deg` или `null` для
|
|
437
|
+
безразмерных величин).
|
|
438
|
+
|
|
439
|
+
#### 🧩 Три режима работы (Полиморфизм данных)
|
|
440
|
+
|
|
441
|
+
В ключе `values` метод принимает три типа данных, полностью меняющих логику вывода:
|
|
442
|
+
|
|
443
|
+
1. **Строка (`String`):** Классическое одиночное свойство. Пара `"w": "width"` развернется в `.w-0`,
|
|
444
|
+
`.w-1` и т.д.
|
|
445
|
+
2. **Список (`List`):** Группировка свойств. Пара `"mx": ("margin-left", "margin-right")` создаст
|
|
446
|
+
утилиту, управляющую сразу обоими свойствами.
|
|
447
|
+
3. **Карта (`Map`):** Продвинутая шаблонизация. Позволяет оборачивать вычисленное число в сложные
|
|
448
|
+
CSS-функции. Знак плейсхолдера `*` внутри строки указывает движку, куда именно нужно подставить
|
|
449
|
+
вычисленное значение с единицей измерения.
|
|
450
|
+
|
|
451
|
+
#### 📝 Пример конфигурации модуля
|
|
452
|
+
|
|
453
|
+
В данном примере мы настраиваем комплексный модуль `dimensions`, используя все три режима
|
|
454
|
+
полиморфизма:
|
|
455
|
+
|
|
456
|
+
```scss
|
|
457
|
+
@use "pkg:@rotcetihra/c2c" as c2c;
|
|
458
|
+
|
|
459
|
+
$steps-module: (
|
|
460
|
+
"name": "dimensions",
|
|
461
|
+
"steps": (
|
|
462
|
+
(
|
|
463
|
+
"use": (
|
|
464
|
+
"breakpoints": true,
|
|
465
|
+
),
|
|
466
|
+
// Описание математического диапазона
|
|
467
|
+
"meta": (
|
|
468
|
+
"from": 0,
|
|
469
|
+
"to": 10,
|
|
470
|
+
"step": 5,
|
|
471
|
+
"unit": "px",
|
|
472
|
+
),
|
|
473
|
+
// Матрица полиморфных значений
|
|
474
|
+
"values": (
|
|
475
|
+
// 1. Строка: Одиночное свойство
|
|
476
|
+
"w": "width",
|
|
477
|
+
// 2. Список: Группа свойств (осевой отступ)
|
|
478
|
+
"my": ("margin-top", "margin-bottom"),
|
|
479
|
+
// 3. Карта: Шаблонизация CSS-переменной с плейсхолдером *
|
|
480
|
+
"translate-y": (
|
|
481
|
+
"--tw-translate-y": "translateY(*)",
|
|
482
|
+
),
|
|
483
|
+
),
|
|
484
|
+
),
|
|
485
|
+
),
|
|
486
|
+
);
|
|
487
|
+
|
|
488
|
+
@include c2c.by($steps-module);
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
#### 📄 Результат компиляции в CSS
|
|
492
|
+
|
|
493
|
+
Движок проитерировал диапазон от 0 до 10 с шагом 5 (получилось три шага: 0, 5, 10), применил единицу
|
|
494
|
+
измерения `px`, корректно обработал списки и подставил значение внутрь функции `translateY()` вместо
|
|
495
|
+
знака `*`:
|
|
496
|
+
|
|
497
|
+
```css
|
|
498
|
+
/* --- Шаг 0 (0px) --- */
|
|
499
|
+
.w-0 {
|
|
500
|
+
width: 0px;
|
|
501
|
+
}
|
|
502
|
+
.my-0 {
|
|
503
|
+
margin-top: 0px;
|
|
504
|
+
margin-bottom: 0px;
|
|
505
|
+
}
|
|
506
|
+
.translate-y-0 {
|
|
507
|
+
--tw-translate-y: translateY(0px);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
/* --- Шаг 5 (5px) --- */
|
|
511
|
+
.w-5 {
|
|
512
|
+
width: 5px;
|
|
513
|
+
}
|
|
514
|
+
.my-5 {
|
|
515
|
+
margin-top: 5px;
|
|
516
|
+
margin-bottom: 5px;
|
|
517
|
+
}
|
|
518
|
+
.translate-y-5 {
|
|
519
|
+
--tw-translate-y: translateY(5px);
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
/* --- Шаг 10 (10px) --- */
|
|
523
|
+
.w-10 {
|
|
524
|
+
width: 10px;
|
|
525
|
+
}
|
|
526
|
+
.my-10 {
|
|
527
|
+
margin-top: 10px;
|
|
528
|
+
margin-bottom: 10px;
|
|
529
|
+
}
|
|
530
|
+
.translate-y-10 {
|
|
531
|
+
--tw-translate-y: translateY(10px);
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
/* Адаптивные модификаторы (внутри медиа-запросов) */
|
|
535
|
+
@media (min-width: 768px) {
|
|
536
|
+
.md\:w-0 {
|
|
537
|
+
width: 0px;
|
|
538
|
+
}
|
|
539
|
+
.md\:my-0 {
|
|
540
|
+
margin-top: 0px;
|
|
541
|
+
margin-bottom: 0px;
|
|
542
|
+
}
|
|
543
|
+
.md\:translate-y-0 {
|
|
544
|
+
--tw-translate-y: translateY(0px);
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
.md\:w-5 {
|
|
548
|
+
width: 5px;
|
|
549
|
+
}
|
|
550
|
+
.md\:my-5 {
|
|
551
|
+
margin-top: 5px;
|
|
552
|
+
margin-bottom: 5px;
|
|
553
|
+
}
|
|
554
|
+
.md\:translate-y-5 {
|
|
555
|
+
--tw-translate-y: translateY(5px);
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
.md\:w-10 {
|
|
559
|
+
width: 10px;
|
|
560
|
+
}
|
|
561
|
+
.md\:my-10 {
|
|
562
|
+
margin-top: 10px;
|
|
563
|
+
margin-bottom: 10px;
|
|
564
|
+
}
|
|
565
|
+
.md\:translate-y-10 {
|
|
566
|
+
--tw-translate-y: translateY(10px);
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
### 4.4. Метод `fractions` (Дроби и Сетки)
|
|
572
|
+
|
|
573
|
+
Метод `fractions` — специализированный генератор для создания пропорциональных и сеточных утилит
|
|
574
|
+
(например, адаптивных сеток в стиле `cols-1/3`, `w-2/5`). Он автоматически рассчитывает дроби во
|
|
575
|
+
вложенных циклах `@while`, генерирует правильные имена классов с экранированием слэша (`\/`) и умеет
|
|
576
|
+
работать в двух принципиально разных режимах калькуляции.
|
|
577
|
+
|
|
578
|
+
Для управления диапазонами и логикой генерации блок `"meta"` принимает следующие обязательные
|
|
579
|
+
параметры:
|
|
580
|
+
|
|
581
|
+
- `from` (Number) — стартовая точка для числителя и знаменателя (обычно `0` или `1`).
|
|
582
|
+
- `to` (Number) — максимальный предел разрешения сетки или знаменателя (например, `4` для четвертей
|
|
583
|
+
или `12` для стандартной двенадцатиколоночной сетки).
|
|
584
|
+
- `unit` (String | Null) — единица измерения для вычисляемых значений (например, `%` или `vh`).
|
|
585
|
+
- `divide` (Boolean) — **Главный переключатель режима:**
|
|
586
|
+
- `true` (Режим процентов): Движок делит числитель на знаменатель и умножает на 100
|
|
587
|
+
(`(1 / 2) * 100 = 50%`). Идеально для `width`, `height`, `flex-basis`.
|
|
588
|
+
- `false` (Режим разделителя/сеток): Движок не считает математику, а выводит числитель и знаменатель
|
|
589
|
+
через пробел со слэшем (`1 / 2`). Идеально для CSS Grid утилит вроде `grid-column-start`.
|
|
590
|
+
|
|
591
|
+
- `incorrect` (Boolean) — разрешить генерацию неправильных дробей, где числитель больше знаменателя
|
|
592
|
+
или равен ему (например, `w-4/3` или `w-2/2`). При значении `false` генерируются строго правильные
|
|
593
|
+
дроби (числитель всегда меньше знаменателя).
|
|
594
|
+
- `negative` (Boolean) — инвертировать вычисленное процентное значение в отрицательное (умножает
|
|
595
|
+
результат на `-1`). Используется для утилит отрицательных сдвигов.
|
|
596
|
+
|
|
597
|
+
#### 📝 Пример конфигурации модуля
|
|
598
|
+
|
|
599
|
+
В данном примере мы объявляем два разных блока в рамках одного модуля: один для процентной ширины (с
|
|
600
|
+
математическим делением от 1 до 3), второй — для позиционирования в CSS Grid (без деления):
|
|
601
|
+
|
|
602
|
+
```scss
|
|
603
|
+
@use "pkg:@rotcetihra/c2c" as c2c;
|
|
604
|
+
|
|
605
|
+
$grid-module: (
|
|
606
|
+
"name": "grid-system",
|
|
607
|
+
"fractions": (
|
|
608
|
+
(
|
|
609
|
+
"use": (
|
|
610
|
+
"breakpoints": true,
|
|
611
|
+
),
|
|
612
|
+
"meta": (
|
|
613
|
+
"from": 1,
|
|
614
|
+
"to": 3,
|
|
615
|
+
"unit": "%",
|
|
616
|
+
"divide": true,
|
|
617
|
+
// Включаем деление в проценты
|
|
618
|
+
"incorrect": false,
|
|
619
|
+
// Запрещаем дроби вроде 2/2 или 3/2
|
|
620
|
+
"negative": false,
|
|
621
|
+
),
|
|
622
|
+
"values": (
|
|
623
|
+
"w": "width",
|
|
624
|
+
),
|
|
625
|
+
),
|
|
626
|
+
(
|
|
627
|
+
"use": (
|
|
628
|
+
"breakpoints": true,
|
|
629
|
+
),
|
|
630
|
+
"meta": (
|
|
631
|
+
"from": 1,
|
|
632
|
+
"to": 2,
|
|
633
|
+
"unit": null,
|
|
634
|
+
"divide": false,
|
|
635
|
+
// Отключаем деление, выводим строку "1 / 2"
|
|
636
|
+
"incorrect": true,
|
|
637
|
+
// Разрешаем неправильные дроби (2/1 и т.д.)
|
|
638
|
+
"negative": false,
|
|
639
|
+
),
|
|
640
|
+
"values": (
|
|
641
|
+
"col-start": "grid-column-start",
|
|
642
|
+
),
|
|
643
|
+
),
|
|
644
|
+
),
|
|
645
|
+
);
|
|
646
|
+
|
|
647
|
+
@include c2c.by($grid-module);
|
|
648
|
+
```
|
|
649
|
+
|
|
650
|
+
#### 📄 Результат компиляции в CSS
|
|
651
|
+
|
|
652
|
+
Обратите внимание, как движок автоматически экранирует символ слэша `\/` в именах классов, как
|
|
653
|
+
отрабатывают вложенные циклы и как меняется CSS-значение в зависимости от флага `divide`:
|
|
654
|
+
|
|
655
|
+
```css
|
|
656
|
+
/* --- Блок 1: Процентная ширина (divide: true, incorrect: false) --- */
|
|
657
|
+
.w-1\/2 {
|
|
658
|
+
width: 50%;
|
|
659
|
+
}
|
|
660
|
+
.w-1\/3 {
|
|
661
|
+
width: 33.3333333%;
|
|
662
|
+
}
|
|
663
|
+
.w-2\/3 {
|
|
664
|
+
width: 66.6666666%;
|
|
665
|
+
}
|
|
666
|
+
/* Классы вроде .w-1/1 или .w-2/2 не создаются, так как числитель строго меньше знаменателя */
|
|
667
|
+
|
|
668
|
+
/* --- Блок 2: Сеточное позиционирование (divide: false, incorrect: true) --- */
|
|
669
|
+
.col-start-1\/1 {
|
|
670
|
+
grid-column-start: 1 / 1;
|
|
671
|
+
}
|
|
672
|
+
.col-start-2\/1 {
|
|
673
|
+
grid-column-start: 2 / 1;
|
|
674
|
+
} /* Сгенерировано благодаря incorrect: true */
|
|
675
|
+
.col-start-1\/2 {
|
|
676
|
+
grid-column-start: 1 / 2;
|
|
677
|
+
}
|
|
678
|
+
.col-start-2\/2 {
|
|
679
|
+
grid-column-start: 2 / 2;
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
/* Адаптивные модификаторы (внутри медиа-запросов) */
|
|
683
|
+
@media (min-width: 768px) {
|
|
684
|
+
.md\:w-1\/2 {
|
|
685
|
+
width: 50%;
|
|
686
|
+
}
|
|
687
|
+
.md\:w-1\/3 {
|
|
688
|
+
width: 33.3333333%;
|
|
689
|
+
}
|
|
690
|
+
.md\:w-2\/3 {
|
|
691
|
+
width: 66.6666666%;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
.md\:col-start-1\/1 {
|
|
695
|
+
grid-column-start: 1 / 1;
|
|
696
|
+
}
|
|
697
|
+
.md\:col-start-2\/1 {
|
|
698
|
+
grid-column-start: 2 / 1;
|
|
699
|
+
}
|
|
700
|
+
.md\:col-start-1\/2 {
|
|
701
|
+
grid-column-start: 1 / 2;
|
|
702
|
+
}
|
|
703
|
+
.md\:col-start-2\/2 {
|
|
704
|
+
grid-column-start: 2 / 2;
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
```
|
|
708
|
+
|
|
709
|
+
### 4.5. Метод `palettes` (Цветовые схемы)
|
|
710
|
+
|
|
711
|
+
Метод `palettes` — это специализированный генератор для массового создания цветовых утилит (текст,
|
|
712
|
+
фоны, границы, заливка SVG). Он автоматически берет встроенную в компилятор палитру цветов и
|
|
713
|
+
прогоняет её через переданные вами префиксы классов.
|
|
714
|
+
|
|
715
|
+
Вшитая палитра компилятора включает два типа структуры цветов, которые генерируют разные виды
|
|
716
|
+
классов:
|
|
717
|
+
|
|
718
|
+
1. **Цвета со шкалой оттенков:** Для цветов с цифровыми индексами яркости (например, `blue-500`)
|
|
719
|
+
метод генерирует трехсоставный класс (например, `.bg-blue-500`).
|
|
720
|
+
2. **Одиночные цвета:** Для базовых цветов без оттенков (например, `white`) метод генерирует
|
|
721
|
+
лаконичный двухсоставный класс без лишних дефисов (`.bg-white`).
|
|
722
|
+
|
|
723
|
+
#### 📝 Пример конфигурации модуля
|
|
724
|
+
|
|
725
|
+
Каждая группа настроек оформляется в виде карты, которая передается внутри **списка (List)**
|
|
726
|
+
конфигураций конкретного метода. Вы лишь указываете префикс класса и целевое CSS-свойство:
|
|
727
|
+
|
|
728
|
+
```scss
|
|
729
|
+
@use "pkg:@rotcetihra/c2c" as c2c;
|
|
730
|
+
|
|
731
|
+
$colors-module: (
|
|
732
|
+
"name": "design-colors",
|
|
733
|
+
|
|
734
|
+
// Передаем список конфигураций для метода palettes
|
|
735
|
+
"palettes": (
|
|
736
|
+
// Первая конфигурационная карта: фоны с поддержкой ховеров
|
|
737
|
+
(
|
|
738
|
+
"use": (
|
|
739
|
+
"breakpoints": true,
|
|
740
|
+
"states": (
|
|
741
|
+
"h",
|
|
742
|
+
),
|
|
743
|
+
),
|
|
744
|
+
"values": (
|
|
745
|
+
"bg": "background-color",
|
|
746
|
+
),
|
|
747
|
+
),
|
|
748
|
+
// Вторая конфигурационная карта: цвет текста (без ховеров)
|
|
749
|
+
(
|
|
750
|
+
"use": (
|
|
751
|
+
"breakpoints": true,
|
|
752
|
+
"states": false,
|
|
753
|
+
),
|
|
754
|
+
"values": (
|
|
755
|
+
"text": "color",
|
|
756
|
+
),
|
|
757
|
+
),
|
|
758
|
+
),
|
|
759
|
+
);
|
|
760
|
+
|
|
761
|
+
@include c2c.by($colors-module);
|
|
762
|
+
```
|
|
763
|
+
|
|
764
|
+
#### 📄 Результат компиляции в CSS
|
|
765
|
+
|
|
766
|
+
Компилятор берет встроенные цвета и разворачивает их для каждого префикса из вашего списка
|
|
767
|
+
конфигураций с учетом заданных вариантов:
|
|
768
|
+
|
|
769
|
+
```css
|
|
770
|
+
/* --- Базовые цветовые утилиты (Фоны и Текст) --- */
|
|
771
|
+
.bg-white {
|
|
772
|
+
background-color: #ffffff;
|
|
773
|
+
}
|
|
774
|
+
.bg-blue-500 {
|
|
775
|
+
background-color: #3b82f6;
|
|
776
|
+
}
|
|
777
|
+
.text-white {
|
|
778
|
+
color: #ffffff;
|
|
779
|
+
}
|
|
780
|
+
.text-blue-500 {
|
|
781
|
+
color: #3b82f6;
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
/* --- Модификаторы состояний (Только для первой карты, где были разрешены states) --- */
|
|
785
|
+
.h\:bg-white:hover {
|
|
786
|
+
background-color: #ffffff;
|
|
787
|
+
}
|
|
788
|
+
.h\:bg-blue-500:hover {
|
|
789
|
+
background-color: #3b82f6;
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
/* --- Адаптивные модификаторы (внутри медиа-запросов) --- */
|
|
793
|
+
@media (min-width: 768px) {
|
|
794
|
+
.md\:bg-white {
|
|
795
|
+
background-color: #ffffff;
|
|
796
|
+
}
|
|
797
|
+
.md\:bg-blue-500 {
|
|
798
|
+
background-color: #3b82f6;
|
|
799
|
+
}
|
|
800
|
+
.md\:text-white {
|
|
801
|
+
color: #ffffff;
|
|
802
|
+
}
|
|
803
|
+
.md\:text-blue-500 {
|
|
804
|
+
color: #3b82f6;
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
/* Адаптивные ховеры для фонов */
|
|
808
|
+
.md\:h\:bg-white:hover {
|
|
809
|
+
background-color: #ffffff;
|
|
810
|
+
}
|
|
811
|
+
.md\:h\:bg-blue-500:hover {
|
|
812
|
+
background-color: #3b82f6;
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
```
|
|
816
|
+
|
|
817
|
+
### 4.6. Метод `classes` (Составные утилиты)
|
|
818
|
+
|
|
819
|
+
Метод `classes` предназначен для генерации комплексных составных утилит. В отличие от метода
|
|
820
|
+
`properties`, где структура данных строится от свойства к классу, здесь логика инвертирована:
|
|
821
|
+
`Желаемый CSS-Класс -> ( Карта статических CSS-Свойств и их Значений )`
|
|
822
|
+
|
|
823
|
+
Этот генератор идеально подходит для создания утилит, которые должны применять сразу несколько
|
|
824
|
+
CSS-правил к одному селектору (например, утилиты центрирования, сброса обтекания `clearfix`,
|
|
825
|
+
создания красивых эффектов или фиксированных кастомных компонентов).
|
|
826
|
+
|
|
827
|
+
#### 📝 Пример конфигурации модуля
|
|
828
|
+
|
|
829
|
+
Каждая конфигурация оформляется в виде карты внутри общего **списка (List)** метода `classes`. В
|
|
830
|
+
данном примере настраивается генерация утилит для центрирования контента и создания эффекта скрытия
|
|
831
|
+
элементов с поддержкой адаптивных модификаторов:
|
|
832
|
+
|
|
833
|
+
```scss
|
|
834
|
+
@use "pkg:@rotcetihra/c2c" as c2c;
|
|
835
|
+
|
|
836
|
+
$effects-module: (
|
|
837
|
+
"name": "custom-utilities",
|
|
838
|
+
|
|
839
|
+
// Передаем список конфигураций для метода classes
|
|
840
|
+
"classes": (
|
|
841
|
+
(
|
|
842
|
+
// Настройки вариантов (модификаторов)
|
|
843
|
+
"use": (
|
|
844
|
+
"breakpoints": true,
|
|
845
|
+
"states": (
|
|
846
|
+
"h",
|
|
847
|
+
),
|
|
848
|
+
),
|
|
849
|
+
// Матрица составных классов
|
|
850
|
+
"values": (
|
|
851
|
+
// Утилита для центрирования флекс-контента
|
|
852
|
+
"flex-center": (
|
|
853
|
+
"display": "flex",
|
|
854
|
+
"align-items": "center",
|
|
855
|
+
"justify-content": "center",
|
|
856
|
+
),
|
|
857
|
+
// Утилита для создания "невидимого", но доступного элемента
|
|
858
|
+
"sr-only": (
|
|
859
|
+
"position": "absolute",
|
|
860
|
+
"width": "1px",
|
|
861
|
+
"height": "1px",
|
|
862
|
+
"padding": "0",
|
|
863
|
+
"margin": "-1px",
|
|
864
|
+
"overflow": "hidden",
|
|
865
|
+
"clip": "rect(0, 0, 0, 0)",
|
|
866
|
+
"border-width": "0",
|
|
867
|
+
)
|
|
868
|
+
)
|
|
869
|
+
),
|
|
870
|
+
),
|
|
871
|
+
);
|
|
872
|
+
|
|
873
|
+
@include c2c.by($effects-module);
|
|
874
|
+
```
|
|
875
|
+
|
|
876
|
+
#### 📄 Результат компиляции в CSS
|
|
877
|
+
|
|
878
|
+
Компилятор разворачивает имя класса, генерирует для него все указанные внутри свойства как единый
|
|
879
|
+
блок и накатывает модификаторы брейкпоинтов и состояний:
|
|
880
|
+
|
|
881
|
+
```css
|
|
882
|
+
/* --- Базовые составные утилиты --- */
|
|
883
|
+
.flex-center {
|
|
884
|
+
display: flex;
|
|
885
|
+
align-items: center;
|
|
886
|
+
justify-content: center;
|
|
887
|
+
}
|
|
888
|
+
.sr-only {
|
|
889
|
+
position: absolute;
|
|
890
|
+
width: 1px;
|
|
891
|
+
height: 1px;
|
|
892
|
+
padding: 0;
|
|
893
|
+
margin: -1px;
|
|
894
|
+
overflow: hidden;
|
|
895
|
+
clip: rect(0, 0, 0, 0);
|
|
896
|
+
border-width: 0;
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
/* --- Модификаторы состояний --- */
|
|
900
|
+
.h\:flex-center:hover {
|
|
901
|
+
display: flex;
|
|
902
|
+
align-items: center;
|
|
903
|
+
justify-content: center;
|
|
904
|
+
}
|
|
905
|
+
.h\:sr-only:hover {
|
|
906
|
+
position: absolute;
|
|
907
|
+
width: 1px;
|
|
908
|
+
height: 1px;
|
|
909
|
+
padding: 0;
|
|
910
|
+
margin: -1px;
|
|
911
|
+
overflow: hidden;
|
|
912
|
+
clip: rect(0, 0, 0, 0);
|
|
913
|
+
border-width: 0;
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
/* --- Адаптивные модификаторы (внутри медиа-запросов) --- */
|
|
917
|
+
@media (min-width: 768px) {
|
|
918
|
+
.md\:flex-center {
|
|
919
|
+
display: flex;
|
|
920
|
+
align-items: center;
|
|
921
|
+
justify-content: center;
|
|
922
|
+
}
|
|
923
|
+
.md\:sr-only {
|
|
924
|
+
position: absolute;
|
|
925
|
+
width: 1px;
|
|
926
|
+
height: 1px;
|
|
927
|
+
padding: 0;
|
|
928
|
+
margin: -1px;
|
|
929
|
+
overflow: hidden;
|
|
930
|
+
clip: rect(0, 0, 0, 0);
|
|
931
|
+
border-width: 0;
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
/* Адаптивные модификаторы состояний */
|
|
935
|
+
.md\:h\:flex-center:hover {
|
|
936
|
+
display: flex;
|
|
937
|
+
align-items: center;
|
|
938
|
+
justify-content: center;
|
|
939
|
+
}
|
|
940
|
+
.md\:h\:sr-only:hover {
|
|
941
|
+
position: absolute;
|
|
942
|
+
width: 1px;
|
|
943
|
+
height: 1px;
|
|
944
|
+
padding: 0;
|
|
945
|
+
margin: -1px;
|
|
946
|
+
overflow: hidden;
|
|
947
|
+
clip: rect(0, 0, 0, 0);
|
|
948
|
+
border-width: 0;
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
```
|
|
952
|
+
|
|
953
|
+
### 4.7. Метод `blocks` (Глобальные CSS-директивы)
|
|
954
|
+
|
|
955
|
+
Метод `blocks` предназначен для генерации сложных именованных CSS-конструкций и глобальных директив,
|
|
956
|
+
которые выходят за рамки обычных классов.
|
|
957
|
+
|
|
958
|
+
> ⚠️ **Важное ограничение:** На текущий момент компилятор поддерживает генерацию только одного типа
|
|
959
|
+
> блоков — анимационных циклов **`keyframes`**. Поддержка других глобальных директив будет добавлена
|
|
960
|
+
> в будущих релизах.
|
|
961
|
+
|
|
962
|
+
Поскольку анимации являются глобальными правилами автоматизации интерфейса, этот метод генерирует
|
|
963
|
+
чистые CSS-блоки `@keyframes` без привязки к адаптивным брейкпоинтам или интерактивным состояниям
|
|
964
|
+
(параметр `"use"` здесь игнорируется или опускается).
|
|
965
|
+
|
|
966
|
+
Структура данных внутри `values` строится по следующему многомерному принципу:
|
|
967
|
+
`Имя анимации -> ( Шаг таймлайна/Ключевой кадр -> ( CSS-Свойства и их Значения ) )`
|
|
968
|
+
|
|
969
|
+
#### 📝 Пример конфигурации модуля
|
|
970
|
+
|
|
971
|
+
Конфигурационная карта передается внутри общего **списка (List)** метода `blocks`. В данном примере
|
|
972
|
+
мы описываем параметры для создания двух стандартных анимаций интерфейса: плавного появления
|
|
973
|
+
(`fade-in`) и бесконечного вращения (`spin`):
|
|
974
|
+
|
|
975
|
+
```scss
|
|
976
|
+
@use "pkg:@rotcetihra/c2c" as c2c;
|
|
977
|
+
|
|
978
|
+
$animations-module: (
|
|
979
|
+
"name": "global-animations",
|
|
980
|
+
|
|
981
|
+
// Передаем список конфигураций для метода blocks
|
|
982
|
+
"blocks": (
|
|
983
|
+
(
|
|
984
|
+
// Указываем тип блока, который мы конфигурируем
|
|
985
|
+
"type": "keyframes",
|
|
986
|
+
|
|
987
|
+
// Матрица ключевых кадров анимаций
|
|
988
|
+
"values": (
|
|
989
|
+
// Анимация 1: Плавное проявление
|
|
990
|
+
"fade-in": (
|
|
991
|
+
"from": (
|
|
992
|
+
"opacity": "0",
|
|
993
|
+
),
|
|
994
|
+
"to": (
|
|
995
|
+
"opacity": "1",
|
|
996
|
+
),
|
|
997
|
+
),
|
|
998
|
+
// Анимация 2: Цикличное вращение лоадера
|
|
999
|
+
"spin": (
|
|
1000
|
+
"0%": (
|
|
1001
|
+
"transform": "rotate(0deg)",
|
|
1002
|
+
),
|
|
1003
|
+
"100%": (
|
|
1004
|
+
"transform": "rotate(360deg)",
|
|
1005
|
+
),
|
|
1006
|
+
)
|
|
1007
|
+
)
|
|
1008
|
+
),
|
|
1009
|
+
),
|
|
1010
|
+
);
|
|
1011
|
+
|
|
1012
|
+
@include c2c.by($animations-module);
|
|
1013
|
+
```
|
|
1014
|
+
|
|
1015
|
+
#### 📄 Результат компиляции в CSS
|
|
1016
|
+
|
|
1017
|
+
Компилятор обрабатывает переданную многомерную карту, изолирует каждый шаг таймлайна и разворачивает
|
|
1018
|
+
валидные директивы `@keyframes`, которые затем можно использовать в стандартных свойствах
|
|
1019
|
+
`animation` вашего проекта:
|
|
1020
|
+
|
|
1021
|
+
```css
|
|
1022
|
+
/* --- Глобальные блоки анимаций CSS --- */
|
|
1023
|
+
@keyframes fade-in {
|
|
1024
|
+
from {
|
|
1025
|
+
opacity: 0;
|
|
1026
|
+
}
|
|
1027
|
+
to {
|
|
1028
|
+
opacity: 1;
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
@keyframes spin {
|
|
1033
|
+
0% {
|
|
1034
|
+
transform: rotate(0deg);
|
|
1035
|
+
}
|
|
1036
|
+
100% {
|
|
1037
|
+
transform: rotate(360deg);
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
```
|
|
1041
|
+
|
|
1042
|
+
---
|
|
1043
|
+
|
|
1044
|
+
## 5. Управление вариантами: Модификаторы (`use`)
|
|
1045
|
+
|
|
1046
|
+
Одной из самых мощных возможностей компилятора **C2C** является система автоматической генерации
|
|
1047
|
+
вариантов (модификаторов) для базовых классов. Вместо того чтобы вручную дублировать конфигурации
|
|
1048
|
+
для адаптивной верстки или интерактивных состояний, вы управляете этим с помощью декларативного
|
|
1049
|
+
блока `"use"`, который присутствует в каждой конфигурационной карте.
|
|
1050
|
+
|
|
1051
|
+
Блок `"use"` принимает следующие параметры:
|
|
1052
|
+
|
|
1053
|
+
- `breakpoints` (Boolean) — включать ли генерацию адаптивных префиксов. Если установлено в `true`,
|
|
1054
|
+
компилятор автоматически обернет утилиты в медиа-запросы и добавит префиксы вида `sm:`, `md:`,
|
|
1055
|
+
`lg:` к именам классов.
|
|
1056
|
+
- `states` (Boolean | List) — флаг или список целевых псевдоклассов. Принимает два типа значений:
|
|
1057
|
+
- `true` — автоматически генерирует **весь встроенный список состояний** компилятора.
|
|
1058
|
+
- Список вида `("h", "f", "a")` — генерирует **только указанные** псевдоклассы (режим `only`).
|
|
1059
|
+
|
|
1060
|
+
---
|
|
1061
|
+
|
|
1062
|
+
### 📋 Встроенная карта состояний компилятора
|
|
1063
|
+
|
|
1064
|
+
При использовании `states: true` или точечном выборе сокращений, компилятор опирается на следующий
|
|
1065
|
+
зашитый набор состояний:
|
|
1066
|
+
|
|
1067
|
+
| Сокращение | Псевдокласс | Категория | Описание |
|
|
1068
|
+
| ----------- | ------------------ | --------------- | ----------------------------------------------------- |
|
|
1069
|
+
| **`h`** | `:hover` | Интерактивность | Наведение курсора (защищено `@media (hover: hover)`) |
|
|
1070
|
+
| **`f`** | `:focus` | Интерактивность | Получение фокуса элементом |
|
|
1071
|
+
| **`a`** | `:active` | Интерактивность | Состояние в момент нажатия (клик) |
|
|
1072
|
+
| **`fw`** | `:focus-within` | Доступность | Фокус на самом элементе или любом его потомке |
|
|
1073
|
+
| **`fv`** | `:focus-visible` | Доступность | Фокус от клавиатуры (скрывает контур при клике мышью) |
|
|
1074
|
+
| **`t`** | `:target` | Навигация | Элемент, на который ссылается текущий URL (якорь) |
|
|
1075
|
+
| **`v`** | `:visited` | Навигация | Ссылка, по которой пользователь уже переходил |
|
|
1076
|
+
| **`val`** | `:valid` | Формы | Поле ввода с корректно заполненными данными |
|
|
1077
|
+
| **`inval`** | `:invalid` | Формы | Поле ввода с ошибкой валидации |
|
|
1078
|
+
| **`req`** | `:required` | Формы | Обязательное для заполнения поле ввода |
|
|
1079
|
+
| **`dis`** | `:disabled` | Формы | Заблокированный элемент (кнопка или инпут) |
|
|
1080
|
+
| **`first`** | `:first-child` | Структура | Первый дочерний элемент в контейнере |
|
|
1081
|
+
| **`last`** | `:last-child` | Структура | Последний дочерний элемент в контейнере |
|
|
1082
|
+
| **`odd`** | `:nth-child(odd)` | Структура | Нечетные элементы (эффект "зебры" в списках/таблицах) |
|
|
1083
|
+
| **`even`** | `:nth-child(even)` | Структура | Четные элементы |
|
|
1084
|
+
|
|
1085
|
+
---
|
|
1086
|
+
|
|
1087
|
+
### 📝 Пример конфигурации с точечным выбором состояний
|
|
1088
|
+
|
|
1089
|
+
Пример оформления блока `"use"` внутри списка конфигураций для метода `properties`, где мы
|
|
1090
|
+
активируем брейкпоинты и выбираем только `hover` и `focus`:
|
|
1091
|
+
|
|
1092
|
+
```scss
|
|
1093
|
+
@use "pkg:@rotcetihra/c2c" as c2c;
|
|
1094
|
+
|
|
1095
|
+
$interactive-module: (
|
|
1096
|
+
"name": "interactive-components",
|
|
1097
|
+
"properties": (
|
|
1098
|
+
(
|
|
1099
|
+
// Настраиваем генерацию вариантов
|
|
1100
|
+
"use": (
|
|
1101
|
+
"breakpoints": true,
|
|
1102
|
+
"states": (
|
|
1103
|
+
"h",
|
|
1104
|
+
"f",
|
|
1105
|
+
),
|
|
1106
|
+
// Генерируем ТОЛЬКО hover и focus
|
|
1107
|
+
),
|
|
1108
|
+
"values": (
|
|
1109
|
+
"outline": (
|
|
1110
|
+
"accent": "2px solid #3b82f6",
|
|
1111
|
+
"none": "none",
|
|
1112
|
+
),
|
|
1113
|
+
)
|
|
1114
|
+
),
|
|
1115
|
+
),
|
|
1116
|
+
);
|
|
1117
|
+
|
|
1118
|
+
@include c2c.by($interactive-module);
|
|
1119
|
+
```
|
|
1120
|
+
|
|
1121
|
+
#### 📄 Результат компиляции в CSS
|
|
1122
|
+
|
|
1123
|
+
Компилятор подставляет короткое сокращение в качестве префикса класса (например, `h\:`), а полное
|
|
1124
|
+
имя псевдокласса — в конец селектора:
|
|
1125
|
+
|
|
1126
|
+
```css
|
|
1127
|
+
/* Базовые утилиты */
|
|
1128
|
+
.outline-accent {
|
|
1129
|
+
outline: 2px solid #3b82f6;
|
|
1130
|
+
}
|
|
1131
|
+
.outline-none {
|
|
1132
|
+
outline: none;
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
/* Глобальные модификаторы состояний (точечная выборка) */
|
|
1136
|
+
.h\:outline-accent:hover {
|
|
1137
|
+
outline: 2px solid #3b82f6;
|
|
1138
|
+
}
|
|
1139
|
+
.h\:outline-none:hover {
|
|
1140
|
+
outline: none;
|
|
1141
|
+
}
|
|
1142
|
+
.f\:outline-accent:focus {
|
|
1143
|
+
outline: 2px solid #3b82f6;
|
|
1144
|
+
}
|
|
1145
|
+
.f\:outline-none:focus {
|
|
1146
|
+
outline: none;
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
/* Адаптивный слой (внутри медиа-запроса) */
|
|
1150
|
+
@media (min-width: 768px) {
|
|
1151
|
+
.md\:outline-accent {
|
|
1152
|
+
outline: 2px solid #3b82f6;
|
|
1153
|
+
}
|
|
1154
|
+
.md\:outline-none {
|
|
1155
|
+
outline: none;
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
/* Адаптивные состояния */
|
|
1159
|
+
.md\:h\:outline-accent:hover {
|
|
1160
|
+
outline: 2px solid #3b82f6;
|
|
1161
|
+
}
|
|
1162
|
+
.md\:h\:outline-none:hover {
|
|
1163
|
+
outline: none;
|
|
1164
|
+
}
|
|
1165
|
+
.md\:f\:outline-accent:focus {
|
|
1166
|
+
outline: 2px solid #3b82f6;
|
|
1167
|
+
}
|
|
1168
|
+
.md\:f\:outline-none:focus {
|
|
1169
|
+
outline: none;
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
```
|
|
1173
|
+
|
|
1174
|
+
---
|
|
1175
|
+
|
|
1176
|
+
## 6. Валидация и Логирование ошибок (Error Handling)
|
|
1177
|
+
|
|
1178
|
+
Компилятор **C2C** оснащен строгим изолированным миксином валидации, который проверяет целостность
|
|
1179
|
+
структуры данных перед тем, как запустить конвейер генерации CSS. Если в вашей конфигурации
|
|
1180
|
+
отсутствует обязательный параметр или вложенное подполе, компилятор не станет генерировать сломанный
|
|
1181
|
+
CSS, а мгновенно прервет сборку проекта, выбросив системное исключение с точным указанием места
|
|
1182
|
+
ошибки.
|
|
1183
|
+
|
|
1184
|
+
---
|
|
1185
|
+
|
|
1186
|
+
### 🔍 Карта обязательных полей
|
|
1187
|
+
|
|
1188
|
+
Валидатор автоматически проверяет каждую конфигурационную карту внутри списков методов на наличие
|
|
1189
|
+
следующих обязательных ключей:
|
|
1190
|
+
|
|
1191
|
+
| Метод компиляции | Обязательные поля верхнего уровня | Обязательные вложенные подполя |
|
|
1192
|
+
| ---------------- | --------------------------------- | -------------------------------- |
|
|
1193
|
+
| **`properties`** | `"values"` | _Нет_ |
|
|
1194
|
+
| **`classes`** | `"values"` | _Нет_ |
|
|
1195
|
+
| **`palettes`** | `"values"` | _Нет_ |
|
|
1196
|
+
| **`blocks`** | `"values"` | _Нет_ |
|
|
1197
|
+
| **`steps`** | `"meta"`, `"values"` | `"meta" -> "step", "from", "to"` |
|
|
1198
|
+
| **`fractions`** | `"meta"`, `"values"` | `"meta" -> "from", "to"` |
|
|
1199
|
+
|
|
1200
|
+
Если вы конфигурируете сложный метод (например, `steps` или `fractions`), валидатор рекурсивно
|
|
1201
|
+
спустится в карту `"meta"` и проверит наличие всех математических границ диапазона.
|
|
1202
|
+
|
|
1203
|
+
---
|
|
1204
|
+
|
|
1205
|
+
### 🚨 Строгая цепочка локализации ошибок
|
|
1206
|
+
|
|
1207
|
+
При обнаружении пропущенного поля компилятор вызывает директиву `@error`, останавливая сборку. Вывод
|
|
1208
|
+
ошибки стандартизирован и собирает полную цепочку контекста через двойное двоеточие по принципу:
|
|
1209
|
+
`Имя модуля :: Метод (Группа) :: Индекс карты в списке :: Пропущенный параметр`
|
|
1210
|
+
|
|
1211
|
+
#### 📝 Формат системного исключения:
|
|
1212
|
+
|
|
1213
|
+
```text
|
|
1214
|
+
Error: Отсутствует обязательное поле '[Имя модуля]::[Группа]::[Индекс конфигурации]::[Параметр]'.
|
|
1215
|
+
|
|
1216
|
+
```
|
|
1217
|
+
|
|
1218
|
+
#### Примеры реального вывода ошибок в консоль:
|
|
1219
|
+
|
|
1220
|
+
- Если вы забыли указать шаг `step` во второй карте конфигурации метода `steps` внутри модуля
|
|
1221
|
+
`spacing`:
|
|
1222
|
+
|
|
1223
|
+
```text
|
|
1224
|
+
Error: Отсутствует обязательное поле 'spacing::steps::2::meta::step'.
|
|
1225
|
+
|
|
1226
|
+
```
|
|
1227
|
+
|
|
1228
|
+
- Если вы забыли передать блок `values` в первой карте конфигурации метода `properties` внутри
|
|
1229
|
+
модуля `display`:
|
|
1230
|
+
|
|
1231
|
+
```text
|
|
1232
|
+
Error: Отсутствует обязательное поле 'display::properties::1::values'.
|
|
1233
|
+
|
|
1234
|
+
```
|
|
1235
|
+
|
|
1236
|
+
---
|
|
1237
|
+
|
|
1238
|
+
## 7. Интеграция с PurgeCSS (Production Build)
|
|
1239
|
+
|
|
1240
|
+
Поскольку **C2C** генерирует утилиты динамически на основе конфигурационных матриц, ваш CSS-файл на
|
|
1241
|
+
этапе разработки может весить достаточно много. Для очистки неиспользуемого кода в продакшн-сборке
|
|
1242
|
+
настоятельно рекомендуется использовать **PurgeCSS** (или встроенные инструменты сборщиков, такие
|
|
1243
|
+
как PostCSS PurgeCSS).
|
|
1244
|
+
|
|
1245
|
+
---
|
|
1246
|
+
|
|
1247
|
+
### ⚠️ Важная особенность экстракции классов
|
|
1248
|
+
|
|
1249
|
+
Из-за того, что компилятор **C2C** активно использует спецсимволы для разделения модификаторов
|
|
1250
|
+
(двоеточие `\:` для состояний и брейкпоинтов) и дробей (экранированный слэш `\/`), стандартные
|
|
1251
|
+
экстракторы PurgeCSS не смогут распознать эти классы в ваших HTML/JS файлах и полностью удалят их из
|
|
1252
|
+
финальной сборки.
|
|
1253
|
+
|
|
1254
|
+
Чтобы этого не произошло, необходимо настроить кастомный **Extractor**, который обучит PurgeCSS
|
|
1255
|
+
корректно считывать спецсимволы **C2C**.
|
|
1256
|
+
|
|
1257
|
+
---
|
|
1258
|
+
|
|
1259
|
+
### ⚙️ Настройка конфигурации (PurgeCSS Config)
|
|
1260
|
+
|
|
1261
|
+
Добавьте следующее регулярное выражение в массив `defaultExtractor` вашего конфигурационного файла
|
|
1262
|
+
(например, `purgecss.config.js` или в настройки плагина PostCSS):
|
|
1263
|
+
|
|
1264
|
+
```javascript
|
|
1265
|
+
module.exports = {
|
|
1266
|
+
content: [
|
|
1267
|
+
"./src/**/*.html",
|
|
1268
|
+
"./src/**/*.js",
|
|
1269
|
+
"./src/**/*.vue",
|
|
1270
|
+
"./src/**/*.jsx",
|
|
1271
|
+
// Укажите пути ко всем вашим шаблонам
|
|
1272
|
+
],
|
|
1273
|
+
defaultExtractor: (content) => {
|
|
1274
|
+
// Регулярное выражение, которое захватывает классы со спецсимволами \: и \/
|
|
1275
|
+
return content.match(/[A-Za-z0-9_-]+(?::[A-Za-z0-9_-]+)*(?:\/[A-Za-z0-9_-]+)?/g) || [];
|
|
1276
|
+
},
|
|
1277
|
+
};
|
|
1278
|
+
```
|
|
1279
|
+
|
|
1280
|
+
### 💡 Как это работает?
|
|
1281
|
+
|
|
1282
|
+
Данное регулярное выражение гарантирует, что PurgeCSS корректно свяжет строковую запись в вашем
|
|
1283
|
+
HTML-шаблоне с селектором в CSS-файле:
|
|
1284
|
+
|
|
1285
|
+
- Строка `class="md:hover:bg-blue-500"` в HTML будет успешно сопоставлена со сгенерированным
|
|
1286
|
+
селектором `.md\:hover\:bg-blue-500`.
|
|
1287
|
+
- Строка `class="w-1/2"` в HTML свяжется с селектором `.w-1\/2`.
|
|
1288
|
+
|
|
1289
|
+
Без этой настройки ваша адаптивная верстка и дробные сетки **сломаются в продакшене**, так как
|
|
1290
|
+
PurgeCSS посчитает их неиспользуемыми.
|
|
1291
|
+
|
|
1292
|
+
---
|
|
1293
|
+
|
|
1294
|
+
## 8. Лицензия (License)
|
|
1295
|
+
|
|
1296
|
+
Этот проект распространяется под свободной лицензией **MIT**.
|
|
1297
|
+
|
|
1298
|
+
Это означает, что вы можете совершенно бесплатно использовать компилятор **C2C** как в личных, так
|
|
1299
|
+
как и в коммерческих проектах, изменять код, форкать репозиторий или интегрировать его в свои
|
|
1300
|
+
проприетарные продукты без каких-либо жестких ограничений.
|
|
1301
|
+
|
|
1302
|
+
Полный текст лицензии находится в файле [LICENSE](https://www.google.com/search?q=./LICENSE) в
|
|
1303
|
+
корневом каталоге данного репозитория.
|
|
1304
|
+
|
|
1305
|
+
---
|
|
1306
|
+
|
|
1307
|
+
Разработано с фокусом на скорость, чистоту кода и гибкость конфигурации. Если у вас возникли вопросы
|
|
1308
|
+
или предложения по улучшению компилятора — создавайте **Issues** или присылайте **Pull Requests**!
|
|
1309
|
+
🚀
|