luxaura 1.0.0 → 1.0.2
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 +365 -208
- package/bin/luxaura.js +813 -394
- package/examples/TodoApp.lux +89 -83
- package/package.json +4 -12
- package/src/compiler/index.js +258 -251
- package/src/index.js +12 -23
- package/src/parser/index.js +162 -185
- package/src/runtime/luxaura.runtime.js +277 -266
- package/src/vault/server.js +88 -131
- package/ui-kit/luxaura.min.css +459 -605
- package/ui-kit/luxaura.min.js +219 -169
- package/templates/luxaura.config +0 -43
package/README.md
CHANGED
|
@@ -1,37 +1,64 @@
|
|
|
1
1
|
# Luxaura Framework
|
|
2
2
|
|
|
3
|
-
> **Intent-
|
|
3
|
+
> **The Intent-Driven Full-Stack Web Framework.**
|
|
4
|
+
> Not React. Not Vue. Not Angular. Not Next.js. Just Luxaura.
|
|
4
5
|
|
|
5
|
-
[](#)
|
|
7
|
+
[](#)
|
|
6
8
|
[](#)
|
|
7
|
-
[](#)
|
|
8
10
|
|
|
9
11
|
---
|
|
10
12
|
|
|
11
|
-
##
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
13
|
+
## Why Luxaura is Different
|
|
14
|
+
|
|
15
|
+
Every concept, every keyword, every folder name was designed from scratch.
|
|
16
|
+
|
|
17
|
+
| Concept | React / Vue / Next | Luxaura |
|
|
18
|
+
|---|---|---|
|
|
19
|
+
| Create project | `npm create vite` / `ng new` | `luxaura release` |
|
|
20
|
+
| Start dev server | `npm run dev` / `ng serve` | `luxaura ignite` |
|
|
21
|
+
| Production build | `npm run build` | `luxaura forge` |
|
|
22
|
+
| Add a library | `npm install` | `luxaura bring` |
|
|
23
|
+
| Make a component | `ng generate component` | `luxaura component` |
|
|
24
|
+
| Route files live in | `/pages` (Next.js) | `/scenes` |
|
|
25
|
+
| Components live in | `/components` | `/craft/<Name>/` |
|
|
26
|
+
| Server logic lives in | `/api` / `.server.js` | `/services/` |
|
|
27
|
+
| Static files | `/public` | `/media` |
|
|
28
|
+
| Build output | `/dist` | `/depot` |
|
|
29
|
+
| Reactive data | `state` / `data()` | `signal` |
|
|
30
|
+
| External inputs | `props` | `receive` |
|
|
31
|
+
| Server code block | `server` | `vault` |
|
|
32
|
+
| Styles block | `style` | `paint` |
|
|
33
|
+
| UI template | `template` / `view` | `canvas` |
|
|
34
|
+
| Binding syntax | `{var}` / `{{ var }}` | `<<var>>` |
|
|
35
|
+
| Event syntax | `@click` / `on:click` | `when click:` |
|
|
36
|
+
| Button element | `<button>` / `Action` | `Trigger` |
|
|
37
|
+
| Text input | `<input>` / `Input` | `Field` |
|
|
38
|
+
| Paragraph | `<p>` / `Text` | `Body` |
|
|
39
|
+
| Heading | `<h1>` / `Title` | `Headline` |
|
|
40
|
+
| Image | `<img>` / `Image` | `Picture` |
|
|
41
|
+
| Nav bar | `<nav>` / `Nav` | `Ribbon` |
|
|
42
|
+
| Sidebar | `<aside>` / `Sidebar` | `Drawer` |
|
|
43
|
+
| Footer | `<footer>` / `Footer` | `Anchor` |
|
|
44
|
+
| Card container | `Card` | `Plate` |
|
|
45
|
+
| List | `<ul>` / `List` | `Roster` |
|
|
46
|
+
| List item | `<li>` / `ListItem` | `Entry` |
|
|
47
|
+
| Badge/tag | `Badge` | `Mark` |
|
|
48
|
+
| Box-shadow style | `shadow: soft` | `glow: soft` |
|
|
49
|
+
| Padding style | `padding: 4` | `breathe: 4` |
|
|
50
|
+
| Margin style | `margin: 4` | `push: 4` |
|
|
51
|
+
| Border radius | `radius: large` | `curve: round` |
|
|
52
|
+
| Text color | `color: #fff` | `ink: #fff` |
|
|
53
|
+
| Background | `background: #000` | `fill: #000` |
|
|
54
|
+
| Font size | `fontSize: xl` | `size: xlarge` |
|
|
55
|
+
| Font weight | `fontWeight: bold` | `weight: strong` |
|
|
56
|
+
| Notification | toast | `flash` |
|
|
57
|
+
| Storage wrapper | `localStorage` | `stash` |
|
|
58
|
+
| HTTP helper | `fetch` / `axios` | `reach` |
|
|
59
|
+
| Auth helper | `auth` | `gate` |
|
|
60
|
+
| Mount component | `.mount()` | `.launch()` |
|
|
61
|
+
| CSS utilities | `lux-` prefix | `lx-` prefix |
|
|
35
62
|
|
|
36
63
|
---
|
|
37
64
|
|
|
@@ -41,299 +68,429 @@ view
|
|
|
41
68
|
npm install -g luxaura
|
|
42
69
|
```
|
|
43
70
|
|
|
44
|
-
Or use it as a project dependency:
|
|
45
|
-
|
|
46
|
-
```bash
|
|
47
|
-
npm install luxaura
|
|
48
|
-
```
|
|
49
|
-
|
|
50
71
|
---
|
|
51
72
|
|
|
52
73
|
## Quick Start
|
|
53
74
|
|
|
54
75
|
```bash
|
|
55
|
-
|
|
56
|
-
luxaura new my-app
|
|
57
|
-
|
|
58
|
-
# 2. Enter the project
|
|
76
|
+
luxaura release my-app
|
|
59
77
|
cd my-app
|
|
60
|
-
|
|
61
|
-
# 3. Start the dev server (HMR enabled)
|
|
62
|
-
luxaura run
|
|
78
|
+
luxaura ignite
|
|
63
79
|
```
|
|
64
80
|
|
|
65
|
-
Open `http://localhost:3000` — your
|
|
81
|
+
Open `http://localhost:3000` — your start scene loads with a full how-to guide built in.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Project Structure
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
my-app/
|
|
89
|
+
├── luxaura.config ← app config (identity, theme, db, mode)
|
|
90
|
+
├── scenes/ ← route entry points (NOT "pages")
|
|
91
|
+
│ └── index.lux ← home scene
|
|
92
|
+
├── craft/ ← all components (NOT "components" or "modules")
|
|
93
|
+
│ └── Ribbon/
|
|
94
|
+
│ ├── Ribbon.lux
|
|
95
|
+
│ ├── Ribbon.paint.css
|
|
96
|
+
│ └── index.js
|
|
97
|
+
├── services/ ← vault-only logic (NOT "api" or "server")
|
|
98
|
+
│ └── index.js
|
|
99
|
+
├── media/ ← static files (NOT "public" or "assets")
|
|
100
|
+
└── depot/ ← build output (NOT "dist")
|
|
101
|
+
├── public/ ← client assets
|
|
102
|
+
└── vault/ ← server modules (NEVER publicly served)
|
|
103
|
+
```
|
|
66
104
|
|
|
67
105
|
---
|
|
68
106
|
|
|
69
107
|
## CLI Reference
|
|
70
108
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
109
|
+
```bash
|
|
110
|
+
luxaura release <n> # Bootstrap a new project
|
|
111
|
+
luxaura ignite # Start dev server + live reload
|
|
112
|
+
luxaura ignite --port 8080 # Custom port
|
|
113
|
+
luxaura forge # Build for production
|
|
114
|
+
luxaura component <n> # Create a component → craft/<n>/
|
|
115
|
+
luxaura service <n> # Create a vault service → services/
|
|
116
|
+
luxaura module <n> # Create a shared module → craft/<n>/
|
|
117
|
+
luxaura bring <lib> # Add an external library
|
|
118
|
+
luxaura polish # Auto-format all .lux files
|
|
119
|
+
luxaura shield # Security scan (XSS, SQL injection, vault leaks)
|
|
120
|
+
luxaura help_me # Full interactive CLI guide
|
|
121
|
+
```
|
|
80
122
|
|
|
81
123
|
---
|
|
82
124
|
|
|
83
|
-
## .lux File
|
|
125
|
+
## The .lux File
|
|
84
126
|
|
|
85
|
-
Every `.lux` file has five blocks:
|
|
127
|
+
Every `.lux` file has five blocks. All block names are unique to Luxaura:
|
|
86
128
|
|
|
87
129
|
```yaml
|
|
88
|
-
#
|
|
89
|
-
|
|
90
|
-
|
|
130
|
+
# MyScene.lux
|
|
131
|
+
|
|
132
|
+
# 1. receive — inputs from outside (NOT "props")
|
|
133
|
+
receive
|
|
134
|
+
title: String = "Hello"
|
|
91
135
|
count: Number = 0
|
|
92
136
|
|
|
93
|
-
# 2.
|
|
94
|
-
|
|
137
|
+
# 2. signal — reactive internal data (NOT "state" or "data")
|
|
138
|
+
signal
|
|
139
|
+
clicks: 0
|
|
95
140
|
name: "World"
|
|
96
|
-
active: false
|
|
97
141
|
|
|
98
|
-
# 3.
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
142
|
+
# 3. vault — server-only logic (NOT "server" block)
|
|
143
|
+
vault
|
|
144
|
+
pull db from "luxaura/db"
|
|
145
|
+
|
|
146
|
+
action saveClick(n):
|
|
147
|
+
return db.insert("clicks", { n, ts: "NOW()" })
|
|
103
148
|
|
|
104
|
-
# 4.
|
|
105
|
-
|
|
149
|
+
# 4. paint — smart styling (NOT "style")
|
|
150
|
+
paint
|
|
106
151
|
self
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
152
|
+
breathe: 8
|
|
153
|
+
fill: #0d0d1a
|
|
154
|
+
Headline
|
|
155
|
+
size: titan
|
|
156
|
+
weight: heavy
|
|
157
|
+
ink: #ffffff
|
|
158
|
+
Trigger
|
|
159
|
+
curve: pill
|
|
160
|
+
glow: soft
|
|
161
|
+
|
|
162
|
+
# 5. canvas — UI composition (NOT "view" or "template")
|
|
163
|
+
canvas
|
|
164
|
+
Scene
|
|
165
|
+
Stack
|
|
166
|
+
Headline "<<title>>"
|
|
167
|
+
Body "Hello, <<name>>!"
|
|
168
|
+
Trigger "Click me"
|
|
169
|
+
when click:
|
|
170
|
+
await vault.saveClick(clicks)
|
|
171
|
+
Body "Clicks: <<clicks>>"
|
|
121
172
|
```
|
|
122
173
|
|
|
123
174
|
---
|
|
124
175
|
|
|
125
|
-
##
|
|
176
|
+
## Canvas Node Vocabulary
|
|
177
|
+
|
|
178
|
+
No HTML tags. No generic names. Every node has a Luxaura-specific name:
|
|
126
179
|
|
|
127
|
-
|
|
180
|
+
### Layout
|
|
181
|
+
| Node | Purpose |
|
|
182
|
+
|---|---|
|
|
183
|
+
| `Frame` | Generic block wrapper |
|
|
184
|
+
| `Strip` | Horizontal flex row |
|
|
185
|
+
| `Stack` | Vertical flex column |
|
|
186
|
+
| `Mosaic` | Auto-responsive grid |
|
|
187
|
+
| `Scene` | Max-width centered wrapper |
|
|
188
|
+
|
|
189
|
+
### Navigation
|
|
190
|
+
| Node | Purpose |
|
|
191
|
+
|---|---|
|
|
192
|
+
| `Ribbon` | Top navigation bar |
|
|
193
|
+
| `Drawer` | Side panel |
|
|
194
|
+
| `Anchor` | Footer bar |
|
|
195
|
+
| `Crown` | Page header |
|
|
196
|
+
| `Chapter` | Content section |
|
|
197
|
+
|
|
198
|
+
### Content
|
|
199
|
+
| Node | Purpose |
|
|
200
|
+
|---|---|
|
|
201
|
+
| `Headline` | Heading (auto-selects h1–h6 by nesting depth) |
|
|
202
|
+
| `Body` | Paragraph text |
|
|
203
|
+
| `Picture` | Image (auto-lazy loaded) |
|
|
204
|
+
| `Glyph` | Icon holder |
|
|
205
|
+
| `Mark` | Badge / tag |
|
|
206
|
+
| `Plate` | Card surface |
|
|
207
|
+
| `Snippet` | Inline code |
|
|
208
|
+
| `Block` | Code block |
|
|
209
|
+
|
|
210
|
+
### Interaction
|
|
211
|
+
| Node | Purpose |
|
|
212
|
+
|---|---|
|
|
213
|
+
| `Trigger` | Button / clickable action |
|
|
214
|
+
| `Field` | Text input |
|
|
215
|
+
| `Vessel` | Form wrapper |
|
|
216
|
+
| `Toggle` | Checkbox / switch |
|
|
217
|
+
| `Pathway` | Navigation link |
|
|
218
|
+
|
|
219
|
+
### Data
|
|
220
|
+
| Node | Purpose |
|
|
221
|
+
|---|---|
|
|
222
|
+
| `Grid` | Data table |
|
|
223
|
+
| `Roster` | List |
|
|
224
|
+
| `Entry` | List item |
|
|
225
|
+
| `Splitter` | Horizontal divider |
|
|
128
226
|
|
|
129
|
-
|
|
227
|
+
### Overlay
|
|
228
|
+
| Node | Purpose |
|
|
130
229
|
|---|---|
|
|
131
|
-
|
|
|
132
|
-
|
|
|
133
|
-
| **Content** | `Title`, `Text`, `Image`, `Icon`, `Badge` |
|
|
134
|
-
| **Interaction** | `Action`, `Input`, `Form`, `Switch`, `Link` |
|
|
135
|
-
| **Data** | `Table`, `List`, `ListItem` |
|
|
136
|
-
| **Overlay** | `Modal`, `Overlay`, `Card` |
|
|
230
|
+
| `Curtain` | Modal overlay |
|
|
231
|
+
| `Popup` | Modal content |
|
|
137
232
|
|
|
138
233
|
---
|
|
139
234
|
|
|
140
|
-
## Smart
|
|
235
|
+
## Paint Smart Tokens
|
|
236
|
+
|
|
237
|
+
Luxaura's styling system uses intent-based tokens — no CSS property names exposed:
|
|
141
238
|
|
|
142
239
|
```yaml
|
|
143
|
-
|
|
240
|
+
paint
|
|
144
241
|
self
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
242
|
+
breathe: 6 # padding: 24px (6 × 4px)
|
|
243
|
+
push: 4 # margin: 16px
|
|
244
|
+
gap: 4 # gap: 16px between children
|
|
245
|
+
fill: #0d0d1a # background color
|
|
246
|
+
ink: #ffffff # text color
|
|
247
|
+
glow: soft # box-shadow (whisper/soft/loud/neon)
|
|
248
|
+
curve: round # border-radius (gentle/smooth/round/pill)
|
|
249
|
+
size: titan # font-size (tiny/small/base/large/xlarge/huge/titan/mega)
|
|
250
|
+
weight: heavy # font-weight (feather/light/normal/firm/strong/heavy)
|
|
251
|
+
wide: 400 # width: 400px
|
|
252
|
+
tall: 200 # height: 200px
|
|
253
|
+
pointer: true # cursor: pointer
|
|
150
254
|
```
|
|
151
255
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
256
|
+
### Glow tokens
|
|
257
|
+
| Token | Result |
|
|
258
|
+
|---|---|
|
|
259
|
+
| `glow: whisper` | `box-shadow: 0 2px 10px rgba(0,0,0,0.07)` |
|
|
260
|
+
| `glow: soft` | `box-shadow: 0 4px 20px rgba(0,0,0,0.11)` |
|
|
261
|
+
| `glow: loud` | `box-shadow: 0 8px 32px rgba(0,0,0,0.22)` |
|
|
262
|
+
| `glow: neon` | `box-shadow: 0 0 28px rgba(108,99,255,0.5)` |
|
|
263
|
+
|
|
264
|
+
### Curve tokens
|
|
265
|
+
| Token | Result |
|
|
266
|
+
|---|---|
|
|
267
|
+
| `curve: gentle` | `border-radius: 4px` |
|
|
268
|
+
| `curve: smooth` | `border-radius: 8px` |
|
|
269
|
+
| `curve: round` | `border-radius: 16px` |
|
|
270
|
+
| `curve: pill` | `border-radius: 9999px` |
|
|
271
|
+
|
|
272
|
+
### Size tokens
|
|
273
|
+
`tiny` · `small` · `base` · `large` · `xlarge` · `huge` · `titan` · `mega`
|
|
274
|
+
|
|
275
|
+
### Weight tokens
|
|
276
|
+
`feather` · `light` · `normal` · `firm` · `strong` · `heavy`
|
|
157
277
|
|
|
158
278
|
---
|
|
159
279
|
|
|
160
|
-
## The Vault (
|
|
280
|
+
## The Vault (Server Security)
|
|
161
281
|
|
|
162
|
-
|
|
282
|
+
`vault` blocks run exclusively on the server. The compiler performs **code stripping** — zero vault code reaches the browser.
|
|
163
283
|
|
|
164
284
|
```yaml
|
|
165
|
-
|
|
166
|
-
|
|
285
|
+
vault
|
|
286
|
+
pull db from "luxaura/db"
|
|
167
287
|
|
|
168
|
-
|
|
169
|
-
# This code NEVER reaches the browser
|
|
288
|
+
action getUser(id):
|
|
170
289
|
return db.query("SELECT * FROM users WHERE id = ?", [id])
|
|
171
290
|
```
|
|
172
291
|
|
|
173
|
-
|
|
292
|
+
Call it from canvas:
|
|
174
293
|
|
|
175
294
|
```yaml
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
result = await
|
|
295
|
+
canvas
|
|
296
|
+
Trigger "Load User"
|
|
297
|
+
when click:
|
|
298
|
+
result = await vault.getUser(userId)
|
|
180
299
|
```
|
|
181
300
|
|
|
182
|
-
|
|
183
|
-
- **Auto-
|
|
184
|
-
- **Auto-
|
|
185
|
-
- **Code
|
|
301
|
+
Security features:
|
|
302
|
+
- **Auto-token**: Every vault request is signed with a rotating session token
|
|
303
|
+
- **Auto-sanitize**: String inputs are sanitized before processing
|
|
304
|
+
- **Code stripping**: The build verifiably excludes vault code from `depot/public`
|
|
305
|
+
- **Shield scan**: `luxaura shield` detects vault leaks, XSS, and SQL injection patterns
|
|
186
306
|
|
|
187
307
|
---
|
|
188
308
|
|
|
189
|
-
##
|
|
190
|
-
|
|
191
|
-
Layouts adapt automatically without media queries:
|
|
192
|
-
|
|
193
|
-
- `Row` → stacks to `Column` on mobile
|
|
194
|
-
- Buttons/inputs auto-enlarge to 44px touch targets on mobile
|
|
195
|
-
- `Image` with `responsive: true` never overflows its container
|
|
196
|
-
- `Nav` auto-collapses on small screens
|
|
197
|
-
|
|
198
|
-
---
|
|
309
|
+
## Component Structure
|
|
199
310
|
|
|
200
|
-
|
|
311
|
+
Every component gets its own folder — not a single file:
|
|
201
312
|
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
313
|
+
```
|
|
314
|
+
craft/
|
|
315
|
+
└── UserCard/
|
|
316
|
+
├── UserCard.lux ← the canvas (UI)
|
|
317
|
+
├── UserCard.paint.css ← scoped styles
|
|
318
|
+
└── index.js ← optional JS bridge / exports
|
|
207
319
|
```
|
|
208
320
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
---
|
|
321
|
+
Create one with: `luxaura component UserCard`
|
|
212
322
|
|
|
213
|
-
|
|
323
|
+
The generated `.lux` file has a styled big title by default:
|
|
214
324
|
|
|
215
325
|
```yaml
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
import storage from "luxaura/storage" # localStorage wrapper
|
|
326
|
+
canvas
|
|
327
|
+
Frame
|
|
328
|
+
Stack
|
|
329
|
+
Headline "I'm UserCard component !!"
|
|
330
|
+
Body "I live in craft/UserCard/UserCard.lux — edit me!"
|
|
222
331
|
```
|
|
223
332
|
|
|
224
333
|
---
|
|
225
334
|
|
|
226
|
-
##
|
|
335
|
+
## Vault Services
|
|
227
336
|
|
|
228
|
-
|
|
337
|
+
Services are server-only modules. They live in `/services/` and are called from vault blocks:
|
|
229
338
|
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
339
|
+
```javascript
|
|
340
|
+
// services/User.service.js
|
|
341
|
+
async function getUser(id) { ... }
|
|
342
|
+
async function createUser(data) { ... }
|
|
343
|
+
module.exports = { getUser, createUser };
|
|
234
344
|
```
|
|
235
345
|
|
|
236
|
-
|
|
346
|
+
Create one with: `luxaura service User`
|
|
237
347
|
|
|
238
348
|
---
|
|
239
349
|
|
|
240
|
-
##
|
|
350
|
+
## Binding Syntax: `<<varName>>`
|
|
241
351
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
352
|
+
Luxaura uses double angle brackets — not `{var}` (Angular/Svelte), not `{{ var }}` (Vue/Handlebars):
|
|
353
|
+
|
|
354
|
+
```yaml
|
|
355
|
+
canvas
|
|
356
|
+
Headline "<<pageTitle>>"
|
|
357
|
+
Body "Welcome, <<userName>>!"
|
|
358
|
+
Mark "<<status>>"
|
|
245
359
|
```
|
|
246
360
|
|
|
247
|
-
|
|
361
|
+
---
|
|
362
|
+
|
|
363
|
+
## Event Syntax: `when <event>:`
|
|
364
|
+
|
|
365
|
+
Not `@click` (Vue), not `on:click` (Svelte), not `onClick` (React):
|
|
248
366
|
|
|
249
367
|
```yaml
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
368
|
+
canvas
|
|
369
|
+
Trigger "Save"
|
|
370
|
+
when click:
|
|
371
|
+
await vault.save(formData)
|
|
372
|
+
|
|
373
|
+
Field kind:"email"
|
|
374
|
+
when input:
|
|
375
|
+
email = this.value
|
|
254
376
|
```
|
|
255
377
|
|
|
256
378
|
---
|
|
257
379
|
|
|
258
|
-
##
|
|
380
|
+
## Vault Block Syntax
|
|
259
381
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
382
|
+
Not `def` (Python-style), not `export async function`:
|
|
383
|
+
|
|
384
|
+
```yaml
|
|
385
|
+
vault
|
|
386
|
+
pull db from "luxaura/db" # (not "import db from")
|
|
387
|
+
|
|
388
|
+
action getItems(userId): # (not "def" or "function")
|
|
389
|
+
return db.query("SELECT * FROM items WHERE user_id = ?", [userId])
|
|
390
|
+
|
|
391
|
+
action createItem(data):
|
|
392
|
+
return db.insert("items", data)
|
|
270
393
|
```
|
|
271
394
|
|
|
272
395
|
---
|
|
273
396
|
|
|
274
|
-
##
|
|
397
|
+
## Runtime API
|
|
275
398
|
|
|
276
399
|
```javascript
|
|
277
|
-
|
|
400
|
+
// Launch a scene (not "mount")
|
|
401
|
+
window.__Lux__.launch('MyScene', '#lux-stage');
|
|
402
|
+
|
|
403
|
+
// Flash notifications (not "toast")
|
|
404
|
+
__Lux__.flash.ok('Saved!');
|
|
405
|
+
__Lux__.flash.fail('Something went wrong');
|
|
406
|
+
__Lux__.flash.warn('Check your input');
|
|
407
|
+
__Lux__.flash.info('Loading...');
|
|
408
|
+
|
|
409
|
+
// Theme
|
|
410
|
+
__Lux__.theme.set('dark');
|
|
411
|
+
__Lux__.theme.toggle();
|
|
412
|
+
|
|
413
|
+
// Navigate
|
|
414
|
+
__Lux__.navigate('/about');
|
|
415
|
+
|
|
416
|
+
// Reach (HTTP requests — not "fetch" or "axios")
|
|
417
|
+
const data = await __Lux__.reach.fetch('https://api.example.com/items');
|
|
418
|
+
await __Lux__.reach.send('https://api.example.com/items', { name: 'New item' });
|
|
419
|
+
|
|
420
|
+
// Stash (storage — not "localStorage" directly)
|
|
421
|
+
__Lux__.stash.local.write('key', 'value');
|
|
422
|
+
__Lux__.stash.local.read('key');
|
|
423
|
+
__Lux__.stash.session.write('key', 'value');
|
|
424
|
+
|
|
425
|
+
// Gate (auth — not "auth")
|
|
426
|
+
await __Lux__.gate.enter({ email, password });
|
|
427
|
+
await __Lux__.gate.leave();
|
|
428
|
+
const user = await __Lux__.gate.whoami();
|
|
429
|
+
```
|
|
278
430
|
|
|
279
|
-
|
|
280
|
-
const ast = luxaura.parse(source, 'MyComponent.lux');
|
|
431
|
+
---
|
|
281
432
|
|
|
282
|
-
|
|
283
|
-
const output = luxaura.compile(ast, { componentName: 'MyComponent' });
|
|
433
|
+
## CSS Utility Classes
|
|
284
434
|
|
|
285
|
-
|
|
286
|
-
console.log(output.serverJS); // Server vault module
|
|
287
|
-
console.log(output.css); // Component styles
|
|
288
|
-
console.log(output.html); // HTML shell
|
|
435
|
+
All utility classes use the `lx-` prefix (not `lux-`, which is reserved for node base classes):
|
|
289
436
|
|
|
290
|
-
|
|
291
|
-
|
|
437
|
+
```html
|
|
438
|
+
class: "lx-flex lx-center lx-gap4"
|
|
439
|
+
class: "lx-titan lx-heavy lx-ink-pulse"
|
|
440
|
+
class: "lx-curve-round lx-glow-soft lx-fill-pulse"
|
|
441
|
+
class: "lx-w-full lx-min-screen"
|
|
292
442
|
```
|
|
293
443
|
|
|
294
444
|
---
|
|
295
445
|
|
|
296
|
-
##
|
|
446
|
+
## Headless Mode
|
|
297
447
|
|
|
298
|
-
|
|
299
|
-
// Mount a component
|
|
300
|
-
const ctx = window.__Lux__.mount('MyApp', '#root', { title: 'Hello' });
|
|
448
|
+
Use Luxaura as a frontend layer over any backend:
|
|
301
449
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
450
|
+
```
|
|
451
|
+
# luxaura.config
|
|
452
|
+
mode: headless
|
|
453
|
+
proxy.target: http://localhost:8080
|
|
454
|
+
```
|
|
306
455
|
|
|
307
|
-
|
|
308
|
-
__Lux__.setTheme('dark');
|
|
309
|
-
__Lux__.setTheme('light');
|
|
456
|
+
All `/api/*` requests are proxied to your existing Java, Python, PHP, or Go backend.
|
|
310
457
|
|
|
311
|
-
|
|
312
|
-
__Lux__.router.navigate('/about');
|
|
458
|
+
---
|
|
313
459
|
|
|
314
|
-
|
|
315
|
-
const data = await __Lux__.http.get('https://api.example.com/data');
|
|
460
|
+
## luxaura.config
|
|
316
461
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
462
|
+
```
|
|
463
|
+
identity.name: my-app
|
|
464
|
+
identity.version: 1.0.0
|
|
465
|
+
theme: light
|
|
466
|
+
mode: full
|
|
467
|
+
port: 3000
|
|
468
|
+
# db.engine: postgres
|
|
469
|
+
# db.link: postgresql://localhost:5432/my-app
|
|
470
|
+
# proxy.target: http://localhost:8080
|
|
320
471
|
```
|
|
321
472
|
|
|
322
473
|
---
|
|
323
474
|
|
|
324
|
-
##
|
|
475
|
+
## Programmatic API
|
|
476
|
+
|
|
477
|
+
```javascript
|
|
478
|
+
const luxaura = require('luxaura');
|
|
325
479
|
|
|
326
|
-
|
|
480
|
+
// Parse a .lux file → AST
|
|
481
|
+
const ast = luxaura.parse(source, 'MyScene.lux');
|
|
482
|
+
// ast.receive / ast.signal / ast.vault / ast.paint / ast.canvas
|
|
327
483
|
|
|
328
|
-
|
|
329
|
-
luxaura
|
|
330
|
-
|
|
484
|
+
// Compile AST → outputs
|
|
485
|
+
const out = luxaura.compile(ast, { componentName: 'MyScene' });
|
|
486
|
+
// out.clientJS — client bundle
|
|
487
|
+
// out.vaultJS — server vault module (NEVER serve publicly)
|
|
488
|
+
// out.paintCSS — resolved CSS
|
|
489
|
+
// out.html — HTML shell
|
|
331
490
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
- Accidental server code outside `server` blocks
|
|
336
|
-
- Sensitive environment variable exposure
|
|
491
|
+
// One-shot
|
|
492
|
+
const out2 = luxaura.transform(source, 'MyScene.lux');
|
|
493
|
+
```
|
|
337
494
|
|
|
338
495
|
---
|
|
339
496
|
|