@reckona/mreact-reactive-dom 0.0.1

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 (55) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +34 -0
  3. package/dist/bind-event.d.ts +3 -0
  4. package/dist/bind-event.d.ts.map +1 -0
  5. package/dist/bind-event.js +17 -0
  6. package/dist/bind-event.js.map +1 -0
  7. package/dist/bind-list.d.ts +6 -0
  8. package/dist/bind-list.d.ts.map +1 -0
  9. package/dist/bind-list.js +287 -0
  10. package/dist/bind-list.js.map +1 -0
  11. package/dist/bind-prop.d.ts +3 -0
  12. package/dist/bind-prop.d.ts.map +1 -0
  13. package/dist/bind-prop.js +89 -0
  14. package/dist/bind-prop.js.map +1 -0
  15. package/dist/bind-spread-props.d.ts +3 -0
  16. package/dist/bind-spread-props.d.ts.map +1 -0
  17. package/dist/bind-spread-props.js +95 -0
  18. package/dist/bind-spread-props.js.map +1 -0
  19. package/dist/bind-text.d.ts +7 -0
  20. package/dist/bind-text.d.ts.map +1 -0
  21. package/dist/bind-text.js +38 -0
  22. package/dist/bind-text.js.map +1 -0
  23. package/dist/index.d.ts +10 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +9 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/insert-dynamic.d.ts +3 -0
  28. package/dist/insert-dynamic.d.ts.map +1 -0
  29. package/dist/insert-dynamic.js +36 -0
  30. package/dist/insert-dynamic.js.map +1 -0
  31. package/dist/normalize.d.ts +3 -0
  32. package/dist/normalize.d.ts.map +1 -0
  33. package/dist/normalize.js +17 -0
  34. package/dist/normalize.js.map +1 -0
  35. package/dist/root.d.ts +3 -0
  36. package/dist/root.d.ts.map +1 -0
  37. package/dist/root.js +12 -0
  38. package/dist/root.js.map +1 -0
  39. package/dist/scope.d.ts +11 -0
  40. package/dist/scope.d.ts.map +1 -0
  41. package/dist/scope.js +55 -0
  42. package/dist/scope.js.map +1 -0
  43. package/dist/template.d.ts +2 -0
  44. package/dist/template.d.ts.map +1 -0
  45. package/dist/template.js +6 -0
  46. package/dist/template.js.map +1 -0
  47. package/dist/types.d.ts +3 -0
  48. package/dist/types.d.ts.map +1 -0
  49. package/dist/types.js +2 -0
  50. package/dist/types.js.map +1 -0
  51. package/dist/url-safety.d.ts +2 -0
  52. package/dist/url-safety.d.ts.map +1 -0
  53. package/dist/url-safety.js +2 -0
  54. package/dist/url-safety.js.map +1 -0
  55. package/package.json +45 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Tatsuo Kaniwa
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,34 @@
1
+ # @reckona/mreact-reactive-dom
2
+
3
+ `@reckona/mreact-reactive-dom` binds fine-grained reactive values to DOM nodes.
4
+ It is the low-level DOM runtime used by compiled client output.
5
+
6
+ ## Basic Usage
7
+
8
+ ```ts
9
+ import { bindText, createRoot } from "@reckona/mreact-reactive-dom";
10
+ import { cell } from "@reckona/mreact-reactive-core";
11
+
12
+ const count = cell(0);
13
+
14
+ createRoot(document.body, () => {
15
+ const text = document.createTextNode("");
16
+ bindText(text, () => count.get());
17
+ return text;
18
+ });
19
+ ```
20
+
21
+ ## Core APIs
22
+
23
+ - `createRoot()` owns a DOM scope and cleanup lifecycle.
24
+ - `createTemplate()` clones static HTML templates.
25
+ - `bindText()` and `bindTextBatch()` update text nodes.
26
+ - `bindProp()` and `bindSpreadProps()` update element properties and attributes.
27
+ - `bindEvent()` attaches event handlers.
28
+ - `bindList()` updates keyed list DOM.
29
+ - `insertDynamic()` inserts runtime values into a parent node.
30
+
31
+ ## Notes
32
+
33
+ Application code should usually use JSX and the router. This package is for
34
+ compiler output and low-level runtime integration.
@@ -0,0 +1,3 @@
1
+ import type { Dispose } from "./types.js";
2
+ export declare function bindEvent<K extends keyof HTMLElementEventMap>(element: HTMLElement, type: K, handler: (event: HTMLElementEventMap[K]) => void): Dispose;
3
+ //# sourceMappingURL=bind-event.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bind-event.d.ts","sourceRoot":"","sources":["../src/bind-event.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,mBAAmB,EAC3D,OAAO,EAAE,WAAW,EACpB,IAAI,EAAE,CAAC,EACP,OAAO,EAAE,CAAC,KAAK,EAAE,mBAAmB,CAAC,CAAC,CAAC,KAAK,IAAI,GAC/C,OAAO,CAmBT"}
@@ -0,0 +1,17 @@
1
+ import { registerDispose } from "./scope.js";
2
+ export function bindEvent(element, type, handler) {
3
+ const listener = (event) => {
4
+ handler(event);
5
+ };
6
+ const eventElement = element;
7
+ eventElement.__mreactHasEvents = true;
8
+ eventElement.__mreactEventBindings = [
9
+ ...(eventElement.__mreactEventBindings ?? []),
10
+ { listener, type },
11
+ ];
12
+ element.addEventListener(type, listener);
13
+ return registerDispose(() => {
14
+ element.removeEventListener(type, listener);
15
+ });
16
+ }
17
+ //# sourceMappingURL=bind-event.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bind-event.js","sourceRoot":"","sources":["../src/bind-event.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAG7C,MAAM,UAAU,SAAS,CACvB,OAAoB,EACpB,IAAO,EACP,OAAgD;IAEhD,MAAM,QAAQ,GAAG,CAAC,KAAY,EAAE,EAAE;QAChC,OAAO,CAAC,KAA+B,CAAC,CAAC;IAC3C,CAAC,CAAC;IACF,MAAM,YAAY,GAAG,OAGpB,CAAC;IAEF,YAAY,CAAC,iBAAiB,GAAG,IAAI,CAAC;IACtC,YAAY,CAAC,qBAAqB,GAAG;QACnC,GAAG,CAAC,YAAY,CAAC,qBAAqB,IAAI,EAAE,CAAC;QAC7C,EAAE,QAAQ,EAAE,IAAI,EAAE;KACnB,CAAC;IACF,OAAO,CAAC,gBAAgB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAEzC,OAAO,eAAe,CAAC,GAAG,EAAE;QAC1B,OAAO,CAAC,mBAAmB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { Dispose, RenderValue } from "./types.js";
2
+ export interface BindListOptions<T> {
3
+ key?: (item: T, index: number) => unknown;
4
+ }
5
+ export declare function bindList<T>(parent: ParentNode, marker: ChildNode, items: () => readonly T[], renderItem: (item: T, index: number) => RenderValue, options?: BindListOptions<T>): Dispose;
6
+ //# sourceMappingURL=bind-list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bind-list.d.ts","sourceRoot":"","sources":["../src/bind-list.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEvD,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;CAC3C;AAED,wBAAgB,QAAQ,CAAC,CAAC,EACxB,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,MAAM,SAAS,CAAC,EAAE,EACzB,UAAU,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,WAAW,EACnD,OAAO,GAAE,eAAe,CAAC,CAAC,CAAM,GAC/B,OAAO,CAMT"}
@@ -0,0 +1,287 @@
1
+ import { cell, effect } from "@reckona/mreact-reactive-core";
2
+ import { normalizeRenderValue } from "./normalize.js";
3
+ import { registerDispose } from "./scope.js";
4
+ export function bindList(parent, marker, items, renderItem, options = {}) {
5
+ if (options.key === undefined) {
6
+ return bindUnkeyedList(parent, marker, items, renderItem);
7
+ }
8
+ return bindKeyedList(parent, marker, items, renderItem, options.key);
9
+ }
10
+ function bindUnkeyedList(parent, marker, items, renderItem) {
11
+ let current = [];
12
+ const clear = () => {
13
+ for (const node of current) {
14
+ node.parentNode?.removeChild(node);
15
+ }
16
+ current = [];
17
+ };
18
+ const dispose = effect(() => {
19
+ const currentItems = items();
20
+ const next = [];
21
+ for (let index = 0; index < currentItems.length; index += 1) {
22
+ const renderedNodes = normalizeRenderValue(renderItem(currentItems[index], index));
23
+ for (const node of renderedNodes) {
24
+ next.push(node);
25
+ }
26
+ }
27
+ if (isSameNodeList(current, next)) {
28
+ return;
29
+ }
30
+ clear();
31
+ current = next;
32
+ if (marker.parentNode !== parent) {
33
+ current = [];
34
+ return;
35
+ }
36
+ for (const node of current) {
37
+ parent.insertBefore(node, marker);
38
+ }
39
+ });
40
+ return registerDispose(() => {
41
+ dispose();
42
+ clear();
43
+ });
44
+ }
45
+ function bindKeyedList(parent, marker, items, renderItem, key) {
46
+ let records = new Map();
47
+ const dispose = effect(() => {
48
+ const currentItems = items();
49
+ if (marker.parentNode !== parent) {
50
+ removeRecordNodes(Array.from(records.values()));
51
+ records = new Map();
52
+ return;
53
+ }
54
+ if (records.size === currentItems.length && records.size > 0) {
55
+ let sameKeyOrder = true;
56
+ const previousKeys = records.keys();
57
+ for (let index = 0; index < currentItems.length; index += 1) {
58
+ const previousKey = previousKeys.next();
59
+ const itemKey = key(currentItems[index], index);
60
+ if (previousKey.done || !Object.is(previousKey.value, itemKey)) {
61
+ sameKeyOrder = false;
62
+ break;
63
+ }
64
+ }
65
+ if (sameKeyOrder) {
66
+ updateRecords(records, currentItems, key);
67
+ return;
68
+ }
69
+ }
70
+ const ownsParent = records.size > 0 && ownsWholeParent(parent, marker, records);
71
+ if (ownsParent) {
72
+ if (currentItems.length === 0) {
73
+ parent.replaceChildren(marker);
74
+ records = new Map();
75
+ return;
76
+ }
77
+ const appendedRecords = tryAppendKeyedRecords(parent, marker, records, currentItems, renderItem, key);
78
+ if (appendedRecords !== undefined) {
79
+ records = appendedRecords;
80
+ return;
81
+ }
82
+ const removedRecords = tryRemoveKeyedRecords(records, currentItems, key);
83
+ if (removedRecords !== undefined) {
84
+ removeRecordNodes(removedRecords.staleRecords);
85
+ records = removedRecords.nextRecords;
86
+ return;
87
+ }
88
+ }
89
+ const nextRecords = new Map();
90
+ const orderedNodes = [];
91
+ let reusedAllRecords = true;
92
+ currentItems.forEach((item, index) => {
93
+ const itemKey = key(item, index);
94
+ const existingRecord = records.get(itemKey);
95
+ if (existingRecord === undefined) {
96
+ reusedAllRecords = false;
97
+ }
98
+ const record = existingRecord ??
99
+ {
100
+ ...createKeyedRecord(item, index, renderItem),
101
+ };
102
+ record.update(item);
103
+ nextRecords.set(itemKey, record);
104
+ for (const node of record.nodes) {
105
+ orderedNodes.push(node);
106
+ }
107
+ });
108
+ if (ownsParent) {
109
+ parent.replaceChildren(...orderedNodes, marker);
110
+ }
111
+ else {
112
+ for (const node of orderedNodes) {
113
+ parent.insertBefore(node, marker);
114
+ }
115
+ }
116
+ if (!ownsParent && (!reusedAllRecords || nextRecords.size !== records.size)) {
117
+ removeStaleRecords(records, nextRecords);
118
+ }
119
+ records = nextRecords;
120
+ });
121
+ return registerDispose(() => {
122
+ dispose();
123
+ for (const record of records.values()) {
124
+ for (const node of record.nodes) {
125
+ node.parentNode?.removeChild(node);
126
+ }
127
+ }
128
+ records = new Map();
129
+ });
130
+ }
131
+ function tryAppendKeyedRecords(parent, marker, records, currentItems, renderItem, key) {
132
+ if (currentItems.length <= records.size) {
133
+ return undefined;
134
+ }
135
+ const previousKeys = records.keys();
136
+ for (let index = 0; index < records.size; index += 1) {
137
+ const previousKey = previousKeys.next();
138
+ const itemKey = key(currentItems[index], index);
139
+ if (previousKey.done || !Object.is(previousKey.value, itemKey)) {
140
+ return undefined;
141
+ }
142
+ }
143
+ const nextRecords = new Map(records);
144
+ const appendedItems = [];
145
+ for (let index = records.size; index < currentItems.length; index += 1) {
146
+ const item = currentItems[index];
147
+ const itemKey = key(item, index);
148
+ if (nextRecords.has(itemKey)) {
149
+ return undefined;
150
+ }
151
+ appendedItems.push({ index, item, itemKey });
152
+ }
153
+ for (const appended of appendedItems) {
154
+ const record = {
155
+ ...createKeyedRecord(appended.item, appended.index, renderItem),
156
+ };
157
+ nextRecords.set(appended.itemKey, record);
158
+ for (const node of record.nodes) {
159
+ parent.insertBefore(node, marker);
160
+ }
161
+ }
162
+ return nextRecords;
163
+ }
164
+ function updateRecords(records, currentItems, key) {
165
+ currentItems.forEach((item, index) => {
166
+ records.get(key(item, index))?.update(item);
167
+ });
168
+ }
169
+ function createKeyedRecord(item, index, renderItem) {
170
+ const itemRef = createReactiveItemRef(item);
171
+ return {
172
+ nodes: normalizeRenderValue(renderItem(itemRef.value, index)),
173
+ update: itemRef.update,
174
+ };
175
+ }
176
+ function createReactiveItemRef(item) {
177
+ if (!isObjectLike(item)) {
178
+ return {
179
+ value: item,
180
+ update() {
181
+ // Primitive item values are passed by value and cannot be proxied.
182
+ },
183
+ };
184
+ }
185
+ const current = cell(item);
186
+ return {
187
+ value: createItemProxy(current),
188
+ update(next) {
189
+ if (isObjectLike(next)) {
190
+ current.set(next);
191
+ }
192
+ },
193
+ };
194
+ }
195
+ function createItemProxy(current) {
196
+ return new Proxy({}, {
197
+ get(_target, property) {
198
+ const value = current.get();
199
+ return Reflect.get(value, property, value);
200
+ },
201
+ getOwnPropertyDescriptor(_target, property) {
202
+ return Reflect.getOwnPropertyDescriptor(current.get(), property);
203
+ },
204
+ has(_target, property) {
205
+ return Reflect.has(current.get(), property);
206
+ },
207
+ ownKeys() {
208
+ return Reflect.ownKeys(current.get());
209
+ },
210
+ set(_target, property, nextValue) {
211
+ const value = current.get();
212
+ return Reflect.set(value, property, nextValue, value);
213
+ },
214
+ });
215
+ }
216
+ function isObjectLike(value) {
217
+ return typeof value === "object" && value !== null;
218
+ }
219
+ function tryRemoveKeyedRecords(records, currentItems, key) {
220
+ if (currentItems.length >= records.size || currentItems.length === 0) {
221
+ return undefined;
222
+ }
223
+ const nextRecords = new Map();
224
+ const staleRecords = [];
225
+ let previousIndex = 0;
226
+ for (const [previousKey, record] of records) {
227
+ if (previousIndex < currentItems.length) {
228
+ const itemKey = key(currentItems[previousIndex], previousIndex);
229
+ if (Object.is(previousKey, itemKey)) {
230
+ if (nextRecords.has(previousKey)) {
231
+ return undefined;
232
+ }
233
+ nextRecords.set(previousKey, record);
234
+ previousIndex += 1;
235
+ continue;
236
+ }
237
+ }
238
+ staleRecords.push(record);
239
+ }
240
+ return previousIndex === currentItems.length
241
+ ? { nextRecords, staleRecords }
242
+ : undefined;
243
+ }
244
+ function removeStaleRecords(records, nextRecords) {
245
+ const staleRecords = [];
246
+ for (const [itemKey, record] of records) {
247
+ if (nextRecords.has(itemKey)) {
248
+ continue;
249
+ }
250
+ staleRecords.push(record);
251
+ }
252
+ removeRecordNodes(staleRecords);
253
+ }
254
+ function removeRecordNodes(records) {
255
+ for (const record of records) {
256
+ for (const node of record.nodes) {
257
+ node.parentNode?.removeChild(node);
258
+ }
259
+ }
260
+ }
261
+ function ownsWholeParent(parent, marker, records) {
262
+ if (marker.parentNode !== parent || marker.nextSibling !== null) {
263
+ return false;
264
+ }
265
+ let expectedNodes = 0;
266
+ for (const record of records.values()) {
267
+ expectedNodes += record.nodes.length;
268
+ }
269
+ if (parent.childNodes.length !== expectedNodes + 1) {
270
+ return false;
271
+ }
272
+ let childIndex = 0;
273
+ for (const record of records.values()) {
274
+ for (const node of record.nodes) {
275
+ if (parent.childNodes[childIndex] !== node) {
276
+ return false;
277
+ }
278
+ childIndex += 1;
279
+ }
280
+ }
281
+ return parent.childNodes[childIndex] === marker;
282
+ }
283
+ function isSameNodeList(left, right) {
284
+ return (left.length === right.length &&
285
+ left.every((node, index) => node === right[index]));
286
+ }
287
+ //# sourceMappingURL=bind-list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bind-list.js","sourceRoot":"","sources":["../src/bind-list.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Dispose } from "./types.js";
2
+ export declare function bindProp(element: Element, name: string, value: () => unknown): Dispose;
3
+ //# sourceMappingURL=bind-prop.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bind-prop.d.ts","sourceRoot":"","sources":["../src/bind-prop.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,wBAAgB,QAAQ,CACtB,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,OAAO,GACnB,OAAO,CAiBT"}
@@ -0,0 +1,89 @@
1
+ import { effect } from "@reckona/mreact-reactive-core";
2
+ import { registerDispose } from "./scope.js";
3
+ import { isDangerousHtmlAttribute, isDangerousHtmlOptIn, isUnsafeUrlAttribute, isUrlAttribute, } from "./url-safety.js";
4
+ export function bindProp(element, name, value) {
5
+ let initialized = false;
6
+ let previousValue;
7
+ const dispose = effect(() => {
8
+ const nextValue = value();
9
+ if (initialized && Object.is(previousValue, nextValue)) {
10
+ return;
11
+ }
12
+ initialized = true;
13
+ previousValue = nextValue;
14
+ setDomProp(element, name, nextValue);
15
+ });
16
+ return registerDispose(dispose);
17
+ }
18
+ function setDomProp(element, name, value) {
19
+ const attrName = toDomAttributeName(name);
20
+ // Issue 075: URL attributes are scheme-validated even when the binder
21
+ // would otherwise assign directly to the DOM property. An unsafe
22
+ // scheme drops the attribute and clears the matching property.
23
+ if (isUrlAttribute(attrName) &&
24
+ typeof value === "string" &&
25
+ isUnsafeUrlAttribute(attrName, value)) {
26
+ if (attrName in element) {
27
+ element[attrName] = "";
28
+ }
29
+ else if (name in element) {
30
+ element[name] = "";
31
+ }
32
+ element.removeAttribute(attrName);
33
+ return;
34
+ }
35
+ if (value === null || value === undefined || value === false) {
36
+ element.removeAttribute(attrName);
37
+ return;
38
+ }
39
+ if (isDangerousHtmlAttribute(attrName)) {
40
+ if (isDangerousHtmlOptIn(value)) {
41
+ element.setAttribute(attrName, value.__html);
42
+ }
43
+ else {
44
+ element.removeAttribute(attrName);
45
+ }
46
+ return;
47
+ }
48
+ if (name in element &&
49
+ !name.startsWith("aria-") &&
50
+ !name.startsWith("data-")) {
51
+ element[name] = value;
52
+ return;
53
+ }
54
+ if (value === true) {
55
+ element.setAttribute(attrName, "");
56
+ return;
57
+ }
58
+ element.setAttribute(attrName, String(value));
59
+ }
60
+ function toDomAttributeName(name) {
61
+ return HTML_ATTRIBUTE_ALIASES[name] ?? name;
62
+ }
63
+ const HTML_ATTRIBUTE_ALIASES = {
64
+ acceptCharset: "accept-charset",
65
+ autoFocus: "autofocus",
66
+ autoPlay: "autoplay",
67
+ charSet: "charset",
68
+ className: "class",
69
+ colSpan: "colspan",
70
+ contentEditable: "contenteditable",
71
+ crossOrigin: "crossorigin",
72
+ encType: "enctype",
73
+ formAction: "formaction",
74
+ frameBorder: "frameborder",
75
+ htmlFor: "for",
76
+ httpEquiv: "http-equiv",
77
+ maxLength: "maxlength",
78
+ minLength: "minlength",
79
+ noValidate: "novalidate",
80
+ playsInline: "playsinline",
81
+ readOnly: "readonly",
82
+ rowSpan: "rowspan",
83
+ spellCheck: "spellcheck",
84
+ srcDoc: "srcdoc",
85
+ srcSet: "srcset",
86
+ tabIndex: "tabindex",
87
+ useMap: "usemap",
88
+ };
89
+ //# sourceMappingURL=bind-prop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bind-prop.js","sourceRoot":"","sources":["../src/bind-prop.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Dispose } from "./types.js";
2
+ export declare function bindSpreadProps(element: HTMLElement, props: () => Record<string, unknown> | null | undefined): Dispose;
3
+ //# sourceMappingURL=bind-spread-props.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bind-spread-props.d.ts","sourceRoot":"","sources":["../src/bind-spread-props.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,wBAAgB,eAAe,CAC7B,OAAO,EAAE,WAAW,EACpB,KAAK,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,GACtD,OAAO,CAmCT"}
@@ -0,0 +1,95 @@
1
+ import { effect } from "@reckona/mreact-reactive-core";
2
+ import { registerDispose } from "./scope.js";
3
+ import { isDangerousHtmlAttribute, isDangerousHtmlOptIn, isUnsafeUrlAttribute, isUrlAttribute, } from "./url-safety.js";
4
+ export function bindSpreadProps(element, props) {
5
+ const previousNames = new Set();
6
+ const dispose = effect(() => {
7
+ for (const name of previousNames) {
8
+ removeProp(element, name);
9
+ }
10
+ previousNames.clear();
11
+ const nextProps = props();
12
+ if (nextProps === null || nextProps === undefined) {
13
+ return;
14
+ }
15
+ for (const [name, value] of Object.entries(nextProps)) {
16
+ if (name === "children" || name === "key" || name === "ref") {
17
+ continue;
18
+ }
19
+ applyProp(element, name, value);
20
+ previousNames.add(name);
21
+ }
22
+ });
23
+ return registerDispose(() => {
24
+ dispose();
25
+ for (const name of previousNames) {
26
+ removeProp(element, name);
27
+ }
28
+ previousNames.clear();
29
+ });
30
+ }
31
+ function applyProp(element, name, value) {
32
+ const attrName = toDomAttributeName(name);
33
+ if (value === false || value === null || value === undefined) {
34
+ removeProp(element, name);
35
+ return;
36
+ }
37
+ if (name === "style" && typeof value === "object" && value !== null) {
38
+ Object.assign(element.style, value);
39
+ return;
40
+ }
41
+ if (isDangerousHtmlAttribute(attrName)) {
42
+ if (isDangerousHtmlOptIn(value)) {
43
+ element.setAttribute(attrName, value.__html);
44
+ }
45
+ else {
46
+ removeProp(element, name);
47
+ }
48
+ return;
49
+ }
50
+ if (typeof value === "boolean") {
51
+ element.setAttribute(attrName, "");
52
+ return;
53
+ }
54
+ const stringValue = String(value);
55
+ // Issue 075: same URL-scheme filter as the SSR / react-compat paths.
56
+ if (isUrlAttribute(attrName) && isUnsafeUrlAttribute(attrName, stringValue)) {
57
+ removeProp(element, name);
58
+ return;
59
+ }
60
+ element.setAttribute(attrName, stringValue);
61
+ }
62
+ function removeProp(element, name) {
63
+ const attrName = toDomAttributeName(name);
64
+ element.removeAttribute(attrName);
65
+ }
66
+ function toDomAttributeName(name) {
67
+ return HTML_ATTRIBUTE_ALIASES[name] ?? name;
68
+ }
69
+ const HTML_ATTRIBUTE_ALIASES = {
70
+ acceptCharset: "accept-charset",
71
+ autoFocus: "autofocus",
72
+ autoPlay: "autoplay",
73
+ charSet: "charset",
74
+ className: "class",
75
+ colSpan: "colspan",
76
+ contentEditable: "contenteditable",
77
+ crossOrigin: "crossorigin",
78
+ encType: "enctype",
79
+ formAction: "formaction",
80
+ frameBorder: "frameborder",
81
+ htmlFor: "for",
82
+ httpEquiv: "http-equiv",
83
+ maxLength: "maxlength",
84
+ minLength: "minlength",
85
+ noValidate: "novalidate",
86
+ playsInline: "playsinline",
87
+ readOnly: "readonly",
88
+ rowSpan: "rowspan",
89
+ spellCheck: "spellcheck",
90
+ srcDoc: "srcdoc",
91
+ srcSet: "srcset",
92
+ tabIndex: "tabindex",
93
+ useMap: "usemap",
94
+ };
95
+ //# sourceMappingURL=bind-spread-props.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bind-spread-props.js","sourceRoot":"","sources":["../src/bind-spread-props.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { Dispose } from "./types.js";
2
+ export interface BindTextBatchOptions {
3
+ preserveInitial?: boolean;
4
+ }
5
+ export declare function bindText(node: Text, value: () => unknown): Dispose;
6
+ export declare function bindTextBatch(nodes: readonly Text[], value: () => unknown, options?: BindTextBatchOptions): Dispose;
7
+ //# sourceMappingURL=bind-text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bind-text.d.ts","sourceRoot":"","sources":["../src/bind-text.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,WAAW,oBAAoB;IACnC,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAgBD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,OAAO,GAAG,OAAO,CASlE;AAED,wBAAgB,aAAa,CAC3B,KAAK,EAAE,SAAS,IAAI,EAAE,EACtB,KAAK,EAAE,MAAM,OAAO,EACpB,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAoBT"}
@@ -0,0 +1,38 @@
1
+ import { effect } from "@reckona/mreact-reactive-core";
2
+ import { registerDispose } from "./scope.js";
3
+ function writeTextBatch(nodes, text) {
4
+ for (let index = 0; index < nodes.length; index += 1) {
5
+ nodes[index].data = text;
6
+ }
7
+ }
8
+ function normalizeText(value) {
9
+ if (typeof value === "string") {
10
+ return value;
11
+ }
12
+ return value == null ? "" : String(value);
13
+ }
14
+ export function bindText(node, value) {
15
+ const reactiveText = node;
16
+ reactiveText.__mreactReactiveText = true;
17
+ const dispose = effect(() => {
18
+ node.data = normalizeText(value());
19
+ });
20
+ return registerDispose(dispose);
21
+ }
22
+ export function bindTextBatch(nodes, value, options) {
23
+ for (let index = 0; index < nodes.length; index += 1) {
24
+ const reactiveText = nodes[index];
25
+ reactiveText.__mreactReactiveText = true;
26
+ }
27
+ let shouldWrite = options?.preserveInitial !== true;
28
+ const dispose = effect(() => {
29
+ const text = normalizeText(value());
30
+ if (!shouldWrite) {
31
+ shouldWrite = true;
32
+ return;
33
+ }
34
+ writeTextBatch(nodes, text);
35
+ });
36
+ return registerDispose(dispose);
37
+ }
38
+ //# sourceMappingURL=bind-text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bind-text.js","sourceRoot":"","sources":["../src/bind-text.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAO7C,SAAS,cAAc,CAAC,KAAsB,EAAE,IAAY;IAC1D,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACpD,KAAK,CAAC,KAAK,CAAU,CAAC,IAAI,GAAG,IAAI,CAAC;IACrC,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,IAAU,EAAE,KAAoB;IACvD,MAAM,YAAY,GAAG,IAA8C,CAAC;IAEpE,YAAY,CAAC,oBAAoB,GAAG,IAAI,CAAC;IACzC,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,EAAE;QAC1B,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC,KAAK,EAAE,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,OAAO,eAAe,CAAC,OAAO,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,KAAsB,EACtB,KAAoB,EACpB,OAA8B;IAE9B,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACrD,MAAM,YAAY,GAAG,KAAK,CAAC,KAAK,CAA2C,CAAC;QAC5E,YAAY,CAAC,oBAAoB,GAAG,IAAI,CAAC;IAC3C,CAAC;IAED,IAAI,WAAW,GAAG,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;IAEpD,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,EAAE;QAC1B,MAAM,IAAI,GAAG,aAAa,CAAC,KAAK,EAAE,CAAC,CAAC;QAEpC,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,WAAW,GAAG,IAAI,CAAC;YACnB,OAAO;QACT,CAAC;QAED,cAAc,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,OAAO,eAAe,CAAC,OAAO,CAAC,CAAC;AAClC,CAAC"}
@@ -0,0 +1,10 @@
1
+ export { bindEvent } from "./bind-event.js";
2
+ export { bindList } from "./bind-list.js";
3
+ export { bindProp } from "./bind-prop.js";
4
+ export { bindSpreadProps } from "./bind-spread-props.js";
5
+ export { bindText, bindTextBatch } from "./bind-text.js";
6
+ export { createRoot } from "./root.js";
7
+ export { createTemplate } from "./template.js";
8
+ export { insertDynamic } from "./insert-dynamic.js";
9
+ export type { Dispose, RenderValue } from "./types.js";
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,YAAY,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ export { bindEvent } from "./bind-event.js";
2
+ export { bindList } from "./bind-list.js";
3
+ export { bindProp } from "./bind-prop.js";
4
+ export { bindSpreadProps } from "./bind-spread-props.js";
5
+ export { bindText, bindTextBatch } from "./bind-text.js";
6
+ export { createRoot } from "./root.js";
7
+ export { createTemplate } from "./template.js";
8
+ export { insertDynamic } from "./insert-dynamic.js";
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Dispose, RenderValue } from "./types.js";
2
+ export declare function insertDynamic(parent: ParentNode, marker: ChildNode, value: () => RenderValue): Dispose;
3
+ //# sourceMappingURL=insert-dynamic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"insert-dynamic.d.ts","sourceRoot":"","sources":["../src/insert-dynamic.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEvD,wBAAgB,aAAa,CAC3B,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,MAAM,WAAW,GACvB,OAAO,CAmCT"}
@@ -0,0 +1,36 @@
1
+ import { effect } from "@reckona/mreact-reactive-core";
2
+ import { normalizeRenderValue } from "./normalize.js";
3
+ import { registerDispose } from "./scope.js";
4
+ export function insertDynamic(parent, marker, value) {
5
+ let current = [];
6
+ const clear = () => {
7
+ for (const node of current) {
8
+ node.parentNode?.removeChild(node);
9
+ }
10
+ current = [];
11
+ };
12
+ const dispose = effect(() => {
13
+ const next = normalizeRenderValue(value());
14
+ if (isSameNodeList(current, next)) {
15
+ return;
16
+ }
17
+ clear();
18
+ current = next;
19
+ if (marker.parentNode !== parent) {
20
+ current = [];
21
+ return;
22
+ }
23
+ for (const node of current) {
24
+ parent.insertBefore(node, marker);
25
+ }
26
+ });
27
+ return registerDispose(() => {
28
+ dispose();
29
+ clear();
30
+ });
31
+ }
32
+ function isSameNodeList(left, right) {
33
+ return (left.length === right.length &&
34
+ left.every((node, index) => node === right[index]));
35
+ }
36
+ //# sourceMappingURL=insert-dynamic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"insert-dynamic.js","sourceRoot":"","sources":["../src/insert-dynamic.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAG7C,MAAM,UAAU,aAAa,CAC3B,MAAkB,EAClB,MAAiB,EACjB,KAAwB;IAExB,IAAI,OAAO,GAAW,EAAE,CAAC;IAEzB,MAAM,KAAK,GAAG,GAAG,EAAE;QACjB,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;YAC3B,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC;QACrC,CAAC;QAED,OAAO,GAAG,EAAE,CAAC;IACf,CAAC,CAAC;IAEF,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,EAAE;QAC1B,MAAM,IAAI,GAAG,oBAAoB,CAAC,KAAK,EAAE,CAAC,CAAC;QAE3C,IAAI,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC;YAClC,OAAO;QACT,CAAC;QAED,KAAK,EAAE,CAAC;QACR,OAAO,GAAG,IAAI,CAAC;QAEf,IAAI,MAAM,CAAC,UAAU,KAAK,MAAM,EAAE,CAAC;YACjC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO;QACT,CAAC;QAED,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;YAC3B,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACpC,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,eAAe,CAAC,GAAG,EAAE;QAC1B,OAAO,EAAE,CAAC;QACV,KAAK,EAAE,CAAC;IACV,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,cAAc,CAAC,IAAqB,EAAE,KAAsB;IACnE,OAAO,CACL,IAAI,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM;QAC5B,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,KAAK,KAAK,CAAC,KAAK,CAAC,CAAC,CACnD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { RenderValue } from "./types.js";
2
+ export declare function normalizeRenderValue(value: RenderValue): Node[];
3
+ //# sourceMappingURL=normalize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../src/normalize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,EAAE,CAoB/D"}
@@ -0,0 +1,17 @@
1
+ export function normalizeRenderValue(value) {
2
+ if (value === null || value === undefined || typeof value === "boolean") {
3
+ return [];
4
+ }
5
+ if (typeof value === "string" || typeof value === "number") {
6
+ return [document.createTextNode(String(value))];
7
+ }
8
+ if (value instanceof Node) {
9
+ return [value];
10
+ }
11
+ const nodes = [];
12
+ for (const item of value) {
13
+ nodes.push(...normalizeRenderValue(item));
14
+ }
15
+ return nodes;
16
+ }
17
+ //# sourceMappingURL=normalize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize.js","sourceRoot":"","sources":["../src/normalize.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,oBAAoB,CAAC,KAAkB;IACrD,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,IAAI,OAAO,KAAK,KAAK,SAAS,EAAE,CAAC;QACxE,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC3D,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAClD,CAAC;IAED,IAAI,KAAK,YAAY,IAAI,EAAE,CAAC;QAC1B,OAAO,CAAC,KAAK,CAAC,CAAC;IACjB,CAAC;IAED,MAAM,KAAK,GAAW,EAAE,CAAC;IAEzB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,KAAK,CAAC,IAAI,CAAC,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC;IAC5C,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
package/dist/root.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import type { Dispose, RenderValue } from "./types.js";
2
+ export declare function createRoot(container: ParentNode, render: () => RenderValue): Dispose;
3
+ //# sourceMappingURL=root.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"root.d.ts","sourceRoot":"","sources":["../src/root.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEvD,wBAAgB,UAAU,CACxB,SAAS,EAAE,UAAU,EACrB,MAAM,EAAE,MAAM,WAAW,GACxB,OAAO,CAUT"}
package/dist/root.js ADDED
@@ -0,0 +1,12 @@
1
+ import { normalizeRenderValue } from "./normalize.js";
2
+ import { createScope, disposeScope, withScope } from "./scope.js";
3
+ export function createRoot(container, render) {
4
+ const scope = createScope();
5
+ const nodes = withScope(scope, () => normalizeRenderValue(render()));
6
+ container.replaceChildren(...nodes);
7
+ return () => {
8
+ disposeScope(scope);
9
+ container.replaceChildren();
10
+ };
11
+ }
12
+ //# sourceMappingURL=root.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"root.js","sourceRoot":"","sources":["../src/root.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAGlE,MAAM,UAAU,UAAU,CACxB,SAAqB,EACrB,MAAyB;IAEzB,MAAM,KAAK,GAAG,WAAW,EAAE,CAAC;IAC5B,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,oBAAoB,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAErE,SAAS,CAAC,eAAe,CAAC,GAAG,KAAK,CAAC,CAAC;IAEpC,OAAO,GAAG,EAAE;QACV,YAAY,CAAC,KAAK,CAAC,CAAC;QACpB,SAAS,CAAC,eAAe,EAAE,CAAC;IAC9B,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { Dispose } from "./types.js";
2
+ interface DomScope {
3
+ disposers: Set<Dispose>;
4
+ disposed: boolean;
5
+ }
6
+ export declare function withScope<T>(scope: DomScope, fn: () => T): T;
7
+ export declare function createScope(): DomScope;
8
+ export declare function registerDispose(dispose: Dispose): Dispose;
9
+ export declare function disposeScope(scope: DomScope): void;
10
+ export {};
11
+ //# sourceMappingURL=scope.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../src/scope.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,UAAU,QAAQ;IAChB,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IACxB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAID,wBAAgB,SAAS,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAS5D;AAED,wBAAgB,WAAW,IAAI,QAAQ,CAKtC;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAoBzD;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,CAuBlD"}
package/dist/scope.js ADDED
@@ -0,0 +1,55 @@
1
+ let activeScope = null;
2
+ export function withScope(scope, fn) {
3
+ const previous = activeScope;
4
+ activeScope = scope;
5
+ try {
6
+ return fn();
7
+ }
8
+ finally {
9
+ activeScope = previous;
10
+ }
11
+ }
12
+ export function createScope() {
13
+ return {
14
+ disposers: new Set(),
15
+ disposed: false,
16
+ };
17
+ }
18
+ export function registerDispose(dispose) {
19
+ const scope = activeScope;
20
+ if (scope === null || scope.disposed) {
21
+ return dispose;
22
+ }
23
+ let active = true;
24
+ const wrapped = () => {
25
+ if (!active) {
26
+ return;
27
+ }
28
+ active = false;
29
+ scope.disposers.delete(wrapped);
30
+ dispose();
31
+ };
32
+ scope.disposers.add(wrapped);
33
+ return wrapped;
34
+ }
35
+ export function disposeScope(scope) {
36
+ if (scope.disposed) {
37
+ return;
38
+ }
39
+ scope.disposed = true;
40
+ const disposers = Array.from(scope.disposers).reverse();
41
+ scope.disposers.clear();
42
+ let firstError;
43
+ for (const dispose of disposers) {
44
+ try {
45
+ dispose();
46
+ }
47
+ catch (error) {
48
+ firstError ??= error;
49
+ }
50
+ }
51
+ if (firstError !== undefined) {
52
+ throw firstError;
53
+ }
54
+ }
55
+ //# sourceMappingURL=scope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scope.js","sourceRoot":"","sources":["../src/scope.ts"],"names":[],"mappings":"AAOA,IAAI,WAAW,GAAoB,IAAI,CAAC;AAExC,MAAM,UAAU,SAAS,CAAI,KAAe,EAAE,EAAW;IACvD,MAAM,QAAQ,GAAG,WAAW,CAAC;IAC7B,WAAW,GAAG,KAAK,CAAC;IAEpB,IAAI,CAAC;QACH,OAAO,EAAE,EAAE,CAAC;IACd,CAAC;YAAS,CAAC;QACT,WAAW,GAAG,QAAQ,CAAC;IACzB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,OAAO;QACL,SAAS,EAAE,IAAI,GAAG,EAAE;QACpB,QAAQ,EAAE,KAAK;KAChB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAgB;IAC9C,MAAM,KAAK,GAAG,WAAW,CAAC;IAE1B,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QACrC,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,IAAI,MAAM,GAAG,IAAI,CAAC;IAClB,MAAM,OAAO,GAAG,GAAG,EAAE;QACnB,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO;QACT,CAAC;QAED,MAAM,GAAG,KAAK,CAAC;QACf,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAChC,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC;IAEF,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC7B,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,KAAe;IAC1C,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QACnB,OAAO;IACT,CAAC;IAED,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC;IAEtB,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC;IACxD,KAAK,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;IAExB,IAAI,UAAmB,CAAC;IAExB,KAAK,MAAM,OAAO,IAAI,SAAS,EAAE,CAAC;QAChC,IAAI,CAAC;YACH,OAAO,EAAE,CAAC;QACZ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,UAAU,KAAK,KAAK,CAAC;QACvB,CAAC;IACH,CAAC;IAED,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,MAAM,UAAU,CAAC;IACnB,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function createTemplate(html: string): () => DocumentFragment;
2
+ //# sourceMappingURL=template.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../src/template.ts"],"names":[],"mappings":"AAAA,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,gBAAgB,CAKnE"}
@@ -0,0 +1,6 @@
1
+ export function createTemplate(html) {
2
+ const template = document.createElement("template");
3
+ template.innerHTML = html;
4
+ return () => template.content.cloneNode(true);
5
+ }
6
+ //# sourceMappingURL=template.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template.js","sourceRoot":"","sources":["../src/template.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,MAAM,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;IACpD,QAAQ,CAAC,SAAS,GAAG,IAAI,CAAC;IAE1B,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAqB,CAAC;AACpE,CAAC"}
@@ -0,0 +1,3 @@
1
+ export type Dispose = () => void;
2
+ export type RenderValue = Node | string | number | boolean | null | undefined | readonly RenderValue[];
3
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC;AAEjC,MAAM,MAAM,WAAW,GACnB,IAAI,GACJ,MAAM,GACN,MAAM,GACN,OAAO,GACP,IAAI,GACJ,SAAS,GACT,SAAS,WAAW,EAAE,CAAC"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export { isDangerousHtmlAttribute, isDangerousHtmlOptIn, isSrcsetAttribute, isUnsafeUrlAttribute, isUrlAttribute, } from "@reckona/mreact-shared/url-safety";
2
+ //# sourceMappingURL=url-safety.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url-safety.d.ts","sourceRoot":"","sources":["../src/url-safety.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,oBAAoB,EACpB,iBAAiB,EACjB,oBAAoB,EACpB,cAAc,GACf,MAAM,mCAAmC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { isDangerousHtmlAttribute, isDangerousHtmlOptIn, isSrcsetAttribute, isUnsafeUrlAttribute, isUrlAttribute, } from "@reckona/mreact-shared/url-safety";
2
+ //# sourceMappingURL=url-safety.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url-safety.js","sourceRoot":"","sources":["../src/url-safety.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,oBAAoB,EACpB,iBAAiB,EACjB,oBAAoB,EACpB,cAAc,GACf,MAAM,mCAAmC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@reckona/mreact-reactive-dom",
3
+ "version": "0.0.1",
4
+ "description": "Fine-grained DOM binding runtime for compiled mreact output.",
5
+ "keywords": [
6
+ "compiler-runtime",
7
+ "dom",
8
+ "jsx",
9
+ "mreact",
10
+ "reactivity",
11
+ "typescript"
12
+ ],
13
+ "homepage": "https://github.com/t-k/mreact/tree/main/packages/reactive-dom#readme",
14
+ "bugs": {
15
+ "url": "https://github.com/t-k/mreact/issues"
16
+ },
17
+ "license": "MIT",
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "https://github.com/t-k/mreact.git",
21
+ "directory": "packages/reactive-dom"
22
+ },
23
+ "files": [
24
+ "dist/**/*.js",
25
+ "dist/**/*.js.map",
26
+ "dist/**/*.d.ts",
27
+ "dist/**/*.d.ts.map"
28
+ ],
29
+ "type": "module",
30
+ "sideEffects": false,
31
+ "types": "./dist/index.d.ts",
32
+ "exports": {
33
+ ".": {
34
+ "types": "./dist/index.d.ts",
35
+ "default": "./dist/index.js"
36
+ }
37
+ },
38
+ "publishConfig": {
39
+ "access": "public"
40
+ },
41
+ "dependencies": {
42
+ "@reckona/mreact-reactive-core": "0.0.1",
43
+ "@reckona/mreact-shared": "0.0.1"
44
+ }
45
+ }