elements-kit 0.0.14 → 0.0.16
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 +138 -31
- package/dist/attributes-Dtn68R1u.d.mts +94 -0
- package/dist/attributes.d.mts +1 -93
- package/dist/custom-elements.d.mts +74 -0
- package/dist/custom-elements.mjs +100 -0
- package/dist/define-CjbTZ3VG.d.mts +23 -0
- package/dist/{element-C_4VbkvQ.mjs → element-CGVy_8TW.mjs} +12 -18
- package/dist/for.d.mts +45 -0
- package/dist/for.mjs +136 -0
- package/dist/{index-DUshSQ_6.d.mts → index-DydGTqZU.d.mts} +60 -10
- package/dist/index.d.mts +1 -36
- package/dist/index.mjs +1 -144
- package/dist/infer-BfzRJoCn.d.mts +203 -0
- package/dist/integrations/react.d.mts +1 -1
- package/dist/integrations/react.mjs +1 -1
- package/dist/jsx-runtime/index.d.mts +18 -25
- package/dist/jsx-runtime/index.mjs +2 -2
- package/dist/signals/index.d.mts +2 -2
- package/dist/signals/index.mjs +2 -2
- package/dist/{signals-BHmWX6ox.mjs → signals-J8dK_rA4.mjs} +57 -17
- package/dist/slot-C7GQZe-r.d.mts +104 -0
- package/dist/{slot-Cydy7-0L.mjs → slot-Kb61AcgW.mjs} +21 -2
- package/dist/slot.d.mts +2 -84
- package/dist/slot.mjs +2 -2
- package/dist/{test.BmQO5GaM-ANkhHvbr.mjs → test.BmQO5GaM-DfGStnii.mjs} +1 -1
- package/dist/utilities/_observe.d.mts +11 -0
- package/dist/utilities/_observe.mjs +15 -0
- package/dist/utilities/active-element.d.mts +1 -1
- package/dist/utilities/active-element.mjs +6 -2
- package/dist/utilities/active-element.test.mjs +1 -1
- package/dist/utilities/async.d.mts +1 -1
- package/dist/utilities/async.mjs +1 -1
- package/dist/utilities/async.test.mjs +2 -2
- package/dist/utilities/debounced.d.mts +1 -1
- package/dist/utilities/debounced.mjs +1 -1
- package/dist/utilities/debounced.test.mjs +2 -2
- package/dist/utilities/element-rect.d.mts +1 -1
- package/dist/utilities/element-rect.mjs +1 -1
- package/dist/utilities/element-rect.test.mjs +2 -2
- package/dist/utilities/element-scroll.d.mts +1 -1
- package/dist/utilities/element-scroll.mjs +7 -34
- package/dist/utilities/element-scroll.test.mjs +2 -2
- package/dist/utilities/environment.d.mts +5 -0
- package/dist/utilities/environment.mjs +5 -0
- package/dist/utilities/event-driven.d.mts +1 -1
- package/dist/utilities/event-driven.mjs +2 -2
- package/dist/utilities/event-listener.d.mts +1 -1
- package/dist/utilities/event-listener.mjs +1 -1
- package/dist/utilities/event-listener.test.mjs +2 -2
- package/dist/utilities/focus-within.d.mts +1 -1
- package/dist/utilities/focus-within.mjs +1 -1
- package/dist/utilities/focus-within.test.mjs +2 -2
- package/dist/utilities/hover.d.mts +1 -1
- package/dist/utilities/hover.mjs +1 -1
- package/dist/utilities/hover.test.mjs +2 -2
- package/dist/utilities/intersection-observer.mjs +4 -6
- package/dist/utilities/intersection-observer.test.mjs +2 -2
- package/dist/utilities/interval.d.mts +1 -1
- package/dist/utilities/interval.mjs +1 -1
- package/dist/utilities/interval.test.mjs +18 -2
- package/dist/utilities/location.d.mts +2 -14
- package/dist/utilities/location.mjs +12 -3
- package/dist/utilities/location.test.mjs +5 -5
- package/dist/utilities/long-press.mjs +1 -1
- package/dist/utilities/long-press.test.mjs +2 -2
- package/dist/utilities/media-devices.d.mts +1 -1
- package/dist/utilities/media-devices.mjs +1 -1
- package/dist/utilities/media-devices.test.mjs +2 -2
- package/dist/utilities/media-player.d.mts +1 -1
- package/dist/utilities/media-player.test.mjs +2 -2
- package/dist/utilities/media-query.d.mts +2 -3
- package/dist/utilities/media-query.mjs +3 -3
- package/dist/utilities/mutation-observer.mjs +4 -7
- package/dist/utilities/mutation-observer.test.mjs +2 -2
- package/dist/utilities/network.d.mts +2 -2
- package/dist/utilities/network.mjs +5 -3
- package/dist/utilities/network.test.mjs +1 -1
- package/dist/utilities/on-click-outside.test.mjs +2 -2
- package/dist/utilities/orientation.d.mts +1 -1
- package/dist/utilities/orientation.mjs +9 -1
- package/dist/utilities/previous.d.mts +1 -1
- package/dist/utilities/previous.mjs +1 -1
- package/dist/utilities/previous.test.mjs +2 -2
- package/dist/utilities/promise.d.mts +1 -1
- package/dist/utilities/promise.mjs +1 -1
- package/dist/utilities/promise.test.mjs +2 -2
- package/dist/utilities/resize-observer.mjs +4 -6
- package/dist/utilities/retry.mjs +1 -1
- package/dist/utilities/retry.test.mjs +2 -2
- package/dist/utilities/routing.d.mts +1 -1
- package/dist/utilities/routing.mjs +1 -1
- package/dist/utilities/routing.test.mjs +1 -1
- package/dist/utilities/search-params.d.mts +1 -1
- package/dist/utilities/search-params.test.mjs +2 -2
- package/dist/utilities/ssr.test.d.mts +1 -0
- package/dist/utilities/ssr.test.mjs +64 -0
- package/dist/utilities/storage.d.mts +1 -1
- package/dist/utilities/storage.test.mjs +2 -2
- package/dist/utilities/throttled.d.mts +1 -1
- package/dist/utilities/throttled.mjs +1 -1
- package/dist/utilities/throttled.test.mjs +2 -2
- package/dist/utilities/timeout.d.mts +1 -1
- package/dist/utilities/timeout.mjs +1 -1
- package/dist/utilities/timeout.test.mjs +57 -2
- package/dist/utilities/window-focus.d.mts +2 -2
- package/dist/utilities/window-focus.mjs +5 -3
- package/dist/utilities/window-size.d.mts +1 -1
- package/dist/utilities/window-size.mjs +10 -5
- package/dist/utilities/window-size.test.mjs +1 -1
- package/package.json +11 -1
- package/dist/lib-JA05lzCN.d.mts +0 -4
- /package/dist/{polyfill-DR5XVnh_.d.mts → polyfill-BVNd6ogU.d.mts} +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { _ as onCleanup, b as untracked, d as effect, f as effectScope, t as isReactive } from "./signals-J8dK_rA4.mjs";
|
|
2
2
|
import "./polyfill-B1lNNcum.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { on } from "./utilities/event-listener.mjs";
|
|
4
|
+
import { i as resolveNode$1, n as Slot, r as Slots, t as SLOTS } from "./slot-Kb61AcgW.mjs";
|
|
4
5
|
//#region \0rolldown/runtime.js
|
|
5
6
|
var __defProp = Object.defineProperty;
|
|
6
7
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -40,21 +41,21 @@ const ReservedNameSpaces = new Set([
|
|
|
40
41
|
//#endregion
|
|
41
42
|
//#region src/jsx-runtime/children.ts
|
|
42
43
|
function hasSlots(node) {
|
|
43
|
-
return
|
|
44
|
+
return SLOTS in node;
|
|
44
45
|
}
|
|
45
46
|
function isChildrenProperty(node, key) {
|
|
46
47
|
if (key === "children" && (node instanceof Element || node instanceof DocumentFragment)) return true;
|
|
47
48
|
if (hasSlots(node)) {
|
|
48
49
|
const slotName = key.replace(/^slot:/, "");
|
|
49
|
-
if (Slots.has(node[
|
|
50
|
+
if (Slots.has(node[SLOTS], slotName)) return true;
|
|
50
51
|
}
|
|
51
52
|
return key in node && node[key] instanceof Slot;
|
|
52
53
|
}
|
|
53
54
|
function applyChildren(node, key, value) {
|
|
54
55
|
if (hasSlots(node)) {
|
|
55
56
|
const slotName = key.replace(/^slot:/, "");
|
|
56
|
-
if (Slots.has(node[
|
|
57
|
-
applySlot(node[
|
|
57
|
+
if (Slots.has(node[SLOTS], slotName)) {
|
|
58
|
+
applySlot(node[SLOTS][slotName], value);
|
|
58
59
|
return;
|
|
59
60
|
}
|
|
60
61
|
}
|
|
@@ -126,7 +127,7 @@ function applyProps(node, props) {
|
|
|
126
127
|
if (isReactive(value)) {
|
|
127
128
|
if (isEventKey(key)) {
|
|
128
129
|
effect(() => {
|
|
129
|
-
|
|
130
|
+
on(node, eventName(key), value());
|
|
130
131
|
});
|
|
131
132
|
continue;
|
|
132
133
|
}
|
|
@@ -134,7 +135,7 @@ function applyProps(node, props) {
|
|
|
134
135
|
continue;
|
|
135
136
|
}
|
|
136
137
|
if (isEventKey(key)) {
|
|
137
|
-
|
|
138
|
+
on(node, eventName(key), value);
|
|
138
139
|
continue;
|
|
139
140
|
}
|
|
140
141
|
setProp(node, key, value);
|
|
@@ -210,19 +211,12 @@ function setAttribute(el, key, value) {
|
|
|
210
211
|
function isEventKey(key) {
|
|
211
212
|
return key.startsWith("on:") || key.length > 2 && key.startsWith("on") && key[2] >= "A" && key[2] <= "Z";
|
|
212
213
|
}
|
|
213
|
-
function
|
|
214
|
-
|
|
215
|
-
el.addEventListener(event, handler);
|
|
216
|
-
return () => el.removeEventListener(event, handler);
|
|
214
|
+
function eventName(key) {
|
|
215
|
+
return key.startsWith("on:") ? key.slice(3) : key[2].toLowerCase() + key.slice(3);
|
|
217
216
|
}
|
|
218
217
|
//#endregion
|
|
219
|
-
//#region src/jsx-runtime/ref.ts
|
|
220
|
-
const $ref = Symbol("ref");
|
|
221
|
-
//#endregion
|
|
222
218
|
//#region src/jsx-runtime/element.ts
|
|
223
|
-
function createElement(type,
|
|
224
|
-
const ref = rawProps[$ref];
|
|
225
|
-
const props = Object.fromEntries(Object.entries(rawProps));
|
|
219
|
+
function createElement(type, { ref, ...props } = {}) {
|
|
226
220
|
if (typeof type === "function" && !type.prototype?.render) return createFunctionElement(type, props, ref);
|
|
227
221
|
return createNodeElement(type, props, ref);
|
|
228
222
|
}
|
package/dist/for.d.mts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { a as Props, o as Require } from "./infer-BfzRJoCn.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/for.d.ts
|
|
4
|
+
type KeyFn<T> = (item: T, index: number) => string | number;
|
|
5
|
+
type RenderFn<T> = (item: T, index: number) => Element | DocumentFragment | null;
|
|
6
|
+
/**
|
|
7
|
+
* Keyed list renderer. Reconciles a reactive array into the DOM using a key
|
|
8
|
+
* function to match existing nodes — minimising create/destroy churn.
|
|
9
|
+
*
|
|
10
|
+
* Reconciliation strategy (inspired by udomdiff / dom-expressions):
|
|
11
|
+
* 1. Remove stale entries (keys absent from the new array).
|
|
12
|
+
* 2. Skip unchanged common prefix and suffix.
|
|
13
|
+
* 3. Pure-append fast path when the surviving old range is empty.
|
|
14
|
+
* 4. Backward scan of the middle region — move or create entries so that
|
|
15
|
+
* each entry's range lands immediately before the already-correct cursor.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```tsx
|
|
19
|
+
* <For each={visibleTodos} by={(todo) => todo.id}>
|
|
20
|
+
* {(todo) => <li>{todo.text}</li>}
|
|
21
|
+
* </For>
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* Props:
|
|
25
|
+
* each — reactive getter returning the array (e.g. a `computed`)
|
|
26
|
+
* by — extracts a stable key per item (default: index)
|
|
27
|
+
* children — render function called once per new key
|
|
28
|
+
*/
|
|
29
|
+
/**
|
|
30
|
+
* Props for `<For>`, derived from its public instance fields.
|
|
31
|
+
* All props are optional — the class initializes sane defaults at runtime.
|
|
32
|
+
* Non-function props also accept a reactive getter.
|
|
33
|
+
*/
|
|
34
|
+
type ForProps<T> = Require<Props<For<T>>, "each" | "children">;
|
|
35
|
+
declare class For<T = unknown> {
|
|
36
|
+
#private;
|
|
37
|
+
constructor(_props?: ForProps<T>);
|
|
38
|
+
get each(): T[];
|
|
39
|
+
set each(v: T[]);
|
|
40
|
+
by: KeyFn<T>;
|
|
41
|
+
children: RenderFn<T>;
|
|
42
|
+
render(): DocumentFragment;
|
|
43
|
+
}
|
|
44
|
+
//#endregion
|
|
45
|
+
export { For, ForProps };
|
package/dist/for.mjs
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { n as disposeElement } from "./element-CGVy_8TW.mjs";
|
|
2
|
+
import { _ as onCleanup, b as untracked, d as effect, f as effectScope, v as signal, y as trigger } from "./signals-J8dK_rA4.mjs";
|
|
3
|
+
//#region src/for.ts
|
|
4
|
+
var For = class {
|
|
5
|
+
constructor(_props) {}
|
|
6
|
+
#each = signal([]);
|
|
7
|
+
get each() {
|
|
8
|
+
return this.#each();
|
|
9
|
+
}
|
|
10
|
+
set each(v) {
|
|
11
|
+
if (v === untracked(this.#each)) {
|
|
12
|
+
trigger(this.#each);
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
this.#each(v);
|
|
16
|
+
}
|
|
17
|
+
by = (_, i) => i;
|
|
18
|
+
children = () => null;
|
|
19
|
+
#start = document.createComment("<For>");
|
|
20
|
+
#end = document.createComment("</For>");
|
|
21
|
+
#cache = /* @__PURE__ */ new Map();
|
|
22
|
+
/** Keys in current DOM order — needed for prefix/suffix optimisation. */
|
|
23
|
+
#order = [];
|
|
24
|
+
render() {
|
|
25
|
+
const fragment = document.createDocumentFragment();
|
|
26
|
+
fragment.appendChild(this.#start);
|
|
27
|
+
fragment.appendChild(this.#end);
|
|
28
|
+
effect(() => this.#reconcile());
|
|
29
|
+
onCleanup(() => {
|
|
30
|
+
for (const entry of this.#cache.values()) cleanEntry(entry);
|
|
31
|
+
this.#cache.clear();
|
|
32
|
+
this.#order = [];
|
|
33
|
+
});
|
|
34
|
+
return fragment;
|
|
35
|
+
}
|
|
36
|
+
#reconcile() {
|
|
37
|
+
const parent = this.#start.parentNode;
|
|
38
|
+
if (!parent) return;
|
|
39
|
+
const items = this.each;
|
|
40
|
+
const b = items.map((item, i) => this.by(item, i));
|
|
41
|
+
const bSet = new Set(b);
|
|
42
|
+
for (const [key, entry] of this.#cache) if (!bSet.has(key)) {
|
|
43
|
+
removeEntry(entry);
|
|
44
|
+
this.#cache.delete(key);
|
|
45
|
+
}
|
|
46
|
+
const a = this.#order.filter((k) => this.#cache.has(k));
|
|
47
|
+
let aStart = 0, aEnd = a.length;
|
|
48
|
+
let bStart = 0, bEnd = b.length;
|
|
49
|
+
while (aStart < aEnd && bStart < bEnd && a[aStart] === b[bStart]) {
|
|
50
|
+
aStart++;
|
|
51
|
+
bStart++;
|
|
52
|
+
}
|
|
53
|
+
while (aEnd > aStart && bEnd > bStart && a[aEnd - 1] === b[bEnd - 1]) {
|
|
54
|
+
aEnd--;
|
|
55
|
+
bEnd--;
|
|
56
|
+
}
|
|
57
|
+
const after = bEnd < b.length ? this.#cache.get(b[bEnd]).start : this.#end;
|
|
58
|
+
if (aStart === aEnd) {
|
|
59
|
+
let cursor = after;
|
|
60
|
+
for (let i = bEnd - 1; i >= bStart; i--) {
|
|
61
|
+
const key = b[i];
|
|
62
|
+
const { entry, rendered } = this.#makeEntry(key, items[i], i);
|
|
63
|
+
insertEntry(parent, entry, cursor, rendered);
|
|
64
|
+
this.#cache.set(key, entry);
|
|
65
|
+
cursor = entry.start;
|
|
66
|
+
}
|
|
67
|
+
this.#order = [...b];
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
let cursor = after;
|
|
71
|
+
for (let i = bEnd - 1; i >= bStart; i--) {
|
|
72
|
+
const key = b[i];
|
|
73
|
+
let entry = this.#cache.get(key);
|
|
74
|
+
if (!entry) {
|
|
75
|
+
const made = this.#makeEntry(key, items[i], i);
|
|
76
|
+
entry = made.entry;
|
|
77
|
+
insertEntry(parent, entry, cursor, made.rendered);
|
|
78
|
+
this.#cache.set(key, entry);
|
|
79
|
+
} else if (entry.end.nextSibling !== cursor) moveEntry(parent, entry, cursor);
|
|
80
|
+
cursor = entry.start;
|
|
81
|
+
}
|
|
82
|
+
this.#order = [...b];
|
|
83
|
+
}
|
|
84
|
+
#makeEntry(key, item, index) {
|
|
85
|
+
let rendered = null;
|
|
86
|
+
let dispose;
|
|
87
|
+
untracked(() => {
|
|
88
|
+
dispose = effectScope(() => {
|
|
89
|
+
rendered = this.children(item, index);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
return {
|
|
93
|
+
entry: {
|
|
94
|
+
start: document.createComment(`[${key}]`),
|
|
95
|
+
end: document.createComment(`[/${key}]`),
|
|
96
|
+
dispose
|
|
97
|
+
},
|
|
98
|
+
rendered
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
function insertEntry(parent, entry, before, rendered) {
|
|
103
|
+
parent.insertBefore(entry.start, before);
|
|
104
|
+
if (rendered) parent.insertBefore(rendered, before);
|
|
105
|
+
parent.insertBefore(entry.end, before);
|
|
106
|
+
}
|
|
107
|
+
function cleanEntry(entry) {
|
|
108
|
+
let node = entry.start.nextSibling;
|
|
109
|
+
while (node && node !== entry.end) {
|
|
110
|
+
const next = node.nextSibling;
|
|
111
|
+
if (node instanceof Element) disposeElement(node);
|
|
112
|
+
node = next;
|
|
113
|
+
}
|
|
114
|
+
entry.dispose();
|
|
115
|
+
}
|
|
116
|
+
function removeEntry(entry) {
|
|
117
|
+
let node = entry.start.nextSibling;
|
|
118
|
+
while (node && node !== entry.end) {
|
|
119
|
+
const next = node.nextSibling;
|
|
120
|
+
if (node instanceof Element) disposeElement(node);
|
|
121
|
+
node = next;
|
|
122
|
+
}
|
|
123
|
+
entry.dispose();
|
|
124
|
+
const range = document.createRange();
|
|
125
|
+
range.setStartBefore(entry.start);
|
|
126
|
+
range.setEndAfter(entry.end);
|
|
127
|
+
range.deleteContents();
|
|
128
|
+
}
|
|
129
|
+
function moveEntry(parent, entry, before) {
|
|
130
|
+
const range = document.createRange();
|
|
131
|
+
range.setStartBefore(entry.start);
|
|
132
|
+
range.setEndAfter(entry.end);
|
|
133
|
+
parent.insertBefore(range.extractContents(), before);
|
|
134
|
+
}
|
|
135
|
+
//#endregion
|
|
136
|
+
export { For };
|
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
//#region src/signals/lib.d.ts
|
|
2
|
-
declare const
|
|
3
|
-
declare const
|
|
4
|
-
declare const
|
|
5
|
-
declare const
|
|
2
|
+
declare const SIGNAL: unique symbol;
|
|
3
|
+
declare const COMPUTED: unique symbol;
|
|
4
|
+
declare const EFFECT: unique symbol;
|
|
5
|
+
declare const EFFECT_SCOPE: unique symbol;
|
|
6
6
|
/**
|
|
7
7
|
* Returns `true` if `fn` is a signal handle created by {@link signal}.
|
|
8
8
|
*
|
|
9
|
-
* Relies on
|
|
9
|
+
* Relies on the SIGNAL symbol.
|
|
10
10
|
*/
|
|
11
11
|
declare function isSignal(fn: unknown): boolean;
|
|
12
12
|
/**
|
|
13
13
|
* Returns `true` if `fn` is a computed handle created by {@link computed}.
|
|
14
14
|
*
|
|
15
|
-
* Relies on
|
|
15
|
+
* Relies on the COMPUTED symbol.
|
|
16
16
|
*/
|
|
17
17
|
declare function isComputed(fn: unknown): boolean;
|
|
18
18
|
/**
|
|
19
19
|
* Returns `true` if `fn` is an effect cleanup handle created by {@link effect}.
|
|
20
20
|
*
|
|
21
|
-
* Relies on the
|
|
21
|
+
* Relies on the EFFECT symbol.
|
|
22
22
|
*/
|
|
23
23
|
declare function isEffect(fn: unknown): boolean;
|
|
24
24
|
/**
|
|
@@ -255,11 +255,61 @@ type Signal<T> = Updater<T> & Computed<T>;
|
|
|
255
255
|
* ```
|
|
256
256
|
*/
|
|
257
257
|
declare function reactive<This extends object, Value>(source?: (self: This) => Signal<Value>): (_target: unknown, context: ClassFieldDecoratorContext<This, Value>) => (this: This, initialValue: Value) => Value;
|
|
258
|
+
/**
|
|
259
|
+
* A value that may be static or reactive. Accepts a plain `T` or a
|
|
260
|
+
* zero-arg getter (`() => T`) — typically a `signal` or `computed`.
|
|
261
|
+
*
|
|
262
|
+
* Used across the library anywhere a prop or attribute may be bound to
|
|
263
|
+
* reactive state. Resolve with {@link resolve}, detect with {@link isReactive}.
|
|
264
|
+
*
|
|
265
|
+
* @template T — the value type.
|
|
266
|
+
*
|
|
267
|
+
* @example
|
|
268
|
+
* ```ts
|
|
269
|
+
* import { signal, computed } from "elements-kit/signals";
|
|
270
|
+
*
|
|
271
|
+
* const count = signal(0);
|
|
272
|
+
* const double = computed(() => count() * 2);
|
|
273
|
+
*
|
|
274
|
+
* const a: MaybeReactive<number> = 5; // static
|
|
275
|
+
* const b: MaybeReactive<number> = count; // signal (getter)
|
|
276
|
+
* const c: MaybeReactive<number> = double; // computed (getter)
|
|
277
|
+
* ```
|
|
278
|
+
*/
|
|
258
279
|
type MaybeReactive<T> = T | Computed<T>;
|
|
259
280
|
/**
|
|
260
|
-
*
|
|
261
|
-
*
|
|
281
|
+
* Resolve a {@link MaybeReactive} to its current value. Calls the getter
|
|
282
|
+
* when reactive; returns the value as-is when static.
|
|
283
|
+
*
|
|
284
|
+
* @example
|
|
285
|
+
* ```ts
|
|
286
|
+
* resolve(5); // 5
|
|
287
|
+
* resolve(() => count()); // current count value
|
|
288
|
+
* ```
|
|
262
289
|
*/
|
|
263
290
|
declare function resolve<T>(value: MaybeReactive<T>): T;
|
|
291
|
+
/**
|
|
292
|
+
* Turn a reactive-props object into a bag of per-key getters. Callers may
|
|
293
|
+
* pass values or reactive sources (`signal`, `computed`); reading
|
|
294
|
+
* `props.name()` inside an effect or JSX getter subscribes to whatever
|
|
295
|
+
* drives it. Static values become stable thunks, signals and computed pass
|
|
296
|
+
* through unchanged — so identity is preserved (`props.name === props.name`).
|
|
297
|
+
*
|
|
298
|
+
* @example
|
|
299
|
+
* ```tsx
|
|
300
|
+
* import { resolveProps } from "elements-kit/signals";
|
|
301
|
+
*
|
|
302
|
+
* function Greeting(raw: MaybeReactiveProps<{ name: string; excited?: boolean }>) {
|
|
303
|
+
* const props = resolveProps(raw);
|
|
304
|
+
* return (
|
|
305
|
+
* <p>
|
|
306
|
+
* Hello, {props.name}
|
|
307
|
+
* {() => (props.excited() ? "!" : ".")}
|
|
308
|
+
* </p>
|
|
309
|
+
* );
|
|
310
|
+
* }
|
|
311
|
+
* ```
|
|
312
|
+
*/
|
|
313
|
+
declare function resolveProps<P extends object>(raw: { [K in keyof P]: MaybeReactive<P[K]> }): { readonly [K in keyof P]: Computed<P[K]> };
|
|
264
314
|
//#endregion
|
|
265
|
-
export {
|
|
315
|
+
export { trigger as C, signal as S, isComputed as _, isReactive as a, isSignal as b, resolveProps as c, EFFECT_SCOPE as d, SIGNAL as f, effectScope as g, effect as h, Updater as i, COMPUTED as l, computed as m, MaybeReactive as n, reactive as o, batch as p, Signal as r, resolve as s, Computed as t, EFFECT as u, isEffect as v, untracked as w, onCleanup as x, isEffectScope as y };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,36 +1 @@
|
|
|
1
|
-
|
|
2
|
-
type KeyFn<T> = (item: T, index: number) => string | number;
|
|
3
|
-
type RenderFn<T> = (item: T, index: number) => Element | DocumentFragment | null;
|
|
4
|
-
/**
|
|
5
|
-
* Keyed list renderer. Reconciles a reactive array into the DOM using a key
|
|
6
|
-
* function to match existing nodes — minimising create/destroy churn.
|
|
7
|
-
*
|
|
8
|
-
* Reconciliation strategy (inspired by udomdiff / dom-expressions):
|
|
9
|
-
* 1. Remove stale entries (keys absent from the new array).
|
|
10
|
-
* 2. Skip unchanged common prefix and suffix.
|
|
11
|
-
* 3. Pure-append fast path when the surviving old range is empty.
|
|
12
|
-
* 4. Backward scan of the middle region — move or create entries so that
|
|
13
|
-
* each entry's range lands immediately before the already-correct cursor.
|
|
14
|
-
*
|
|
15
|
-
* @example
|
|
16
|
-
* ```tsx
|
|
17
|
-
* <For each={visibleTodos} by={(todo) => todo.id}>
|
|
18
|
-
* {(todo) => <li>{todo.text}</li>}
|
|
19
|
-
* </For>
|
|
20
|
-
* ```
|
|
21
|
-
*
|
|
22
|
-
* Props:
|
|
23
|
-
* each — reactive getter returning the array (e.g. a `computed`)
|
|
24
|
-
* by — extracts a stable key per item (default: index)
|
|
25
|
-
* children — render function called once per new key
|
|
26
|
-
*/
|
|
27
|
-
declare class For<T = unknown> {
|
|
28
|
-
#private;
|
|
29
|
-
get each(): T[];
|
|
30
|
-
set each(v: T[]);
|
|
31
|
-
by: KeyFn<T>;
|
|
32
|
-
children: RenderFn<T>;
|
|
33
|
-
render(): DocumentFragment;
|
|
34
|
-
}
|
|
35
|
-
//#endregion
|
|
36
|
-
export { For };
|
|
1
|
+
export { };
|
package/dist/index.mjs
CHANGED
|
@@ -1,144 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { _ as signal, g as onCleanup, u as effect, v as trigger, y as untracked } from "./signals-BHmWX6ox.mjs";
|
|
3
|
-
//#region src/jsx-runtime/for.ts
|
|
4
|
-
/**
|
|
5
|
-
* Keyed list renderer. Reconciles a reactive array into the DOM using a key
|
|
6
|
-
* function to match existing nodes — minimising create/destroy churn.
|
|
7
|
-
*
|
|
8
|
-
* Reconciliation strategy (inspired by udomdiff / dom-expressions):
|
|
9
|
-
* 1. Remove stale entries (keys absent from the new array).
|
|
10
|
-
* 2. Skip unchanged common prefix and suffix.
|
|
11
|
-
* 3. Pure-append fast path when the surviving old range is empty.
|
|
12
|
-
* 4. Backward scan of the middle region — move or create entries so that
|
|
13
|
-
* each entry's range lands immediately before the already-correct cursor.
|
|
14
|
-
*
|
|
15
|
-
* @example
|
|
16
|
-
* ```tsx
|
|
17
|
-
* <For each={visibleTodos} by={(todo) => todo.id}>
|
|
18
|
-
* {(todo) => <li>{todo.text}</li>}
|
|
19
|
-
* </For>
|
|
20
|
-
* ```
|
|
21
|
-
*
|
|
22
|
-
* Props:
|
|
23
|
-
* each — reactive getter returning the array (e.g. a `computed`)
|
|
24
|
-
* by — extracts a stable key per item (default: index)
|
|
25
|
-
* children — render function called once per new key
|
|
26
|
-
*/
|
|
27
|
-
var For = class {
|
|
28
|
-
#each = signal([]);
|
|
29
|
-
get each() {
|
|
30
|
-
return this.#each();
|
|
31
|
-
}
|
|
32
|
-
set each(v) {
|
|
33
|
-
if (v === untracked(this.#each)) {
|
|
34
|
-
trigger(this.#each);
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
this.#each(v);
|
|
38
|
-
}
|
|
39
|
-
by = (_, i) => i;
|
|
40
|
-
children = () => null;
|
|
41
|
-
#start = document.createComment("<For>");
|
|
42
|
-
#end = document.createComment("</For>");
|
|
43
|
-
#cache = /* @__PURE__ */ new Map();
|
|
44
|
-
/** Keys in current DOM order — needed for prefix/suffix optimisation. */
|
|
45
|
-
#order = [];
|
|
46
|
-
render() {
|
|
47
|
-
const fragment = document.createDocumentFragment();
|
|
48
|
-
fragment.appendChild(this.#start);
|
|
49
|
-
fragment.appendChild(this.#end);
|
|
50
|
-
effect(() => this.#reconcile());
|
|
51
|
-
onCleanup(() => {
|
|
52
|
-
for (const entry of this.#cache.values()) cleanEntry(entry);
|
|
53
|
-
this.#cache.clear();
|
|
54
|
-
this.#order = [];
|
|
55
|
-
});
|
|
56
|
-
return fragment;
|
|
57
|
-
}
|
|
58
|
-
#reconcile() {
|
|
59
|
-
const parent = this.#start.parentNode;
|
|
60
|
-
if (!parent) return;
|
|
61
|
-
const items = this.each;
|
|
62
|
-
const b = items.map((item, i) => this.by(item, i));
|
|
63
|
-
const bSet = new Set(b);
|
|
64
|
-
for (const [key, entry] of this.#cache) if (!bSet.has(key)) {
|
|
65
|
-
removeEntry(entry);
|
|
66
|
-
this.#cache.delete(key);
|
|
67
|
-
}
|
|
68
|
-
const a = this.#order.filter((k) => this.#cache.has(k));
|
|
69
|
-
let aStart = 0, aEnd = a.length;
|
|
70
|
-
let bStart = 0, bEnd = b.length;
|
|
71
|
-
while (aStart < aEnd && bStart < bEnd && a[aStart] === b[bStart]) {
|
|
72
|
-
aStart++;
|
|
73
|
-
bStart++;
|
|
74
|
-
}
|
|
75
|
-
while (aEnd > aStart && bEnd > bStart && a[aEnd - 1] === b[bEnd - 1]) {
|
|
76
|
-
aEnd--;
|
|
77
|
-
bEnd--;
|
|
78
|
-
}
|
|
79
|
-
const after = bEnd < b.length ? this.#cache.get(b[bEnd]).start : this.#end;
|
|
80
|
-
if (aStart === aEnd) {
|
|
81
|
-
let cursor = after;
|
|
82
|
-
for (let i = bEnd - 1; i >= bStart; i--) {
|
|
83
|
-
const key = b[i];
|
|
84
|
-
const entry = this.#makeEntry(key);
|
|
85
|
-
insertEntry(parent, entry, cursor, untracked(() => this.children(items[i], i)));
|
|
86
|
-
this.#cache.set(key, entry);
|
|
87
|
-
cursor = entry.start;
|
|
88
|
-
}
|
|
89
|
-
this.#order = [...b];
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
let cursor = after;
|
|
93
|
-
for (let i = bEnd - 1; i >= bStart; i--) {
|
|
94
|
-
const key = b[i];
|
|
95
|
-
let entry = this.#cache.get(key);
|
|
96
|
-
if (!entry) {
|
|
97
|
-
entry = this.#makeEntry(key);
|
|
98
|
-
insertEntry(parent, entry, cursor, untracked(() => this.children(items[i], i)));
|
|
99
|
-
this.#cache.set(key, entry);
|
|
100
|
-
} else if (entry.end.nextSibling !== cursor) moveEntry(parent, entry, cursor);
|
|
101
|
-
cursor = entry.start;
|
|
102
|
-
}
|
|
103
|
-
this.#order = [...b];
|
|
104
|
-
}
|
|
105
|
-
#makeEntry(key) {
|
|
106
|
-
return {
|
|
107
|
-
start: document.createComment(`[${key}]`),
|
|
108
|
-
end: document.createComment(`[/${key}]`)
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
};
|
|
112
|
-
function insertEntry(parent, entry, before, rendered) {
|
|
113
|
-
parent.insertBefore(entry.start, before);
|
|
114
|
-
if (rendered) parent.insertBefore(rendered, before);
|
|
115
|
-
parent.insertBefore(entry.end, before);
|
|
116
|
-
}
|
|
117
|
-
function cleanEntry(entry) {
|
|
118
|
-
let node = entry.start.nextSibling;
|
|
119
|
-
while (node && node !== entry.end) {
|
|
120
|
-
const next = node.nextSibling;
|
|
121
|
-
if (node instanceof Element) disposeElement(node);
|
|
122
|
-
node = next;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
function removeEntry(entry) {
|
|
126
|
-
let node = entry.start.nextSibling;
|
|
127
|
-
while (node && node !== entry.end) {
|
|
128
|
-
const next = node.nextSibling;
|
|
129
|
-
if (node instanceof Element) disposeElement(node);
|
|
130
|
-
node = next;
|
|
131
|
-
}
|
|
132
|
-
const range = document.createRange();
|
|
133
|
-
range.setStartBefore(entry.start);
|
|
134
|
-
range.setEndAfter(entry.end);
|
|
135
|
-
range.deleteContents();
|
|
136
|
-
}
|
|
137
|
-
function moveEntry(parent, entry, before) {
|
|
138
|
-
const range = document.createRange();
|
|
139
|
-
range.setStartBefore(entry.start);
|
|
140
|
-
range.setEndAfter(entry.end);
|
|
141
|
-
parent.insertBefore(range.extractContents(), before);
|
|
142
|
-
}
|
|
143
|
-
//#endregion
|
|
144
|
-
export { For };
|
|
1
|
+
export {};
|