elements-kit 0.0.2 → 0.0.3
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 +228 -154
- package/dist/attributes.mjs +1 -2
- package/dist/builder/dom.d.mts +1 -2
- package/dist/builder/dom.mjs +1 -4
- package/dist/builder/index.d.mts +1 -88
- package/dist/builder/index.mjs +3 -5
- package/dist/{element-B3gwJmBr.mjs → element-CCHXkEsj.mjs} +16 -31
- package/dist/index-C6xwOPCO.d.mts +263 -0
- package/dist/index-DJejH8Ff.d.mts +89 -0
- package/dist/index.mjs +3 -6
- package/dist/jsx-runtime/index.d.mts +1 -1
- package/dist/jsx-runtime/index.mjs +2 -4
- package/dist/{polyfill-DAalJpCO.mjs → lib-B2drrxlV.mjs} +1 -6
- package/dist/signals/index.d.mts +2 -0
- package/dist/signals/index.mjs +2 -0
- package/dist/signals/lib/media.d.mts +14 -0
- package/dist/signals/lib/media.mjs +26 -0
- package/dist/signals/lib/react.d.mts +62 -0
- package/dist/signals/lib/react.mjs +82 -0
- package/dist/signals-Cr7xgAJH.mjs +966 -0
- package/dist/slot.d.mts +2 -3
- package/dist/slot.mjs +1 -2
- package/package.json +33 -5
- package/dist/signals.d.mts +0 -40
- package/dist/signals.mjs +0 -76
- /package/dist/{polyfill-Bvo2e52W.d.mts → polyfill-BEL-HWkO.d.mts} +0 -0
package/README.md
CHANGED
|
@@ -1,217 +1,277 @@
|
|
|
1
1
|
# ElementsKit
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Universal reactive primitives for the web.** Signals, JSX, and custom elements that work anywhere — standalone, inside React, Vue, or any framework, or as the foundation of your own component model.
|
|
4
4
|
|
|
5
5
|
```tsx
|
|
6
|
-
import { signal, computed } from "elements-kit/signals";
|
|
6
|
+
import { signal, computed, reactive } from "elements-kit/signals";
|
|
7
|
+
import { attributes, ATTRIBUTES as attr } from "elements-kit/attributes";
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
@attributes
|
|
10
|
+
class CounterElement extends HTMLElement {
|
|
11
|
+
static [attr] = {
|
|
12
|
+
count(this: CounterElement, value: string | null) {
|
|
13
|
+
this.count = Number(value ?? 0);
|
|
14
|
+
},
|
|
15
|
+
};
|
|
10
16
|
|
|
11
|
-
|
|
12
|
-
|
|
17
|
+
@reactive() count = 0;
|
|
18
|
+
doubled = computed(() => this.count * 2);
|
|
19
|
+
|
|
20
|
+
connectedCallback() {
|
|
21
|
+
this.appendChild(
|
|
13
22
|
<section>
|
|
14
|
-
<p>Count: <strong>{this
|
|
15
|
-
<button onClick={() => this
|
|
16
|
-
|
|
17
|
-
|
|
23
|
+
<p>Count: <strong>{() => this.count}</strong> — Doubled: <strong>{this.doubled}</strong></p>
|
|
24
|
+
<button onClick={() => this.count++}>+1</button>{" "}
|
|
25
|
+
<button onClick={() => this.count--}>−1</button>
|
|
26
|
+
</section> as Element,
|
|
27
|
+
);
|
|
18
28
|
}
|
|
19
29
|
}
|
|
20
30
|
|
|
21
|
-
|
|
31
|
+
customElements.define("x-counter", CounterElement);
|
|
22
32
|
```
|
|
23
33
|
|
|
24
|
-
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Why ElementsKit
|
|
37
|
+
|
|
38
|
+
Modern UI frameworks solve reactivity and rendering together — you adopt the whole system or none of it. ElementsKit separates the two:
|
|
39
|
+
|
|
40
|
+
- **Signals** are the reactive core — fine-grained, framework-agnostic, composable with any rendering model.
|
|
41
|
+
- **JSX** compiles to real `document.createElement` calls — no virtual DOM, no runtime overhead.
|
|
42
|
+
- **Custom elements** are standard browser components — ElementsKit enhances them with signals and JSX without wrapping or abstracting the platform.
|
|
25
43
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
44
|
+
Use one piece, or all three. Integrate with React for complex UIs. Build web components that work anywhere HTML does.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Installation
|
|
49
|
+
|
|
50
|
+
```sh
|
|
51
|
+
npm install elements-kit
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Configure JSX in your `tsconfig.json`:
|
|
55
|
+
|
|
56
|
+
```json
|
|
57
|
+
{
|
|
58
|
+
"compilerOptions": {
|
|
59
|
+
"jsx": "react-jsx",
|
|
60
|
+
"jsxImportSource": "elements-kit"
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
```
|
|
32
64
|
|
|
33
65
|
---
|
|
34
66
|
|
|
35
67
|
## Signals
|
|
36
68
|
|
|
69
|
+
Fine-grained reactive state. Signals track their dependencies automatically — only the exact computeds and effects that depend on a changed signal are re-evaluated.
|
|
70
|
+
|
|
37
71
|
```ts
|
|
38
|
-
import { signal, computed, effect, batch, untracked } from "elements-kit/signals";
|
|
72
|
+
import { signal, computed, effect, batch, untracked, onCleanup } from "elements-kit/signals";
|
|
39
73
|
|
|
40
|
-
const count = signal(0);
|
|
41
|
-
const doubled = computed(() => count() * 2);
|
|
74
|
+
const count = signal(0);
|
|
75
|
+
const doubled = computed(() => count() * 2);
|
|
42
76
|
|
|
43
|
-
effect(() =>
|
|
77
|
+
const stop = effect(() => {
|
|
78
|
+
console.log("count:", count()); // runs on every change
|
|
79
|
+
});
|
|
44
80
|
|
|
45
|
-
count(
|
|
46
|
-
|
|
81
|
+
count(1); // → count: 1
|
|
82
|
+
count(2); // → count: 2
|
|
83
|
+
stop(); // unsubscribe
|
|
47
84
|
|
|
48
|
-
batch(() => {
|
|
49
|
-
count(10);
|
|
50
|
-
count(20);
|
|
51
|
-
});
|
|
85
|
+
batch(() => { count(10); count(20); }); // single notification
|
|
52
86
|
|
|
53
87
|
const raw = untracked(() => count()); // read without subscribing
|
|
54
|
-
```
|
|
55
88
|
|
|
56
|
-
|
|
89
|
+
effect(() => {
|
|
90
|
+
const id = setInterval(() => count(count() + 1), 1000);
|
|
91
|
+
onCleanup(() => clearInterval(id)); // runs before re-run or on stop
|
|
92
|
+
});
|
|
93
|
+
```
|
|
57
94
|
|
|
58
|
-
|
|
59
|
-
const name = signal("world");
|
|
95
|
+
### Store
|
|
60
96
|
|
|
61
|
-
|
|
62
|
-
<p>{name}</p>
|
|
63
|
-
<p>{() => name()}</p>
|
|
64
|
-
```
|
|
97
|
+
A **store** is a class whose fields are made reactive with `@reactive`. It holds shared state — no `render()`, no DOM — and any subscriber updates automatically.
|
|
65
98
|
|
|
66
|
-
|
|
99
|
+
```ts
|
|
100
|
+
import { reactive, computed } from "elements-kit/signals";
|
|
67
101
|
|
|
68
|
-
|
|
102
|
+
export class CartStore {
|
|
103
|
+
@reactive() items: { name: string; price: number }[] = [];
|
|
104
|
+
@reactive() discount = 0;
|
|
69
105
|
|
|
70
|
-
|
|
106
|
+
total = computed(() =>
|
|
107
|
+
this.items.reduce((s, i) => s + i.price, 0) * (1 - this.discount),
|
|
108
|
+
);
|
|
71
109
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
"compilerOptions": {
|
|
75
|
-
"jsx": "react-jsx",
|
|
76
|
-
"jsxImportSource": "elements-kit"
|
|
110
|
+
add(item: { name: string; price: number }) {
|
|
111
|
+
this.items = [...this.items, item];
|
|
77
112
|
}
|
|
78
113
|
}
|
|
114
|
+
|
|
115
|
+
export const cart = new CartStore();
|
|
79
116
|
```
|
|
80
117
|
|
|
81
|
-
|
|
118
|
+
Stores are **framework-agnostic** — the same instance drives a custom element, a React component, and a plain effect in sync.
|
|
82
119
|
|
|
83
|
-
|
|
84
|
-
| --- | --- |
|
|
85
|
-
| `value={signal}` | Live-bound — updates DOM when signal changes |
|
|
86
|
-
| `value={42}` | Set once at render time |
|
|
87
|
-
| `onClick={fn}` | Camel-case event listener (`onclick`) |
|
|
88
|
-
| `on:click={fn}` | Explicit event namespace |
|
|
89
|
-
| `style:color={signal}` | Reactive inline style property |
|
|
90
|
-
| `class:active={signal}` | Reactive `classList.toggle` |
|
|
91
|
-
| `prop:foo={val}` | Force property assignment (bypasses `setAttribute`) |
|
|
120
|
+
---
|
|
92
121
|
|
|
93
|
-
|
|
94
|
-
const active = signal(false);
|
|
95
|
-
const label = signal("Submit");
|
|
96
|
-
|
|
97
|
-
<button
|
|
98
|
-
class:active={active}
|
|
99
|
-
style:opacity={computed(() => active() ? "1" : "0.5")}
|
|
100
|
-
onClick={() => (active(!active()))}
|
|
101
|
-
>
|
|
102
|
-
{label}
|
|
103
|
-
</button>
|
|
104
|
-
```
|
|
122
|
+
## JSX → DOM
|
|
105
123
|
|
|
106
|
-
|
|
124
|
+
JSX compiles directly to `document.createElement`. No virtual DOM, no diffing.
|
|
107
125
|
|
|
108
|
-
|
|
126
|
+
```tsx
|
|
127
|
+
// This:
|
|
128
|
+
const el = <button onClick={() => count(count() + 1)}>{count}</button>;
|
|
129
|
+
|
|
130
|
+
// Is equivalent to:
|
|
131
|
+
const el = document.createElement("button");
|
|
132
|
+
el.addEventListener("click", () => count(count() + 1));
|
|
133
|
+
// `count` signal creates a live text node — updates in place on change
|
|
134
|
+
```
|
|
109
135
|
|
|
110
|
-
|
|
111
|
-
- `Node` / `Element`
|
|
112
|
-
- A signal or `computed` — re-renders in place when it changes
|
|
113
|
-
- A plain function `() => value` — re-evaluated reactively
|
|
114
|
-
- Arrays of the above
|
|
136
|
+
Passing a signal or `() => T` as a child or prop creates a **live binding** — the DOM updates in place, never re-rendering the surrounding tree.
|
|
115
137
|
|
|
116
138
|
```tsx
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
<
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
{() => show() && <span>Conditional</span>}
|
|
124
|
-
</div>
|
|
139
|
+
const name = signal("Alice");
|
|
140
|
+
|
|
141
|
+
<p>Hello, {name}!</p> // live text node
|
|
142
|
+
<input value={name} /> // live attribute
|
|
143
|
+
<div class:active={computed(() => name() !== "")} /> // reactive class
|
|
144
|
+
<span style:color={signal("red")} /> // reactive style
|
|
125
145
|
```
|
|
126
146
|
|
|
127
|
-
|
|
147
|
+
### Prop namespaces
|
|
128
148
|
|
|
129
|
-
|
|
149
|
+
| Syntax | Effect |
|
|
150
|
+
|--------|--------|
|
|
151
|
+
| `{signal}` / `{() => fn()}` | Live-bound reactive child |
|
|
152
|
+
| `onClick={fn}` | Event listener (camelCase → `onclick`) |
|
|
153
|
+
| `on:click={fn}` | Explicit event namespace |
|
|
154
|
+
| `class:active={bool}` | Reactive `classList.toggle` |
|
|
155
|
+
| `style:color={value}` | Reactive inline style property |
|
|
156
|
+
| `prop:foo={val}` | Force property assignment (skips `setAttribute`) |
|
|
130
157
|
|
|
131
|
-
|
|
158
|
+
---
|
|
132
159
|
|
|
133
|
-
|
|
134
|
-
import { computed, reactive } from "elements-kit/signals";
|
|
160
|
+
## Class Components
|
|
135
161
|
|
|
136
|
-
class
|
|
137
|
-
text: string;
|
|
138
|
-
@reactive() done: boolean;
|
|
139
|
-
}
|
|
162
|
+
Any class with a `render()` method returning an `Element` is a component. Components own their state and produce elements.
|
|
140
163
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
todos: Todo[] = [];
|
|
164
|
+
```tsx
|
|
165
|
+
import { reactive, computed } from "elements-kit/signals";
|
|
144
166
|
|
|
145
|
-
|
|
146
|
-
|
|
167
|
+
class Counter {
|
|
168
|
+
@reactive() count = 0;
|
|
169
|
+
doubled = computed(() => this.count * 2);
|
|
147
170
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
171
|
+
render() {
|
|
172
|
+
return (
|
|
173
|
+
<section>
|
|
174
|
+
<p>{() => this.count} × 2 = {this.doubled}</p>
|
|
175
|
+
<button onClick={() => this.count++}>+1</button>
|
|
176
|
+
</section>
|
|
177
|
+
) as Element;
|
|
178
|
+
}
|
|
151
179
|
}
|
|
152
|
-
```
|
|
153
180
|
|
|
154
|
-
|
|
181
|
+
document.getElementById("app")!.appendChild(new Counter().render());
|
|
182
|
+
```
|
|
155
183
|
|
|
156
184
|
---
|
|
157
185
|
|
|
158
|
-
##
|
|
186
|
+
## Custom Elements
|
|
159
187
|
|
|
160
|
-
|
|
188
|
+
ElementsKit enhances native `HTMLElement` subclasses — start with the platform, add only what you need.
|
|
161
189
|
|
|
162
190
|
```ts
|
|
191
|
+
import { reactive, computed } from "elements-kit/signals";
|
|
163
192
|
import { attributes, ATTRIBUTES as attr } from "elements-kit/attributes";
|
|
164
|
-
import { signal, reactive } from "elements-kit/signals";
|
|
165
193
|
|
|
166
194
|
@attributes
|
|
167
|
-
class
|
|
195
|
+
class CounterElement extends HTMLElement {
|
|
168
196
|
static [attr] = {
|
|
169
|
-
count(this:
|
|
170
|
-
this.count = Number(value);
|
|
197
|
+
count(this: CounterElement, value: string | null) {
|
|
198
|
+
this.count = Number(value ?? 0);
|
|
171
199
|
},
|
|
172
200
|
};
|
|
173
201
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
@reactive((s) => s.#count)
|
|
177
|
-
count: number = 0;
|
|
202
|
+
@reactive() count = 0;
|
|
203
|
+
doubled = computed(() => this.count * 2);
|
|
178
204
|
|
|
179
205
|
connectedCallback() {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
206
|
+
this.appendChild(
|
|
207
|
+
<section>
|
|
208
|
+
<p>{() => this.count} × 2 = {this.doubled}</p>
|
|
209
|
+
<button onClick={() => this.count++}>+1</button>
|
|
210
|
+
</section> as Element,
|
|
211
|
+
);
|
|
185
212
|
}
|
|
186
213
|
}
|
|
187
214
|
|
|
188
|
-
customElements.define("x-counter",
|
|
215
|
+
customElements.define("x-counter", CounterElement);
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
`<x-counter count="5" />` — attribute bound, reactive, works in any HTML context.
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## React Integration
|
|
223
|
+
|
|
224
|
+
Connect signals and stores to React components via `useSyncExternalStore`:
|
|
225
|
+
|
|
226
|
+
```tsx
|
|
227
|
+
import { useSignal, useScope } from "elements-kit/signals/react";
|
|
228
|
+
import { cart } from "./cart-store";
|
|
229
|
+
|
|
230
|
+
function CartSummary() {
|
|
231
|
+
// Reads a @reactive field — re-renders only when cart.items changes
|
|
232
|
+
const items = useSignal(() => cart.items);
|
|
233
|
+
const total = useSignal(cart.total); // Computed<T> works directly
|
|
234
|
+
|
|
235
|
+
// Effects tied to this component's lifetime
|
|
236
|
+
useScope(() => {
|
|
237
|
+
effect(() => console.log("cart updated:", items));
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
return <p>{items.length} items — ${total.toFixed(2)}</p>;
|
|
241
|
+
}
|
|
189
242
|
```
|
|
190
243
|
|
|
191
|
-
|
|
244
|
+
The same `cart` store drives custom elements, React trees, and plain scripts — all in sync.
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## Signal Helpers
|
|
249
|
+
|
|
250
|
+
Pre-built signal factories for common browser APIs:
|
|
251
|
+
|
|
252
|
+
```ts
|
|
253
|
+
import { createMediaSignal } from "elements-kit/signals/media";
|
|
254
|
+
|
|
255
|
+
const isDark = createMediaSignal("(prefers-color-scheme: dark)");
|
|
256
|
+
const isMobile = createMediaSignal("(max-width: 640px)");
|
|
257
|
+
|
|
258
|
+
effect(() => document.documentElement.classList.toggle("dark", isDark()));
|
|
259
|
+
```
|
|
192
260
|
|
|
193
261
|
---
|
|
194
262
|
|
|
195
263
|
## `For` — Keyed List Rendering
|
|
196
264
|
|
|
197
|
-
|
|
265
|
+
Reconciles a reactive array into the DOM. Each item renders once per key — no full re-renders on reorder, add, or remove.
|
|
198
266
|
|
|
199
267
|
```tsx
|
|
200
268
|
import { For } from "elements-kit";
|
|
201
269
|
|
|
202
|
-
const todos = computed(() => state.todos.filter(t => !t.done));
|
|
203
|
-
|
|
204
270
|
<ul>
|
|
205
271
|
<For each={todos} by={(todo) => todo.id}>
|
|
206
272
|
{(todo) => (
|
|
207
|
-
<li
|
|
208
|
-
|
|
209
|
-
>
|
|
210
|
-
<input
|
|
211
|
-
type="checkbox"
|
|
212
|
-
checked={computed(() => todo.done)}
|
|
213
|
-
on:change={() => (todo.done = !todo.done)}
|
|
214
|
-
/>{" "}
|
|
273
|
+
<li>
|
|
274
|
+
<input type="checkbox" checked={computed(() => todo.done)} on:change={() => (todo.done = !todo.done)} />
|
|
215
275
|
{todo.text}
|
|
216
276
|
</li>
|
|
217
277
|
)}
|
|
@@ -219,40 +279,54 @@ const todos = computed(() => state.todos.filter(t => !t.done));
|
|
|
219
279
|
</ul>
|
|
220
280
|
```
|
|
221
281
|
|
|
222
|
-
| Prop | Type | Description |
|
|
223
|
-
| --- | --- | --- |
|
|
224
|
-
| `each` | `T[] \| (() => T[])` | Reactive array to render |
|
|
225
|
-
| `by` | `(item: T, index: number) => string \| number` | Key function — defaults to index |
|
|
226
|
-
| `children` | `(item: T, index: number) => Element` | Render function, called once per new key |
|
|
227
|
-
|
|
228
282
|
---
|
|
229
283
|
|
|
230
|
-
##
|
|
284
|
+
## `@reactive()` Decorator
|
|
231
285
|
|
|
232
|
-
|
|
286
|
+
Makes any class field reactive — reads subscribe, writes trigger updates.
|
|
233
287
|
|
|
234
|
-
```
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
}
|
|
288
|
+
```ts
|
|
289
|
+
import { reactive, computed } from "elements-kit/signals";
|
|
290
|
+
|
|
291
|
+
class TodoApp {
|
|
292
|
+
@reactive() todos: Todo[] = [];
|
|
293
|
+
@reactive() showDone = true;
|
|
294
|
+
|
|
295
|
+
visible = computed(() =>
|
|
296
|
+
this.showDone ? this.todos : this.todos.filter((t) => !t.done),
|
|
297
|
+
);
|
|
245
298
|
}
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
## `@attributes` Decorator
|
|
304
|
+
|
|
305
|
+
Wires `observedAttributes` and `attributeChangedCallback` from a static map:
|
|
306
|
+
|
|
307
|
+
```ts
|
|
308
|
+
import { attributes, ATTRIBUTES as attr } from "elements-kit/attributes";
|
|
309
|
+
|
|
310
|
+
@attributes
|
|
311
|
+
class MyElement extends HTMLElement {
|
|
312
|
+
static [attr] = {
|
|
313
|
+
value(this: MyElement, v: string | null) {
|
|
314
|
+
this.value = v ?? "";
|
|
315
|
+
},
|
|
316
|
+
};
|
|
246
317
|
|
|
247
|
-
|
|
318
|
+
@reactive() value = "";
|
|
319
|
+
}
|
|
248
320
|
```
|
|
249
321
|
|
|
250
322
|
---
|
|
251
323
|
|
|
252
|
-
##
|
|
324
|
+
## Roadmap
|
|
253
325
|
|
|
254
|
-
- [ ]
|
|
255
|
-
- [ ]
|
|
256
|
-
- [ ]
|
|
257
|
-
- [ ]
|
|
258
|
-
- [ ]
|
|
326
|
+
- [ ] More signal helpers (`localStorage`, `IntersectionObserver`, `ResizeObserver`, …)
|
|
327
|
+
- [ ] Context — share state across a subtree without prop drilling
|
|
328
|
+
- [ ] Async signal — `signal.from(promise)`, `signal.from(observable)`
|
|
329
|
+
- [ ] UI library — pre-built reactive components built on ElementsKit primitives
|
|
330
|
+
- [ ] More framework integrations (Vue, Solid, Angular, …)
|
|
331
|
+
- [ ] Tutorial — building a full app from scratch
|
|
332
|
+
- [ ] Complete TypeScript strict-mode coverage
|
package/dist/attributes.mjs
CHANGED
package/dist/builder/dom.d.mts
CHANGED
package/dist/builder/dom.mjs
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import "../polyfill-DAalJpCO.mjs";
|
|
2
1
|
import { builder } from "./index.mjs";
|
|
3
|
-
|
|
4
2
|
//#region src/builder/dom.ts
|
|
5
3
|
const a = () => builder(document.createElement("a"));
|
|
6
4
|
const abbr = () => builder(document.createElement("abbr"));
|
|
@@ -203,6 +201,5 @@ const mtr = () => builder(document.createElement("mtr"));
|
|
|
203
201
|
const munder = () => builder(document.createElement("munder"));
|
|
204
202
|
const munderover = () => builder(document.createElement("munderover"));
|
|
205
203
|
const semantics = () => builder(document.createElement("semantics"));
|
|
206
|
-
|
|
207
204
|
//#endregion
|
|
208
|
-
export { a, abbr, address, animate, animateMotion, animateTransform, annotation, annotationXml, area, article, aside, audio, b, base, bdi, bdo, blockquote, body, br, button, canvas, caption, circle, cite, clipPath, code, col, colgroup, data, datalist, dd, defs, del, desc, details, dfn, dialog, div, dl, dt, ellipse, em, embed, feBlend, feColorMatrix, feComponentTransfer, feComposite, feConvolveMatrix, feDiffuseLighting, feDisplacementMap, feDistantLight, feDropShadow, feFlood, feFuncA, feFuncB, feFuncG, feFuncR, feGaussianBlur, feImage, feMerge, feMergeNode, feMorphology, feOffset, fePointLight, feSpecularLighting, feSpotLight, feTile, feTurbulence, fieldset, figcaption, figure, filter, footer, foreignObject, form, g, h1, h2, h3, h4, h5, h6, head, header, hgroup, hr, html, i, iframe, image, img, input, ins, kbd, label, legend, li, line, linearGradient, link, maction, main, map, mark, marker, mask, math, mathVar, menu, merror, meta, metadata, meter, mfrac, mi, mmultiscripts, mn, mo, mover, mpadded, mpath, mphantom, mprescripts, mroot, mrow, ms, mspace, msqrt, mstyle, msub, msubsup, msup, mtable, mtd, mtext, mtr, munder, munderover, nav, noscript, object, ol, optgroup, option, output, p, path, pattern, picture, polygon, polyline, pre, progress, q, radialGradient, rect, rp, rt, ruby, s, samp, script, search, section, select, semantics, set, slot, small, source, span, stop, strong, style, sub, summary, sup, svg, svgSwitch, symbol, table, tbody, td, template, text, textPath, textarea, tfoot, th, thead, time, title, tr, track, tspan, u, ul, use, video, view, wbr };
|
|
205
|
+
export { a, abbr, address, animate, animateMotion, animateTransform, annotation, annotationXml, area, article, aside, audio, b, base, bdi, bdo, blockquote, body, br, button, canvas, caption, circle, cite, clipPath, code, col, colgroup, data, datalist, dd, defs, del, desc, details, dfn, dialog, div, dl, dt, ellipse, em, embed, feBlend, feColorMatrix, feComponentTransfer, feComposite, feConvolveMatrix, feDiffuseLighting, feDisplacementMap, feDistantLight, feDropShadow, feFlood, feFuncA, feFuncB, feFuncG, feFuncR, feGaussianBlur, feImage, feMerge, feMergeNode, feMorphology, feOffset, fePointLight, feSpecularLighting, feSpotLight, feTile, feTurbulence, fieldset, figcaption, figure, filter, footer, foreignObject, form, g, h1, h2, h3, h4, h5, h6, head, header, hgroup, hr, html, i, iframe, image, img, input, ins, kbd, label, legend, li, line, linearGradient, link, maction, main, map, mark, marker, mask, math, mathVar, menu, merror, meta, metadata, meter, mfrac, mi, mmultiscripts, mn, mo, mover, mpadded, mpath, mphantom, mprescripts, mroot, mrow, ms, mspace, msqrt, mstyle, msub, msubsup, msup, mtable, mtd, mtext, mtr, munder, munderover, nav, noscript, object, ol, optgroup, option, output, p, path, pattern, picture, polygon, polyline, pre, progress, q, radialGradient, rect, rp, rt, ruby, s, samp, script, search, section, select, semantics, set, slot, small, source, span, stop, strong, style, sub, summary, sup, svg, svgSwitch, symbol, table, tbody, td, template, text, textPath, textarea, tfoot, th, thead, time, title, tr, track, tspan, u, ul, use, video, view, wbr };
|
package/dist/builder/index.d.mts
CHANGED
|
@@ -1,89 +1,2 @@
|
|
|
1
|
-
import { t as
|
|
2
|
-
|
|
3
|
-
//#region src/builder/index.d.ts
|
|
4
|
-
declare const DISPOSABLES: unique symbol;
|
|
5
|
-
declare const DISPOSE: symbol;
|
|
6
|
-
declare const VALUE: unique symbol;
|
|
7
|
-
declare const EFFECT: unique symbol;
|
|
8
|
-
declare class ElementBuilder<T extends Element = Element> {
|
|
9
|
-
/** Dispose the reactive element and run all cleanup functions */
|
|
10
|
-
[DISPOSE]: () => void;
|
|
11
|
-
/** The underlying DOM element */
|
|
12
|
-
private [VALUE];
|
|
13
|
-
/** A set of cleanup functions to run when disposing the element */
|
|
14
|
-
private [DISPOSABLES];
|
|
15
|
-
[EFFECT](fn: () => void): this;
|
|
16
|
-
private constructor();
|
|
17
|
-
static create<T extends Element>(el: T): ReactiveElement<T>;
|
|
18
|
-
children(...children: ValueOrReactive<ElementBuilder | Node | string | number>[]): T;
|
|
19
|
-
ref(): T;
|
|
20
|
-
ref(apply: (ref: T) => void | (() => void)): this;
|
|
21
|
-
on<K extends keyof HTMLElementEventMap>(eventType: K, listener: (ev: HTMLElementEventMap[K]) => void, options?: boolean | AddEventListenerOptions): this;
|
|
22
|
-
}
|
|
23
|
-
declare function toNode(c: ElementBuilder | PrimitiveNodeType): Node;
|
|
24
|
-
declare function builder<T extends Element>(el: T): ReactiveElementOf<T>;
|
|
25
|
-
/**
|
|
26
|
-
* Callable overloads matching the Proxy apply trap → ref() behavior.
|
|
27
|
-
* Calling a reactive element as a function delegates to ref():
|
|
28
|
-
* el() → returns the raw DOM element
|
|
29
|
-
* el((ref) => {}) → applies a side-effect, returns the builder for chaining
|
|
30
|
-
*/
|
|
31
|
-
interface RefCallable<T extends Element> {
|
|
32
|
-
(): T;
|
|
33
|
-
(apply: (ref: T) => void | (() => void)): this;
|
|
34
|
-
}
|
|
35
|
-
type ReactiveElement<T extends Element> = ElementBuilder<T> & RefCallable<T>;
|
|
36
|
-
type ValueOrReactive<T> = (() => T) | T;
|
|
37
|
-
type ValueOrReactiveArray<T extends any[]> = { [K in keyof T]: ValueOrReactive<T[K]> | T[K] };
|
|
38
|
-
/**
|
|
39
|
-
* Filter keys that are writable (exclude readonly and getter-only).
|
|
40
|
-
*/
|
|
41
|
-
type WritableKeys<T> = { [K in keyof T]: (<U>() => U extends { [Q in K]: T[K] } ? 1 : 2) extends (<U>() => U extends { readonly [Q in K]: T[K] } ? 1 : 2) ? never : K }[keyof T];
|
|
42
|
-
/**
|
|
43
|
-
* Extracts the object chaining part of ReactiveBuilder.
|
|
44
|
-
* Used for properties like `style` where you can do both:
|
|
45
|
-
* .style("padding: 20px;") // setter
|
|
46
|
-
* .style.padding("20px") // sub-property chaining
|
|
47
|
-
*/
|
|
48
|
-
type Chain<R, T> = T extends object ? { [K in WritableKeys<T>]: Builder<R, T[K]> } : {};
|
|
49
|
-
type Builder<R, T = R> = T extends ((...args: infer U) => unknown) ? (...value: ValueOrReactiveArray<U>) => R : (value?: ValueOrReactive<T>) => R;
|
|
50
|
-
/**
|
|
51
|
-
* Types eligible for sub-property chaining (e.g., `.style.padding("20px")`).
|
|
52
|
-
*/
|
|
53
|
-
type ChainableType = CSSStyleDeclaration | DOMTokenList | DOMStringMap | StylePropertyMap;
|
|
54
|
-
/**
|
|
55
|
-
* Filters keys to only writable data properties.
|
|
56
|
-
* Excludes methods (function-valued properties) and event handlers (`on*`).
|
|
57
|
-
*/
|
|
58
|
-
type DataPropertyKeys<T> = { [K in keyof T]: K extends `on${string}` ? never : T[K] extends ((...args: any[]) => any) ? never : K }[keyof T];
|
|
59
|
-
/**
|
|
60
|
-
* Reactive setter for a single property.
|
|
61
|
-
* Chainable types (CSSStyleDeclaration, DOMTokenList, etc.) get both
|
|
62
|
-
* sub-property chaining and direct setter support.
|
|
63
|
-
*/
|
|
64
|
-
type ReactiveSetter<R, T> = T extends ChainableType ? Chain<R, T> & ((value: ValueOrReactive<T>) => R) : (value: ValueOrReactive<T>) => R;
|
|
65
|
-
/**
|
|
66
|
-
* A fully-typed reactive element builder for any Element type.
|
|
67
|
-
* Automatically maps all writable data properties into reactive setters.
|
|
68
|
-
*
|
|
69
|
-
* Use this for custom elements instead of needing generated builder interfaces.
|
|
70
|
-
*
|
|
71
|
-
* @example
|
|
72
|
-
* ```ts
|
|
73
|
-
* import { reactive, type ReactiveElementOf } from "elements-kit";
|
|
74
|
-
*
|
|
75
|
-
* class MyElement extends HTMLElement {
|
|
76
|
-
* greeting = "hello";
|
|
77
|
-
* }
|
|
78
|
-
* customElements.define("my-element", MyElement);
|
|
79
|
-
*
|
|
80
|
-
* const myEl = () =>
|
|
81
|
-
* reactive(document.createElement("my-element") as MyElement);
|
|
82
|
-
*
|
|
83
|
-
* // Full type support for both own and inherited properties:
|
|
84
|
-
* myEl().greeting("world").style.padding("20px").id("main");
|
|
85
|
-
* ```
|
|
86
|
-
*/
|
|
87
|
-
type ReactiveElementOf<T extends Element> = ElementBuilder<T> & { [K in WritableKeys<T> & DataPropertyKeys<T> & keyof T]: ReactiveSetter<ReactiveElementOf<T>, T[K]> };
|
|
88
|
-
//#endregion
|
|
1
|
+
import { a as EFFECT, c as ReactiveElementOf, d as builder, f as toNode, i as DISPOSE, l as VALUE, n as Chain, o as ElementBuilder, r as DISPOSABLES, s as ReactiveElement, t as Builder, u as ValueOrReactive } from "../index-DJejH8Ff.mjs";
|
|
89
2
|
export { Builder, Chain, DISPOSABLES, DISPOSE, EFFECT, ElementBuilder, ReactiveElement, ReactiveElementOf, VALUE, ValueOrReactive, builder, toNode };
|
package/dist/builder/index.mjs
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { effect, isReactive } from "../signals.mjs";
|
|
1
|
+
import { a as effect, t as isReactive } from "../signals-Cr7xgAJH.mjs";
|
|
2
2
|
import { Slot } from "../slot.mjs";
|
|
3
|
-
import { t as resolveNode } from "../
|
|
4
|
-
|
|
3
|
+
import { t as resolveNode } from "../lib-B2drrxlV.mjs";
|
|
5
4
|
//#region src/builder/index.ts
|
|
6
5
|
const DISPOSABLES = Symbol("disposables");
|
|
7
6
|
const DISPOSE = Symbol.dispose;
|
|
@@ -110,6 +109,5 @@ function isObject(v) {
|
|
|
110
109
|
function builder(el) {
|
|
111
110
|
return ElementBuilder.create(el);
|
|
112
111
|
}
|
|
113
|
-
|
|
114
112
|
//#endregion
|
|
115
|
-
export { DISPOSABLES, DISPOSE, EFFECT, ElementBuilder, VALUE, builder, toNode };
|
|
113
|
+
export { DISPOSABLES, DISPOSE, EFFECT, ElementBuilder, VALUE, builder, toNode };
|