@simpreact/simpreact 0.0.3 → 0.0.5

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/core/patching.js CHANGED
@@ -1,50 +1,44 @@
1
- import { emptyMap, emptyObject } from '../shared/index.js';
1
+ import { emptyObject } from '../shared/index.js';
2
2
  import { normalizeRoot } from './createElement.js';
3
3
  import { hostAdapter } from './hostAdapter.js';
4
4
  import { clearElementHostReference, remove, unmount } from './unmounting.js';
5
- import { mount, mountArrayChildren } from './mounting.js';
5
+ import { mount, mountArrayChildren, mountFunctionalElement } from './mounting.js';
6
6
  import { applyRef } from './ref.js';
7
7
  import { lifecycleEventBus } from './lifecycleEventBus.js';
8
- import { batchingRerenderLocker } from './rerender.js';
9
- export function patch(prevElement, nextElement, parentReference, nextReference, contextMap, hostNamespace) {
8
+ import { isMemo } from './memo.js';
9
+ export function patch(prevElement, nextElement, parentReference, nextReference, context, hostNamespace) {
10
10
  if (prevElement.type !== nextElement.type || prevElement.key !== nextElement.key) {
11
- replaceWithNewElement(prevElement, nextElement, parentReference, contextMap, hostNamespace);
11
+ replaceWithNewElement(prevElement, nextElement, parentReference, context, hostNamespace);
12
12
  }
13
13
  else if (nextElement.flag === 'HOST') {
14
- patchHostElement(prevElement, nextElement, contextMap, hostNamespace);
14
+ patchHostElement(prevElement, nextElement, context, hostNamespace);
15
15
  }
16
16
  else if (nextElement.flag === 'FC') {
17
- patchFunctionalComponent(prevElement, nextElement, parentReference, nextReference, contextMap, hostNamespace);
17
+ patchFunctionalComponent(prevElement, nextElement, parentReference, nextReference, context, hostNamespace);
18
18
  }
19
19
  else if (nextElement.flag === 'TEXT') {
20
20
  patchTextElement(prevElement, nextElement);
21
21
  }
22
22
  else if (nextElement.flag === 'FRAGMENT') {
23
- patchFragment(prevElement, nextElement, parentReference, contextMap, hostNamespace);
24
- }
25
- else if (nextElement.flag === 'PROVIDER') {
26
- patchProvider(prevElement, nextElement, parentReference, contextMap, hostNamespace);
27
- }
28
- else if (nextElement.flag === 'PORTAL') {
29
- patchPortal(prevElement, nextElement, contextMap);
23
+ patchFragment(prevElement, nextElement, parentReference, context, hostNamespace);
30
24
  }
31
25
  else {
32
- patchConsumer(prevElement, nextElement, parentReference, nextReference, contextMap, hostNamespace);
26
+ patchPortal(prevElement, nextElement, context);
33
27
  }
34
28
  }
35
- function replaceWithNewElement(prevElement, nextElement, parentReference, contextMap, hostNamespace) {
29
+ function replaceWithNewElement(prevElement, nextElement, parentReference, context, hostNamespace) {
36
30
  unmount(prevElement);
37
31
  nextElement.parent = prevElement.parent;
38
32
  if (nextElement.flag === 'HOST' && prevElement.flag === 'HOST') {
39
- mount(nextElement, null, null, contextMap, hostNamespace);
33
+ mount(nextElement, null, null, context, hostNamespace);
40
34
  hostAdapter.replaceChild(parentReference, nextElement.reference, prevElement.reference);
41
35
  }
42
36
  else {
43
- mount(nextElement, parentReference, findHostReferenceFromElement(prevElement), contextMap, hostNamespace);
37
+ mount(nextElement, parentReference, findHostReferenceFromElement(prevElement), context, hostNamespace);
44
38
  clearElementHostReference(prevElement, parentReference);
45
39
  }
46
40
  }
47
- function patchHostElement(prevElement, nextElement, contextMap, hostNamespace) {
41
+ function patchHostElement(prevElement, nextElement, context, hostNamespace) {
48
42
  if (prevElement.ref) {
49
43
  nextElement.ref = prevElement.ref;
50
44
  }
@@ -52,25 +46,32 @@ function patchHostElement(prevElement, nextElement, contextMap, hostNamespace) {
52
46
  hostNamespace = hostNamespaces?.self;
53
47
  nextElement.reference = prevElement.reference;
54
48
  hostAdapter.attachElementToReference(nextElement, nextElement.reference);
55
- patchChildren(prevElement.children || prevElement.props?.children, nextElement.children || nextElement.props?.children, nextElement.reference, null, nextElement, contextMap, hostNamespaces?.children);
49
+ patchChildren(prevElement.children || prevElement.props?.children, nextElement.children || nextElement.props?.children, nextElement.reference, null, nextElement, context, hostNamespaces?.children);
56
50
  hostAdapter.patchProps(nextElement.reference, prevElement, nextElement, hostNamespace);
57
51
  if (prevElement.className !== nextElement.className) {
58
52
  hostAdapter.setClassname(nextElement.reference, nextElement.className, hostNamespace);
59
53
  }
60
54
  applyRef(nextElement);
61
55
  }
62
- function patchFunctionalComponent(prevElement, nextElement, parentReference, nextReference, contextMap, hostNamespace) {
63
- const prevStore = !prevElement.store || prevElement.unmounted
64
- ? { hostNamespace: prevElement.store?.hostNamespace }
65
- : prevElement.store;
66
- prevStore.latestElement = nextElement;
67
- nextElement.store = prevStore;
56
+ function patchFunctionalComponent(prevElement, nextElement, parentReference, nextReference, context, hostNamespace) {
57
+ nextElement.store = prevElement.store || {};
58
+ nextElement.store.latestElement = nextElement;
68
59
  if (hostNamespace) {
69
60
  nextElement.store.hostNamespace = hostNamespace;
70
61
  }
71
- if (contextMap) {
72
- nextElement.contextMap = contextMap;
62
+ let forceRender = false;
63
+ if (prevElement.store?.forceRender) {
64
+ forceRender = true;
65
+ prevElement.store.forceRender = false;
73
66
  }
67
+ if (prevElement.unmounted) {
68
+ mountFunctionalElement(nextElement, parentReference, nextReference, context, hostNamespace);
69
+ return;
70
+ }
71
+ if (!forceRender && isMemo(nextElement.type) && nextElement.type._compare(prevElement.props, nextElement.props)) {
72
+ return;
73
+ }
74
+ nextElement.context = prevElement.context || context;
74
75
  // FC element always has Maybe<SimpElement> children due to normalization process.
75
76
  let nextChildren;
76
77
  let triedToRerenderUnsubscribe;
@@ -85,44 +86,29 @@ function patchFunctionalComponent(prevElement, nextElement, parentReference, nex
85
86
  do {
86
87
  triedToRerender = false;
87
88
  if (++rerenderCounter >= 25) {
88
- lifecycleEventBus.publish({
89
- type: 'errored',
90
- element: nextElement,
91
- error: new Error('Too many re-renders. SimpReact limits the number of renders to prevent an infinite loop.'),
92
- phase: 'updating',
93
- });
94
- return;
89
+ throw new Error('Too many re-renders.');
95
90
  }
96
91
  lifecycleEventBus.publish({ type: 'beforeRender', element: nextElement, phase: 'updating' });
97
- batchingRerenderLocker.lock();
98
92
  nextChildren = nextElement.type(nextElement.props || emptyObject);
99
- batchingRerenderLocker.flush();
100
93
  lifecycleEventBus.publish({ type: 'afterRender', element: nextElement, phase: 'updating' });
101
94
  } while (triedToRerender);
102
95
  nextChildren = normalizeRoot(nextChildren, false);
103
96
  }
104
97
  catch (error) {
105
98
  lifecycleEventBus.publish({ type: 'errored', element: nextElement, error, phase: 'updating' });
99
+ remove(prevElement, parentReference);
106
100
  return;
107
101
  }
108
102
  finally {
109
103
  triedToRerenderUnsubscribe();
110
104
  }
105
+ // Keep prevElement's children reference when prev and next elements are identical to avoid reassignment.
111
106
  const prevChildren = prevElement.children;
112
107
  if (nextChildren) {
113
108
  nextElement.children = nextChildren;
114
109
  }
115
- if (!prevElement.unmounted) {
116
- patchChildren(prevChildren, nextChildren, parentReference, nextReference, nextElement, contextMap, hostNamespace);
117
- lifecycleEventBus.publish({ type: 'updated', element: nextElement });
118
- return;
119
- }
120
- prevElement.unmounted = false;
121
- if (nextChildren) {
122
- nextChildren.parent = nextElement;
123
- mount(nextChildren, parentReference, nextReference, contextMap, hostNamespace);
124
- }
125
- lifecycleEventBus.publish({ type: 'mounted', element: nextElement });
110
+ patchChildren(prevChildren, nextChildren, parentReference, nextReference, nextElement, nextElement.context, hostNamespace);
111
+ lifecycleEventBus.publish({ type: 'updated', element: nextElement });
126
112
  }
127
113
  function patchTextElement(prevElement, nextElement) {
128
114
  nextElement.reference = prevElement.reference;
@@ -130,57 +116,41 @@ function patchTextElement(prevElement, nextElement) {
130
116
  hostAdapter.setTextContent(nextElement.reference, nextElement.children);
131
117
  }
132
118
  }
133
- function patchFragment(prevElement, nextElement, parentReference, contextMap, hostNamespace) {
134
- let nextReference = null;
135
- if (Array.isArray(prevElement.children) && !Array.isArray(nextElement.children) && nextElement.children) {
136
- nextReference = hostAdapter.findNextSiblingReference(findHostReferenceFromElement(prevElement.children[prevElement.children.length - 1]));
137
- }
138
- patchChildren(prevElement.children, nextElement.children, parentReference, nextReference, nextElement, contextMap, hostNamespace);
139
- }
140
- function patchProvider(prevElement, nextElement, parentReference, contextMap, hostNamespace) {
119
+ function patchFragment(prevElement, nextElement, parentReference, context, hostNamespace) {
141
120
  let nextReference = null;
142
121
  if (Array.isArray(prevElement.children) && !Array.isArray(nextElement.children) && nextElement.children) {
143
122
  nextReference = hostAdapter.findNextSiblingReference(findHostReferenceFromElement(prevElement.children[prevElement.children.length - 1]));
144
123
  }
145
- contextMap = new Map(contextMap);
146
- contextMap.set(nextElement.type.context, nextElement.props.value);
147
- patchChildren(prevElement.children, nextElement.children, parentReference, nextReference, nextElement, contextMap, hostNamespace);
148
- }
149
- function patchConsumer(prevElement, nextElement, parentReference, nextReference, contextMap, hostNamespace) {
150
- const children = normalizeRoot(nextElement.type(nextElement.props || emptyObject, contextMap || emptyMap), false);
151
- if (children) {
152
- nextElement.children = children;
153
- }
154
- patchChildren(prevElement.children, nextElement.children, parentReference, nextReference, nextElement, contextMap, hostNamespace);
124
+ patchChildren(prevElement.children, nextElement.children, parentReference, nextReference, nextElement, context, hostNamespace);
155
125
  }
156
- export function patchPortal(prevElement, nextElement, contextMap) {
126
+ export function patchPortal(prevElement, nextElement, context) {
157
127
  const prevContainer = prevElement.ref;
158
128
  const nextContainer = nextElement.ref;
159
129
  const nextChildren = nextElement.children;
160
- patchChildren(prevElement.children, nextChildren, prevContainer, null, nextElement, contextMap, hostAdapter.getHostNamespaces(nextChildren, undefined)?.self);
130
+ patchChildren(prevElement.children, nextChildren, prevContainer, null, nextElement, context, hostAdapter.getHostNamespaces(nextChildren, undefined)?.self);
161
131
  nextElement.reference = prevElement.reference;
162
132
  if (prevContainer !== nextContainer && nextChildren != null) {
163
133
  hostAdapter.removeChild(prevContainer, nextChildren.reference);
164
134
  hostAdapter.appendChild(nextContainer, nextChildren.reference);
165
135
  }
166
136
  }
167
- export function updateFunctionalComponent(element, parentReference, nextReference, contextMap, hostNamespace) {
168
- patchFunctionalComponent(element, element, parentReference, nextReference, contextMap, hostNamespace);
137
+ export function updateFunctionalComponent(element, parentReference, nextReference, context, hostNamespace) {
138
+ patchFunctionalComponent(element, element, parentReference, nextReference, context, hostNamespace);
169
139
  }
170
- function patchChildren(prevChildren, nextChildren, parentReference, nextReference, nextElement, contextMap, hostNamespace) {
140
+ function patchChildren(prevChildren, nextChildren, parentReference, nextReference, nextElement, context, hostNamespace) {
171
141
  if (Array.isArray(prevChildren)) {
172
142
  if (Array.isArray(nextChildren)) {
173
143
  for (const child of nextChildren) {
174
144
  child.parent = nextElement;
175
145
  }
176
- patchKeyedChildren(prevChildren, nextChildren, parentReference, nextReference, contextMap, hostNamespace);
146
+ patchKeyedChildren(prevChildren, nextChildren, parentReference, nextReference, context, hostNamespace);
177
147
  }
178
148
  else if (typeof nextChildren === 'string') {
179
149
  unmount(prevChildren);
180
150
  hostAdapter.setTextContent(parentReference, nextChildren);
181
151
  }
182
152
  else if (nextChildren) {
183
- patchKeyedChildren(prevChildren, [nextChildren], parentReference, nextReference, contextMap, hostNamespace);
153
+ patchKeyedChildren(prevChildren, [nextChildren], parentReference, nextReference, context, hostNamespace);
184
154
  }
185
155
  else {
186
156
  unmount(prevChildren);
@@ -190,7 +160,7 @@ function patchChildren(prevChildren, nextChildren, parentReference, nextReferenc
190
160
  else if (typeof prevChildren === 'string') {
191
161
  if (Array.isArray(nextChildren)) {
192
162
  hostAdapter.clearNode(parentReference);
193
- mountArrayChildren(nextChildren, parentReference, nextReference, contextMap, nextElement, hostNamespace);
163
+ mountArrayChildren(nextChildren, parentReference, nextReference, context, nextElement, hostNamespace);
194
164
  }
195
165
  else if (typeof nextChildren === 'string') {
196
166
  if (prevChildren !== nextChildren) {
@@ -200,7 +170,7 @@ function patchChildren(prevChildren, nextChildren, parentReference, nextReferenc
200
170
  else if (nextChildren) {
201
171
  hostAdapter.clearNode(parentReference);
202
172
  nextChildren.parent = nextElement;
203
- mount(nextChildren, parentReference, nextReference, contextMap, hostNamespace);
173
+ mount(nextChildren, parentReference, nextReference, context, hostNamespace);
204
174
  }
205
175
  else {
206
176
  hostAdapter.clearNode(parentReference);
@@ -208,7 +178,7 @@ function patchChildren(prevChildren, nextChildren, parentReference, nextReferenc
208
178
  }
209
179
  else if (prevChildren) {
210
180
  if (Array.isArray(nextChildren)) {
211
- patchKeyedChildren([prevChildren], nextChildren, parentReference, nextReference, contextMap, hostNamespace);
181
+ patchKeyedChildren([prevChildren], nextChildren, parentReference, nextReference, context, hostNamespace);
212
182
  }
213
183
  else if (typeof nextChildren === 'string') {
214
184
  unmount(prevChildren);
@@ -216,7 +186,7 @@ function patchChildren(prevChildren, nextChildren, parentReference, nextReferenc
216
186
  }
217
187
  else if (nextChildren) {
218
188
  nextChildren.parent = nextElement;
219
- patch(prevChildren, nextChildren, parentReference, nextReference, contextMap, hostNamespace);
189
+ patch(prevChildren, nextChildren, parentReference, nextReference, context, hostNamespace);
220
190
  }
221
191
  else {
222
192
  remove(prevChildren, parentReference);
@@ -224,18 +194,18 @@ function patchChildren(prevChildren, nextChildren, parentReference, nextReferenc
224
194
  }
225
195
  else {
226
196
  if (Array.isArray(nextChildren)) {
227
- mountArrayChildren(nextChildren, parentReference, nextReference, contextMap, nextElement, hostNamespace);
197
+ mountArrayChildren(nextChildren, parentReference, nextReference, context, nextElement, hostNamespace);
228
198
  }
229
199
  else if (typeof nextChildren === 'string') {
230
200
  hostAdapter.setTextContent(parentReference, nextChildren);
231
201
  }
232
202
  else if (nextChildren) {
233
203
  nextChildren.parent = nextElement;
234
- mount(nextChildren, parentReference, nextReference, contextMap, hostNamespace);
204
+ mount(nextChildren, parentReference, nextReference, context, hostNamespace);
235
205
  }
236
206
  }
237
207
  }
238
- export function patchKeyedChildren(prevChildren, nextChildren, parentReference, nextReference, contextMap, hostNamespace) {
208
+ export function patchKeyedChildren(prevChildren, nextChildren, parentReference, nextReference, context, hostNamespace) {
239
209
  let prevStart = 0;
240
210
  let nextStart = 0;
241
211
  let prevEnd = prevChildren.length - 1;
@@ -244,13 +214,13 @@ export function patchKeyedChildren(prevChildren, nextChildren, parentReference,
244
214
  while (prevStart <= prevEnd &&
245
215
  nextStart <= nextEnd &&
246
216
  prevChildren[prevStart].key === nextChildren[nextStart].key) {
247
- patch(prevChildren[prevStart], nextChildren[nextStart], parentReference, null, contextMap, hostNamespace);
217
+ patch(prevChildren[prevStart], nextChildren[nextStart], parentReference, null, context, hostNamespace);
248
218
  prevStart++;
249
219
  nextStart++;
250
220
  }
251
221
  // Step 2: Sync from end
252
222
  while (prevStart <= prevEnd && nextStart <= nextEnd && prevChildren[prevEnd].key === nextChildren[nextEnd].key) {
253
- patch(prevChildren[prevEnd], nextChildren[nextEnd], parentReference, null, contextMap, hostNamespace);
223
+ patch(prevChildren[prevEnd], nextChildren[nextEnd], parentReference, null, context, hostNamespace);
254
224
  prevEnd--;
255
225
  nextEnd--;
256
226
  }
@@ -258,7 +228,7 @@ export function patchKeyedChildren(prevChildren, nextChildren, parentReference,
258
228
  if (prevStart > prevEnd) {
259
229
  const before = findHostReferenceFromElement(nextChildren[nextEnd + 1]) || nextReference;
260
230
  for (let i = nextStart; i <= nextEnd; i++) {
261
- mount(nextChildren[i], parentReference, before, contextMap, hostNamespace);
231
+ mount(nextChildren[i], parentReference, before, context, hostNamespace);
262
232
  }
263
233
  // Step 4: Remove prev nodes if next list is exhausted
264
234
  }
@@ -286,12 +256,12 @@ export function patchKeyedChildren(prevChildren, nextChildren, parentReference,
286
256
  const prevIndex = keyToPrevIndexMap.get(nextChild.key);
287
257
  if (prevIndex != null) {
288
258
  const prevElement = prevChildren[prevIndex];
289
- patch(prevElement, nextChild, parentReference, null, contextMap, hostNamespace);
259
+ patch(prevElement, nextChild, parentReference, null, context, hostNamespace);
290
260
  toMove[i - nextStart] = prevIndex;
291
261
  usedIndices.add(prevIndex);
292
262
  }
293
263
  else {
294
- mount(nextChild, parentReference, findHostReferenceFromElement(nextChildren[i + 1]) || nextReference, contextMap, hostNamespace);
264
+ mount(nextChild, parentReference, findHostReferenceFromElement(nextChildren[i + 1]) || nextReference, context, hostNamespace);
295
265
  toMove[i - nextStart] = -1;
296
266
  }
297
267
  }
@@ -1,10 +1,11 @@
1
- import type { SimpElement } from './createElement.js';
1
+ import type { SimpElement, SimpElementStore } from './createElement.js';
2
2
  export declare function rerender(element: SimpElement): void;
3
3
  interface IRendererLocker {
4
4
  _isLocked: boolean;
5
- _elements: Set<SimpElement>;
6
- _track(element: SimpElement): void;
7
- _untrack(element: SimpElement): void;
5
+ _elementStores: Set<SimpElementStore>;
6
+ _last: SimpElementStore | undefined;
7
+ _track(element: SimpElementStore): void;
8
+ _untrack(element: SimpElementStore): void;
8
9
  lock(): void;
9
10
  flush(): void;
10
11
  }
package/core/rerender.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import { findParentReferenceFromElement, updateFunctionalComponent } from './patching.js';
2
2
  import { lifecycleEventBus } from './lifecycleEventBus.js';
3
3
  lifecycleEventBus.subscribe(event => {
4
- if (event.type === 'afterRender') {
5
- batchingRerenderLocker._untrack(event.element);
6
- renderingRerenderLocker._untrack(event.element);
4
+ if (event.type === 'afterRender' || event.type === 'errored' || event.type === 'unmounted') {
5
+ batchingRerenderLocker._untrack(event.element.store);
6
+ renderingRerenderLocker._untrack(event.element.store);
7
7
  }
8
8
  });
9
9
  export function rerender(element) {
@@ -15,62 +15,114 @@ export function rerender(element) {
15
15
  }
16
16
  lifecycleEventBus.publish({ type: 'triedToRerender', element });
17
17
  if (batchingRerenderLocker._isLocked) {
18
- batchingRerenderLocker._track(element);
18
+ batchingRerenderLocker._track(element.store);
19
19
  return;
20
20
  }
21
21
  if (renderingRerenderLocker._isLocked) {
22
- renderingRerenderLocker._track(element);
22
+ renderingRerenderLocker._track(element.store);
23
23
  return;
24
24
  }
25
25
  renderingRerenderLocker.lock();
26
- updateFunctionalComponent(element, findParentReferenceFromElement(element), null, element.contextMap || null, element.store.hostNamespace);
26
+ updateFunctionalComponent(element, findParentReferenceFromElement(element), null, element.context || null, element.store.hostNamespace);
27
27
  renderingRerenderLocker.flush();
28
28
  }
29
29
  export const batchingRerenderLocker = {
30
30
  _isLocked: false,
31
- _elements: new Set(),
32
- _track(element) {
33
- this._elements.add(element);
31
+ _elementStores: new Set(),
32
+ _last: undefined,
33
+ _track(store) {
34
+ if (this._elementStores.has(store)) {
35
+ return;
36
+ }
37
+ if (this._elementStores.size === 0 || store.forceRender) {
38
+ this._elementStores.add(store);
39
+ this._last = store;
40
+ return;
41
+ }
42
+ if (isParentOf(store.latestElement, this._last.latestElement)) {
43
+ return;
44
+ }
45
+ if (isParentOf(this._last.latestElement, store.latestElement)) {
46
+ this._elementStores.clear();
47
+ this._elementStores.add(store);
48
+ this._last = store;
49
+ }
34
50
  },
35
- _untrack(element) {
36
- this._elements.delete(element);
51
+ _untrack(store) {
52
+ if (this._elementStores.delete(store) && store === this._last) {
53
+ this._last = undefined;
54
+ for (const val of this._elementStores) {
55
+ this._last = val;
56
+ }
57
+ }
37
58
  },
38
59
  lock() {
39
60
  this._isLocked = true;
40
61
  },
41
62
  flush() {
42
63
  this._isLocked = false;
43
- if (this._elements.size === 0) {
64
+ if (this._elementStores.size === 0) {
44
65
  return;
45
66
  }
46
- for (const element of this._elements) {
47
- this._untrack(element);
48
- rerender(element.store.latestElement);
67
+ for (const store of this._elementStores) {
68
+ this._untrack(store);
69
+ rerender(store.latestElement);
49
70
  }
50
71
  },
51
72
  };
52
73
  export const renderingRerenderLocker = {
53
74
  _isLocked: false,
54
- _elements: new Set(),
55
- _track(element) {
56
- this._elements.add(element);
75
+ _elementStores: new Set(),
76
+ _last: undefined,
77
+ _track(store) {
78
+ if (this._elementStores.has(store)) {
79
+ return;
80
+ }
81
+ if (this._elementStores.size === 0 || store.forceRender) {
82
+ this._elementStores.add(store);
83
+ this._last = store;
84
+ return;
85
+ }
86
+ if (isParentOf(store.latestElement, this._last.latestElement)) {
87
+ return;
88
+ }
89
+ if (isParentOf(this._last.latestElement, store.latestElement)) {
90
+ this._elementStores.clear();
91
+ this._elementStores.add(store);
92
+ this._last = store;
93
+ }
57
94
  },
58
- _untrack(element) {
59
- this._elements.delete(element);
95
+ _untrack(store) {
96
+ if (this._elementStores.delete(store) && store === this._last) {
97
+ this._last = undefined;
98
+ for (const val of this._elementStores) {
99
+ this._last = val;
100
+ }
101
+ }
60
102
  },
61
103
  lock() {
62
104
  this._isLocked = true;
63
105
  },
64
106
  flush() {
65
107
  this._isLocked = false;
66
- if (this._elements.size === 0) {
108
+ if (this._elementStores.size === 0) {
67
109
  return;
68
110
  }
69
111
  queueMicrotask(() => {
70
- for (const element of this._elements) {
71
- this._untrack(element);
72
- rerender(element.store.latestElement);
112
+ for (const store of this._elementStores) {
113
+ this._untrack(store);
114
+ rerender(store.latestElement);
73
115
  }
74
116
  });
75
117
  },
76
118
  };
119
+ function isParentOf(element, parent) {
120
+ let current = element.parent;
121
+ while (current) {
122
+ if (current.store === parent.store) {
123
+ return true;
124
+ }
125
+ current = current.parent;
126
+ }
127
+ return false;
128
+ }
@@ -28,7 +28,7 @@ export function unmount(element) {
28
28
  remove(element.children, element.ref);
29
29
  return;
30
30
  }
31
- // Only FRAGMENT, PROVIDER, CONSUMER, and HOST elements remain,
31
+ // Only FRAGMENT and HOST elements remain,
32
32
  // with Maybe<Many<SimpElement>> children due to normalization.
33
33
  if (element.children) {
34
34
  unmount(element.children);
@@ -45,11 +45,11 @@ export function clearElementHostReference(element, parentHostReference) {
45
45
  return;
46
46
  }
47
47
  const children = element.children;
48
- if (element.flag === 'FC' || element.flag === 'CONSUMER') {
48
+ if (element.flag === 'FC') {
49
49
  element = children;
50
50
  continue;
51
51
  }
52
- if (element.flag === 'FRAGMENT' || element.flag === 'PROVIDER') {
52
+ if (element.flag === 'FRAGMENT') {
53
53
  if (Array.isArray(children)) {
54
54
  for (let i = 0, len = children.length; i < len; ++i) {
55
55
  clearElementHostReference(children[i], parentHostReference);
@@ -5,5 +5,14 @@ export function attachElementToDom(element, dom) {
5
5
  }
6
6
  }
7
7
  export function getElementFromDom(target) {
8
- return target?.[elementPropertyName] ?? null;
8
+ if (!target) {
9
+ return null;
10
+ }
11
+ while (target && !(elementPropertyName in target)) {
12
+ target = target.parentElement;
13
+ }
14
+ if (!target) {
15
+ return null;
16
+ }
17
+ return target[elementPropertyName];
9
18
  }
package/dom/events.d.ts CHANGED
@@ -4,15 +4,20 @@ export declare class SyntheticEvent {
4
4
  nativeEvent: Event;
5
5
  currentTarget: Nullable<EventTarget>;
6
6
  isPropagationStopped: boolean;
7
- isDefaultPrevented: boolean;
7
+ _isDefaultPrevented: boolean;
8
8
  button?: number;
9
9
  buttons?: number;
10
10
  pointerId?: number;
11
+ altKey?: boolean;
12
+ ctrlKey?: boolean;
13
+ shiftKey?: boolean;
14
+ metaKey?: boolean;
11
15
  constructor(event: Event);
12
16
  get target(): EventTarget | null;
13
17
  get type(): string;
14
18
  stopPropagation(): void;
15
19
  preventDefault(): void;
20
+ isDefaultPrevented(): boolean;
16
21
  }
17
22
  export declare function dispatchDelegatedEvent(event: Event): void;
18
23
  export declare function patchEvent(name: string, prevValue: any, nextValue: any, dom: Element): void;
package/dom/events.js CHANGED
@@ -39,15 +39,22 @@ export class SyntheticEvent {
39
39
  nativeEvent;
40
40
  currentTarget = null;
41
41
  isPropagationStopped = false;
42
- isDefaultPrevented = false;
42
+ _isDefaultPrevented = false;
43
43
  button;
44
44
  buttons;
45
45
  pointerId;
46
+ altKey;
47
+ ctrlKey;
48
+ shiftKey;
49
+ metaKey;
46
50
  constructor(event) {
47
51
  this.nativeEvent = event;
48
52
  this.button = event.button;
49
53
  this.buttons = event.buttons;
50
54
  this.pointerId = event.pointerId;
55
+ this.altKey = event.altKey;
56
+ this.ctrlKey = event.ctrlKey;
57
+ this.metaKey = event.metaKey;
51
58
  }
52
59
  get target() {
53
60
  return this.nativeEvent.target;
@@ -60,9 +67,12 @@ export class SyntheticEvent {
60
67
  this.nativeEvent.stopPropagation();
61
68
  }
62
69
  preventDefault() {
63
- this.isDefaultPrevented = true;
70
+ this._isDefaultPrevented = true;
64
71
  this.nativeEvent.preventDefault();
65
72
  }
73
+ isDefaultPrevented() {
74
+ return this._isDefaultPrevented;
75
+ }
66
76
  }
67
77
  export function dispatchDelegatedEvent(event) {
68
78
  batchingRerenderLocker.lock();
package/hooks/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { RefObject, SimpContext } from '../core/index.js';
1
+ import type { RefObject } from '../core/index.js';
2
2
 
3
3
  export type Cleanup = () => void;
4
4
  export type Effect = () => void | Cleanup;
@@ -22,8 +22,6 @@ declare function useMounted(effect: Effect): void;
22
22
 
23
23
  declare function useUnmounted(cleanup: Cleanup): void;
24
24
 
25
- declare function useContext<T>(context: SimpContext<T>): T;
26
-
27
25
  declare function useCatch(cb: (error: any) => void): void;
28
26
 
29
27
  declare function areDepsEqual(nextDeps: DependencyList | undefined, prevDeps: DependencyList | undefined): boolean;