lithent 1.21.3 → 1.21.5

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.
@@ -0,0 +1,126 @@
1
+ # Lithent Agent Addon
2
+
3
+ > Version: 1.21.5
4
+
5
+ You are a coding agent with Lithent virtual DOM guidance enabled.
6
+
7
+ ACTIVATION CONDITIONS:
8
+
9
+ These guidelines apply ONLY when Lithent is installed in the current project.
10
+
11
+ Before suggesting Lithent patterns, verify Lithent availability:
12
+ 1. Check if `package.json` contains lithent in dependencies or devDependencies
13
+ 2. Check if `node_modules/lithent` directory exists
14
+ 3. Check if lithent imports are present in existing code
15
+
16
+ If Lithent is NOT installed:
17
+ - Do not enforce these guidelines
18
+ - Use standard coding practices appropriate for the project
19
+ - Never suggest installing lithent unless explicitly requested
20
+
21
+ If Lithent IS installed:
22
+ - Apply all guidelines below
23
+ - Suggest Lithent patterns for UI component creation
24
+ - Prioritize closure-based state management patterns
25
+
26
+ CODING GUIDELINES:
27
+
28
+ 1. COMPONENT MODE SELECTION
29
+ - Use `mount` for explicit render control with `renew()`
30
+ - Use `lmount` for automatic reactivity with `lstate`/`lstore`
31
+ - Don't mix modes: use `state`/`store` with `mount`, use `lstate`/`lstore` with `lmount`
32
+ - Suggest `lmount` for simpler components, `mount` for fine-grained control
33
+
34
+ 2. COMPONENT STRUCTURE
35
+ - Outer function (mounter) runs once for initialization
36
+ - Inner function (updater) runs on every render
37
+ - Keep state setup in mounter, return JSX from updater
38
+ - Always return a function from mounter, never JSX directly
39
+
40
+ 3. STATE MANAGEMENT
41
+ - Use `state(initialValue, renew)` with `mount` components
42
+ - Use `lstate(initialValue)` with `lmount` components
43
+ - Access values via `.value` property
44
+ - For global state, use `store`/`lstore` instead of prop drilling
45
+ - Use `computed` for derived values, `effect` for side effects
46
+
47
+ 4. LIFECYCLE HOOKS
48
+ - Use `mountCallback` for setup after mount (return cleanup function)
49
+ - Use `updateCallback` for logic before each update
50
+ - Use `mountReadyCallback` for logic after initial render
51
+ - Place hooks in mounter function, not in updater
52
+
53
+ 5. LIST RENDERING
54
+ - Always use `key` prop for list items
55
+ - Keys must be unique and stable (prefer IDs over indices)
56
+ - Suggest adding keys when iterating over arrays without them
57
+
58
+ 6. PERFORMANCE OPTIMIZATION
59
+ - Suggest `cacheUpdate` when multiple state updates cause re-renders
60
+ - Suggest `nextTickRender` for deferring expensive renders
61
+ - Avoid creating new functions in updater when possible
62
+ - Move event handlers to mounter scope when they don't need updater closure
63
+
64
+ 7. SSR AND HYDRATION
65
+ - Use `renderToString` for server-side rendering
66
+ - Use `hydration` flag with `render` for client-side hydration
67
+ - Ensure component output is deterministic for hydration to work
68
+
69
+ 8. TEMPLATE ALTERNATIVES
70
+ - Prefer JSX for most cases
71
+ - Suggest `fTags` for no-build-step environments
72
+ - Suggest `lTag` (HTM) for template literal preference
73
+ - Don't mix template styles within a single component
74
+
75
+ 9. CONTEXT USAGE
76
+ - Use `createContext` with `mount`, `createLContext` with `lmount`
77
+ - Pass `renew` to `useContext()` in manual mode
78
+ - Suggest context over deep prop drilling (3+ levels)
79
+
80
+ 10. CHILDREN HANDLING
81
+ - Use `unwrapChildren` helper when manipulating children
82
+ - Access children as third parameter in mounter function
83
+ - Don't modify children directly, wrap or filter them
84
+
85
+ IMPORT PATHS:
86
+ - Core: `import { mount, lmount, render, h, Fragment, portal, ref, nextTick } from 'lithent'`
87
+ - Lifecycle: `import { mountCallback, updateCallback, mountReadyCallback } from 'lithent'`
88
+ - Helper (manual): `import { state, store, createContext, computed, effect } from 'lithent/helper'`
89
+ - Helper (light): `import { lstate, lstore, createLContext } from 'lithent/helper'`
90
+ - Helper (utils): `import { cacheUpdate, nextTickRender, unwrapChildren } from 'lithent/helper'`
91
+ - SSR: `import { renderToString, hydration } from 'lithent/ssr'`
92
+ - FTags: `import { fTags, fFragment, fMount } from 'lithent/ftags'`
93
+ - HTM: `import { lTag } from 'lithent/tag'`
94
+
95
+ GUIDANCE APPROACH:
96
+
97
+ When user creates UI components:
98
+ 1. Suggest appropriate component mode (mount vs lmount)
99
+ 2. Ensure proper mounter/updater structure
100
+ 3. Add keys to list renderings if missing
101
+
102
+ When reviewing existing Lithent code:
103
+ 1. Check for mode consistency (don't mix state/lstate)
104
+ 2. Suggest lifecycle hooks for side effects
105
+ 3. Recommend performance optimizations when applicable
106
+
107
+ When user requests could benefit from Lithent patterns:
108
+ 1. Provide solution using Lithent idioms
109
+ 2. Explain the closure-based component model
110
+ 3. If user prefers different approach, respect their choice
111
+
112
+ COMMON MISTAKES TO CATCH:
113
+ - Returning JSX directly from mounter instead of returning a function
114
+ - Using `state` without passing `renew` parameter
115
+ - Using `lstate` with `mount` instead of `lmount`
116
+ - Missing `key` prop in list iterations
117
+ - Calling hooks inside updater instead of mounter
118
+ - Mutating state directly instead of using `.value`
119
+
120
+ REFERENCE MATERIALS (NOT PART OF BEHAVIORAL RULES):
121
+
122
+ For detailed code examples and API usage, refer to:
123
+ node_modules/lithent/dist/skills/SKILL.md
124
+
125
+ This reference material provides comprehensive examples, patterns,
126
+ and import references that complement the behavioral guidelines above.
@@ -0,0 +1,382 @@
1
+ ---
2
+ name: lithent
3
+ title: Lithent Agent Skills
4
+ version: 1.21.5
5
+ description: AI agent skills for working with the Lithent library.
6
+ additional_materials:
7
+ - constraints/
8
+ - reference/
9
+ - examples/
10
+ ---
11
+
12
+ # Lithent Agent Skills
13
+
14
+ > Version: 1.21.5
15
+
16
+ This file provides AI agent skills for working with the Lithent library.
17
+
18
+ ## Overview
19
+
20
+ Lithent is a lightweight (~4KB) JSX-based virtual DOM library with closure-based state management. It offers two component modes:
21
+ - **Manual Mode** (`mount`): Explicit control with `renew()` function
22
+ - **Light API Mode** (`lmount`): Auto-reactive with `lstate`/`lstore`
23
+
24
+ ## Component Creation
25
+
26
+ ### Manual Mode (mount)
27
+
28
+ ```tsx
29
+ import { mount, render } from 'lithent';
30
+ import { state } from 'lithent/helper';
31
+
32
+ const Counter = mount<{ initial?: number }>((renew, props) => {
33
+ const count = state(props.initial ?? 0, renew);
34
+
35
+ return () => (
36
+ <div>
37
+ <p>Count: {count.value}</p>
38
+ <button onClick={() => count.value++}>+1</button>
39
+ </div>
40
+ );
41
+ });
42
+
43
+ render(<Counter initial={10} />, document.getElementById('app')!);
44
+ ```
45
+
46
+ ### Light API Mode (lmount)
47
+
48
+ ```tsx
49
+ import { lmount, render } from 'lithent';
50
+ import { lstate } from 'lithent/helper';
51
+
52
+ const Counter = lmount<{ initial?: number }>((props) => {
53
+ const count = lstate(props.initial ?? 0);
54
+
55
+ return () => (
56
+ <div>
57
+ <p>Count: {count.value}</p>
58
+ <button onClick={() => count.value++}>+1</button>
59
+ </div>
60
+ );
61
+ });
62
+
63
+ render(<Counter initial={10} />, document.getElementById('app')!);
64
+ ```
65
+
66
+ ## State Management
67
+
68
+ ### State (Manual Mode)
69
+
70
+ ```tsx
71
+ import { mount } from 'lithent';
72
+ import { state, computed, effect } from 'lithent/helper';
73
+
74
+ const Component = mount((renew) => {
75
+ const firstName = state('John', renew);
76
+ const lastName = state('Doe', renew);
77
+
78
+ // Derived value
79
+ const fullName = computed(() => `${firstName.value} ${lastName.value}`);
80
+
81
+ // Side effect
82
+ effect(() => {
83
+ console.log('Name changed:', fullName.value);
84
+ return () => console.log('Cleanup');
85
+ });
86
+
87
+ return () => <p>{fullName.value}</p>;
88
+ });
89
+ ```
90
+
91
+ ### State (Light API Mode)
92
+
93
+ ```tsx
94
+ import { lmount } from 'lithent';
95
+ import { lstate, computed, effect } from 'lithent/helper';
96
+
97
+ const Component = lmount(() => {
98
+ const firstName = lstate('John');
99
+ const lastName = lstate('Doe');
100
+
101
+ const fullName = computed(() => `${firstName.value} ${lastName.value}`);
102
+
103
+ effect(() => {
104
+ console.log('Name changed:', fullName.value);
105
+ });
106
+
107
+ return () => <p>{fullName.value}</p>;
108
+ });
109
+ ```
110
+
111
+ ### Global Store
112
+
113
+ ```tsx
114
+ // Manual Mode
115
+ import { store } from 'lithent/helper';
116
+ const userStore = store({ name: '', loggedIn: false });
117
+
118
+ const Component = mount((renew) => {
119
+ const user = userStore(renew);
120
+ return () => <p>{user.name}</p>;
121
+ });
122
+
123
+ // Light API Mode
124
+ import { lstore } from 'lithent/helper';
125
+ const userStore = lstore({ name: '', loggedIn: false });
126
+
127
+ const Component = lmount(() => {
128
+ const user = userStore();
129
+ return () => <p>{user.name}</p>;
130
+ });
131
+ ```
132
+
133
+ ## Lifecycle Hooks
134
+
135
+ ```tsx
136
+ import { mount, mountCallback, updateCallback, mountReadyCallback } from 'lithent';
137
+
138
+ const Component = mount((renew) => {
139
+ // After mount (return cleanup function for unmount)
140
+ mountCallback(() => {
141
+ console.log('Mounted');
142
+ return () => console.log('Unmounted');
143
+ });
144
+
145
+ // Before each update
146
+ updateCallback(() => {
147
+ console.log('Will update');
148
+ });
149
+
150
+ // After initial render complete
151
+ mountReadyCallback(() => {
152
+ console.log('Initial render done');
153
+ });
154
+
155
+ return () => <div>Hello</div>;
156
+ });
157
+ ```
158
+
159
+ ## DOM References
160
+
161
+ ```tsx
162
+ import { mount, ref } from 'lithent';
163
+
164
+ const Component = mount((renew) => {
165
+ const inputRef = ref<HTMLInputElement>(null);
166
+
167
+ const focusInput = () => inputRef.value?.focus();
168
+
169
+ return () => (
170
+ <div>
171
+ <input ref={inputRef} type="text" />
172
+ <button onClick={focusInput}>Focus</button>
173
+ </div>
174
+ );
175
+ });
176
+ ```
177
+
178
+ ## Context API
179
+
180
+ ```tsx
181
+ // Manual Mode
182
+ import { mount } from 'lithent';
183
+ import { createContext } from 'lithent/helper';
184
+
185
+ const ThemeContext = createContext<{ theme: string }>();
186
+
187
+ const Provider = mount((renew, _props, children) => {
188
+ return () => (
189
+ <ThemeContext.Provider value={{ theme: 'dark' }}>
190
+ {children}
191
+ </ThemeContext.Provider>
192
+ );
193
+ });
194
+
195
+ const Consumer = mount((renew) => {
196
+ const { theme } = ThemeContext.useContext(renew);
197
+ return () => <p>{theme}</p>;
198
+ });
199
+
200
+ // Light API Mode
201
+ import { lmount } from 'lithent';
202
+ import { createLContext } from 'lithent/helper';
203
+
204
+ const ThemeContext = createLContext<{ theme: string }>();
205
+
206
+ const Consumer = lmount(() => {
207
+ const { theme } = ThemeContext.useContext();
208
+ return () => <p>{theme}</p>;
209
+ });
210
+ ```
211
+
212
+ ## Portal
213
+
214
+ ```tsx
215
+ import { mount, portal } from 'lithent';
216
+
217
+ const Modal = mount((renew, props: { onClose: () => void }) => {
218
+ return () => portal(
219
+ <div class="modal-overlay" onClick={props.onClose}>
220
+ <div class="modal-content" onClick={(e) => e.stopPropagation()}>
221
+ <h2>Modal</h2>
222
+ <button onClick={props.onClose}>Close</button>
223
+ </div>
224
+ </div>,
225
+ document.body
226
+ );
227
+ });
228
+ ```
229
+
230
+ ## List Rendering
231
+
232
+ Always use `key` prop for lists:
233
+
234
+ ```tsx
235
+ import { mount } from 'lithent';
236
+ import { state } from 'lithent/helper';
237
+
238
+ const TodoList = mount((renew) => {
239
+ const todos = state([
240
+ { id: 1, text: 'Learn Lithent', done: false },
241
+ { id: 2, text: 'Build app', done: false },
242
+ ], renew);
243
+
244
+ const toggle = (id: number) => {
245
+ todos.value = todos.value.map(t =>
246
+ t.id === id ? { ...t, done: !t.done } : t
247
+ );
248
+ };
249
+
250
+ return () => (
251
+ <ul>
252
+ {todos.value.map(todo => (
253
+ <li key={todo.id} onClick={() => toggle(todo.id)}>
254
+ {todo.text} {todo.done && '✓'}
255
+ </li>
256
+ ))}
257
+ </ul>
258
+ );
259
+ });
260
+ ```
261
+
262
+ ## SSR and Hydration
263
+
264
+ ```tsx
265
+ // Server
266
+ import { renderToString } from 'lithent/ssr';
267
+ const html = renderToString(<App />);
268
+
269
+ // Client (hydrate existing DOM)
270
+ import { render } from 'lithent';
271
+ import { hydration } from 'lithent/ssr';
272
+ render(<App />, document.getElementById('app')!, hydration);
273
+ ```
274
+
275
+ ## FTags (No JSX)
276
+
277
+ ```ts
278
+ import { fTags, fMount } from 'lithent/ftags';
279
+ import { state } from 'lithent/helper';
280
+
281
+ const { div, button, p } = fTags;
282
+
283
+ const Counter = fMount((renew) => {
284
+ const count = state(0, renew);
285
+ return () => div({},
286
+ p({}, `Count: ${count.value}`),
287
+ button({ onClick: () => count.value++ }, '+1')
288
+ );
289
+ });
290
+ ```
291
+
292
+ ## HTM (Tagged Templates)
293
+
294
+ ```ts
295
+ import { lTag } from 'lithent/tag';
296
+ import { mount } from 'lithent';
297
+ import { state } from 'lithent/helper';
298
+
299
+ const html = lTag;
300
+
301
+ const Counter = mount((renew) => {
302
+ const count = state(0, renew);
303
+ return () => html`
304
+ <div>
305
+ <p>Count: ${count.value}</p>
306
+ <button onClick=${() => count.value++}>+1</button>
307
+ </div>
308
+ `;
309
+ });
310
+ ```
311
+
312
+ ## Performance
313
+
314
+ ```tsx
315
+ import { cacheUpdate, nextTickRender } from 'lithent/helper';
316
+
317
+ // Batch multiple state updates into single render
318
+ cacheUpdate(() => {
319
+ a.value = 1;
320
+ b.value = 2;
321
+ c.value = 3;
322
+ });
323
+
324
+ // Defer render to next tick
325
+ nextTickRender(() => {
326
+ items.value = [...items.value, ...newItems];
327
+ });
328
+ ```
329
+
330
+ ## Children Handling
331
+
332
+ ```tsx
333
+ import { mount } from 'lithent';
334
+ import { unwrapChildren } from 'lithent/helper';
335
+
336
+ const Card = mount((renew, props: { title: string }, children) => {
337
+ return () => (
338
+ <div class="card">
339
+ <h3>{props.title}</h3>
340
+ <div class="card-body">{unwrapChildren(children)}</div>
341
+ </div>
342
+ );
343
+ });
344
+
345
+ // Usage
346
+ <Card title="Title"><p>Content</p></Card>
347
+ ```
348
+
349
+ ## Import Reference
350
+
351
+ ```tsx
352
+ // Core
353
+ import {
354
+ mount, lmount, render, h, Fragment, portal,
355
+ ref, nextTick, mountCallback, updateCallback, mountReadyCallback
356
+ } from 'lithent';
357
+
358
+ // Helper
359
+ import {
360
+ state, lstate, // Reactive state
361
+ computed, effect, // Derived values & side effects
362
+ store, lstore, // Global state
363
+ createContext, createLContext, // Context API
364
+ cacheUpdate, nextTickRender, // Performance
365
+ unwrapChildren // Utility
366
+ } from 'lithent/helper';
367
+
368
+ // SSR
369
+ import { renderToString, hydration } from 'lithent/ssr';
370
+
371
+ // FTags
372
+ import { fTags, fFragment, fMount } from 'lithent/ftags';
373
+
374
+ // HTM
375
+ import { lTag } from 'lithent/tag';
376
+ ```
377
+
378
+ ## Additional materials (optional)
379
+
380
+ - `constraints/` (rules, mistakes, troubleshooting)
381
+ - `reference/` (props types, children types, lstore inference)
382
+ - `examples/` (quick examples)
@@ -0,0 +1,15 @@
1
+ ---
2
+ title: Common Mistakes
3
+ category: constraints
4
+ version: 1.21.5
5
+ ---
6
+
7
+ # Common Mistakes
8
+
9
+ - Destructuring props in the mounter and expecting primitive values to update.
10
+ - Using `props.children` instead of the `children` argument.
11
+ - Swapping argument order for `mount` or `lmount`.
12
+ - Calling `state`/`lstate` outside the mounter (e.g., in updaters/handlers).
13
+ - Using `state` with `lmount` or `lstate` with `mount`.
14
+ - Creating `store`/`lstore` inside components (new store per render).
15
+ - Mutating arrays or nested objects directly instead of replacing references.
@@ -0,0 +1,16 @@
1
+ ---
2
+ title: Rules
3
+ category: constraints
4
+ version: 1.21.5
5
+ ---
6
+
7
+ # Rules
8
+
9
+ - Use `state` with `mount` and pass `renew` as the second argument.
10
+ - Use `lstate` with `lmount` (no `renew` argument is needed).
11
+ - Call `state`/`lstate` only inside the mounter (not in updaters or handlers).
12
+ - Use `store` with `mount`, `lstore` with `lmount`, and create stores outside components.
13
+ - `store` is shallow‑reactive: replace first‑level properties or arrays to update.
14
+ - Don’t rely on `props.children`; use the separate `children` argument.
15
+ - Argument order is `mount(renew, props, children)` and `lmount(props, children)`.
16
+ - Avoid destructuring props in the mounter if you need live updates.
@@ -0,0 +1,13 @@
1
+ ---
2
+ title: Troubleshooting
3
+ category: constraints
4
+ version: 1.21.5
5
+ ---
6
+
7
+ # Troubleshooting
8
+
9
+ - **Props look stale:** avoid destructuring props in the mounter; read `props.x` directly or use the updater’s props argument.
10
+ - **Children missing:** use the `children` argument (not `props.children`); remember children are only passed to the mounter.
11
+ - **Updates not rendering:** don’t mutate arrays/objects in place—assign a new array or replace first‑level properties.
12
+ - **State doesn’t react:** `state` requires `mount` + `renew`; `lstate` requires `lmount` and is mounter‑only.
13
+ - **Stores reset unexpectedly:** define `store`/`lstore` outside components and reuse them.
@@ -0,0 +1,195 @@
1
+ ---
2
+ title: Quick Examples
3
+ category: examples
4
+ version: 1.21.5
5
+ ---
6
+
7
+ # Quick Examples
8
+
9
+ ## Manual Counter (mount + state)
10
+
11
+ ```tsx
12
+ import { mount } from 'lithent';
13
+ import { state } from 'lithent/helper';
14
+
15
+ const Counter = mount((renew) => {
16
+ const count = state(0, renew);
17
+ return () => <button onClick={() => count.value++}>{count.value}</button>;
18
+ });
19
+ ```
20
+
21
+ ## Light Counter (lmount + lstate)
22
+
23
+ ```tsx
24
+ import { lmount } from 'lithent';
25
+ import { lstate } from 'lithent/helper';
26
+
27
+ const Counter = lmount(() => {
28
+ const count = lstate(0);
29
+ return () => <button onClick={() => count.value++}>{count.value}</button>;
30
+ });
31
+ ```
32
+
33
+ ## Computed + Effect
34
+
35
+ ```tsx
36
+ import { lmount } from 'lithent';
37
+ import { lstate, computed, effect } from 'lithent/helper';
38
+
39
+ const Profile = lmount(() => {
40
+ const first = lstate('Ada');
41
+ const last = lstate('Lovelace');
42
+ const full = computed(() => `${first.value} ${last.value}`);
43
+
44
+ effect(() => {
45
+ console.log('Name changed:', full.value);
46
+ });
47
+
48
+ return () => <p>{full.value}</p>;
49
+ });
50
+ ```
51
+
52
+ ## Lifecycle Hooks (mount / update)
53
+
54
+ ```tsx
55
+ import { mount, mountCallback, updateCallback, mountReadyCallback } from 'lithent';
56
+ import { state } from 'lithent/helper';
57
+
58
+ const Widget = mount((renew) => {
59
+ const count = state(0, renew);
60
+
61
+ // Runs after DOM mount
62
+ mountCallback(() => {
63
+ console.log('mounted');
64
+ return () => console.log('unmounted');
65
+ });
66
+
67
+ // Runs right after virtual DOM creation (before DOM mount)
68
+ mountReadyCallback(() => {
69
+ console.log('mountReady');
70
+ });
71
+
72
+ // Runs before every update; returned function runs after DOM update
73
+ updateCallback(() => {
74
+ console.log('before update');
75
+ return () => console.log('after update');
76
+ });
77
+
78
+ return () => (
79
+ <button onClick={() => count.value++}>
80
+ Count: {count.value}
81
+ </button>
82
+ );
83
+ });
84
+ ```
85
+
86
+ ## Ref
87
+
88
+ ```tsx
89
+ import { mount, ref } from 'lithent';
90
+
91
+ const FocusInput = mount((renew) => {
92
+ const inputRef = ref<HTMLInputElement>(null);
93
+ return () => (
94
+ <div>
95
+ <input ref={inputRef} />
96
+ <button onClick={() => inputRef.value?.focus()}>Focus</button>
97
+ </div>
98
+ );
99
+ });
100
+ ```
101
+
102
+ ## Portal
103
+
104
+ ```tsx
105
+ import { mount, portal } from 'lithent';
106
+
107
+ const Modal = mount((renew, props: { onClose: () => void }) => {
108
+ return () => portal(
109
+ <div class="modal" onClick={props.onClose}>Close</div>,
110
+ document.body
111
+ );
112
+ });
113
+ ```
114
+
115
+ ## Context (mount + lmount)
116
+
117
+ ```tsx
118
+ import { mount, lmount } from 'lithent';
119
+ import { createContext, createLContext } from 'lithent/helper';
120
+
121
+ const ThemeContext = createContext<{ theme: string }>();
122
+ const LThemeContext = createLContext<{ theme: string }>();
123
+
124
+ const ThemeProvider = mount((renew, _props, children) => {
125
+ return () => (
126
+ <ThemeContext.Provider value={{ theme: 'dark' }}>
127
+ {children}
128
+ </ThemeContext.Provider>
129
+ );
130
+ });
131
+
132
+ const LThemeProvider = lmount((_props, children) => {
133
+ return () => (
134
+ <LThemeContext.Provider value={{ theme: 'dark' }}>
135
+ {children}
136
+ </LThemeContext.Provider>
137
+ );
138
+ });
139
+
140
+ const Consumer = lmount(() => {
141
+ const { theme } = LThemeContext.useContext();
142
+ return () => <p>{theme}</p>;
143
+ });
144
+ ```
145
+
146
+ ## Store (store + lstore)
147
+
148
+ ```tsx
149
+ import { mount, lmount } from 'lithent';
150
+ import { store, lstore } from 'lithent/helper';
151
+
152
+ const userStore = store({ name: '', loggedIn: false });
153
+ const userLStore = lstore({ name: '', loggedIn: false });
154
+
155
+ const User = mount((renew) => {
156
+ const user = userStore(renew);
157
+ return () => <p>{user.name}</p>;
158
+ });
159
+
160
+ const UserLite = lmount(() => {
161
+ const user = userLStore();
162
+ return () => <p>{user.name}</p>;
163
+ });
164
+ ```
165
+
166
+ ## Performance (cacheUpdate + nextTickRender)
167
+
168
+ ```ts
169
+ import { cacheUpdate, nextTickRender } from 'lithent/helper';
170
+
171
+ cacheUpdate(() => {
172
+ a.value = 1;
173
+ b.value = 2;
174
+ });
175
+
176
+ nextTickRender(() => {
177
+ items.value = [...items.value, ...more];
178
+ });
179
+ ```
180
+
181
+ ## Children Helpers
182
+
183
+ ```tsx
184
+ import { mount } from 'lithent';
185
+ import { unwrapChildren } from 'lithent/helper';
186
+
187
+ const Card = mount((renew, props: { title: string }, children) => {
188
+ return () => (
189
+ <div class="card">
190
+ <h3>{props.title}</h3>
191
+ {unwrapChildren(children)}
192
+ </div>
193
+ );
194
+ });
195
+ ```
@@ -0,0 +1,25 @@
1
+ ---
2
+ title: Children Type
3
+ category: reference
4
+ version: 1.21.5
5
+ ---
6
+
7
+ # Children Type
8
+
9
+ - Lithent does **not** use `props.children`. Use the separate `children` argument.
10
+ - Argument order: `mount(renew, props, children)` and `lmount(props, children)`.
11
+ - Children are always `WDom[]`, even with a single child.
12
+ - Children are only provided to the mounter; use closure inside the updater.
13
+
14
+ ```tsx
15
+ import { mount, WDom } from 'lithent';
16
+
17
+ const Panel = mount<{ title: string }>((renew, props, children: WDom[]) => {
18
+ return () => (
19
+ <section>
20
+ <h2>{props.title}</h2>
21
+ {children}
22
+ </section>
23
+ );
24
+ });
25
+ ```
@@ -0,0 +1,19 @@
1
+ ---
2
+ title: lstore Type Inference
3
+ category: reference
4
+ version: 1.21.5
5
+ ---
6
+
7
+ # lstore Type Inference
8
+
9
+ - Defining stores as **objects** is usually better than primitives.
10
+ - Grouping related fields improves type inference and clarity.
11
+
12
+ ```tsx
13
+ import { lstore } from 'lithent/helper';
14
+
15
+ const userStore = lstore({
16
+ name: '',
17
+ loggedIn: false,
18
+ });
19
+ ```
@@ -0,0 +1,28 @@
1
+ ---
2
+ title: Props Types
3
+ category: reference
4
+ version: 1.21.5
5
+ ---
6
+
7
+ # Props Types
8
+
9
+ - Props are the **second** argument to the mounter and the **first** argument to the updater.
10
+ - The same props reference is preserved for the component’s lifetime.
11
+ - For TypeScript, define the props type via a `mount`/`lmount` generic.
12
+ - If you destructure props in the mounter, primitive values are copied and won’t update.
13
+ Prefer `props.property` or the updater’s props argument for fresh values.
14
+
15
+ ```tsx
16
+ import { mount } from 'lithent';
17
+
18
+ type Props = { count: number };
19
+
20
+ const Counter = mount<Props>((renew, props) => {
21
+ return (updaterProps) => (
22
+ <div>
23
+ <p>props: {props.count}</p>
24
+ <p>updater: {updaterProps.count}</p>
25
+ </div>
26
+ );
27
+ });
28
+ ```
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "lithent",
4
- "version": "1.21.3",
4
+ "version": "1.21.5",
5
5
  "description": "An extensible virtual DOM library for lightweight use in a variety of environments.",
6
6
  "main": "./dist/lithent.umd.js",
7
7
  "module": "./dist/lithent.mjs",
@@ -113,7 +113,8 @@
113
113
  "dev:devHelper": "pnpm watch:core & pnpm --filter lithent-dev-helper dev",
114
114
  "dev:ssr": "pnpm watch:core & pnpm --filter lithent-ssr dev",
115
115
  "dev:docs": "pnpm watch:core & pnpm watch:helper & pnpm --filter lithent-docs dev",
116
- "build:core": "vite build",
116
+ "build:core": "vite build && node scripts/build-skills.js",
117
+ "build:skills": "node scripts/build-skills.js",
117
118
  "build:helper": "pnpm --filter lithent-helper build",
118
119
  "build:devHelper": "pnpm --filter lithent-dev-helper build",
119
120
  "build:hmrParser": "pnpm --filter @lithent/hmr-parser build",
package/ssr/package.json CHANGED
@@ -25,7 +25,7 @@
25
25
  "lithent"
26
26
  ],
27
27
  "peerDependencies": {
28
- "lithent": "^1.21.2"
28
+ "lithent": "^1.21.3"
29
29
  },
30
30
  "devDependencies": {
31
31
  "express": "^4.21.1",