elements-kit 0.0.16 → 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.
Files changed (2) hide show
  1. package/README.md +90 -12
  2. package/package.json +17 -12
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/attributes` | `@attributes` decorator + `ATTRIBUTES` symbol for custom elements |
49
- | `elements-kit/slot` | `Slot` class comment-marker DOM regions |
50
- | `elements-kit/jsx-runtime` | JSX factory (configure via `jsxImportSource`) |
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")!.appendChild(new Counter().render());
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
- ```ts
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.appendChild(
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> as Element,
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.16",
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",
@@ -18,7 +18,7 @@
18
18
  "author": "@waelbettayeb",
19
19
  "license": "MIT",
20
20
  "main": "./dist/index.mjs",
21
- "types": "./dist/index.d.ts",
21
+ "types": "./dist/index.d.mts",
22
22
  "files": [
23
23
  "dist"
24
24
  ],
@@ -26,52 +26,57 @@
26
26
  ".": {
27
27
  "source": "./src/index.ts",
28
28
  "import": "./dist/index.mjs",
29
- "types": "./dist/index.d.ts"
29
+ "types": "./dist/index.d.mts"
30
30
  },
31
31
  "./signals": {
32
32
  "source": "./src/signals/index.ts",
33
33
  "import": "./dist/signals/index.mjs",
34
- "types": "./dist/signals/index.d.ts"
34
+ "types": "./dist/signals/index.d.mts"
35
35
  },
36
36
  "./slot": {
37
37
  "source": "./src/slot.ts",
38
38
  "import": "./dist/slot.mjs",
39
- "types": "./dist/slot.d.ts"
39
+ "types": "./dist/slot.d.mts"
40
40
  },
41
41
  "./for": {
42
42
  "source": "./src/for.ts",
43
43
  "import": "./dist/for.mjs",
44
- "types": "./dist/for.d.ts"
44
+ "types": "./dist/for.d.mts"
45
45
  },
46
46
  "./attributes": {
47
47
  "source": "./src/attributes.ts",
48
48
  "import": "./dist/attributes.mjs",
49
- "types": "./dist/attributes.d.ts"
49
+ "types": "./dist/attributes.d.mts"
50
50
  },
51
51
  "./custom-elements": {
52
52
  "source": "./src/custom-elements.ts",
53
53
  "import": "./dist/custom-elements.mjs",
54
- "types": "./dist/custom-elements.d.ts"
54
+ "types": "./dist/custom-elements.d.mts"
55
+ },
56
+ "./render": {
57
+ "source": "./src/render.ts",
58
+ "import": "./dist/render.mjs",
59
+ "types": "./dist/render.d.mts"
55
60
  },
56
61
  "./jsx-runtime": {
57
62
  "source": "./src/jsx-runtime/index.ts",
58
63
  "import": "./dist/jsx-runtime/index.mjs",
59
- "types": "./dist/jsx-runtime/index.d.ts"
64
+ "types": "./dist/jsx-runtime/index.d.mts"
60
65
  },
61
66
  "./jsx-dev-runtime": {
62
67
  "source": "./src/jsx-runtime/index.ts",
63
68
  "import": "./dist/jsx-runtime/index.mjs",
64
- "types": "./dist/jsx-runtime/index.d.ts"
69
+ "types": "./dist/jsx-runtime/index.d.mts"
65
70
  },
66
71
  "./integrations/*": {
67
72
  "source": "./src/integrations/*.ts",
68
73
  "import": "./dist/integrations/*.mjs",
69
- "types": "./dist/integrations/*.d.ts"
74
+ "types": "./dist/integrations/*.d.mts"
70
75
  },
71
76
  "./utilities/*": {
72
77
  "source": "./src/utilities/*.ts",
73
78
  "import": "./dist/utilities/*.mjs",
74
- "types": "./dist/utilities/*.d.ts"
79
+ "types": "./dist/utilities/*.d.mts"
75
80
  }
76
81
  },
77
82
  "scripts": {