elements-kit 0.0.1 → 0.0.2

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.
@@ -0,0 +1,277 @@
1
+ import { effect, isReactive } from "./signals.mjs";
2
+ import { $slots, Slot, Slots } from "./slot.mjs";
3
+ import { t as resolveNode } from "./polyfill-DAalJpCO.mjs";
4
+
5
+ //#region \0rolldown/runtime.js
6
+ var __defProp = Object.defineProperty;
7
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
8
+ var __getOwnPropNames = Object.getOwnPropertyNames;
9
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
10
+ var __exportAll = (all, no_symbols) => {
11
+ let target = {};
12
+ for (var name in all) {
13
+ __defProp(target, name, {
14
+ get: all[name],
15
+ enumerable: true
16
+ });
17
+ }
18
+ if (!no_symbols) {
19
+ __defProp(target, Symbol.toStringTag, { value: "Module" });
20
+ }
21
+ return target;
22
+ };
23
+ var __copyProps = (to, from, except, desc) => {
24
+ if (from && typeof from === "object" || typeof from === "function") {
25
+ for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
26
+ key = keys[i];
27
+ if (!__hasOwnProp.call(to, key) && key !== except) {
28
+ __defProp(to, key, {
29
+ get: ((k) => from[k]).bind(null, key),
30
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
31
+ });
32
+ }
33
+ }
34
+ }
35
+ return to;
36
+ };
37
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
38
+
39
+ //#endregion
40
+ //#region src/jsx-runtime/constants.ts
41
+ var constants_exports = /* @__PURE__ */ __exportAll({ ReservedNameSpaces: () => ReservedNameSpaces });
42
+ import * as import_dom_expressions_src_constants from "dom-expressions/src/constants";
43
+ __reExport(constants_exports, import_dom_expressions_src_constants);
44
+ const ReservedNameSpaces = new Set([
45
+ "class",
46
+ "on",
47
+ "style",
48
+ "prop"
49
+ ]);
50
+
51
+ //#endregion
52
+ //#region src/jsx-runtime/children.ts
53
+ function hasSlots(node) {
54
+ return $slots in node;
55
+ }
56
+ function isChildrenProperty(node, key) {
57
+ if (key === "children" && (node instanceof Element || node instanceof DocumentFragment)) return true;
58
+ if (hasSlots(node)) {
59
+ const slotName = key.replace(/^slot:/, "");
60
+ if (Slots.has(node[$slots], slotName)) return true;
61
+ }
62
+ return key in node && node[key] instanceof Slot;
63
+ }
64
+ function applyChildren(node, key, value) {
65
+ if (hasSlots(node)) {
66
+ const slotName = key.replace(/^slot:/, "");
67
+ if (Slots.has(node[$slots], slotName)) return applySlot(node[$slots][slotName], value);
68
+ }
69
+ if (key === "children" && (node instanceof Element || node instanceof DocumentFragment)) return mountChildren(node, value);
70
+ if (key in node) {
71
+ const slot = node[key];
72
+ if (!(slot instanceof Slot)) return;
73
+ return applySlot(slot, value);
74
+ }
75
+ }
76
+ /**
77
+ * Sets a Slot's content from a Child value.
78
+ */
79
+ function applySlot(slot, value) {
80
+ if (typeof value === "function") return effect(() => slot.set(resolveChild(value())));
81
+ slot.set(resolveChild(value));
82
+ }
83
+ function mountChildren(el, value) {
84
+ const children = ensureFlatArray(value);
85
+ const disposers = [];
86
+ for (const child of children) {
87
+ if (typeof child === "function") {
88
+ const slot = Slot.new();
89
+ el.appendChild(slot());
90
+ disposers.push(effect(() => slot.set(resolveChild(child()))));
91
+ continue;
92
+ }
93
+ el.appendChild(resolveChild(child));
94
+ }
95
+ return disposers.length > 0 ? () => disposers.forEach((d) => d()) : void 0;
96
+ }
97
+ function resolveChild(value) {
98
+ if (Array.isArray(value)) {
99
+ const fragment = document.createDocumentFragment();
100
+ for (const item of value) fragment.appendChild(resolveChild(item));
101
+ return fragment;
102
+ }
103
+ if (typeof value === "function") return resolveChild(value());
104
+ return resolveNode(value);
105
+ }
106
+ /** Normalises the children prop into a flat array. */
107
+ function ensureFlatArray(raw) {
108
+ return (Array.isArray(raw) ? raw : [raw]).flat(Infinity);
109
+ }
110
+
111
+ //#endregion
112
+ //#region src/jsx-runtime/properties.ts
113
+ function applyProps(node, props) {
114
+ const disposables = /* @__PURE__ */ new Set();
115
+ for (const [key, value] of Object.entries(props)) {
116
+ if (isChildrenProperty(node, key)) {
117
+ const disposable = applyChildren(node, key, value);
118
+ if (disposable) disposables.add(disposable);
119
+ continue;
120
+ }
121
+ if (isReactive(value)) {
122
+ if (isEventKey(key)) {
123
+ let cleanup;
124
+ const dispose = effect(() => {
125
+ if (cleanup) cleanup();
126
+ cleanup = setEvent(node, key, value());
127
+ });
128
+ disposables.add(() => {
129
+ dispose();
130
+ if (cleanup) cleanup();
131
+ });
132
+ continue;
133
+ }
134
+ disposables.add(effect(() => setProp(node, key, value())));
135
+ continue;
136
+ }
137
+ if (isEventKey(key)) {
138
+ disposables.add(setEvent(node, key, value));
139
+ continue;
140
+ }
141
+ setProp(node, key, value);
142
+ }
143
+ return disposables;
144
+ }
145
+ function setProp(node, key, value) {
146
+ const colonIdx = key.indexOf(":");
147
+ if (colonIdx > -1) {
148
+ const ns = key.slice(0, colonIdx);
149
+ const name = key.slice(colonIdx + 1);
150
+ if (ReservedNameSpaces.has(ns)) {
151
+ if (ns === "prop") {
152
+ node[name] = value;
153
+ return;
154
+ }
155
+ if (ns === "class") {
156
+ node.classList.toggle(name, Boolean(value));
157
+ return;
158
+ }
159
+ if (ns === "style") {
160
+ if (value == null || value === false) node.style.removeProperty(name);
161
+ else node.style.setProperty(name, String(value));
162
+ return;
163
+ }
164
+ return;
165
+ }
166
+ const svgNs = constants_exports.SVGNamespace[ns];
167
+ if (svgNs) {
168
+ node.setAttributeNS(svgNs, key, String(value ?? ""));
169
+ return;
170
+ }
171
+ }
172
+ if (key === "class") {
173
+ node.className = String(value ?? "");
174
+ return;
175
+ }
176
+ if (key === "style") {
177
+ applyStyle(node, value);
178
+ return;
179
+ }
180
+ if (constants_exports.ChildProperties.has(key)) {
181
+ node[key] = value ?? "";
182
+ return;
183
+ }
184
+ if (!(node instanceof SVGElement) && constants_exports.Properties.has(key)) {
185
+ node[key] = value;
186
+ return;
187
+ }
188
+ if (node instanceof Element && node.nodeName.includes("-") && key in node) {
189
+ try {
190
+ node[key] = value;
191
+ } catch {
192
+ setAttribute(node, key, value);
193
+ }
194
+ return;
195
+ }
196
+ if (!(node instanceof Element)) {
197
+ node[key] = value;
198
+ return;
199
+ }
200
+ setAttribute(node, key, value);
201
+ }
202
+ function applyStyle(el, value) {
203
+ const s = el.style;
204
+ if (!s) return;
205
+ if (typeof value === "string") s.cssText = value;
206
+ else if (value && typeof value === "object") Object.assign(s, value);
207
+ }
208
+ function setAttribute(el, key, value) {
209
+ if (value == null || value === false) el.removeAttribute(key);
210
+ else el.setAttribute(key, value === true ? "" : String(value));
211
+ }
212
+ function isEventKey(key) {
213
+ return key.startsWith("on:") || key.length > 2 && key.startsWith("on") && key[2] >= "A" && key[2] <= "Z";
214
+ }
215
+ function setEvent(el, key, handler) {
216
+ const event = key.startsWith("on:") ? key.slice(3) : key[2].toLowerCase() + key.slice(3);
217
+ el.addEventListener(event, handler);
218
+ return () => el.removeEventListener(event, handler);
219
+ }
220
+
221
+ //#endregion
222
+ //#region src/jsx-runtime/ref.ts
223
+ const $ref = Symbol("ref");
224
+
225
+ //#endregion
226
+ //#region src/jsx-runtime/element.ts
227
+ function createElement(type, { [$ref]: ref, ...props } = {}) {
228
+ if (typeof type === "function" && !type.prototype?.render) {
229
+ const el = type(props);
230
+ if (typeof ref === "function" && el instanceof Element) ref(el);
231
+ return el;
232
+ }
233
+ const node = resolveElement(type);
234
+ if (!node) return null;
235
+ const disposables = applyProps(node, props);
236
+ if (disposables.size > 0) attachDisposables(node, disposables);
237
+ const el = _render(node);
238
+ if (typeof ref === "function" && el instanceof Element) ref(el);
239
+ return el;
240
+ }
241
+ function _render(node) {
242
+ if (node instanceof Element || node instanceof DocumentFragment) return node;
243
+ if (!node || typeof node.render !== "function") return null;
244
+ return _render(node.render());
245
+ }
246
+ /**
247
+ * Resolves the `type` argument of createElement into a concrete DOM node:
248
+ * - string → document.createElement(type)
249
+ * - Element → the element itself (apply props to an existing node)
250
+ * - class component → new type()
251
+ */
252
+ function resolveElement(type) {
253
+ if (typeof type === "string") return document.createElement(type);
254
+ if (type instanceof Element || type instanceof DocumentFragment) return type;
255
+ return new type();
256
+ }
257
+ function hasOwnDisposable(el) {
258
+ return Object.hasOwn(el, Symbol.dispose);
259
+ }
260
+ function attachDisposables(el, disposables) {
261
+ const existingDispose = hasOwnDisposable(el) ? el[Symbol.dispose].bind(el) : null;
262
+ Object.defineProperty(el, Symbol.dispose, {
263
+ value() {
264
+ existingDispose?.();
265
+ disposables.forEach((fn) => fn());
266
+ disposables.clear();
267
+ },
268
+ configurable: true
269
+ });
270
+ }
271
+ /** Runs all cleanup functions registered by JSX props/effects on `el`. */
272
+ function disposeElement(el) {
273
+ el[Symbol.dispose]?.();
274
+ }
275
+
276
+ //#endregion
277
+ export { disposeElement as n, createElement as t };
@@ -0,0 +1,36 @@
1
+ //#region src/components/for.d.ts
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 };
package/dist/index.mjs ADDED
@@ -0,0 +1,130 @@
1
+ import { n as disposeElement } from "./element-B3gwJmBr.mjs";
2
+ import { effect, signal, untracked } from "./signals.mjs";
3
+ import "./polyfill-DAalJpCO.mjs";
4
+
5
+ //#region src/components/for.ts
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
+ var For = class {
30
+ #each = signal([]);
31
+ get each() {
32
+ return this.#each();
33
+ }
34
+ set each(v) {
35
+ this.#each(v);
36
+ }
37
+ by = (_, i) => i;
38
+ children = () => null;
39
+ #start = document.createComment("<For>");
40
+ #end = document.createComment("</For>");
41
+ #cache = /* @__PURE__ */ new Map();
42
+ /** Keys in current DOM order — needed for prefix/suffix optimisation. */
43
+ #order = [];
44
+ render() {
45
+ const fragment = document.createDocumentFragment();
46
+ fragment.appendChild(this.#start);
47
+ fragment.appendChild(this.#end);
48
+ effect(() => this.#reconcile());
49
+ return fragment;
50
+ }
51
+ #reconcile() {
52
+ const parent = this.#start.parentNode;
53
+ if (!parent) return;
54
+ const items = this.each;
55
+ const b = items.map((item, i) => this.by(item, i));
56
+ const bSet = new Set(b);
57
+ for (const [key, entry] of this.#cache) if (!bSet.has(key)) {
58
+ removeEntry(entry);
59
+ this.#cache.delete(key);
60
+ }
61
+ const a = this.#order.filter((k) => this.#cache.has(k));
62
+ let aStart = 0, aEnd = a.length;
63
+ let bStart = 0, bEnd = b.length;
64
+ while (aStart < aEnd && bStart < bEnd && a[aStart] === b[bStart]) {
65
+ aStart++;
66
+ bStart++;
67
+ }
68
+ while (aEnd > aStart && bEnd > bStart && a[aEnd - 1] === b[bEnd - 1]) {
69
+ aEnd--;
70
+ bEnd--;
71
+ }
72
+ const after = bEnd < b.length ? this.#cache.get(b[bEnd]).start : this.#end;
73
+ if (aStart === aEnd) {
74
+ let cursor = after;
75
+ for (let i = bEnd - 1; i >= bStart; i--) {
76
+ const key = b[i];
77
+ const entry = this.#makeEntry(key);
78
+ insertEntry(parent, entry, cursor, untracked(() => this.children(items[i], i)));
79
+ this.#cache.set(key, entry);
80
+ cursor = entry.start;
81
+ }
82
+ this.#order = [...b];
83
+ return;
84
+ }
85
+ let cursor = after;
86
+ for (let i = bEnd - 1; i >= bStart; i--) {
87
+ const key = b[i];
88
+ let entry = this.#cache.get(key);
89
+ if (!entry) {
90
+ entry = this.#makeEntry(key);
91
+ insertEntry(parent, entry, cursor, untracked(() => this.children(items[i], i)));
92
+ this.#cache.set(key, entry);
93
+ } else if (entry.end.nextSibling !== cursor) moveEntry(parent, entry, cursor);
94
+ cursor = entry.start;
95
+ }
96
+ this.#order = [...b];
97
+ }
98
+ #makeEntry(key) {
99
+ return {
100
+ start: document.createComment(`[${key}]`),
101
+ end: document.createComment(`[/${key}]`)
102
+ };
103
+ }
104
+ };
105
+ function insertEntry(parent, entry, before, rendered) {
106
+ parent.insertBefore(entry.start, before);
107
+ if (rendered) parent.insertBefore(rendered, before);
108
+ parent.insertBefore(entry.end, before);
109
+ }
110
+ function removeEntry(entry) {
111
+ let node = entry.start.nextSibling;
112
+ while (node && node !== entry.end) {
113
+ const next = node.nextSibling;
114
+ if (node instanceof Element) disposeElement(node);
115
+ node = next;
116
+ }
117
+ const range = document.createRange();
118
+ range.setStartBefore(entry.start);
119
+ range.setEndAfter(entry.end);
120
+ range.deleteContents();
121
+ }
122
+ function moveEntry(parent, entry, before) {
123
+ const range = document.createRange();
124
+ range.setStartBefore(entry.start);
125
+ range.setEndAfter(entry.end);
126
+ parent.insertBefore(range.extractContents(), before);
127
+ }
128
+
129
+ //#endregion
130
+ export { For };
@@ -0,0 +1,70 @@
1
+ import { t as PrimitiveNodeType } from "../polyfill-Bvo2e52W.mjs";
2
+ import { JSX as JSX$1 } from "dom-expressions/src/jsx-h";
3
+
4
+ //#region src/jsx-runtime/types.d.ts
5
+ /** An instance created by a component class — must expose `render()`. */
6
+ interface ComponentInstance {
7
+ render(): Element | DocumentFragment | null;
8
+ }
9
+ /** A class whose constructor returns a ComponentInstance. */
10
+ type ComponentClass = new (...args: any[]) => ComponentInstance;
11
+ /** Anything that can appear as a JSX child. */
12
+ type Child = PrimitiveNodeType | AnyFn | Child[];
13
+ /** A function that renders props into an element or fragment. */
14
+ type AnyFn = (...args: any[]) => any;
15
+ //#endregion
16
+ //#region src/jsx-runtime/ref.d.ts
17
+ declare const $ref: unique symbol;
18
+ //#endregion
19
+ //#region src/jsx-runtime/element.d.ts
20
+ declare function createElement(type: string | Element | DocumentFragment | ComponentClass | ((props: Record<string | symbol, unknown>) => null | Element | DocumentFragment), {
21
+ [$ref]: ref,
22
+ ...props
23
+ }?: Record<string | symbol, unknown>): Element | DocumentFragment | null;
24
+ //#endregion
25
+ //#region src/jsx-runtime/index.d.ts
26
+ /** A value or a reactive zero-argument getter. */
27
+ type FunctionMaybe<T> = JSX$1.FunctionMaybe<T>;
28
+ /**
29
+ * Maps slot names to `Child` content.
30
+ * Use this to type `slot:name` JSX props on a custom component.
31
+ *
32
+ * @example
33
+ * ```tsx
34
+ * function Card(props: { title: string } & SlotProps<"header" | "footer">) { … }
35
+ * // caller: <Card title="…" slot:header={<h1>…</h1>} slot:footer={<p>…</p>} />
36
+ * ```
37
+ */
38
+ type SlotProps<K extends string> = { [P in K as `slot:${P}`]?: Child };
39
+ /**
40
+ * Get the full JSX prop types for a given tag name, including reactive
41
+ * attributes, events, and all our namespace extensions.
42
+ *
43
+ * @example
44
+ * ```ts
45
+ * type InputProps = Attrs<"input">; // typed props for <input>
46
+ * type DivProps = Attrs<"div">; // typed props for <div>
47
+ * ```
48
+ */
49
+ type Attrs<K extends keyof JSX.IntrinsicElements> = JSX.IntrinsicElements[K];
50
+ /** Extra props injected into every intrinsic element beyond dom-expressions defaults. */
51
+ type OurProps = {
52
+ [$ref]?: (el: Element) => void;
53
+ [slot: `slot:${string}`]: Child;
54
+ [cls: `class:${string}`]: FunctionMaybe<boolean>;
55
+ [sty: `style:${string}`]: FunctionMaybe<string | null>;
56
+ [prop: `prop:${string}`]: unknown;
57
+ };
58
+ type WithOurProps<T> = T & OurProps;
59
+ declare namespace JSX {
60
+ type Element = globalThis.Element | globalThis.DocumentFragment | null;
61
+ type ElementType = Child | ComponentClass;
62
+ interface ElementChildrenAttribute {
63
+ children: {};
64
+ }
65
+ type IntrinsicElements = { [K in keyof JSX$1.IntrinsicElements]: WithOurProps<JSX$1.IntrinsicElements[K]> } & {
66
+ /** Custom elements (`x-foo`, `my-component`, …) get a loose typed fallback. */[customElement: `${string}-${string}`]: WithOurProps<JSX$1.DOMAttributes<HTMLElement>> & Record<string, unknown>;
67
+ };
68
+ }
69
+ //#endregion
70
+ export { Attrs, FunctionMaybe, JSX, SlotProps, createElement as h, createElement as jsx, createElement as jsxDEV, createElement as jsxs };
@@ -0,0 +1,4 @@
1
+ import { t as createElement } from "../element-B3gwJmBr.mjs";
2
+ import "../polyfill-DAalJpCO.mjs";
3
+
4
+ export { createElement as h, createElement as jsx, createElement as jsxDEV, createElement as jsxs };
@@ -0,0 +1,14 @@
1
+ //#region src/lib.d.ts
2
+ type PrimitiveNodeType = Node | string | boolean | number | bigint | symbol | Date | RegExp | null | undefined;
3
+ //#endregion
4
+ //#region src/polyfill.d.ts
5
+ declare global {
6
+ interface SymbolConstructor {
7
+ readonly dispose: symbol;
8
+ }
9
+ interface Disposable {
10
+ [Symbol.dispose](): void;
11
+ }
12
+ }
13
+ //#endregion
14
+ export { PrimitiveNodeType as t };
@@ -0,0 +1,20 @@
1
+ //#region src/lib.ts
2
+ var UnsupportedChildError = class extends Error {
3
+ constructor(value) {
4
+ super(`Unsupported child type: ${typeof value}`);
5
+ this.name = "UnsupportedChildError";
6
+ }
7
+ };
8
+ function resolveNode(c) {
9
+ if (c instanceof Node) return c;
10
+ if (c === null || c === void 0 || typeof c === "boolean") return document.createComment("");
11
+ if (typeof c === "string" || typeof c === "number" || typeof c === "bigint" || typeof c === "symbol" || c instanceof Date || c instanceof RegExp) return document.createTextNode(String(c));
12
+ throw new UnsupportedChildError(c);
13
+ }
14
+
15
+ //#endregion
16
+ //#region src/polyfill.ts
17
+ if (!Symbol.dispose) Object.defineProperty(Symbol, "dispose", { value: Symbol("dispose") });
18
+
19
+ //#endregion
20
+ export { resolveNode as t };
@@ -1,3 +1,40 @@
1
- import { t as isReactiveValue } from "./signals-BzhB4Ch2.mjs";
2
- export * from "alien-signals";
3
- export { isReactiveValue };
1
+ import "./polyfill-Bvo2e52W.mjs";
2
+ import { ValueOrReactive } from "./builder/index.mjs";
3
+ import { computed, effect, effectScope, isComputed, isEffect, isEffectScope, isSignal, signal, signal as signal$1, trigger } from "alien-signals";
4
+
5
+ //#region src/signals.d.ts
6
+ declare function isReactive<T>(value: ValueOrReactive<T>): value is () => T;
7
+ type Signal<T> = ReturnType<typeof signal$1<T>>;
8
+ declare const batch: (fn: () => void) => void;
9
+ declare const untracked: <T>(fn: () => T) => T;
10
+ /**
11
+ * A decorator that makes a class field reactive by automatically wrapping its value in a signal.
12
+ *
13
+ * The field behaves like a normal property (get/set) but reactivity is tracked under the hood.
14
+ * Any reads will subscribe to the signal and any writes will trigger updates.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * class Counter {
19
+ * @reactive()
20
+ * count: number = 0;
21
+ * }
22
+ *
23
+ * const counter = new Counter();
24
+ * counter.count++; // Triggers reactivity
25
+ * console.log(counter.count); // Subscribes to changes
26
+ * ```
27
+ *
28
+ * @remarks
29
+ * Equivalent to manually creating a private signal and getter/setter:
30
+ * ```ts
31
+ * class Counter {
32
+ * #count = signal(0);
33
+ * get count() { return this.#count(); }
34
+ * set count(value) { this.#count(value); }
35
+ * }
36
+ * ```
37
+ */
38
+ declare function reactive<This extends object, Value>(source?: (self: This) => Signal<Value>): (_target: unknown, context: ClassFieldDecoratorContext<This, Value>) => (this: This, initialValue: Value) => Value;
39
+ //#endregion
40
+ export { Signal, batch, computed, effect, effectScope, isComputed, isEffect, isEffectScope, isReactive, isSignal, reactive, signal, trigger, untracked };
package/dist/signals.mjs CHANGED
@@ -1,5 +1,76 @@
1
- import { t as isReactiveValue } from "./signals-BGUPt0zl.mjs";
1
+ import { computed, effect, effectScope, endBatch, isComputed, isComputed as isComputed$1, isEffect, isEffectScope, isSignal, isSignal as isSignal$1, setActiveSub, signal, signal as signal$1, startBatch, trigger } from "alien-signals";
2
2
 
3
- export * from "alien-signals"
3
+ //#region src/signals.ts
4
+ function isReactive(value) {
5
+ return isSignal$1(value) || isComputed$1(value);
6
+ }
7
+ const batch = (fn) => {
8
+ startBatch();
9
+ try {
10
+ fn();
11
+ } finally {
12
+ endBatch();
13
+ }
14
+ };
15
+ const untracked = (fn) => {
16
+ const sub = setActiveSub(void 0);
17
+ try {
18
+ return fn();
19
+ } finally {
20
+ setActiveSub(sub);
21
+ }
22
+ };
23
+ /**
24
+ * A decorator that makes a class field reactive by automatically wrapping its value in a signal.
25
+ *
26
+ * The field behaves like a normal property (get/set) but reactivity is tracked under the hood.
27
+ * Any reads will subscribe to the signal and any writes will trigger updates.
28
+ *
29
+ * @example
30
+ * ```ts
31
+ * class Counter {
32
+ * @reactive()
33
+ * count: number = 0;
34
+ * }
35
+ *
36
+ * const counter = new Counter();
37
+ * counter.count++; // Triggers reactivity
38
+ * console.log(counter.count); // Subscribes to changes
39
+ * ```
40
+ *
41
+ * @remarks
42
+ * Equivalent to manually creating a private signal and getter/setter:
43
+ * ```ts
44
+ * class Counter {
45
+ * #count = signal(0);
46
+ * get count() { return this.#count(); }
47
+ * set count(value) { this.#count(value); }
48
+ * }
49
+ * ```
50
+ */
51
+ function reactive(source) {
52
+ const signalStore = /* @__PURE__ */ new WeakMap();
53
+ return (_target, context) => {
54
+ context.addInitializer(function() {
55
+ const sig = signalStore.get(this);
56
+ const writable = !isComputed$1(sig);
57
+ Object.defineProperty(this, context.name, {
58
+ get() {
59
+ return sig();
60
+ },
61
+ ...writable && { set(value) {
62
+ sig(value);
63
+ } },
64
+ enumerable: true,
65
+ configurable: true
66
+ });
67
+ });
68
+ return function(initialValue) {
69
+ signalStore.set(this, source ? source(this) : signal$1(initialValue));
70
+ return initialValue;
71
+ };
72
+ };
73
+ }
4
74
 
5
- export { isReactiveValue };
75
+ //#endregion
76
+ export { batch, computed, effect, effectScope, isComputed, isEffect, isEffectScope, isReactive, isSignal, reactive, signal, trigger, untracked };