teawindcss 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/README.md +218 -0
- package/package.json +25 -0
- package/teawind.js +310 -0
package/README.md
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# 🍵 TeaWind CSS
|
|
2
|
+
|
|
3
|
+
**A lightweight, zero-build, utility-first CSS engine built entirely in Vanilla JavaScript.**
|
|
4
|
+
|
|
5
|
+
CSS can be incredibly stressful. Centering a div, fighting specificity, and managing massive stylesheets is enough to make anyone pull their hair out.
|
|
6
|
+
|
|
7
|
+
That's exactly why every class in this library starts with the prefix `chai-`. It's a built-in reminder: whenever you're styling your app and things get overwhelming, take a deep breath, take a sip of **chai (tea)** ☕️, and calm down. We've got the styles covered.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## What is TeaWind?
|
|
12
|
+
|
|
13
|
+
TeaWind is a Just-In-Time (JIT) CSS engine that runs entirely on the client side in the browser. Instead of writing traditional CSS files, you write simple class names directly in your HTML or JSX (like `chai-bg-red` or `chai-p-20`). TeaWind scans your webpage, translates those classes into perfectly formatted inline styles, and then automatically sweeps the DOM to remove the classes, keeping your markup clean.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## ✨ Key Features
|
|
18
|
+
|
|
19
|
+
- **Blisteringly Fast:** Powered by an intelligent `Map()` caching system. Once a utility is calculated, it's remembered, dropping execution times to roughly ~1 millisecond.
|
|
20
|
+
- **Smart Dynamic Values:** Need a specific width? Type `chai-w-42` for pixels, or `chai-w-full` for 100%. TeaWind handles both seamlessly.
|
|
21
|
+
- **Multi-Dimensional Palette:** Built-in modern color system with light and dark shades (e.g., `chai-text-blue-dark`, `chai-bg-red-light`).
|
|
22
|
+
- ** MutationObserver Powered:** Automatically styles dynamically added elements — perfect for React, Vue, and other frameworks without any extra setup. No `useEffect` needed.
|
|
23
|
+
- **Self-Cleaning DOM:** Once TeaWind applies your styles, it removes the original utility classes from your HTML, leaving only clean inline styles.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 📦 Installation
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install teawindcss
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## ⚡️ Quick Start
|
|
36
|
+
|
|
37
|
+
### HTML / Vanilla JS
|
|
38
|
+
|
|
39
|
+
Just import the package once. TeaWind auto-initializes and processes the entire DOM on load.
|
|
40
|
+
|
|
41
|
+
```javascript
|
|
42
|
+
import 'teawindcss';
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
That's it. Write your classes and TeaWind handles the rest:
|
|
46
|
+
|
|
47
|
+
```html
|
|
48
|
+
<div class="chai-flex chai-justify-center chai-items-center chai-p-16
|
|
49
|
+
chai-bg-slate-dark chai-flex-column chai-shadow-md chai-rounded-lg">
|
|
50
|
+
<h1 class="chai-text-3xl chai-font-bold chai-text-white">Welcome to TeaWind CSS</h1>
|
|
51
|
+
<p class="chai-m-10 chai-text-white">A modern framework with a calming touch.</p>
|
|
52
|
+
</div>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
### Manual Control with `brew()`
|
|
58
|
+
|
|
59
|
+
If you need to manually trigger processing — for example, after injecting HTML dynamically — use the named `brew()` export:
|
|
60
|
+
|
|
61
|
+
```javascript
|
|
62
|
+
import { brew } from 'teawindcss';
|
|
63
|
+
|
|
64
|
+
// Process all chai- classes in the DOM right now
|
|
65
|
+
brew();
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
### React Usage
|
|
71
|
+
|
|
72
|
+
Import TeaWind **once** at the root of your app. Because of the built-in `MutationObserver`, all components — including dynamically rendered ones — are styled automatically. No `useEffect` needed anywhere.
|
|
73
|
+
|
|
74
|
+
**main.jsx**
|
|
75
|
+
```jsx
|
|
76
|
+
import React from 'react';
|
|
77
|
+
import ReactDOM from 'react-dom/client';
|
|
78
|
+
import App from './App';
|
|
79
|
+
import 'teawindcss'; // Import once here — done
|
|
80
|
+
|
|
81
|
+
ReactDOM.createRoot(document.getElementById('root')).render(
|
|
82
|
+
<React.StrictMode>
|
|
83
|
+
<App />
|
|
84
|
+
</React.StrictMode>
|
|
85
|
+
);
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**App.jsx**
|
|
89
|
+
```jsx
|
|
90
|
+
export default function App() {
|
|
91
|
+
return (
|
|
92
|
+
<div className="chai-flex chai-justify-center chai-items-center
|
|
93
|
+
chai-w-screen chai-h-screen chai-bg-black chai-flex-column">
|
|
94
|
+
<div className="chai-p-32 chai-rounded-xl chai-bg-slate-dark chai-shadow-xl">
|
|
95
|
+
<h1 className="chai-text-4xl chai-font-bold chai-text-white chai-text-center">
|
|
96
|
+
React + TeaWind
|
|
97
|
+
</h1>
|
|
98
|
+
<button className="chai-m-16 chai-p-16 chai-bg-blue-dark chai-text-white
|
|
99
|
+
chai-rounded-4xl chai-cursor-pointer">
|
|
100
|
+
Click Me
|
|
101
|
+
</button>
|
|
102
|
+
</div>
|
|
103
|
+
</div>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## 📚 Supported Utilities
|
|
111
|
+
|
|
112
|
+
TeaWind supports **100+ utilities**. Use this as your quick-reference cheat sheet.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
### 📝 Typography
|
|
117
|
+
|
|
118
|
+
| Class Name | CSS Equivalent | Description |
|
|
119
|
+
|---|---|---|
|
|
120
|
+
| `chai-text-xs` to `chai-text-6xl` | `font-size: 12px` to `48px` | Scales text size. Supports `xs`, `sm`, `md`, `lg`, `xl`, `2xl`, `3xl`, `4xl`, `5xl`, `6xl`. |
|
|
121
|
+
| `chai-font-thin` | `font-weight: 100` | Ultra-light text. |
|
|
122
|
+
| `chai-font-normal` | `font-weight: 400` | Standard text weight. |
|
|
123
|
+
| `chai-font-bold` | `font-weight: 700` | Bold text for emphasis or headings. |
|
|
124
|
+
| `chai-text-center` / `left` / `right` / `justify` | `text-align: ...` | Aligns text within its container. |
|
|
125
|
+
| `chai-uppercase` / `lowercase` / `capitalize` | `text-transform: ...` | Changes letter casing. |
|
|
126
|
+
| `chai-italic` | `font-style: italic` | Italicizes the text. |
|
|
127
|
+
| `chai-underline` / `chai-line-through` | `text-decoration: ...` | Adds underline or strikethrough. |
|
|
128
|
+
| `chai-sans` / `chai-serif` / `chai-mono` / `chai-fira` / `chai-fraunces` | `font-family: ...` | Applies modern fallback font stacks. |
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
### 🎨 Colors (Text & Background)
|
|
133
|
+
|
|
134
|
+
Built-in palette: `red`, `blue`, `green`, `yellow`, `orange`, `purple`, `pink`, `slate`, `black`, and `white`. Each palette color supports `-light` and `-dark` variants.
|
|
135
|
+
|
|
136
|
+
| Class Name | CSS Equivalent | Description |
|
|
137
|
+
|---|---|---|
|
|
138
|
+
| `chai-bg-blue` | `background-color: blue` | Standard browser blue background. |
|
|
139
|
+
| `chai-bg-blue-light` | `background-color: #93c5fd` | Light blue from the TeaWind palette. |
|
|
140
|
+
| `chai-bg-blue-dark` | `background-color: #1e40af` | Dark blue from the TeaWind palette. |
|
|
141
|
+
| `chai-text-red` | `color: red` | Standard red text. |
|
|
142
|
+
| `chai-text-slate-dark` | `color: #334155` | Dark slate text from the TeaWind palette. |
|
|
143
|
+
|
|
144
|
+
> All 8 palette colors (`red`, `yellow`, `blue`, `purple`, `orange`, `green`, `pink`, `slate`) support both `-light` and `-dark` variants for both `chai-bg-*` and `chai-text-*`.
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
### 📏 Sizing & Spacing (Dynamic)
|
|
149
|
+
|
|
150
|
+
Pass any number — it converts to pixels automatically. Special string values like `full`, `screen`, and `auto` are also supported.
|
|
151
|
+
|
|
152
|
+
| Class Name | CSS Equivalent | Description |
|
|
153
|
+
|---|---|---|
|
|
154
|
+
| `chai-p-24` | `padding: 24px` | 24px of padding. |
|
|
155
|
+
| `chai-m-15` | `margin: 15px` | 15px of margin. |
|
|
156
|
+
| `chai-mx-auto` | `margin-left: auto; margin-right: auto` | Centers block-level elements. |
|
|
157
|
+
| `chai-w-200` | `width: 200px` | Strict pixel width. |
|
|
158
|
+
| `chai-w-full` | `width: 100%` | Full width of parent. |
|
|
159
|
+
| `chai-w-screen` | `width: 100vw` | Full viewport width. |
|
|
160
|
+
| `chai-h-full` / `chai-h-screen` | `height: 100%` / `100vh` | Full height variants. |
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
### 🧱 Layout, Flexbox & Grid
|
|
165
|
+
|
|
166
|
+
| Class Name | CSS Equivalent | Description |
|
|
167
|
+
|---|---|---|
|
|
168
|
+
| `chai-flex` / `chai-grid` | `display: flex / grid` | Enables Flexbox or CSS Grid. |
|
|
169
|
+
| `chai-block` / `chai-inline-block` | `display: block / inline-block` | Standard block displays. |
|
|
170
|
+
| `chai-flex-column` / `chai-flex-row` | `flex-direction: column / row` | Controls flex direction. |
|
|
171
|
+
| `chai-flex-wrap` / `chai-flex-nowrap` | `flex-wrap: wrap / nowrap` | Controls flex wrapping. |
|
|
172
|
+
| `chai-justify-center` / `between` / `around` / `evenly` | `justify-content: ...` | Spaces items along the main axis. |
|
|
173
|
+
| `chai-items-center` / `start` / `end` / `stretch` | `align-items: ...` | Aligns items along the cross axis. |
|
|
174
|
+
| `chai-gap-20` | `gap: 20px` | 20px gap between flex/grid children. |
|
|
175
|
+
| `chai-flex-1` / `chai-flex-2` | `flex: 1 / 2` | Flex grow values. |
|
|
176
|
+
| `chai-absolute` / `chai-relative` / `chai-fixed` / `chai-sticky` | `position: ...` | Element positioning. |
|
|
177
|
+
| `chai-hidden` | `display: none` | Hides the element. |
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
### 🌫️ Borders, Radius & Effects
|
|
182
|
+
|
|
183
|
+
| Class Name | CSS Equivalent | Description |
|
|
184
|
+
|---|---|---|
|
|
185
|
+
| `chai-rounded-md` | `border-radius: 6px` | Medium rounded corners. Supports `xs` through `4xl`. |
|
|
186
|
+
| `chai-border-w-2` | `border-width: 2px` | Dynamic border width. |
|
|
187
|
+
| `chai-border-dashed` / `dotted` / `solid` | `border-style: ...` | Border style variants. |
|
|
188
|
+
| `chai-border-blue` | `border-color: blue` | Border color. |
|
|
189
|
+
| `chai-shadow-lg` | `box-shadow: ...` | Multi-layered drop shadow. Supports `xs` through `xl`. |
|
|
190
|
+
| `chai-text-shadow-md` | `text-shadow: ...` | Text shadow. Supports `xs` through `xl`. |
|
|
191
|
+
| `chai-opacity-50` | `opacity: 0.5` | 50% transparency. Supports `0`, `25`, `50`, `75`, `100`. |
|
|
192
|
+
| `chai-cursor-pointer` | `cursor: pointer` | Pointer cursor for buttons and links. |
|
|
193
|
+
| `chai-overflow-hidden` / `chai-overflow-auto` | `overflow: hidden / auto` | Controls element overflow. |
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## 🔧 Advanced Usage
|
|
198
|
+
|
|
199
|
+
### Using as a Class (programmatic control)
|
|
200
|
+
|
|
201
|
+
```javascript
|
|
202
|
+
import TeaWind from 'teawindcss';
|
|
203
|
+
|
|
204
|
+
const engine = new TeaWind();
|
|
205
|
+
engine.init(); // scans and processes the DOM
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### CommonJS
|
|
209
|
+
|
|
210
|
+
```javascript
|
|
211
|
+
const { default: TeaWind, brew } = require('teawindcss');
|
|
212
|
+
|
|
213
|
+
brew(); // or
|
|
214
|
+
const engine = new TeaWind();
|
|
215
|
+
engine.init();
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
---
|
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "teawindcss",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A lightweight utility-first CSS engine for the browser",
|
|
5
|
+
"main": "teawind.js",
|
|
6
|
+
"files": [
|
|
7
|
+
"teawind.js",
|
|
8
|
+
"README.md"
|
|
9
|
+
],
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/PreetMax85/teawindcss.git"
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"css",
|
|
19
|
+
"utility-first",
|
|
20
|
+
"dom"
|
|
21
|
+
],
|
|
22
|
+
"author": "Preet",
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"type": "commonjs"
|
|
25
|
+
}
|
package/teawind.js
ADDED
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
const stylesDictionary = {
|
|
2
|
+
// BACKGROUNDS
|
|
3
|
+
"chai-bg-white": "background-color:white",
|
|
4
|
+
"chai-bg-black": "background-color:black",
|
|
5
|
+
"chai-bg-red": "background-color:red",
|
|
6
|
+
"chai-bg-green": "background-color:green",
|
|
7
|
+
"chai-bg-blue": "background-color:blue",
|
|
8
|
+
"chai-bg-orange": "background-color:orange",
|
|
9
|
+
"chai-bg-yellow": "background-color:yellow",
|
|
10
|
+
"chai-bg-purple": "background-color:purple",
|
|
11
|
+
"chai-bg-pink": "background-color:pink",
|
|
12
|
+
"chai-bg-slate": "background-color: #64748b",
|
|
13
|
+
"chai-bg-subtle-dark": "background-color: #292929",
|
|
14
|
+
|
|
15
|
+
// TYPOGRAPHY
|
|
16
|
+
"chai-sans": "font-family: ui-sans-serif, system-ui, sans-serif",
|
|
17
|
+
"chai-serif": "font-family: ui-serif, Georgia, serif",
|
|
18
|
+
"chai-mono": "font-family: ui-monospace, SFMono-Regular, monospace",
|
|
19
|
+
"chai-font-dm-sans": "font-family: 'DM Sans', sans-serif",
|
|
20
|
+
"chai-font-fraunces": "font-family: 'Fraunces', serif",
|
|
21
|
+
"chai-font-fira": "font-family: 'Fira Code', monospace",
|
|
22
|
+
"chai-uppercase": "text-transform: uppercase",
|
|
23
|
+
"chai-lowercase": "text-transform: lowercase",
|
|
24
|
+
"chai-capitalize": "text-transform: capitalize",
|
|
25
|
+
"chai-italic": "font-style: italic",
|
|
26
|
+
"chai-underline": "text-decoration: underline",
|
|
27
|
+
"chai-line-through": "text-decoration: line-through",
|
|
28
|
+
"chai-text-xs": "font-size:12px",
|
|
29
|
+
"chai-text-sm": "font-size:14px",
|
|
30
|
+
"chai-text-md": "font-size:16px",
|
|
31
|
+
"chai-text-lg": "font-size:18px",
|
|
32
|
+
"chai-text-xl": "font-size:20px",
|
|
33
|
+
"chai-text-2xl": "font-size:24px",
|
|
34
|
+
"chai-text-3xl": "font-size:30px",
|
|
35
|
+
"chai-text-4xl": "font-size:36px",
|
|
36
|
+
"chai-text-5xl": "font-size:42px",
|
|
37
|
+
"chai-text-6xl": "font-size:48px",
|
|
38
|
+
"chai-leading-none": "line-height: 1",
|
|
39
|
+
"chai-leading-tight": "line-height: 1.1",
|
|
40
|
+
"chai-leading-snug": "line-height: 1.375",
|
|
41
|
+
"chai-leading-normal": "line-height: 1.5",
|
|
42
|
+
"chai-leading-relaxed": "line-height: 1.625",
|
|
43
|
+
"chai-leading-loose": "line-height: 2",
|
|
44
|
+
"chai-font-thin": "font-weight: 100",
|
|
45
|
+
"chai-font-normal": "font-weight: 400",
|
|
46
|
+
"chai-font-bold": "font-weight: 700",
|
|
47
|
+
"chai-text-left": "text-align: left",
|
|
48
|
+
"chai-text-center": "text-align: center",
|
|
49
|
+
"chai-text-right": "text-align: right",
|
|
50
|
+
"chai-text-justify": "text-align: justify",
|
|
51
|
+
"chai-text-black": "color:black",
|
|
52
|
+
"chai-text-white": "color:white",
|
|
53
|
+
"chai-text-red": "color:red",
|
|
54
|
+
"chai-text-orange": "color:orange",
|
|
55
|
+
"chai-text-yellow": "color:yellow",
|
|
56
|
+
"chai-text-green": "color:green",
|
|
57
|
+
"chai-text-blue": "color:blue",
|
|
58
|
+
"chai-text-purple": "color:purple",
|
|
59
|
+
"chai-text-pink": "color:pink",
|
|
60
|
+
"chai-text-slate": "color: #64748b",
|
|
61
|
+
|
|
62
|
+
// BORDERS
|
|
63
|
+
"chai-rounded-xs": "border-radius:2px",
|
|
64
|
+
"chai-rounded-sm": "border-radius:4px",
|
|
65
|
+
"chai-rounded-md": "border-radius:6px",
|
|
66
|
+
"chai-rounded-lg": "border-radius:8px",
|
|
67
|
+
"chai-rounded-xl": "border-radius:12px",
|
|
68
|
+
"chai-rounded-2xl": "border-radius:16px",
|
|
69
|
+
"chai-rounded-3xl": "border-radius:24px",
|
|
70
|
+
"chai-rounded-4xl": "border-radius:32px",
|
|
71
|
+
"chai-border-white": "border-color: white",
|
|
72
|
+
"chai-border-black": "border-color: black",
|
|
73
|
+
"chai-border-red": "border-color: red",
|
|
74
|
+
"chai-border-green": "border-color: green",
|
|
75
|
+
"chai-border-blue": "border-color: blue",
|
|
76
|
+
"chai-border-solid": "border-style: solid",
|
|
77
|
+
"chai-border-dashed": "border-style: dashed",
|
|
78
|
+
"chai-border-dotted": "border-style: dotted",
|
|
79
|
+
"chai-border-none": "border-style: none",
|
|
80
|
+
|
|
81
|
+
// LAYOUT UTILITIES
|
|
82
|
+
"chai-block": "display: block",
|
|
83
|
+
"chai-inline-block": "display: inline-block",
|
|
84
|
+
"chai-hidden": "display: none",
|
|
85
|
+
"chai-relative": "position: relative",
|
|
86
|
+
"chai-absolute": "position: absolute",
|
|
87
|
+
"chai-fixed": "position: fixed",
|
|
88
|
+
"chai-overflow-hidden": "overflow: hidden",
|
|
89
|
+
"chai-overflow-auto": "overflow: auto",
|
|
90
|
+
"chai-cursor-pointer": "cursor: pointer",
|
|
91
|
+
"chai-cursor-default": "cursor: default",
|
|
92
|
+
"chai-box-border": "box-sizing: border-box",
|
|
93
|
+
"chai-box-content": "box-sizing: content-box",
|
|
94
|
+
"chai-scroll-smooth": "scroll-behavior: smooth",
|
|
95
|
+
"chai-scroll-auto": "scroll-behavior: auto",
|
|
96
|
+
|
|
97
|
+
// EFFECTS
|
|
98
|
+
"chai-shadow-xs": "box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05)",
|
|
99
|
+
"chai-shadow-sm": "box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px -1px rgba(0, 0, 0, 0.1)",
|
|
100
|
+
"chai-shadow-md": "box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1)",
|
|
101
|
+
"chai-shadow-lg": "box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1)",
|
|
102
|
+
"chai-shadow-xl": "box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1)",
|
|
103
|
+
"chai-text-shadow-xs": "text-shadow: 0 1px 2px rgba(0, 0, 0, 0.05)",
|
|
104
|
+
"chai-text-shadow-sm": "text-shadow: 0 1px 3px rgba(0, 0, 0, 0.1)",
|
|
105
|
+
"chai-text-shadow-md": "text-shadow: 0 4px 6px rgba(0, 0, 0, 0.1)",
|
|
106
|
+
"chai-text-shadow-lg": "text-shadow: 0 10px 15px rgba(0, 0, 0, 0.1)",
|
|
107
|
+
"chai-text-shadow-xl": "text-shadow: 0 20px 25px rgba(0, 0, 0, 0.1)",
|
|
108
|
+
"chai-opacity-0": "opacity: 0",
|
|
109
|
+
"chai-opacity-25": "opacity: 0.25",
|
|
110
|
+
"chai-opacity-50": "opacity: 0.5",
|
|
111
|
+
"chai-opacity-75": "opacity: 0.75",
|
|
112
|
+
"chai-opacity-100": "opacity: 1",
|
|
113
|
+
|
|
114
|
+
// FLEXBOX AND GRID
|
|
115
|
+
"chai-flex": "display:flex",
|
|
116
|
+
"chai-grid": "display:grid",
|
|
117
|
+
"chai-flex-row": "flex-direction:row",
|
|
118
|
+
"chai-flex-row-reverse": "flex-direction:row-reverse",
|
|
119
|
+
"chai-flex-column": "flex-direction:column",
|
|
120
|
+
"chai-flex-column-reverse": "flex-direction:column-reverse",
|
|
121
|
+
"chai-justify-start": "justify-content: flex-start",
|
|
122
|
+
"chai-justify-end": "justify-content: flex-end",
|
|
123
|
+
"chai-justify-center": "justify-content: center",
|
|
124
|
+
"chai-justify-between": "justify-content: space-between",
|
|
125
|
+
"chai-justify-around": "justify-content: space-around",
|
|
126
|
+
"chai-justify-evenly": "justify-content: space-evenly",
|
|
127
|
+
"chai-justify-stretch": "justify-content: stretch",
|
|
128
|
+
"chai-justify-items-start": "justify-items: flex-start",
|
|
129
|
+
"chai-justify-items-end": "justify-items: flex-end",
|
|
130
|
+
"chai-justify-items-center": "justify-items: center",
|
|
131
|
+
"chai-justify-items-stretch": "justify-items: stretch",
|
|
132
|
+
"chai-items-start": "align-items: flex-start",
|
|
133
|
+
"chai-items-end": "align-items: flex-end",
|
|
134
|
+
"chai-items-center": "align-items: center",
|
|
135
|
+
"chai-items-stretch": "align-items: stretch",
|
|
136
|
+
"chai-content-center": "align-content: center",
|
|
137
|
+
"chai-content-start": "align-content: flex-start",
|
|
138
|
+
"chai-content-end": "align-content: flex-end",
|
|
139
|
+
"chai-content-between": "align-content: space-between",
|
|
140
|
+
"chai-content-around": "align-content: space-around",
|
|
141
|
+
"chai-content-stretch": "align-content: stretch",
|
|
142
|
+
"chai-flex-wrap": "flex-wrap: wrap",
|
|
143
|
+
"chai-flex-wrap-reverse": "flex-wrap: wrap-reverse",
|
|
144
|
+
"chai-flex-nowrap": "flex-wrap: nowrap",
|
|
145
|
+
|
|
146
|
+
// SIZING
|
|
147
|
+
"chai-w-full": "width: 100%",
|
|
148
|
+
"chai-w-screen": "width: 100vw",
|
|
149
|
+
"chai-h-full": "height: 100%",
|
|
150
|
+
"chai-h-screen": "height: 100vh",
|
|
151
|
+
"chai-mx-auto": "margin-left: auto; margin-right: auto",
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const dynamicPrefixes = {
|
|
155
|
+
// SPACING
|
|
156
|
+
"chai-p-": "padding",
|
|
157
|
+
"chai-m-": "margin",
|
|
158
|
+
|
|
159
|
+
// SIZING
|
|
160
|
+
"chai-w-": "width",
|
|
161
|
+
"chai-h-": "height",
|
|
162
|
+
|
|
163
|
+
// BORDERS
|
|
164
|
+
"chai-rounded-": "border-radius",
|
|
165
|
+
"chai-border-w-": "border-width",
|
|
166
|
+
|
|
167
|
+
// FLEXBOX & GRID
|
|
168
|
+
"chai-gap-": "gap",
|
|
169
|
+
"chai-flex-": "flex",
|
|
170
|
+
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
const palette = {
|
|
174
|
+
red: { light: "#fca5a5", dark: "#991b1b" },
|
|
175
|
+
yellow: { light: "#fef08a", dark: "#854d0e" },
|
|
176
|
+
blue: { light: "#93c5fd", dark: "#1e40af" },
|
|
177
|
+
purple: { light: "#d8b4fe", dark: "#6b21a8" },
|
|
178
|
+
orange: { light: "#fdba74", dark: "#c2410c" },
|
|
179
|
+
green: { light: "#86efac", dark: "#166534" },
|
|
180
|
+
pink: { light: "#f9a8d4", dark: "#be185d" },
|
|
181
|
+
slate: { light: "#cbd5e1", dark: "#334155" }
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
class TeaWind {
|
|
186
|
+
constructor() {
|
|
187
|
+
this.cache = new Map();
|
|
188
|
+
this.prefix = "chai-";
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
resolveClass(c) {
|
|
192
|
+
// 1. Instant Cache Return
|
|
193
|
+
if (this.cache.has(c)) {
|
|
194
|
+
return this.cache.get(c);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
let styleToApply = null;
|
|
198
|
+
|
|
199
|
+
// 2. Static Dictionary Check
|
|
200
|
+
let style = stylesDictionary[c];
|
|
201
|
+
if (style) {
|
|
202
|
+
styleToApply = style + ";";
|
|
203
|
+
}
|
|
204
|
+
// 3. Dynamic Prefix & Palette Checks
|
|
205
|
+
else {
|
|
206
|
+
let keys = Object.keys(dynamicPrefixes);
|
|
207
|
+
for (let k of keys) {
|
|
208
|
+
if (c.startsWith(k)) {
|
|
209
|
+
let attribute = dynamicPrefixes[k];
|
|
210
|
+
let value = c.replace(k, "");
|
|
211
|
+
const cssValue = isNaN(value) ? value : `${value}px`;
|
|
212
|
+
styleToApply = `${attribute}: ${cssValue};`;
|
|
213
|
+
break;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if (!styleToApply) {
|
|
218
|
+
if (c.startsWith("chai-text-")) {
|
|
219
|
+
let textColor = c.replace("chai-text-", "");
|
|
220
|
+
let textColorSplit = textColor.split("-");
|
|
221
|
+
if (palette[textColorSplit[0]]) {
|
|
222
|
+
let colorHexCode = palette[textColorSplit[0]][textColorSplit[1]];
|
|
223
|
+
if (colorHexCode) {
|
|
224
|
+
styleToApply = `color:${colorHexCode};`;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
} else if (c.startsWith("chai-bg-")) {
|
|
228
|
+
let bgColor = c.replace("chai-bg-", "");
|
|
229
|
+
let bgColorSplit = bgColor.split("-");
|
|
230
|
+
if (palette[bgColorSplit[0]]) {
|
|
231
|
+
let bgHexCode = palette[bgColorSplit[0]][bgColorSplit[1]];
|
|
232
|
+
if (bgHexCode) {
|
|
233
|
+
styleToApply = `background-color:${bgHexCode};`;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// 4. Save to Cache & Return
|
|
241
|
+
if (styleToApply) {
|
|
242
|
+
this.cache.set(c, styleToApply);
|
|
243
|
+
} else if (c.startsWith(this.prefix)) {
|
|
244
|
+
console.warn(`🍵 TeaWind: unknown utility class "${c}"`);
|
|
245
|
+
}
|
|
246
|
+
return styleToApply;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
processElement(e) {
|
|
250
|
+
let count = 0;
|
|
251
|
+
const multipleClasses = [...e.classList];
|
|
252
|
+
multipleClasses.forEach(c => {
|
|
253
|
+
if (!c.startsWith(this.prefix)) return;
|
|
254
|
+
const styleString = this.resolveClass(c);
|
|
255
|
+
if (styleString) {
|
|
256
|
+
e.style.cssText += styleString;
|
|
257
|
+
e.classList.remove(c);
|
|
258
|
+
count++;
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
if (e.classList.length === 0) e.removeAttribute("class");
|
|
262
|
+
return count;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// DOM Scanner and Injector
|
|
266
|
+
init() {
|
|
267
|
+
const startTime = performance.now();
|
|
268
|
+
let parsedCount = 0;
|
|
269
|
+
|
|
270
|
+
const elements = document.querySelectorAll(`[class*="${this.prefix}"]`);
|
|
271
|
+
|
|
272
|
+
elements.forEach(e => {
|
|
273
|
+
parsedCount += this.processElement(e);
|
|
274
|
+
})
|
|
275
|
+
|
|
276
|
+
const endTime = performance.now();
|
|
277
|
+
console.log(`🍵 TeaWind initialized in ${(endTime - startTime).toFixed(2)}ms. Processed ${parsedCount} utility classes.`);
|
|
278
|
+
|
|
279
|
+
const observer = new MutationObserver((mutations) => {
|
|
280
|
+
mutations.forEach(mutation => {
|
|
281
|
+
mutation.addedNodes.forEach(node => {
|
|
282
|
+
if (node.nodeType !== 1) return;
|
|
283
|
+
if (node.className && node.className.includes(this.prefix)) {
|
|
284
|
+
this.processElement(node);
|
|
285
|
+
}
|
|
286
|
+
node.querySelectorAll?.(`[class*="${this.prefix}"]`)
|
|
287
|
+
.forEach(child => this.processElement(child));
|
|
288
|
+
});
|
|
289
|
+
});
|
|
290
|
+
});
|
|
291
|
+
const targetNode = document.body || document.documentElement;
|
|
292
|
+
observer.observe(targetNode, { childList: true, subtree: true });
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
const _instance = new TeaWind();
|
|
299
|
+
if (typeof document !== 'undefined') {
|
|
300
|
+
document.addEventListener("DOMContentLoaded", () => _instance.init());
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
function brew() {
|
|
304
|
+
const engine = new TeaWind();
|
|
305
|
+
engine.init();
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
if (typeof module !== 'undefined' && module.exports) {
|
|
309
|
+
module.exports = { default: TeaWind, brew };
|
|
310
|
+
}
|