Skip to content
This repository was archived by the owner on Mar 26, 2026. It is now read-only.

Commit 76f44cc

Browse files
committed
update
1 parent 15a0b2f commit 76f44cc

16 files changed

Lines changed: 1544 additions & 1260 deletions

File tree

content/docs/coolgrid/index.mdx

Lines changed: 334 additions & 330 deletions
Large diffs are not rendered by default.

content/docs/core/index.mdx

Lines changed: 104 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -262,72 +262,66 @@ import { h, Fragment } from "@pyreon/core"
262262

263263
### Creating Elements
264264

265-
```ts
265+
```tsx
266266
// Simple element with text
267-
h("div", null, "Hello World")
267+
<div>Hello World</div>
268268

269269
// Element with props
270-
h("div", { class: "container", id: "main" }, "Content")
270+
<div class="container" id="main">Content</div>
271271

272272
// Element with reactive props
273-
h("div", { class: () => isActive() ? "active" : "inactive" })
273+
<div class={() => isActive() ? "active" : "inactive"} />
274274

275275
// Element with event handlers
276-
h("button", { onClick: () => count.update(n => n + 1) }, "Click me")
276+
<button onClick={() => count.update(n => n + 1)}>Click me</button>
277277

278278
// Element with style (string or object)
279-
h("div", { style: "color: red; font-size: 16px" })
280-
h("div", { style: { color: "red", fontSize: "16px" } })
281-
h("div", { style: () => ({ color: isError() ? "red" : "green" }) })
279+
<div style="color: red; font-size: 16px" />
280+
<div style={{ color: "red", fontSize: "16px" }} />
281+
<div style={() => ({ color: isError() ? "red" : "green" })} />
282282
```
283283

284284
### Nesting Children
285285

286-
```ts
286+
```tsx
287287
// Multiple children
288-
h("div", null,
289-
h("h1", null, "Title"),
290-
h("p", null, "Paragraph one"),
291-
h("p", null, "Paragraph two")
292-
)
288+
<div>
289+
<h1>Title</h1>
290+
<p>Paragraph one</p>
291+
<p>Paragraph two</p>
292+
</div>
293293

294294
// Mixed children: strings, numbers, VNodes
295-
h("div", null,
296-
"Text node",
297-
42,
298-
h("span", null, "Nested")
299-
)
295+
<div>
296+
Text node
297+
{42}
298+
<span>Nested</span>
299+
</div>
300300

301301
// Reactive children via accessor functions
302-
h("div", null,
303-
() => count() > 0 ? h("span", null, "Positive") : h("span", null, "Zero or negative")
304-
)
302+
<div>
303+
{() => count() > 0 ? <span>Positive</span> : <span>Zero or negative</span>}
304+
</div>
305305
```
306306

307307
### Components
308308

309-
```ts
309+
```tsx
310310
// Render a component
311-
h(Counter, { initial: 0 })
311+
<Counter initial={0} />
312312

313313
// Component with children
314-
h(Card, { title: "Hello" },
315-
h("p", null, "Card body")
316-
)
314+
<Card title="Hello">
315+
<p>Card body</p>
316+
</Card>
317317
```
318318

319319
### Fragments
320320

321321
Fragments let you group children without adding a wrapper DOM element:
322322

323-
```ts
323+
```tsx
324324
// Fragment (no wrapper element)
325-
h(Fragment, null,
326-
h("span", null, "A"),
327-
h("span", null, "B")
328-
)
329-
330-
// Equivalent JSX
331325
<>
332326
<span>A</span>
333327
<span>B</span>
@@ -362,12 +356,12 @@ Children can be:
362356

363357
`EMPTY_PROPS` is a shared empty object used when `h()` is called with `null` props. The renderer identity-checks against it to skip unnecessary prop application:
364358

365-
```ts
359+
```tsx
366360
import { EMPTY_PROPS } from "@pyreon/core"
367361

368362
// These produce the same result
369-
h("div", null, "Hello")
370-
h("div", EMPTY_PROPS, "Hello")
363+
<div>Hello</div>
364+
<div>Hello</div>
371365
```
372366

