Claude-skill-registry lithent
AI agent skills for working with the Lithent library.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/lithent" ~/.claude/skills/majiayu000-claude-skill-registry-lithent && rm -rf "$T"
manifest:
skills/data/lithent/SKILL.mdsource content
Lithent Agent Skills
Version: {{VERSION}}
This file provides AI agent skills for working with the Lithent library.
Overview
Lithent is a lightweight (~4KB) JSX-based virtual DOM library with closure-based state management. It offers two component modes:
- Manual Mode (
): Explicit control withmount
functionrenew() - Light API Mode (
): Auto-reactive withlmount
/lstatelstore
Component Creation
Manual Mode (mount)
import { mount, render } from 'lithent'; import { state } from 'lithent/helper'; const Counter = mount<{ initial?: number }>((renew, props) => { const count = state(props.initial ?? 0, renew); return () => ( <div> <p>Count: {count.value}</p> <button onClick={() => count.value++}>+1</button> </div> ); }); render(<Counter initial={10} />, document.getElementById('app')!);
Light API Mode (lmount)
import { lmount, render } from 'lithent'; import { lstate } from 'lithent/helper'; const Counter = lmount<{ initial?: number }>((props) => { const count = lstate(props.initial ?? 0); return () => ( <div> <p>Count: {count.value}</p> <button onClick={() => count.value++}>+1</button> </div> ); }); render(<Counter initial={10} />, document.getElementById('app')!);
State Management
State (Manual Mode)
import { mount } from 'lithent'; import { state, computed, effect } from 'lithent/helper'; const Component = mount((renew) => { const firstName = state('John', renew); const lastName = state('Doe', renew); // Derived value const fullName = computed(() => `${firstName.value} ${lastName.value}`); // Side effect effect(() => { console.log('Name changed:', fullName.value); return () => console.log('Cleanup'); }); return () => <p>{fullName.value}</p>; });
State (Light API Mode)
import { lmount } from 'lithent'; import { lstate, computed, effect } from 'lithent/helper'; const Component = lmount(() => { const firstName = lstate('John'); const lastName = lstate('Doe'); const fullName = computed(() => `${firstName.value} ${lastName.value}`); effect(() => { console.log('Name changed:', fullName.value); }); return () => <p>{fullName.value}</p>; });
Global Store
// Manual Mode import { store } from 'lithent/helper'; const userStore = store({ name: '', loggedIn: false }); const Component = mount((renew) => { const user = userStore(renew); return () => <p>{user.name}</p>; }); // Light API Mode import { lstore } from 'lithent/helper'; const userStore = lstore({ name: '', loggedIn: false }); const Component = lmount(() => { const user = userStore(); return () => <p>{user.name}</p>; });
Lifecycle Hooks
import { mount, mountCallback, updateCallback, mountReadyCallback } from 'lithent'; const Component = mount((renew) => { // After mount (return cleanup function for unmount) mountCallback(() => { console.log('Mounted'); return () => console.log('Unmounted'); }); // Before each update updateCallback(() => { console.log('Will update'); }); // After initial render complete mountReadyCallback(() => { console.log('Initial render done'); }); return () => <div>Hello</div>; });
DOM References
import { mount, ref } from 'lithent'; const Component = mount((renew) => { const inputRef = ref<HTMLInputElement>(null); const focusInput = () => inputRef.value?.focus(); return () => ( <div> <input ref={inputRef} type="text" /> <button onClick={focusInput}>Focus</button> </div> ); });
Context API
// Manual Mode import { mount } from 'lithent'; import { createContext } from 'lithent/helper'; const ThemeContext = createContext<{ theme: string }>(); const Provider = mount((renew, _props, children) => { return () => ( <ThemeContext.Provider value={{ theme: 'dark' }}> {children} </ThemeContext.Provider> ); }); const Consumer = mount((renew) => { const { theme } = ThemeContext.useContext(renew); return () => <p>{theme}</p>; }); // Light API Mode import { lmount } from 'lithent'; import { createLContext } from 'lithent/helper'; const ThemeContext = createLContext<{ theme: string }>(); const Consumer = lmount(() => { const { theme } = ThemeContext.useContext(); return () => <p>{theme}</p>; });
Portal
import { mount, portal } from 'lithent'; const Modal = mount((renew, props: { onClose: () => void }) => { return () => portal( <div class="modal-overlay" onClick={props.onClose}> <div class="modal-content" onClick={(e) => e.stopPropagation()}> <h2>Modal</h2> <button onClick={props.onClose}>Close</button> </div> </div>, document.body ); });
List Rendering
Always use
key prop for lists:
import { mount } from 'lithent'; import { state } from 'lithent/helper'; const TodoList = mount((renew) => { const todos = state([ { id: 1, text: 'Learn Lithent', done: false }, { id: 2, text: 'Build app', done: false }, ], renew); const toggle = (id: number) => { todos.value = todos.value.map(t => t.id === id ? { ...t, done: !t.done } : t ); }; return () => ( <ul> {todos.value.map(todo => ( <li key={todo.id} onClick={() => toggle(todo.id)}> {todo.text} {todo.done && '✓'} </li> ))} </ul> ); });
SSR and Hydration
// Server import { renderToString } from 'lithent/ssr'; const html = renderToString(<App />); // Client (hydrate existing DOM) import { render } from 'lithent'; import { hydration } from 'lithent/ssr'; render(<App />, document.getElementById('app')!, hydration);
FTags (No JSX)
import { fTags, fMount } from 'lithent/ftags'; import { state } from 'lithent/helper'; const { div, button, p } = fTags; const Counter = fMount((renew) => { const count = state(0, renew); return () => div({}, p({}, `Count: ${count.value}`), button({ onClick: () => count.value++ }, '+1') ); });
HTM (Tagged Templates)
import { lTag } from 'lithent/tag'; import { mount } from 'lithent'; import { state } from 'lithent/helper'; const html = lTag; const Counter = mount((renew) => { const count = state(0, renew); return () => html` <div> <p>Count: ${count.value}</p> <button onClick=${() => count.value++}>+1</button> </div> `; });
Performance
import { cacheUpdate, nextTickRender } from 'lithent/helper'; // Batch multiple state updates into single render cacheUpdate(() => { a.value = 1; b.value = 2; c.value = 3; }); // Defer render to next tick nextTickRender(() => { items.value = [...items.value, ...newItems]; });
Children Handling
import { mount } from 'lithent'; import { unwrapChildren } from 'lithent/helper'; const Card = mount((renew, props: { title: string }, children) => { return () => ( <div class="card"> <h3>{props.title}</h3> <div class="card-body">{unwrapChildren(children)}</div> </div> ); }); // Usage <Card title="Title"><p>Content</p></Card>
Import Reference
// Core import { mount, lmount, render, h, Fragment, portal, ref, nextTick, mountCallback, updateCallback, mountReadyCallback } from 'lithent'; // Helper import { state, lstate, // Reactive state computed, effect, // Derived values & side effects store, lstore, // Global state createContext, createLContext, // Context API cacheUpdate, nextTickRender, // Performance unwrapChildren // Utility } from 'lithent/helper'; // SSR import { renderToString, hydration } from 'lithent/ssr'; // FTags import { fTags, fFragment, fMount } from 'lithent/ftags'; // HTM import { lTag } from 'lithent/tag';
Additional materials (optional)
(rules, mistakes, troubleshooting)constraints/
(props types, children types, lstore inference)reference/
(quick examples)examples/