elements-kit 0.0.17 → 0.0.18
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 +90 -12
- package/package.json +6 -1
package/README.md
CHANGED
|
@@ -43,11 +43,14 @@ Every feature is a separate subpath export — import only what you use.
|
|
|
43
43
|
|
|
44
44
|
| Entry | Purpose |
|
|
45
45
|
|-------|---------|
|
|
46
|
-
| `elements-kit` | `For` and core re-exports |
|
|
47
|
-
| `elements-kit/signals` | `signal`, `computed`, `effect`, `effectScope`, `batch`, `untracked`, `trigger`, `onCleanup`, `@reactive` |
|
|
48
|
-
| `elements-kit/
|
|
49
|
-
| `elements-kit/
|
|
50
|
-
| `elements-kit/
|
|
46
|
+
| `elements-kit` | `For` component and core re-exports |
|
|
47
|
+
| `elements-kit/signals` | `signal`, `computed`, `effect`, `effectScope`, `batch`, `untracked`, `trigger`, `onCleanup`, `MaybeReactive`, `resolve`, `resolveProps`, `@reactive` |
|
|
48
|
+
| `elements-kit/render` | `render(target, setup)` — mount a node with a scoped lifetime; returns `unmount` |
|
|
49
|
+
| `elements-kit/attributes` | `@attributes` decorator + `ATTRIBUTES` symbol |
|
|
50
|
+
| `elements-kit/slot` | `Slot`, `Slots`, `SLOTS` symbol — comment-marker DOM regions |
|
|
51
|
+
| `elements-kit/custom-elements` | `defineElement`, `CustomElementRegistry` |
|
|
52
|
+
| `elements-kit/for` | `For` keyed-list component |
|
|
53
|
+
| `elements-kit/jsx-runtime` | JSX factory + type helpers (`ElementProps`, `Props`, `ComponentProps`, `MaybeReactiveProps`, `Require`) — configure via `jsxImportSource` |
|
|
51
54
|
| `elements-kit/integrations/react` | `useSignal`, `useScope` React bridge hooks |
|
|
52
55
|
| `elements-kit/utilities/*` | Reactive browser-API utilities — see [src/utilities/README.md](src/utilities/README.md) |
|
|
53
56
|
|
|
@@ -204,6 +207,7 @@ Any class with a `render()` method returning an `Element` is a component. Compon
|
|
|
204
207
|
|
|
205
208
|
```tsx
|
|
206
209
|
import { reactive, computed } from "elements-kit/signals";
|
|
210
|
+
import { render } from "elements-kit/render";
|
|
207
211
|
|
|
208
212
|
class Counter {
|
|
209
213
|
@reactive() count = 0;
|
|
@@ -219,7 +223,7 @@ class Counter {
|
|
|
219
223
|
}
|
|
220
224
|
}
|
|
221
225
|
|
|
222
|
-
document.getElementById("app")
|
|
226
|
+
const unmount = render(document.getElementById("app")!, () => <Counter/>);
|
|
223
227
|
```
|
|
224
228
|
|
|
225
229
|
---
|
|
@@ -228,9 +232,10 @@ document.getElementById("app")!.appendChild(new Counter().render());
|
|
|
228
232
|
|
|
229
233
|
ElementsKit enhances native `HTMLElement` subclasses — start with the platform, add only what you need.
|
|
230
234
|
|
|
231
|
-
```
|
|
235
|
+
```tsx
|
|
232
236
|
import { reactive, computed } from "elements-kit/signals";
|
|
233
237
|
import { attributes, ATTRIBUTES as attr } from "elements-kit/attributes";
|
|
238
|
+
import { render } from "elements-kit/render";
|
|
234
239
|
|
|
235
240
|
@attributes
|
|
236
241
|
class CounterElement extends HTMLElement {
|
|
@@ -243,13 +248,20 @@ class CounterElement extends HTMLElement {
|
|
|
243
248
|
@reactive() count = 0;
|
|
244
249
|
doubled = computed(() => this.count * 2);
|
|
245
250
|
|
|
251
|
+
#unmount?: () => void;
|
|
252
|
+
|
|
246
253
|
connectedCallback() {
|
|
247
|
-
this
|
|
254
|
+
this.#unmount = render(this, () => (
|
|
248
255
|
<section>
|
|
249
256
|
<p>{() => this.count} × 2 = {this.doubled}</p>
|
|
250
257
|
<button onClick={() => this.count++}>+1</button>
|
|
251
|
-
</section>
|
|
252
|
-
);
|
|
258
|
+
</section>
|
|
259
|
+
));
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
disconnectedCallback() {
|
|
263
|
+
this.#unmount?.();
|
|
264
|
+
this.#unmount = undefined;
|
|
253
265
|
}
|
|
254
266
|
}
|
|
255
267
|
|
|
@@ -258,6 +270,26 @@ customElements.define("x-counter", CounterElement);
|
|
|
258
270
|
|
|
259
271
|
`<x-counter count="5" />` — attribute bound, reactive, works in any HTML context.
|
|
260
272
|
|
|
273
|
+
### Typed JSX for custom elements
|
|
274
|
+
|
|
275
|
+
Register the tag and augment the `CustomElementRegistry` interface — JSX infers the full prop shape (attributes, events, slots, children) from the class itself.
|
|
276
|
+
|
|
277
|
+
```ts
|
|
278
|
+
import { defineElement } from "elements-kit/custom-elements";
|
|
279
|
+
|
|
280
|
+
defineElement("x-counter", CounterElement);
|
|
281
|
+
|
|
282
|
+
declare module "elements-kit/custom-elements" {
|
|
283
|
+
interface CustomElementRegistry {
|
|
284
|
+
"x-counter": typeof CounterElement;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// Now `<x-counter count={5} />` is fully typed — no hand-written `declare global` block.
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
See [Types](docs/src/content/docs/writing-ui/types.mdx) for the full set of prop-inference helpers.
|
|
292
|
+
|
|
261
293
|
---
|
|
262
294
|
|
|
263
295
|
## React Integration
|
|
@@ -408,7 +440,7 @@ effect(() => console.log(fetchTodo.state, fetchTodo.value));
|
|
|
408
440
|
|
|
409
441
|
## `For` — Keyed List Rendering
|
|
410
442
|
|
|
411
|
-
Reconciles a reactive array into the DOM. Each item renders once per key — no full re-renders on reorder, add, or remove.
|
|
443
|
+
Reconciles a reactive array into the DOM. Each item renders once per key — no full re-renders on reorder, add, or remove. `T` is inferred from `each`.
|
|
412
444
|
|
|
413
445
|
```tsx
|
|
414
446
|
import { For } from "elements-kit/for";
|
|
@@ -427,6 +459,33 @@ import { For } from "elements-kit/for";
|
|
|
427
459
|
|
|
428
460
|
---
|
|
429
461
|
|
|
462
|
+
## Prop types
|
|
463
|
+
|
|
464
|
+
Six type helpers derive JSX prop shapes from your components — no parallel `declare global` block to maintain. Full guide at [docs/src/content/docs/writing-ui/types.mdx](docs/src/content/docs/writing-ui/types.mdx).
|
|
465
|
+
|
|
466
|
+
| Helper | For |
|
|
467
|
+
| ------ | --- |
|
|
468
|
+
| `ElementProps<typeof Cls>` | `HTMLElement` subclass — full surface (attrs, events, slots, children) |
|
|
469
|
+
| `Props<C>` | Class instance, constructor, or function component — unified |
|
|
470
|
+
| `ComponentProps<typeof Cls>` | Class components with `constructor(props: P)` |
|
|
471
|
+
| `MaybeReactiveProps<P>` | Wrap every prop in `MaybeReactive` |
|
|
472
|
+
| `MaybeReactive<T>` | Scalar value-or-getter (from `elements-kit/signals`) |
|
|
473
|
+
| `Require<P, K>` | Promote optional keys to required |
|
|
474
|
+
|
|
475
|
+
Function components pair `MaybeReactiveProps<P>` on the signature with `resolveProps` at the top of the body — each key becomes a callable getter, subscribing to updates on read:
|
|
476
|
+
|
|
477
|
+
```tsx
|
|
478
|
+
import { resolveProps } from "elements-kit/signals";
|
|
479
|
+
import type { MaybeReactiveProps } from "elements-kit/jsx-runtime";
|
|
480
|
+
|
|
481
|
+
function Greeting(raw: MaybeReactiveProps<{ name: string }>) {
|
|
482
|
+
const props = resolveProps(raw);
|
|
483
|
+
return <p>Hello, {props.name}</p>;
|
|
484
|
+
}
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
---
|
|
488
|
+
|
|
430
489
|
## `@reactive()` Decorator
|
|
431
490
|
|
|
432
491
|
Makes any class field reactive — reads subscribe, writes trigger updates.
|
|
@@ -465,6 +524,26 @@ class MyElement extends HTMLElement {
|
|
|
465
524
|
}
|
|
466
525
|
```
|
|
467
526
|
|
|
527
|
+
For typed slots, attach a `[SLOTS]` instance field — pass the key list with `as const` so TS can narrow:
|
|
528
|
+
|
|
529
|
+
```ts
|
|
530
|
+
import { SLOTS, Slots } from "elements-kit/slot";
|
|
531
|
+
|
|
532
|
+
class Card extends HTMLElement {
|
|
533
|
+
[SLOTS] = Slots.new(["header", "footer"] as const);
|
|
534
|
+
}
|
|
535
|
+
// ElementProps<typeof Card> now includes `slot:header` / `slot:footer`
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
For typed events, declare a `static events` map:
|
|
539
|
+
|
|
540
|
+
```ts
|
|
541
|
+
class XPicker extends HTMLElement {
|
|
542
|
+
declare static events: { commit: CustomEvent<number> };
|
|
543
|
+
}
|
|
544
|
+
// ElementProps<typeof XPicker> now includes `on:commit` / `onCommit`
|
|
545
|
+
```
|
|
546
|
+
|
|
468
547
|
---
|
|
469
548
|
|
|
470
549
|
## Roadmap
|
|
@@ -473,4 +552,3 @@ class MyElement extends HTMLElement {
|
|
|
473
552
|
- [ ] UI library — pre-built reactive components built on ElementsKit primitives
|
|
474
553
|
- [ ] More framework integrations (Vue, Solid, Angular, …)
|
|
475
554
|
- [ ] Tutorial — building a full app from scratch
|
|
476
|
-
- [ ] Complete TypeScript strict-mode coverage
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "elements-kit",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.18",
|
|
5
5
|
"description": "A lightweight reactive UI library that transforms native HTMLElements into reactive components with signals. Ideal for framework-agnostic applications and web components.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"webcomponents",
|
|
@@ -53,6 +53,11 @@
|
|
|
53
53
|
"import": "./dist/custom-elements.mjs",
|
|
54
54
|
"types": "./dist/custom-elements.d.mts"
|
|
55
55
|
},
|
|
56
|
+
"./render": {
|
|
57
|
+
"source": "./src/render.ts",
|
|
58
|
+
"import": "./dist/render.mjs",
|
|
59
|
+
"types": "./dist/render.d.mts"
|
|
60
|
+
},
|
|
56
61
|
"./jsx-runtime": {
|
|
57
62
|
"source": "./src/jsx-runtime/index.ts",
|
|
58
63
|
"import": "./dist/jsx-runtime/index.mjs",
|