373367
## JSX Runtime
@@ -1171,11 +1165,10 @@ function Tooltip(props: { text: string; children: VNodeChild }) {
11711165

11721166
### Suspense
11731167

1174-
Shows a fallback while a lazy child component is still loading. Works with the `lazy()` helper from `@pyreon/react-compat` or `@pyreon/router`.
1168+
Shows a fallback while a lazy child component is still loading. Works with the `lazy()` helper from `@pyreon/core` (or `@pyreon/react-compat`).
11751169

11761170
```tsx
1177-
import { Suspense } from "@pyreon/core"
1178-
import { lazy } from "@pyreon/react-compat"
1171+
import { Suspense, lazy } from "@pyreon/core"
11791172

11801173
const HeavyComponent = lazy(() => import("./HeavyComponent"))
11811174

@@ -1275,6 +1268,75 @@ Inner boundaries catch errors first. If an inner boundary is already in an error
12751268

12761269
`ErrorBoundary` uses a module-level stack of handler functions. During setup, it pushes a handler onto the stack. When a child component throws during mount, `dispatchToErrorBoundary()` invokes the innermost handler. The handler stores the error in a signal; when the signal becomes non-null, the fallback renders instead of the children.
12771270

1271+
## Dynamic
1272+
1273+
Renders a component or HTML element dynamically based on a reactive value. Useful for rendering polymorphic components or switching between element types at runtime.
1274+
1275+
```tsx
1276+
import { Dynamic } from "@pyreon/core"
1277+
import { signal } from "@pyreon/reactivity"
1278+
1279+
// Dynamic component
1280+
const currentView = signal<"home" | "settings">("home")
1281+
const views = { home: HomePage, settings: SettingsPage }
1282+
1283+
function App() {
1284+
return <Dynamic component={views[currentView()]} />
1285+
}
1286+
```
1287+
1288+
```tsx
1289+
// Dynamic HTML element
1290+
const tag = signal<"h1" | "h2" | "p">("h1")
1291+
1292+
function Heading(props: { text: string }) {
1293+
return <Dynamic component={tag()} class="heading">{props.text}</Dynamic>
1294+
}
1295+
```
1296+
1297+
### DynamicProps
1298+
1299+
```ts
1300+
interface DynamicProps extends Props {
1301+
/** Component function or HTML tag name to render */
1302+
component: ComponentFn | string
1303+
}
1304+
```
1305+
1306+
All other props are forwarded to the resolved component or element. If `component` is falsy, `Dynamic` returns `null`.
1307+
1308+
## lazy
1309+
1310+
Lazily load a component module. Returns a wrapper component that shows `null` while loading and the resolved component once ready. Pairs with `Suspense` to show a fallback during loading.
1311+
1312+
```tsx
1313+
import { lazy, Suspense } from "@pyreon/core"
1314+
1315+
const HeavyChart = lazy(() => import("./HeavyChart"))
1316+
1317+
function Dashboard() {
1318+
return (
1319+
<Suspense fallback={<div>Loading chart...</div>}>
1320+
<HeavyChart data={chartData()} />
1321+
</Suspense>
1322+
)
1323+
}
1324+
```
1325+
1326+
### How lazy Works
1327+
1328+
1. `lazy()` starts the dynamic `import()` immediately.
1329+
2. While loading, the wrapper component returns `null` and exposes a `__loading()` signal that returns `true`.
1330+
3. `Suspense` detects `__loading()` and renders the fallback instead.
1331+
4. Once the module resolves, the signal flips and `Suspense` renders the actual component.
1332+
5. If the import fails, the error is thrown during rendering and can be caught by `ErrorBoundary`.
1333+
1334+
```ts
1335+
function lazy<P extends Props>(
1336+
load: () => Promise<{ default: ComponentFn<P> }>,
1337+
): LazyComponent<P>
1338+
```
1339+
12781340
## mapArray
12791341

12801342
Keyed reactive list mapping that creates each mapped item exactly once per key and reuses it across updates. When the source array is reordered or partially changed, only new keys invoke `map()`; existing entries return the cached result. Removed keys are evicted from the cache.
@@ -1665,6 +1727,8 @@ Dispatch an error to the nearest active `ErrorBoundary`. Returns `true` if the b
16651727
| `Switch` / `Match` | Multi-branch conditional rendering |
16661728
| `For` | Keyed reactive list rendering |
16671729
| `Portal` | Render into a different DOM target |
1730+
| `Dynamic` | Render a component or element dynamically |
1731+
| `lazy` | Lazily load a component module |
16681732
| `Suspense` | Show fallback while lazy components load |
16691733
| `ErrorBoundary` | Catch and display errors with reset capability |
16701734
| `mapArray` | Keyed reactive list mapping with cache eviction |

0 commit comments

Comments
 (0)