@medcore-ua/concrete-css 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 +265 -0
- package/README.md +102 -0
- package/package.json +55 -0
- package/scss/abstracts/_functions.scss +86 -0
- package/scss/abstracts/_mixins.scss +170 -0
- package/scss/abstracts/_tokens.scss +249 -0
- package/scss/abstracts/_variables.scss +53 -0
- package/scss/base/_reset.scss +100 -0
- package/scss/base/_typography.scss +71 -0
- package/scss/main.scss +39 -0
- package/scss/utilities/_api.scss +406 -0
- package/scss/utilities/_core.scss +103 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
CSSM Unlimited License v2.0
|
|
2
|
+
Copyright (c) 2026 Serhii Cherneha
|
|
3
|
+
Updated November 9, 2025
|
|
4
|
+
|
|
5
|
+
Software License
|
|
6
|
+
Agreement
|
|
7
|
+
|
|
8
|
+
Introduction
|
|
9
|
+
|
|
10
|
+
This license ("License") governs the use, modification, and
|
|
11
|
+
distribution of software provided by the Author
|
|
12
|
+
("Author"). By using this software, you ("User") agree
|
|
13
|
+
to the terms of this License. If you do not agree to
|
|
14
|
+
the terms of this License, you are not permitted to use,
|
|
15
|
+
modify, or distribute the Software.
|
|
16
|
+
|
|
17
|
+
The license is provided free of charge, and you have the
|
|
18
|
+
right to use it according to the specified terms. The
|
|
19
|
+
Author reserves the right to make changes to this License
|
|
20
|
+
at any time, and these changes will take effect upon their
|
|
21
|
+
publication. Your continued use of the Software after
|
|
22
|
+
changes are made will be considered acceptance of the new
|
|
23
|
+
License terms.
|
|
24
|
+
|
|
25
|
+
This License is a legally binding agreement between the
|
|
26
|
+
User and the Author. All terms used in this License have
|
|
27
|
+
the meanings defined in this document unless otherwise
|
|
28
|
+
specified.
|
|
29
|
+
|
|
30
|
+
1. Definitions
|
|
31
|
+
|
|
32
|
+
1.1. Software refers to any software provided by the
|
|
33
|
+
Author, including but not limited to source code, object
|
|
34
|
+
code, documentation, graphic elements, and any accompanying
|
|
35
|
+
materials that accompany this software. All components of
|
|
36
|
+
the Software are part of this License.
|
|
37
|
+
|
|
38
|
+
1.2. Modification refers to any change, addition, or
|
|
39
|
+
adaptation of the Software, including but not limited to
|
|
40
|
+
changes in source code, functionality, interface,
|
|
41
|
+
documentation, or any other elements that comprise the
|
|
42
|
+
Software. Modification may include bug fixes, performance
|
|
43
|
+
improvements, or addition of new features.
|
|
44
|
+
|
|
45
|
+
1.3. User refers to any natural or legal person who
|
|
46
|
+
accesses and uses the Software in accordance with the terms
|
|
47
|
+
of this License. The User may act on their own behalf or
|
|
48
|
+
on behalf of a company, organization, or other legal
|
|
49
|
+
entity.
|
|
50
|
+
|
|
51
|
+
1.4. Documentation refers to any materials accompanying the
|
|
52
|
+
Software that contain information about its use,
|
|
53
|
+
configuration, functionality, and other aspects that help
|
|
54
|
+
the User understand how the Software works.
|
|
55
|
+
|
|
56
|
+
1.5. Derivative Works refers to any new works created based
|
|
57
|
+
on the Software, including but not limited to
|
|
58
|
+
modifications, adaptations, translations, compilations, and
|
|
59
|
+
other forms that alter the original Software.
|
|
60
|
+
|
|
61
|
+
1.6. License Terms refers to all conditions contained in
|
|
62
|
+
this License that govern the rights and obligations of the
|
|
63
|
+
parties, as well as rules for using, modifying, and
|
|
64
|
+
distributing the Software.
|
|
65
|
+
|
|
66
|
+
2. Rights and Obligations of the Author
|
|
67
|
+
|
|
68
|
+
2.1. The Author retains all rights to the authorship of
|
|
69
|
+
the Software, including but not limited to all
|
|
70
|
+
intellectual property rights, patents, trademarks, and
|
|
71
|
+
copyrights. The Author has the right to modify, update, or
|
|
72
|
+
revoke the Software License at any time.
|
|
73
|
+
|
|
74
|
+
2.2. The Author is not liable for any damages arising from
|
|
75
|
+
the use or inability to use the Software. This includes,
|
|
76
|
+
but is not limited to, direct, indirect, incidental,
|
|
77
|
+
special, or consequential damages that may arise from
|
|
78
|
+
using the Software.
|
|
79
|
+
|
|
80
|
+
2.3. The Author has the right to make changes to the
|
|
81
|
+
Software, including but not limited to updates, bug fixes,
|
|
82
|
+
functionality improvements, or adding new features. The
|
|
83
|
+
Author commits to informing Users about significant changes
|
|
84
|
+
in the Software through appropriate communication channels.
|
|
85
|
+
|
|
86
|
+
2.4. The Author has the right to receive compensation for
|
|
87
|
+
the use of the Software if provided for in the terms of a
|
|
88
|
+
separate agreement. In case of commercial use, the User
|
|
89
|
+
agrees to comply with payment terms if such terms have
|
|
90
|
+
been agreed upon.
|
|
91
|
+
|
|
92
|
+
2.5. The Author has the right to protect their
|
|
93
|
+
intellectual property rights, including the right to take
|
|
94
|
+
legal action in case of violation of this License's terms
|
|
95
|
+
or rights to the Software.
|
|
96
|
+
|
|
97
|
+
2.6. The Author commits to providing technical support to
|
|
98
|
+
Users within the limits defined by separate agreements or
|
|
99
|
+
conditions accompanying the Software.
|
|
100
|
+
|
|
101
|
+
3. Rights and Obligations of Users
|
|
102
|
+
|
|
103
|
+
3.1. Users have the right to:
|
|
104
|
+
|
|
105
|
+
- Use: Use the Software for any purpose, including
|
|
106
|
+
commercial, educational, or research purposes. Users may
|
|
107
|
+
run, copy, install, and use the Software on their devices
|
|
108
|
+
without restrictions, subject to compliance with this
|
|
109
|
+
License's terms.
|
|
110
|
+
|
|
111
|
+
- Study and Modify: Study, modify, adapt, and create
|
|
112
|
+
derivative works based on the Software. Users may make
|
|
113
|
+
changes to the source code, improve functionality, or adapt
|
|
114
|
+
the Software to their needs, provided they comply with
|
|
115
|
+
this License's terms.
|
|
116
|
+
|
|
117
|
+
3.2. Users are obligated to:
|
|
118
|
+
|
|
119
|
+
- Authorship: Maintain authorship notices in all copies of
|
|
120
|
+
the Software, including modified versions. This means Users
|
|
121
|
+
must indicate the Author's name and any relevant copyright
|
|
122
|
+
information in documentation and on the program screen.
|
|
123
|
+
|
|
124
|
+
- Notification: Report any discovered errors or problems
|
|
125
|
+
that may arise during Software use. Users should attempt to
|
|
126
|
+
contact the Author to provide feedback that may help
|
|
127
|
+
improve the Software.
|
|
128
|
+
|
|
129
|
+
- Compliance: Comply with all terms of this License,
|
|
130
|
+
including but not limited to authorship, distribution, and
|
|
131
|
+
modification terms.
|
|
132
|
+
|
|
133
|
+
3.3. Users must comply with all applicable laws and
|
|
134
|
+
regulations when using the Software. This includes, but is
|
|
135
|
+
not limited to, compliance with copyright laws, patents,
|
|
136
|
+
trademarks, and other intellectual property rights.
|
|
137
|
+
|
|
138
|
+
3.4. Users are responsible for maintaining the
|
|
139
|
+
confidentiality of their account credentials and
|
|
140
|
+
information related to Software access, and must
|
|
141
|
+
immediately notify the Author of any unauthorized access or
|
|
142
|
+
use of their credentials.
|
|
143
|
+
|
|
144
|
+
4. Distribution Terms
|
|
145
|
+
|
|
146
|
+
4.1. Any distribution of the Software, whether in original
|
|
147
|
+
or modified form, must be accompanied by a copy of this
|
|
148
|
+
License. This ensures that all new users receive the same
|
|
149
|
+
rights and obligations defined in this License.
|
|
150
|
+
|
|
151
|
+
4.2. Modified versions of the Software must be licensed
|
|
152
|
+
under the same terms as the original Software. This means
|
|
153
|
+
any changes made to the Software must remain open for
|
|
154
|
+
further use and modification by other Users.
|
|
155
|
+
|
|
156
|
+
4.3. Users who distribute modified versions must clearly
|
|
157
|
+
indicate what changes were made and provide information on
|
|
158
|
+
how to contact them for additional information about the
|
|
159
|
+
modifications.
|
|
160
|
+
|
|
161
|
+
4.4. Users must comply with all distribution-related terms,
|
|
162
|
+
including but not limited to attribution requirements,
|
|
163
|
+
inclusion of License copy, and compliance with authorship
|
|
164
|
+
terms.
|
|
165
|
+
|
|
166
|
+
4.5. When distributing the Software through online
|
|
167
|
+
platforms, Users must ensure that all links to the License
|
|
168
|
+
and terms of use are accessible to new users.
|
|
169
|
+
|
|
170
|
+
4.6. Users must comply with all rules and regulations
|
|
171
|
+
regarding software distribution in their jurisdiction,
|
|
172
|
+
including but not limited to licensing and reporting
|
|
173
|
+
requirements.
|
|
174
|
+
|
|
175
|
+
5. Disclaimer of Liability
|
|
176
|
+
|
|
177
|
+
5.1. The Software is provided "as is," without any
|
|
178
|
+
warranties, express or implied, including but not limited
|
|
179
|
+
to warranties of merchantability or fitness for a
|
|
180
|
+
particular purpose. The Author does not guarantee that the
|
|
181
|
+
Software will be error-free, uninterrupted, or meet all
|
|
182
|
+
User requirements.
|
|
183
|
+
|
|
184
|
+
5.2. The Author is not liable for any damages arising from
|
|
185
|
+
the use or inability to use the Software, including but
|
|
186
|
+
not limited to loss of data, profit, or other material or
|
|
187
|
+
immaterial damages. Users must understand the risks
|
|
188
|
+
associated with using the Software and accept them.
|
|
189
|
+
|
|
190
|
+
5.3. Users must understand that using the Software may lead
|
|
191
|
+
to unpredictable consequences, and they are responsible
|
|
192
|
+
for any actions that may arise from using the Software.
|
|
193
|
+
The Author is not liable for any consequences arising from
|
|
194
|
+
the use or misuse of the Software.
|
|
195
|
+
|
|
196
|
+
5.4. In the event of any claims related to Software use,
|
|
197
|
+
Users are obligated to indemnify the Author and compensate
|
|
198
|
+
for all costs associated with such claims.
|
|
199
|
+
|
|
200
|
+
5.5. Users must understand that using the Software may
|
|
201
|
+
involve risks such as data loss or system failures, and
|
|
202
|
+
they should take appropriate measures to protect their data
|
|
203
|
+
and systems.
|
|
204
|
+
|
|
205
|
+
6. License Termination
|
|
206
|
+
|
|
207
|
+
6.1. In case of violation of any terms of this License,
|
|
208
|
+
the license automatically terminates, and the User loses
|
|
209
|
+
all rights to use the Software. This includes, but is not
|
|
210
|
+
limited to, cases where the User does not comply with
|
|
211
|
+
authorship or distribution terms.
|
|
212
|
+
|
|
213
|
+
6.2. Users may restore their rights provided they correct
|
|
214
|
+
the violation before the Author discovers it. Rights
|
|
215
|
+
restoration may require confirmation that the User has
|
|
216
|
+
resolved all violations and complies with License terms.
|
|
217
|
+
|
|
218
|
+
6.3. The Author reserves the right to verify compliance
|
|
219
|
+
with this License's terms at any time and take appropriate
|
|
220
|
+
action in case of violations.
|
|
221
|
+
|
|
222
|
+
6.4. Upon License termination, the User must immediately
|
|
223
|
+
cease using the Software and delete all copies from all
|
|
224
|
+
their devices.
|
|
225
|
+
|
|
226
|
+
6.5. License termination does not release the User from
|
|
227
|
+
liability for License violations that occurred before
|
|
228
|
+
termination.
|
|
229
|
+
|
|
230
|
+
6.6. Users must confirm they have removed all Software
|
|
231
|
+
copies from all devices upon License termination.
|
|
232
|
+
|
|
233
|
+
6.7. The Author has the right to compensation for damages
|
|
234
|
+
in case of User violation of this License's terms.
|
|
235
|
+
|
|
236
|
+
7. Changes to License
|
|
237
|
+
|
|
238
|
+
7.1. The Author reserves the right to make changes or
|
|
239
|
+
updates to this License. Users will be notified of any
|
|
240
|
+
changes, and continued use of the Software after changes
|
|
241
|
+
will be considered acceptance of the new License terms.
|
|
242
|
+
Changes may include clarification of terms, new
|
|
243
|
+
requirements, or changes in Users' rights and obligations.
|
|
244
|
+
|
|
245
|
+
7.2. All License changes will be published on the Author's
|
|
246
|
+
official website or in Software documentation. Users are
|
|
247
|
+
responsible for regularly reviewing License updates.
|
|
248
|
+
|
|
249
|
+
7.3. If a User does not agree with new License terms, they
|
|
250
|
+
must cease using the Software and delete all copies from
|
|
251
|
+
all their devices.
|
|
252
|
+
|
|
253
|
+
7.4. When making License changes, the Author commits to
|
|
254
|
+
providing Users sufficient time to review new terms before
|
|
255
|
+
changes take effect.
|
|
256
|
+
|
|
257
|
+
7.5. Users may contact the Author with questions or for
|
|
258
|
+
clarification about new License terms if such arise.
|
|
259
|
+
|
|
260
|
+
7.6. In case of substantial License changes, the Author
|
|
261
|
+
may provide Users the opportunity to express their
|
|
262
|
+
comments or suggestions regarding new terms.
|
|
263
|
+
|
|
264
|
+
7.7. Users should be prepared for possible changes in
|
|
265
|
+
Software functionality due to License updates.
|
package/README.md
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# Concrete CSS Framework
|
|
2
|
+
|
|
3
|
+
Concrete is a lightweight, atomic CSS framework inspired by brutalist design principles. It provides low-level utility classes that let you build completely custom designs without fighting the framework.
|
|
4
|
+
|
|
5
|
+
## Philosophy
|
|
6
|
+
|
|
7
|
+
- **Utility-First**: Compose complex components from simple, single-purpose utilities
|
|
8
|
+
- **Token-Driven**: All values derived from a centralized design token system
|
|
9
|
+
- **Brutalist by Default**: Strong borders, monospace fonts, high contrast
|
|
10
|
+
- **Framework-Agnostic**: Works with React, PHP, vanilla HTML, or any tech stack
|
|
11
|
+
- **Zero Magic Numbers**: Every value comes from the configuration
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install concrete-css
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
```scss
|
|
20
|
+
// your-styles.scss
|
|
21
|
+
@use 'concrete-css' with (
|
|
22
|
+
$primary-color: #000000,
|
|
23
|
+
$font-family: 'Roboto Mono'
|
|
24
|
+
);
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
```html
|
|
28
|
+
<button class="px-4 py-2 bg-black text-white border-4 border-black uppercase">
|
|
29
|
+
Click Me
|
|
30
|
+
</button>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Features
|
|
34
|
+
|
|
35
|
+
- **~50KB** base (before purge)
|
|
36
|
+
- **Responsive** breakpoint system
|
|
37
|
+
- **Customizable** via Sass variables
|
|
38
|
+
- **Tree-shakeable** with PurgeCSS
|
|
39
|
+
- **TypeScript** autocomplete support (coming soon)
|
|
40
|
+
|
|
41
|
+
## Core Concepts
|
|
42
|
+
|
|
43
|
+
### Atomic Classes
|
|
44
|
+
Every utility does one thing:
|
|
45
|
+
- `border-4` - 4px border
|
|
46
|
+
- `uppercase` - text-transform: uppercase
|
|
47
|
+
- `flex` - display: flex
|
|
48
|
+
|
|
49
|
+
### Responsive Modifiers
|
|
50
|
+
```html
|
|
51
|
+
<div class="block md:flex lg:grid">
|
|
52
|
+
<!-- Responsive layout -->
|
|
53
|
+
</div>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### State Modifiers
|
|
57
|
+
```html
|
|
58
|
+
<button class="bg-black hover:bg-gray-800">
|
|
59
|
+
Hover me
|
|
60
|
+
</button>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Documentation
|
|
64
|
+
|
|
65
|
+
- [Installation Guide](./docs/installation.md)
|
|
66
|
+
- [Core Utilities](./docs/utilities.md)
|
|
67
|
+
- [Customization](./docs/customization.md)
|
|
68
|
+
- [Migration from Other Frameworks](./docs/migration.md)
|
|
69
|
+
- [Examples](./examples)
|
|
70
|
+
|
|
71
|
+
## Comparison
|
|
72
|
+
|
|
73
|
+
| Feature | Concrete | Tailwind | Bootstrap |
|
|
74
|
+
|---------|----------|----------|-----------|
|
|
75
|
+
| Approach | Utility-first | Utility-first | Component |
|
|
76
|
+
| File Size | ~50KB | ~80KB | ~160KB |
|
|
77
|
+
| Brutalist | ✅ | ❌ | ❌ |
|
|
78
|
+
| Customizable | ✅ | ✅ | ⚠️ |
|
|
79
|
+
| Learning Curve | Low | Medium | Medium |
|
|
80
|
+
|
|
81
|
+
## Browser Support
|
|
82
|
+
|
|
83
|
+
- Chrome/Edge 90+
|
|
84
|
+
- Firefox 88+
|
|
85
|
+
- Safari 14+
|
|
86
|
+
- Modern mobile browsers
|
|
87
|
+
|
|
88
|
+
## Contributing
|
|
89
|
+
|
|
90
|
+
Contributions are welcome and appreciated! Here's how you can contribute:
|
|
91
|
+
|
|
92
|
+
1. Fork the project
|
|
93
|
+
2. Create your feature branch `git checkout -b feature/AmazingFeature`)
|
|
94
|
+
3. Commit your changes `git commit -m 'Add some AmazingFeature'`)
|
|
95
|
+
4. Push to the branch `git push origin feature/AmazingFeature`)
|
|
96
|
+
5. Open a Pull Request
|
|
97
|
+
|
|
98
|
+
Please make sure to update tests as appropriate and adhere to the existing coding style.
|
|
99
|
+
|
|
100
|
+
## License
|
|
101
|
+
|
|
102
|
+
This library is licensed under the CSSM Unlimited License v2.0 (CSSM-ULv2). See the [LICENSE](LICENSE) file for details.
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@medcore-ua/concrete-css",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A utility-first CSS framework for brutalist and minimalist interfaces.",
|
|
5
|
+
"main": "dist/concrete.css",
|
|
6
|
+
"sass": "scss/main.scss",
|
|
7
|
+
"style": "dist/concrete.css",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist/**/*",
|
|
10
|
+
"scss/**/*",
|
|
11
|
+
"LICENSE",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "sass scss/main.scss dist/concrete.css --style=expanded",
|
|
16
|
+
"build:min": "sass scss/main.scss dist/concrete.min.css --style=compressed",
|
|
17
|
+
"watch": "sass scss/main.scss dist/concrete.css --watch",
|
|
18
|
+
"dev": "npm run watch",
|
|
19
|
+
"lint": "stylelint 'scss/**/*.scss'",
|
|
20
|
+
"test": "echo \"Tests coming soon\" && exit 0"
|
|
21
|
+
},
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "https://github.com/medcore-ua/concrete-css.git"
|
|
25
|
+
},
|
|
26
|
+
"keywords": [
|
|
27
|
+
"css",
|
|
28
|
+
"framework",
|
|
29
|
+
"utility-first",
|
|
30
|
+
"brutalist",
|
|
31
|
+
"atomic-css",
|
|
32
|
+
"sass",
|
|
33
|
+
"scss",
|
|
34
|
+
"design-system"
|
|
35
|
+
],
|
|
36
|
+
"author": "Serhii Cherneha",
|
|
37
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
38
|
+
"bugs": {
|
|
39
|
+
"url": "https://github.com/medcore-ua/concrete-css/issues"
|
|
40
|
+
},
|
|
41
|
+
"homepage": "https://github.com/medcore-ua/concrete-css#readme",
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"sass": "^1.70.0",
|
|
44
|
+
"stylelint": "^16.0.0",
|
|
45
|
+
"stylelint-config-standard-scss": "^13.0.0"
|
|
46
|
+
},
|
|
47
|
+
"peerDependencies": {
|
|
48
|
+
"sass": "^1.70.0"
|
|
49
|
+
},
|
|
50
|
+
"browserslist": [
|
|
51
|
+
"> 1%",
|
|
52
|
+
"last 2 versions",
|
|
53
|
+
"not dead"
|
|
54
|
+
]
|
|
55
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// SASS HELPER FUNCTIONS
|
|
3
|
+
// Utility functions for the framework generator
|
|
4
|
+
// =============================================================================
|
|
5
|
+
|
|
6
|
+
/// Remove units from a value
|
|
7
|
+
/// @param {Number} $value - Value to strip units from
|
|
8
|
+
/// @return {Number} - Unitless value
|
|
9
|
+
@function strip-unit($value) {
|
|
10
|
+
@if type-of($value) == 'number' and not unitless($value) {
|
|
11
|
+
@return $value / ($value * 0 + 1);
|
|
12
|
+
}
|
|
13
|
+
@return $value;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/// Convert px to rem
|
|
17
|
+
/// @param {Number} $px - Pixel value
|
|
18
|
+
/// @param {Number} $base [16px] - Base font size
|
|
19
|
+
/// @return {Number} - rem value
|
|
20
|
+
@function px-to-rem($px, $base: 16px) {
|
|
21
|
+
@return (strip-unit($px) / strip-unit($base)) * 1rem;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/// Generate negative values for a map
|
|
25
|
+
/// @param {Map} $map - Original map
|
|
26
|
+
/// @return {Map} - Map with negative values added
|
|
27
|
+
@function generate-negatives($map) {
|
|
28
|
+
$result: $map;
|
|
29
|
+
@each $key, $value in $map {
|
|
30
|
+
@if type-of($value) == 'number' and $value != 0 {
|
|
31
|
+
$result: map-merge($result, ('-#{$key}': -$value));
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
@return $result;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/// Escape special characters for class names
|
|
38
|
+
/// @param {String} $string - String to escape
|
|
39
|
+
/// @return {String} - Escaped string
|
|
40
|
+
@function escape-class-name($string) {
|
|
41
|
+
$string: str-replace($string, '/', '\\/');
|
|
42
|
+
$string: str-replace($string, ':', '\\:');
|
|
43
|
+
$string: str-replace($string, '.', '\\.');
|
|
44
|
+
$string: str-replace($string, '%', '\\%');
|
|
45
|
+
@return $string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/// String replace helper
|
|
49
|
+
/// @param {String} $string - String to search in
|
|
50
|
+
/// @param {String} $search - String to search for
|
|
51
|
+
/// @param {String} $replace - Replacement string
|
|
52
|
+
/// @return {String} - Modified string
|
|
53
|
+
@function str-replace($string, $search, $replace: '') {
|
|
54
|
+
$index: str-index($string, $search);
|
|
55
|
+
@if $index {
|
|
56
|
+
@return str-slice($string, 1, $index - 1) + $replace +
|
|
57
|
+
str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
|
|
58
|
+
}
|
|
59
|
+
@return $string;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/// Check if a value is a CSS length
|
|
63
|
+
/// @param {*} $value - Value to check
|
|
64
|
+
/// @return {Boolean}
|
|
65
|
+
@function is-length($value) {
|
|
66
|
+
@return type-of($value) == 'number' and
|
|
67
|
+
(unit($value) == 'px' or
|
|
68
|
+
unit($value) == 'rem' or
|
|
69
|
+
unit($value) == 'em' or
|
|
70
|
+
unit($value) == '%' or
|
|
71
|
+
unitless($value));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/// Get deeply nested map value
|
|
75
|
+
/// @param {Map} $map - Map to search
|
|
76
|
+
/// @param {List} $keys - Keys to traverse
|
|
77
|
+
/// @return {*} - Value at path or null
|
|
78
|
+
@function map-deep-get($map, $keys...) {
|
|
79
|
+
@each $key in $keys {
|
|
80
|
+
$map: map-get($map, $key);
|
|
81
|
+
@if $map == null {
|
|
82
|
+
@return null;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
@return $map;
|
|
86
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// UTILITY GENERATOR MIXINS
|
|
3
|
+
// The core engine that generates utility classes
|
|
4
|
+
// =============================================================================
|
|
5
|
+
|
|
6
|
+
@use 'sass:map';
|
|
7
|
+
@use 'sass:string';
|
|
8
|
+
@use 'functions' as *;
|
|
9
|
+
@use 'variables' as *;
|
|
10
|
+
@use 'tokens' as *;
|
|
11
|
+
|
|
12
|
+
// =============================================================================
|
|
13
|
+
// MAIN UTILITY GENERATOR
|
|
14
|
+
// Generates a complete set of utilities from a configuration map
|
|
15
|
+
// =============================================================================
|
|
16
|
+
|
|
17
|
+
/// Generate utility classes from configuration
|
|
18
|
+
/// @param {Map} $utilities-map - Configuration map
|
|
19
|
+
@mixin generate-utilities($utilities-map) {
|
|
20
|
+
@each $property, $config in $utilities-map {
|
|
21
|
+
$prefix: map.get($config, 'prefix');
|
|
22
|
+
$values: map.get($config, 'values');
|
|
23
|
+
$is-important: map.get($config, 'important');
|
|
24
|
+
$responsive: map.get($config, 'responsive');
|
|
25
|
+
|
|
26
|
+
// Default responsive to true if not specified
|
|
27
|
+
@if $responsive == null {
|
|
28
|
+
$responsive: true;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
$important-flag: if($is-important or $enable-important, !important, null);
|
|
32
|
+
|
|
33
|
+
@each $key, $value in $values {
|
|
34
|
+
$class-name: if($key == 'default', $prefix, '#{$prefix}-#{$key}');
|
|
35
|
+
|
|
36
|
+
.#{$class-name} {
|
|
37
|
+
#{$property}: $value $important-flag;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// =============================================================================
|
|
44
|
+
// RESPONSIVE WRAPPER
|
|
45
|
+
// Wraps utilities in media queries
|
|
46
|
+
// =============================================================================
|
|
47
|
+
|
|
48
|
+
/// Generate responsive variants of utilities
|
|
49
|
+
/// @param {String} $breakpoint - Breakpoint name
|
|
50
|
+
/// @param {Map} $utilities-map - Utilities configuration
|
|
51
|
+
@mixin responsive-utilities($breakpoint, $utilities-map) {
|
|
52
|
+
$bp-value: map.get($breakpoints, $breakpoint);
|
|
53
|
+
|
|
54
|
+
@media (min-width: $bp-value) {
|
|
55
|
+
@each $property, $config in $utilities-map {
|
|
56
|
+
// Skip if responsive is disabled for this utility
|
|
57
|
+
$responsive: map.get($config, 'responsive');
|
|
58
|
+
@if $responsive == false {
|
|
59
|
+
// Skip this utility
|
|
60
|
+
} @else {
|
|
61
|
+
$prefix: map.get($config, 'prefix');
|
|
62
|
+
$values: map.get($config, 'values');
|
|
63
|
+
$is-important: map.get($config, 'important');
|
|
64
|
+
$important-flag: if($is-important or $enable-important, !important, null);
|
|
65
|
+
|
|
66
|
+
@each $key, $value in $values {
|
|
67
|
+
$class-name: if($key == 'default', $prefix, '#{$prefix}-#{$key}');
|
|
68
|
+
|
|
69
|
+
// Escape the colon for CSS validity
|
|
70
|
+
.#{$breakpoint}\:#{$class-name} {
|
|
71
|
+
#{$property}: $value $important-flag;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// =============================================================================
|
|
80
|
+
// STATE MODIFIERS (hover, focus, etc.)
|
|
81
|
+
// =============================================================================
|
|
82
|
+
|
|
83
|
+
/// Generate state variants of utilities
|
|
84
|
+
/// @param {String} $state - State name (hover, focus, active, disabled)
|
|
85
|
+
/// @param {Map} $utilities-map - Utilities configuration
|
|
86
|
+
@mixin state-utilities($state, $utilities-map) {
|
|
87
|
+
@each $property, $config in $utilities-map {
|
|
88
|
+
// Skip if states are disabled for this utility
|
|
89
|
+
$allow-states: map.get($config, 'states');
|
|
90
|
+
@if $allow-states == false {
|
|
91
|
+
// Skip this utility
|
|
92
|
+
} @else {
|
|
93
|
+
$prefix: map.get($config, 'prefix');
|
|
94
|
+
$values: map.get($config, 'values');
|
|
95
|
+
$is-important: map.get($config, 'important');
|
|
96
|
+
$important-flag: if($is-important or $enable-important, !important, null);
|
|
97
|
+
|
|
98
|
+
@each $key, $value in $values {
|
|
99
|
+
$class-name: if($key == 'default', $prefix, '#{$prefix}-#{$key}');
|
|
100
|
+
|
|
101
|
+
// Escape the colon for CSS validity
|
|
102
|
+
.#{$state}\:#{$class-name}:#{$state} {
|
|
103
|
+
#{$property}: $value $important-flag;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// =============================================================================
|
|
111
|
+
// DIRECTIONAL UTILITIES (margin, padding)
|
|
112
|
+
// Handles top, right, bottom, left, x, y variants
|
|
113
|
+
// =============================================================================
|
|
114
|
+
|
|
115
|
+
/// Generate directional spacing utilities
|
|
116
|
+
/// @param {String} $prefix - Utility prefix (m, p)
|
|
117
|
+
/// @param {String} $property - CSS property (margin, padding)
|
|
118
|
+
/// @param {Map} $values - Spacing values
|
|
119
|
+
@mixin generate-directional($prefix, $property, $values) {
|
|
120
|
+
@each $dir-key, $dir-value in $directions {
|
|
121
|
+
@each $size-key, $size-value in $values {
|
|
122
|
+
$class-name: if($dir-key == '', '#{$prefix}-#{$size-key}', '#{$prefix}#{$dir-key}-#{$size-key}');
|
|
123
|
+
|
|
124
|
+
.#{$class-name} {
|
|
125
|
+
@if $dir-key == '' {
|
|
126
|
+
#{$property}: $size-value;
|
|
127
|
+
} @else if $dir-key == 'x' {
|
|
128
|
+
#{$property}-left: $size-value;
|
|
129
|
+
#{$property}-right: $size-value;
|
|
130
|
+
} @else if $dir-key == 'y' {
|
|
131
|
+
#{$property}-top: $size-value;
|
|
132
|
+
#{$property}-bottom: $size-value;
|
|
133
|
+
} @else {
|
|
134
|
+
#{$property}#{$dir-value}: $size-value;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// =============================================================================
|
|
142
|
+
// NEGATIVE MARGIN HELPER
|
|
143
|
+
// Generates negative margin utilities
|
|
144
|
+
// =============================================================================
|
|
145
|
+
|
|
146
|
+
/// Generate negative margin utilities
|
|
147
|
+
/// @param {Map} $values - Spacing values
|
|
148
|
+
@mixin generate-negative-margins($values) {
|
|
149
|
+
@each $dir-key, $dir-value in $directions {
|
|
150
|
+
@each $size-key, $size-value in $values {
|
|
151
|
+
@if type-of($size-value) == 'number' and $size-value != 0 and $size-value != auto {
|
|
152
|
+
$class-name: if($dir-key == '', '-m-#{$size-key}', '-m#{$dir-key}-#{$size-key}');
|
|
153
|
+
|
|
154
|
+
.#{$class-name} {
|
|
155
|
+
@if $dir-key == '' {
|
|
156
|
+
margin: -$size-value;
|
|
157
|
+
} @else if $dir-key == 'x' {
|
|
158
|
+
margin-left: -$size-value;
|
|
159
|
+
margin-right: -$size-value;
|
|
160
|
+
} @else if $dir-key == 'y' {
|
|
161
|
+
margin-top: -$size-value;
|
|
162
|
+
margin-bottom: -$size-value;
|
|
163
|
+
} @else {
|
|
164
|
+
margin#{$dir-value}: -$size-value;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|