@expo-forge/forge-ui 0.0.47

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 ADDED
@@ -0,0 +1,385 @@
1
+ # ForgeUI
2
+
3
+ ForgeUI is a utility-first styling engine for:
4
+
5
+ - Web apps (Forge scans classes and generates CSS)
6
+ - React Native / Expo apps (Forge uses a Babel plugin, no CSS file)
7
+
8
+ > **v0.0.10** — Babel plugin now automatically injects `useTheme()` from @expo-forge/forge-ui into all components with `dark:` classes, ensuring they automatically re-render across all pages when theme changes (no manual hook call needed).
9
+
10
+ > **v0.0.9** — Theme preference is now persisted across app restarts using AsyncStorage (React Native) and localStorage (web). The theme will remember your toggle choice.
11
+
12
+ > **v0.0.6** — Native theme detection now uses useColorScheme as the primary source, which fixes Expo system theme detection.
13
+
14
+ ## Quick Start
15
+
16
+ 1. Install:
17
+
18
+ ```bash
19
+ npm install @expo-forge/forge-ui
20
+ ```
21
+
22
+ 2. Choose setup path:
23
+
24
+ - Web: see [Web Setup](#web-setup)
25
+ - React Native / Expo: see [React Native / Expo Setup](#react-native--expo-setup)
26
+
27
+ ## Web Setup
28
+
29
+ ### Step 1: Create forge.config.toml
30
+
31
+ Create this file in your project root:
32
+
33
+ ```toml
34
+ [general]
35
+ input = [
36
+ "src/**/*.html",
37
+ "src/**/*.jsx",
38
+ "src/**/*.tsx",
39
+ "src/**/*.vue",
40
+ "src/**/*.svelte",
41
+ ]
42
+ # CSS only (JS goes next to it):
43
+ output = "dist/forge.css"
44
+ # — or — separate dirs for CSS and JS:
45
+ # output = "public/css, public/js"
46
+
47
+ [options]
48
+ important = false
49
+ minify = false
50
+
51
+ [components]
52
+ enabled = true
53
+ js = true
54
+ ```
55
+
56
+ > When `components.enabled = true`, Forge only emits CSS for components whose class names appear in your scanned source files. Unused component blocks (button, card, modal, etc.) produce no output.
57
+
58
+ ### Step 2: Build or watch
59
+
60
+ One-time build:
61
+
62
+ ```bash
63
+ npx forge build
64
+ ```
65
+
66
+ Dev watch mode:
67
+
68
+ ```bash
69
+ npx forge dev
70
+ ```
71
+
72
+ ### Step 3: Load generated files
73
+
74
+ Required CSS:
75
+
76
+ ```html
77
+ <link rel="stylesheet" href="/forge.css" />
78
+ ```
79
+
80
+ Optional runtime (needed for interactive Forge components and dev auto-refresh):
81
+
82
+ ```html
83
+ <script src="/forge-runtime.js" defer></script>
84
+ ```
85
+
86
+ ## Web Setup By Platform
87
+
88
+ ### Plain HTML
89
+
90
+ 1. Include `src/**/*.html` in `general.input`.
91
+ 2. Run `npx forge build` or `npx forge dev`.
92
+ 3. Load generated files:
93
+
94
+ ```html
95
+ <link rel="stylesheet" href="/dist/forge.css" />
96
+ <script src="/dist/forge-runtime.js" defer></script>
97
+ ```
98
+
99
+ ### React / Vite
100
+
101
+ 1. Include `src/**/*.jsx` and/or `src/**/*.tsx` in `general.input`.
102
+ 2. Run `npx forge dev`.
103
+ 3. Import generated CSS in app entry file:
104
+
105
+ ```tsx
106
+ import "../dist/forge.css";
107
+ ```
108
+
109
+ If using interactive Forge components, include `forge-runtime.js` in `index.html`.
110
+
111
+ ### Next.js
112
+
113
+ Use this config:
114
+
115
+ ```toml
116
+ [general]
117
+ input = ["app/**/*.tsx", "app/**/*.ts", "components/**/*.tsx"]
118
+ output = "public/forge.css"
119
+
120
+ [options]
121
+ important = false
122
+ minify = false
123
+
124
+ [components]
125
+ enabled = true
126
+ js = true
127
+ ```
128
+
129
+ Load in root layout:
130
+
131
+ ```tsx
132
+ <head>
133
+ <link rel="stylesheet" href="/forge.css" />
134
+ </head>
135
+ <body>
136
+ {children}
137
+ <script src="/forge-runtime.js" defer></script>
138
+ </body>
139
+ ```
140
+
141
+ ### Vue
142
+
143
+ 1. Include `src/**/*.vue` in `general.input`.
144
+ 2. Run `npx forge dev`.
145
+ 3. Import generated CSS in app entry file:
146
+
147
+ ```ts
148
+ import "../dist/forge.css";
149
+ ```
150
+
151
+ ### Svelte
152
+
153
+ 1. Include `src/**/*.svelte` in `general.input`.
154
+ 2. Run `npx forge dev`.
155
+ 3. Import generated CSS in root entry/layout file:
156
+
157
+ ```ts
158
+ import "../dist/forge.css";
159
+ ```
160
+
161
+ ## React Native / Expo Setup
162
+
163
+ ### Important
164
+
165
+ React Native does not use:
166
+
167
+ - forge.config.toml
168
+ - forge.css
169
+ - forge-runtime.js
170
+
171
+ ### Step 1: Initialize
172
+
173
+ ```bash
174
+ npx forge init --native
175
+ ```
176
+
177
+ ### Step 2: Enable Babel plugin
178
+
179
+ Use:
180
+
181
+ ```txt
182
+ @expo-forge/forge-ui/babel-plugin
183
+ ```
184
+
185
+ ### Step 3: Wrap app with ThemeProvider
186
+
187
+ ```tsx
188
+ import { ThemeProvider } from "@expo-forge/forge-ui";
189
+
190
+ export default function RootLayout() {
191
+ return <ThemeProvider>{/* app */}</ThemeProvider>;
192
+ }
193
+ ```
194
+
195
+ ### Step 4: Start Expo
196
+
197
+ ```bash
198
+ npx expo start
199
+ ```
200
+
201
+ ### Required app.json settings
202
+
203
+ ```json
204
+ {
205
+ "expo": {
206
+ "userInterfaceStyle": "automatic",
207
+ "experiments": {
208
+ "reactCompiler": false
209
+ }
210
+ }
211
+ }
212
+ ```
213
+
214
+ ### Step 5: Use Forge color palettes in native
215
+
216
+ You can now use all Forge color palettes in your native components:
217
+
218
+ ```tsx
219
+ import { useColors } from "@expo-forge/forge-ui";
220
+
221
+ export default function MyComponent() {
222
+ const colors = useColors();
223
+ return <View style={{ backgroundColor: colors.blue[5] }} />;
224
+ }
225
+ ```
226
+
227
+ ## Dynamic Classes (Web)
228
+
229
+ Literal class strings are supported:
230
+
231
+ ```ts
232
+ const card = {
233
+ color: "bg-gradient-to-r from-blue-1 to-green-1",
234
+ };
235
+ ```
236
+
237
+ For fully runtime-generated class names (example: `bg-${tone}-5`), use:
238
+
239
+ 1. `general.safelist`
240
+ 2. `general.inject_colors = true` (larger CSS output)
241
+
242
+ ## Output Optimizations
243
+
244
+ Forge automatically tree-shakes generated CSS — no extra config needed.
245
+
246
+ ### Selective `:root` color variables
247
+
248
+ The `:root` block only contains variables for color palettes you actually use. A project that only uses `bg-blue-5 text-red-3` gets `--blue-*` and `--red-*` variables only — not all 22 palettes.
249
+
250
+ ### Lazy component CSS
251
+
252
+ When `components.enabled = true`, Forge only emits CSS for components whose class names appear in scanned files:
253
+
254
+ | Component block | Emitted when you use… |
255
+ | --------------- | --------------------------------------------------------------------------------------------------------- |
256
+ | Button | `button`, `button-primary`, `button-secondary`, `button-ghost`, `button-danger`, `button-sm`, `button-lg` |
257
+ | Card | `card`, `card-header`, `card-body`, `card-footer` |
258
+ | Modal | `modal-content`, `data-fg-modal`, `data-fg-toggle` |
259
+ | Utility | `avatar`, `dot`, `spark`, `bar`, `table-wrap` |
260
+ | Visibility | `hidden` |
261
+
262
+ ## Advanced Utilities
263
+
264
+ ### Fluid text sizing
265
+
266
+ Use `text-clamp-*` for responsive font sizes with CSS `clamp(...)`:
267
+
268
+ ```html
269
+ <h1 class="text-clamp-4xl">Fluid heading</h1>
270
+ <p class="text-clamp-sm">Fluid body text</p>
271
+ ```
272
+
273
+ Supported presets: `sx`/`xs`, `sm`, `base`, `lg`, `xl`, `2xl` ... `9xl`.
274
+
275
+ ### Class-driven at-rules
276
+
277
+ Forge can emit custom at-rules directly from class tokens:
278
+
279
+ ```html
280
+ <div class="media-[(min-width:900px)]:text-clamp-xl">Custom media query</div>
281
+
282
+ <div class="layer-[components]:rounded-lg">Wrapped in @layer components</div>
283
+
284
+ <div
285
+ class="keyframes-[wiggle:0%{transform:rotate(-3deg)}100%{transform:rotate(3deg)}] animate-[wiggle_1.2s_ease-in-out_infinite]"
286
+ >
287
+ Custom keyframes + animation
288
+ </div>
289
+ ```
290
+
291
+ Notes:
292
+
293
+ - Replace spaces with underscores inside bracket syntax when needed.
294
+ - These tokens work with existing variants like `md:`, `hover:`, and `dark:`.
295
+
296
+ ## Config Reference
297
+
298
+ | Key | Type | Default | Purpose |
299
+ | ------------------------------- | ---------- | --------------------- | ------------------------------------------------ |
300
+ | `general.input` | `string[]` | common `src/**` globs | Files to scan for classes |
301
+ | `general.output` | `string` | `forge.css` | CSS output (and optional JS output) — see below |
302
+ | `general.safelist` | `string[]` | `[]` | Always include these classes |
303
+ | `general.inject_colors` | `bool` | `false` | Pre-generate full color and gradient utility set |
304
+ | `general.inject_color_variants` | `string[]` | `[]` | Variant prefixes for injected classes |
305
+ | `options.important` | `bool` | `false` | Append `!important` to declarations |
306
+ | `options.minify` | `bool` | `false` | Minify output CSS |
307
+ | `components.enabled` | `bool` | `true` | Include built-in component CSS |
308
+ | `components.js` | `bool` | `true` | Emit forge-runtime.js |
309
+
310
+ ### output format
311
+
312
+ ```toml
313
+ # CSS only — JS written next to it
314
+ output = "dist/forge.css"
315
+
316
+ # CSS in one dir, JS in another
317
+ output = "public/css, public/js"
318
+
319
+ # Bare directories — filenames appended automatically
320
+ # public/css/forge.css + public/js/forge-runtime.js
321
+ output = "public/css, public/js"
322
+
323
+ # Explicit filenames also work
324
+ output = "public/css/styles.css, public/js/runtime.js"
325
+ ```
326
+
327
+ ## Common Mistakes
328
+
329
+ ### No styles applied
330
+
331
+ - Run `npx forge build`
332
+ - Confirm file exists at `general.output`
333
+ - Confirm app loads the same file path
334
+
335
+ ### Some classes missing
336
+
337
+ - Your file globs likely miss some folders
338
+ - Add those folders to `general.input`
339
+
340
+ ### Browser does not update during dev
341
+
342
+ - Use `npx forge dev`
343
+ - Ensure `/forge-runtime.js` is loaded
344
+
345
+ ### React Native styles do not apply
346
+
347
+ - Run `npx forge init --native`
348
+ - Ensure Babel plugin is configured
349
+ - Restart Metro
350
+
351
+ ## Command Summary
352
+
353
+ Same commands on Windows, macOS, and Linux:
354
+
355
+ ```bash
356
+ npx forge build
357
+ npx forge dev
358
+ npx forge init --native
359
+ ```
360
+
361
+ ## Repository
362
+
363
+ https://github.com/semsakadanupol/forge-ui
364
+
365
+ ## Web-like first: and last: pseudo-classes in React Native
366
+
367
+ With Forge-UI's experimental Babel plugin support, you can use `first:` and `last:` pseudo-classes directly in `className` inside a `.map` loop—just like on the web!
368
+
369
+ **Example:**
370
+
371
+ ```jsx
372
+ {
373
+ items.map((item) => (
374
+ <View key={item.id} className="p-4 first:bg-red-1 last:rounded-b-xl">
375
+ {item.text}
376
+ </View>
377
+ ));
378
+ }
379
+ ```
380
+
381
+ - `first:bg-red-1` will only apply to the first child.
382
+ - `last:rounded-b-xl` will only apply to the last child.
383
+ - No manual index checks or helpers needed—just write your classes as you would for web.
384
+
385
+ This works for any dynamic array mapping in JSX in React Native.