liteforge 0.7.6 → 0.7.8
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 +113 -182
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
# liteforge
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Signals-based frontend framework — No Virtual DOM, JSX, zero dependencies.
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
|
-
|
|
6
|
+
npm install liteforge @liteforge/vite-plugin
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
-
>
|
|
10
|
-
> Use one import instead of managing 12 separate packages.
|
|
9
|
+
> `liteforge` re-exports `@liteforge/core` and `@liteforge/runtime`. Use it as the single entry point for signals, effects, and component primitives. All other features are available as separate `@liteforge/*` packages.
|
|
11
10
|
|
|
12
11
|
---
|
|
13
12
|
|
|
@@ -24,39 +23,34 @@ pnpm add liteforge
|
|
|
24
23
|
## Quick Start
|
|
25
24
|
|
|
26
25
|
```bash
|
|
27
|
-
|
|
28
|
-
pnpm add -D vite typescript
|
|
26
|
+
npm install liteforge @liteforge/vite-plugin
|
|
29
27
|
```
|
|
30
28
|
|
|
31
29
|
**`vite.config.ts`**
|
|
32
30
|
```ts
|
|
33
|
-
import { defineConfig } from 'vite'
|
|
34
|
-
import liteforge from 'liteforge/vite-plugin'
|
|
31
|
+
import { defineConfig } from 'vite'
|
|
32
|
+
import { liteforge } from '@liteforge/vite-plugin'
|
|
35
33
|
|
|
36
34
|
export default defineConfig({
|
|
37
|
-
plugins: [liteforge()]
|
|
38
|
-
})
|
|
35
|
+
plugins: [liteforge()]
|
|
36
|
+
})
|
|
39
37
|
```
|
|
40
38
|
|
|
41
39
|
**`src/main.tsx`**
|
|
42
40
|
```tsx
|
|
43
|
-
import { createApp } from 'liteforge'
|
|
44
|
-
import {
|
|
45
|
-
import App from './App.js';
|
|
41
|
+
import { createApp } from 'liteforge'
|
|
42
|
+
import { App } from './App'
|
|
46
43
|
|
|
47
|
-
|
|
48
|
-
.use(routerPlugin({ routes }))
|
|
49
|
-
.mount();
|
|
44
|
+
createApp({ root: App, target: '#app' }).mount()
|
|
50
45
|
```
|
|
51
46
|
|
|
52
47
|
**`src/App.tsx`**
|
|
53
48
|
```tsx
|
|
54
|
-
import { createComponent, Show } from 'liteforge'
|
|
55
|
-
import { signal } from 'liteforge';
|
|
49
|
+
import { createComponent, signal, Show } from 'liteforge'
|
|
56
50
|
|
|
57
51
|
export const App = createComponent({
|
|
58
52
|
component() {
|
|
59
|
-
const count = signal(0)
|
|
53
|
+
const count = signal(0)
|
|
60
54
|
return (
|
|
61
55
|
<div>
|
|
62
56
|
<h1>{() => count()}</h1>
|
|
@@ -65,82 +59,49 @@ export const App = createComponent({
|
|
|
65
59
|
<p>Over 5!</p>
|
|
66
60
|
</Show>
|
|
67
61
|
</div>
|
|
68
|
-
)
|
|
69
|
-
}
|
|
70
|
-
})
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
})
|
|
71
65
|
```
|
|
72
66
|
|
|
73
67
|
---
|
|
74
68
|
|
|
75
|
-
## Sub-path Imports
|
|
76
|
-
|
|
77
|
-
| Import | Contents |
|
|
78
|
-
|--------|----------|
|
|
79
|
-
| `liteforge` | `@liteforge/core` + `@liteforge/runtime` — signals, effects, components, JSX |
|
|
80
|
-
| `liteforge/router` | SPA router, guards, middleware, lazy routes, nested routes |
|
|
81
|
-
| `liteforge/store` | Global state management with time-travel |
|
|
82
|
-
| `liteforge/query` | Data fetching, caching, mutations |
|
|
83
|
-
| `liteforge/client` | HTTP client with interceptors, middleware, query integration |
|
|
84
|
-
| `liteforge/form` | Form management with Zod validation |
|
|
85
|
-
| `liteforge/table` | Data tables — sort, filter, pagination, selection |
|
|
86
|
-
| `liteforge/calendar` | Full scheduling calendar — 4 views, drag & drop, resources |
|
|
87
|
-
| `liteforge/modal` | Signal-based modal system with focus trap |
|
|
88
|
-
| `liteforge/devtools` | Debug panel — signal inspector, store explorer, time-travel |
|
|
89
|
-
| `liteforge/vite-plugin` | Vite plugin for JSX transform & HMR |
|
|
90
|
-
|
|
91
|
-
---
|
|
92
|
-
|
|
93
|
-
## Packages
|
|
94
|
-
|
|
95
|
-
| Package | Version | Description |
|
|
96
|
-
|---------|---------|-------------|
|
|
97
|
-
| `@liteforge/core` | 0.1.0 | `signal`, `computed`, `effect`, `batch`, `onCleanup` |
|
|
98
|
-
| `@liteforge/runtime` | 0.4.1 | `createComponent`, `createApp`, `Show`, `For`, `Switch`, plugin system |
|
|
99
|
-
| `@liteforge/router` | 0.3.0 | Router with guards, middleware, nested routes, lazy loading |
|
|
100
|
-
| `@liteforge/store` | 0.1.0 | `defineStore`, store registry, plugins, time-travel |
|
|
101
|
-
| `@liteforge/query` | 0.1.0 | `createQuery`, `createMutation`, query cache |
|
|
102
|
-
| `@liteforge/client` | 0.1.0 | `createClient`, `createResource`, interceptors |
|
|
103
|
-
| `@liteforge/form` | 0.1.0 | `createForm` with Zod, nested & array fields |
|
|
104
|
-
| `@liteforge/table` | 0.1.0 | `createTable` with sort, filter, pagination, selection |
|
|
105
|
-
| `@liteforge/calendar` | 0.1.0 | `createCalendar` — Day/Week/Month/Agenda, drag & drop |
|
|
106
|
-
| `@liteforge/modal` | 0.1.0 | `createModal`, `confirm`, `alert`, `prompt` presets |
|
|
107
|
-
| `@liteforge/devtools` | 0.1.0 | 5-tab debug panel with signal & store inspection |
|
|
108
|
-
| `@liteforge/vite-plugin` | 0.1.0 | JSX transform, template extraction, HMR |
|
|
109
|
-
|
|
110
|
-
---
|
|
111
|
-
|
|
112
69
|
## Reactivity
|
|
113
70
|
|
|
114
71
|
```ts
|
|
115
|
-
import { signal, computed, effect, batch } from 'liteforge'
|
|
72
|
+
import { signal, computed, effect, batch, onCleanup } from 'liteforge'
|
|
116
73
|
|
|
117
|
-
const count = signal(0)
|
|
118
|
-
const double = computed(() => count() * 2)
|
|
74
|
+
const count = signal(0)
|
|
75
|
+
const double = computed(() => count() * 2)
|
|
119
76
|
|
|
120
77
|
effect(() => {
|
|
121
|
-
console.log(double())
|
|
122
|
-
})
|
|
78
|
+
console.log(double()) // auto-tracks dependencies
|
|
79
|
+
})
|
|
123
80
|
|
|
124
|
-
count.set(5)
|
|
125
|
-
count.update(n => n + 1)
|
|
81
|
+
count.set(5) // → logs 10
|
|
82
|
+
count.update(n => n + 1) // → logs 12
|
|
126
83
|
|
|
127
84
|
batch(() => { // deferred notifications
|
|
128
|
-
count.set(1)
|
|
129
|
-
})
|
|
85
|
+
count.set(1)
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
onCleanup(() => { // runs when the enclosing effect/component is destroyed
|
|
89
|
+
console.log('cleaned up')
|
|
90
|
+
})
|
|
130
91
|
```
|
|
131
92
|
|
|
132
93
|
## Components
|
|
133
94
|
|
|
134
95
|
```tsx
|
|
135
|
-
import { createComponent, Show, For } from 'liteforge'
|
|
136
|
-
import { signal } from 'liteforge';
|
|
96
|
+
import { createComponent, Show, For } from 'liteforge'
|
|
137
97
|
|
|
138
98
|
export const UserList = createComponent({
|
|
139
99
|
async load() {
|
|
140
|
-
const users = await fetch('/api/users').then(r => r.json())
|
|
141
|
-
return { users }
|
|
100
|
+
const users = await fetch('/api/users').then(r => r.json())
|
|
101
|
+
return { users }
|
|
142
102
|
},
|
|
143
103
|
placeholder: () => <div class="skeleton" />,
|
|
104
|
+
error: ({ error, retry }) => <button onclick={retry}>Retry</button>,
|
|
144
105
|
component({ data }) {
|
|
145
106
|
return (
|
|
146
107
|
<ul>
|
|
@@ -148,112 +109,59 @@ export const UserList = createComponent({
|
|
|
148
109
|
{user => <li>{user.name}</li>}
|
|
149
110
|
</For>
|
|
150
111
|
</ul>
|
|
151
|
-
)
|
|
152
|
-
}
|
|
153
|
-
})
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
## Router
|
|
157
|
-
|
|
158
|
-
```ts
|
|
159
|
-
import { createRouter, createBrowserHistory, defineGuard } from 'liteforge/router';
|
|
160
|
-
|
|
161
|
-
const auth = defineGuard(async ({ to }) => {
|
|
162
|
-
if (!isLoggedIn()) return '/login';
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
const router = createRouter({
|
|
166
|
-
history: createBrowserHistory(),
|
|
167
|
-
routes: [
|
|
168
|
-
{ path: '/', component: Home },
|
|
169
|
-
{ path: '/login', component: Login },
|
|
170
|
-
{ path: '/dashboard', component: Dashboard, guard: auth,
|
|
171
|
-
children: [
|
|
172
|
-
{ path: '/', component: Overview },
|
|
173
|
-
{ path: '/users', component: Users },
|
|
174
|
-
],
|
|
175
|
-
},
|
|
176
|
-
],
|
|
177
|
-
});
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
## Store
|
|
181
|
-
|
|
182
|
-
```ts
|
|
183
|
-
import { defineStore } from 'liteforge/store';
|
|
184
|
-
|
|
185
|
-
const userStore = defineStore('users', {
|
|
186
|
-
state: { list: [], loading: false },
|
|
187
|
-
getters: state => ({
|
|
188
|
-
count: () => state.list().length,
|
|
189
|
-
}),
|
|
190
|
-
actions: state => ({
|
|
191
|
-
async fetch() {
|
|
192
|
-
state.loading.set(true);
|
|
193
|
-
state.list.set(await api.getUsers());
|
|
194
|
-
state.loading.set(false);
|
|
195
|
-
},
|
|
196
|
-
}),
|
|
197
|
-
});
|
|
112
|
+
)
|
|
113
|
+
}
|
|
114
|
+
})
|
|
198
115
|
```
|
|
199
116
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
```ts
|
|
203
|
-
import { createQuery, createMutation } from 'liteforge/query';
|
|
204
|
-
|
|
205
|
-
const users = createQuery({
|
|
206
|
-
key: 'users',
|
|
207
|
-
fn: () => fetch('/api/users').then(r => r.json()),
|
|
208
|
-
staleTime: 5 * 60 * 1000,
|
|
209
|
-
});
|
|
117
|
+
**Component lifecycle:** `setup()` → `placeholder` → `load()` → `component()` → `mounted()` → `destroyed()`
|
|
210
118
|
|
|
211
|
-
|
|
212
|
-
users.isLoading() // Signal: boolean
|
|
119
|
+
## Control Flow
|
|
213
120
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
onSubmit: async values => { await api.save(values); },
|
|
233
|
-
validateOn: 'blur',
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
form.field('name').value() // Signal<string>
|
|
237
|
-
form.field('name').error() // Signal<string | undefined>
|
|
121
|
+
```tsx
|
|
122
|
+
import { Show, For, Switch, Match } from 'liteforge'
|
|
123
|
+
|
|
124
|
+
// Conditional rendering
|
|
125
|
+
<Show when={() => isLoggedIn()}>
|
|
126
|
+
<Dashboard />
|
|
127
|
+
</Show>
|
|
128
|
+
|
|
129
|
+
// List rendering
|
|
130
|
+
<For each={() => items()}>
|
|
131
|
+
{(item) => <li>{item.name}</li>}
|
|
132
|
+
</For>
|
|
133
|
+
|
|
134
|
+
// Switch / pattern matching
|
|
135
|
+
<Switch fallback={<NotFound />}>
|
|
136
|
+
<Match when={() => route() === 'home'}><Home /></Match>
|
|
137
|
+
<Match when={() => route() === 'about'}><About /></Match>
|
|
138
|
+
</Switch>
|
|
238
139
|
```
|
|
239
140
|
|
|
240
141
|
## Plugin System
|
|
241
142
|
|
|
143
|
+
Additional capabilities are added via plugins in `createApp`:
|
|
144
|
+
|
|
242
145
|
```ts
|
|
243
|
-
import { createApp } from 'liteforge'
|
|
244
|
-
import { routerPlugin } from 'liteforge/router'
|
|
245
|
-
import { modalPlugin }
|
|
246
|
-
import {
|
|
247
|
-
import {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
146
|
+
import { createApp } from 'liteforge'
|
|
147
|
+
import { routerPlugin } from '@liteforge/router'
|
|
148
|
+
import { modalPlugin } from '@liteforge/modal'
|
|
149
|
+
import { toastPlugin } from '@liteforge/toast'
|
|
150
|
+
import { clientPlugin, queryIntegration } from '@liteforge/client'
|
|
151
|
+
import { devtoolsPlugin } from '@liteforge/devtools'
|
|
152
|
+
import { App } from './App'
|
|
153
|
+
|
|
154
|
+
createApp({ root: App, target: '#app' })
|
|
155
|
+
.use(routerPlugin({ routes: [...] }))
|
|
251
156
|
.use(modalPlugin())
|
|
252
|
-
.use(
|
|
157
|
+
.use(toastPlugin({ position: 'bottom-right' }))
|
|
158
|
+
.use(clientPlugin({ baseUrl: '/api', query: queryIntegration() }))
|
|
253
159
|
.use(devtoolsPlugin())
|
|
254
|
-
.mount()
|
|
160
|
+
.mount()
|
|
255
161
|
```
|
|
256
162
|
|
|
163
|
+
Plugins registered via `.use()` are installed in order before the app mounts. Each plugin can provide values into the app context via `context.provide()` and returns an optional cleanup function.
|
|
164
|
+
|
|
257
165
|
---
|
|
258
166
|
|
|
259
167
|
## JSX
|
|
@@ -261,10 +169,10 @@ await createApp({ root: App, target: '#app' })
|
|
|
261
169
|
LiteForge JSX compiles to direct DOM operations — no diffing, no virtual tree.
|
|
262
170
|
|
|
263
171
|
```tsx
|
|
264
|
-
// Reactive
|
|
172
|
+
// Reactive text — wrap in () =>
|
|
265
173
|
<span>{() => count()}</span>
|
|
266
174
|
|
|
267
|
-
// Event handler
|
|
175
|
+
// Event handler — no wrapper needed
|
|
268
176
|
<button onclick={() => count.update(n => n + 1)}>Click</button>
|
|
269
177
|
|
|
270
178
|
// Dynamic attribute
|
|
@@ -276,25 +184,48 @@ LiteForge JSX compiles to direct DOM operations — no diffing, no virtual tree.
|
|
|
276
184
|
|
|
277
185
|
---
|
|
278
186
|
|
|
279
|
-
##
|
|
187
|
+
## Install What You Need
|
|
188
|
+
|
|
189
|
+
All packages are zero-dependency and published independently:
|
|
190
|
+
|
|
191
|
+
| Package | Description |
|
|
192
|
+
|---------|-------------|
|
|
193
|
+
| `liteforge` | Umbrella: core + runtime |
|
|
194
|
+
| `@liteforge/core` | `signal`, `computed`, `effect`, `batch`, `onCleanup` |
|
|
195
|
+
| `@liteforge/runtime` | `createComponent`, `createApp`, `Show`, `For`, `Switch`, plugin system |
|
|
196
|
+
| `@liteforge/vite-plugin` | JSX transform, signal-safe getter wrapping, HMR |
|
|
197
|
+
| `@liteforge/router` | Client-side routing with guards, middleware, lazy loading |
|
|
198
|
+
| `@liteforge/store` | Signal-based state management with devtools integration |
|
|
199
|
+
| `@liteforge/query` | `createQuery`, `createMutation`, query cache |
|
|
200
|
+
| `@liteforge/form` | Type-safe forms with Zod validation |
|
|
201
|
+
| `@liteforge/table` | Data tables with sorting, filtering, pagination, selection |
|
|
202
|
+
| `@liteforge/calendar` | Full scheduling calendar — 4 views, drag & drop, resources |
|
|
203
|
+
| `@liteforge/modal` | Modal dialogs with `confirm`/`alert`/`prompt` presets |
|
|
204
|
+
| `@liteforge/toast` | Toast notifications |
|
|
205
|
+
| `@liteforge/tooltip` | Tooltip directive and component |
|
|
206
|
+
| `@liteforge/client` | HTTP client with resources, interceptors, query integration |
|
|
207
|
+
| `@liteforge/devtools` | 5-tab debug panel with time-travel |
|
|
280
208
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## Types
|
|
212
|
+
|
|
213
|
+
```ts
|
|
214
|
+
import type {
|
|
215
|
+
Signal,
|
|
216
|
+
ReadonlySignal,
|
|
217
|
+
Computed,
|
|
218
|
+
ComponentFactory,
|
|
219
|
+
ComponentDefinition,
|
|
220
|
+
AppBuilder,
|
|
221
|
+
LiteForgePlugin,
|
|
222
|
+
PluginContext,
|
|
223
|
+
PluginRegistry
|
|
224
|
+
} from 'liteforge'
|
|
294
225
|
```
|
|
295
226
|
|
|
296
227
|
---
|
|
297
228
|
|
|
298
229
|
## License
|
|
299
230
|
|
|
300
|
-
MIT
|
|
231
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "liteforge",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.8",
|
|
4
4
|
"description": "LiteForge — signals-based frontend framework. Re-exports @liteforge/core and @liteforge/runtime.",
|
|
5
5
|
"author": "SchildW3rk <contact@schildw3rk.dev>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
53
|
"@liteforge/core": "0.1.0",
|
|
54
|
-
"@liteforge/runtime": "0.6.
|
|
54
|
+
"@liteforge/runtime": "0.6.7"
|
|
55
55
|
},
|
|
56
56
|
"scripts": {
|
|
57
57
|
"build": "tsc -p tsconfig.build.json",
|