@simpreact/simpreact 0.0.5 → 0.0.7

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 (83) hide show
  1. package/LICENSE.txt +1 -1
  2. package/compat/context.d.ts +4 -4
  3. package/compat/context.js +3 -2
  4. package/compat/core.d.ts +4 -0
  5. package/compat/core.js +9 -5
  6. package/compat/dom.d.ts +4 -5
  7. package/compat/dom.js +3 -2
  8. package/compat/hooks.d.ts +16 -13
  9. package/compat/hooks.js +19 -15
  10. package/compat/index.d.ts +12 -9
  11. package/compat/index.js +3 -0
  12. package/compat/renderRuntime.d.ts +6 -0
  13. package/compat/renderRuntime.js +17 -0
  14. package/component/index.d.ts +16 -0
  15. package/component/index.js +164 -0
  16. package/context/index.d.ts +12 -5
  17. package/context/index.js +62 -57
  18. package/core/createElement.d.ts +29 -20
  19. package/core/createElement.js +159 -133
  20. package/core/hostAdapter.d.ts +8 -12
  21. package/core/hostAdapter.js +1 -4
  22. package/core/hostOperations.d.ts +5 -0
  23. package/core/hostOperations.js +15 -0
  24. package/core/index.d.ts +20 -6
  25. package/core/internal.d.ts +5 -0
  26. package/core/internal.js +5 -0
  27. package/core/lifecycleEventBus.d.ts +15 -6
  28. package/core/lifecycleEventBus.js +16 -2
  29. package/core/memo.d.ts +0 -2
  30. package/core/memo.js +1 -3
  31. package/core/mounting.d.ts +6 -9
  32. package/core/mounting.js +177 -86
  33. package/core/mountingChildren.d.ts +4 -0
  34. package/core/mountingChildren.js +47 -0
  35. package/core/patching.d.ts +7 -8
  36. package/core/patching.js +245 -252
  37. package/core/patchingChildren.d.ts +6 -0
  38. package/core/patchingChildren.js +343 -0
  39. package/core/portal.d.ts +1 -1
  40. package/core/portal.js +17 -7
  41. package/core/processStack.d.ts +106 -0
  42. package/core/processStack.js +75 -0
  43. package/core/ref.d.ts +4 -3
  44. package/core/rerender.d.ts +4 -14
  45. package/core/rerender.js +67 -112
  46. package/core/runtime.d.ts +17 -0
  47. package/core/runtime.js +2 -0
  48. package/core/unmounting.d.ts +6 -5
  49. package/core/unmounting.js +58 -57
  50. package/core/unmountingChildren.d.ts +4 -0
  51. package/core/unmountingChildren.js +23 -0
  52. package/core/utils.d.ts +11 -0
  53. package/core/utils.js +168 -0
  54. package/dom/attach-element-to-dom.d.ts +4 -3
  55. package/dom/attach-element-to-dom.js +12 -7
  56. package/dom/domAdapter.js +22 -25
  57. package/dom/events.d.ts +5 -5
  58. package/dom/events.js +33 -16
  59. package/dom/index.d.ts +16 -5
  60. package/dom/index.js +4 -3
  61. package/dom/props/controlled/index.d.ts +3 -3
  62. package/dom/props/controlled/index.js +8 -8
  63. package/dom/props/controlled/input.d.ts +3 -3
  64. package/dom/props/controlled/input.js +57 -34
  65. package/dom/props/controlled/select.d.ts +3 -3
  66. package/dom/props/controlled/select.js +39 -26
  67. package/dom/props/controlled/textarea.d.ts +3 -3
  68. package/dom/props/controlled/textarea.js +57 -34
  69. package/dom/props/dangerInnerHTML.d.ts +5 -5
  70. package/dom/props/dangerInnerHTML.js +10 -15
  71. package/dom/props/props.d.ts +4 -4
  72. package/dom/props/props.js +24 -21
  73. package/dom/render.d.ts +4 -5
  74. package/dom/render.js +38 -34
  75. package/hooks/index.d.ts +15 -13
  76. package/hooks/index.js +154 -157
  77. package/jsx-runtime/index.d.ts +2 -1
  78. package/package.json +9 -1
  79. package/shared/index.d.ts +10 -0
  80. package/shared/index.js +4 -7
  81. package/shared/utils.js +4 -4
  82. package/shared/EventBus.d.ts +0 -18
  83. package/shared/EventBus.js +0 -28
package/dom/domAdapter.js CHANGED
@@ -1,6 +1,6 @@
1
- import { attachElementToDom } from './attach-element-to-dom.js';
2
- import { mountProps, patchProps, unmountProps } from './props/index.js';
1
+ import { attachElementToDom, detachElementFromDom, getElementFromDom } from './attach-element-to-dom.js';
3
2
  import { defaultNamespace } from './namespace.js';
3
+ import { mountProps, patchProps, unmountProps } from './props/index.js';
4
4
  export const domAdapter = {
5
5
  createReference(type, namespace) {
6
6
  if (namespace) {
@@ -13,14 +13,14 @@ export const domAdapter = {
13
13
  createTextReference(text) {
14
14
  return document.createTextNode(text);
15
15
  },
16
- mountProps(dom, element, namespace) {
17
- mountProps(dom, element, namespace || defaultNamespace);
16
+ mountProps(dom, element, renderRuntime, namespace) {
17
+ mountProps(dom, element, namespace || defaultNamespace, renderRuntime);
18
18
  },
19
- patchProps(dom, prevElement, nextElement, namespace) {
20
- patchProps(dom, prevElement, nextElement, namespace || defaultNamespace);
19
+ patchProps(dom, prevElement, nextElement, renderRuntime, namespace) {
20
+ patchProps(dom, prevElement, nextElement, namespace || defaultNamespace, renderRuntime);
21
21
  },
22
- unmountProps(dom, element) {
23
- unmountProps(dom, element);
22
+ unmountProps(dom, element, renderRuntime) {
23
+ unmountProps(dom, element, renderRuntime);
24
24
  },
25
25
  setClassname(reference, className, namespace) {
26
26
  if (!className) {
@@ -41,18 +41,12 @@ export const domAdapter = {
41
41
  reference.textContent = text;
42
42
  }
43
43
  },
44
- appendChild(parent, child) {
45
- parent.appendChild(child);
46
- },
47
- insertBefore(parent, child, before) {
48
- parent.insertBefore(child, before);
49
- },
50
44
  insertOrAppend(parent, child, before) {
51
45
  if (before) {
52
- domAdapter.insertBefore(parent, child, before);
46
+ parent.insertBefore(child, before);
53
47
  }
54
48
  else {
55
- domAdapter.appendChild(parent, child);
49
+ parent.appendChild(child);
56
50
  }
57
51
  },
58
52
  removeChild(parent, child) {
@@ -61,21 +55,24 @@ export const domAdapter = {
61
55
  replaceChild(parent, replacer, toBeReplaced) {
62
56
  parent.replaceChild(replacer, toBeReplaced);
63
57
  },
64
- findParentReference(reference) {
65
- return reference.parentElement;
66
- },
67
- findNextSiblingReference(reference) {
68
- return reference.nextSibling;
69
- },
70
58
  clearNode(reference) {
71
59
  reference.textContent = '';
72
60
  },
73
- attachElementToReference(element, reference) {
74
- attachElementToDom(element, reference);
61
+ attachElementToReference(element, reference, renderRuntime) {
62
+ attachElementToDom(element, reference, renderRuntime);
63
+ },
64
+ getElementFromReference(reference, renderRuntime) {
65
+ return getElementFromDom(reference, renderRuntime);
66
+ },
67
+ detachElementFromReference(reference, renderRuntime) {
68
+ detachElementFromDom(reference, renderRuntime);
75
69
  },
76
70
  getHostNamespaces(element, currentNamespace) {
77
71
  if (element.type === 'svg') {
78
- return { self: 'http://www.w3.org/2000/svg', children: 'http://www.w3.org/2000/svg' };
72
+ return {
73
+ self: 'http://www.w3.org/2000/svg',
74
+ children: 'http://www.w3.org/2000/svg',
75
+ };
79
76
  }
80
77
  if (element.type === 'foreignObject') {
81
78
  return { self: 'http://www.w3.org/2000/svg', children: null };
package/dom/events.d.ts CHANGED
@@ -1,5 +1,6 @@
1
+ import { type SimpRenderRuntime } from '../core/internal.js';
1
2
  import type { Nullable } from '../shared/index.js';
2
- type DelegatedEventType = 'click' | 'dblclick' | 'mousedown' | 'mouseup' | 'mousemove' | 'pointerdown' | 'pointerup' | 'pointermove' | 'touchstart' | 'touchmove' | 'touchend' | 'keydown' | 'keyup' | 'focusin' | 'focusout';
3
+ export type DelegatedEventType = 'click' | 'dblclick' | 'mousedown' | 'mouseup' | 'mousemove' | 'pointerdown' | 'pointerup' | 'pointermove' | 'touchstart' | 'touchmove' | 'touchend' | 'keydown' | 'keyup' | 'focusin' | 'focusout';
3
4
  export declare class SyntheticEvent {
4
5
  nativeEvent: Event;
5
6
  currentTarget: Nullable<EventTarget>;
@@ -19,9 +20,8 @@ export declare class SyntheticEvent {
19
20
  preventDefault(): void;
20
21
  isDefaultPrevented(): boolean;
21
22
  }
22
- export declare function dispatchDelegatedEvent(event: Event): void;
23
- export declare function patchEvent(name: string, prevValue: any, nextValue: any, dom: Element): void;
24
- export declare function patchDelegatedEvent(eventType: DelegatedEventType, handler: any, eventHandlerCounts: Record<DelegatedEventType, number>): void;
23
+ export declare function dispatchDelegatedEvent(event: Event, renderRuntime: SimpRenderRuntime): void;
24
+ export declare function patchEvent(name: string, prevValue: any, nextValue: any, dom: Element, renderRuntime: SimpRenderRuntime): void;
25
+ export declare function patchDelegatedEvent(eventType: DelegatedEventType, prevHandler: any, nextHandler: any, eventHandlerCounts: Record<DelegatedEventType, number>, renderRuntime: SimpRenderRuntime): void;
25
26
  export declare function patchNormalEvent(eventType: string, prevValue: any, nextValue: any, dom: Element, capture: boolean): void;
26
27
  export declare function isPropNameEventName(name: string): boolean;
27
- export {};
package/dom/events.js CHANGED
@@ -1,5 +1,4 @@
1
- import { batchingRerenderLocker } from '../core/internal.js';
2
- import { getElementFromDom } from './attach-element-to-dom.js';
1
+ import { SIMP_ELEMENT_FLAG_HOST } from '../core/internal.js';
3
2
  const eventNameByTypes = {
4
3
  click: 'onClick',
5
4
  dblclick: 'onDblClick',
@@ -18,7 +17,7 @@ const eventNameByTypes = {
18
17
  focusout: 'onFocusOut',
19
18
  };
20
19
  const delegatedEventTypes = new Set(Object.keys(eventNameByTypes));
21
- const eventHandlerCounts = {
20
+ const createEventHandlerCounts = () => ({
22
21
  click: 0,
23
22
  dblclick: 0,
24
23
  mousedown: 0,
@@ -34,7 +33,25 @@ const eventHandlerCounts = {
34
33
  keyup: 0,
35
34
  focusin: 0,
36
35
  focusout: 0,
37
- };
36
+ });
37
+ const eventHandlerCountsByRuntime = new WeakMap();
38
+ const delegatedEventDispatchersByRuntime = new WeakMap();
39
+ function getEventHandlerCounts(renderRuntime) {
40
+ let eventHandlerCounts = eventHandlerCountsByRuntime.get(renderRuntime);
41
+ if (!eventHandlerCounts) {
42
+ eventHandlerCounts = createEventHandlerCounts();
43
+ eventHandlerCountsByRuntime.set(renderRuntime, eventHandlerCounts);
44
+ }
45
+ return eventHandlerCounts;
46
+ }
47
+ function getDelegatedEventDispatcher(renderRuntime) {
48
+ let dispatcher = delegatedEventDispatchersByRuntime.get(renderRuntime);
49
+ if (!dispatcher) {
50
+ dispatcher = event => dispatchDelegatedEvent(event, renderRuntime);
51
+ delegatedEventDispatchersByRuntime.set(renderRuntime, dispatcher);
52
+ }
53
+ return dispatcher;
54
+ }
38
55
  export class SyntheticEvent {
39
56
  nativeEvent;
40
57
  currentTarget = null;
@@ -74,14 +91,13 @@ export class SyntheticEvent {
74
91
  return this._isDefaultPrevented;
75
92
  }
76
93
  }
77
- export function dispatchDelegatedEvent(event) {
78
- batchingRerenderLocker.lock();
94
+ export function dispatchDelegatedEvent(event, renderRuntime) {
79
95
  const syntheticEvent = new SyntheticEvent(event);
80
96
  const captureHandlers = [];
81
97
  const bubbleHandlers = [];
82
- let element = getElementFromDom(event.target);
98
+ let element = renderRuntime.hostAdapter.getElementFromReference(event.target, renderRuntime);
83
99
  while (element) {
84
- if (element.flag === 'HOST') {
100
+ if ((element.flag & SIMP_ELEMENT_FLAG_HOST) !== 0) {
85
101
  const captureHandler = element.props?.[eventNameByTypes[event.type] + 'Capture'];
86
102
  const bubbleHandler = element.props?.[eventNameByTypes[event.type]];
87
103
  if (captureHandler) {
@@ -107,28 +123,29 @@ export function dispatchDelegatedEvent(event) {
107
123
  return;
108
124
  }
109
125
  }
110
- batchingRerenderLocker.flush();
111
126
  }
112
127
  const captureRegex = /Capture/;
113
- export function patchEvent(name, prevValue, nextValue, dom) {
128
+ export function patchEvent(name, prevValue, nextValue, dom, renderRuntime) {
114
129
  const isCapture = captureRegex.test(name);
115
130
  name = name.replace(captureRegex, '').substring(2).toLowerCase();
116
131
  if (delegatedEventTypes.has(name)) {
117
- patchDelegatedEvent(name, nextValue, eventHandlerCounts);
132
+ patchDelegatedEvent(name, prevValue, nextValue, getEventHandlerCounts(renderRuntime), renderRuntime);
118
133
  }
119
134
  else {
120
135
  patchNormalEvent(name, prevValue, nextValue, dom, isCapture);
121
136
  }
122
137
  }
123
- export function patchDelegatedEvent(eventType, handler, eventHandlerCounts) {
124
- if (typeof handler === 'function') {
138
+ export function patchDelegatedEvent(eventType, prevHandler, nextHandler, eventHandlerCounts, renderRuntime) {
139
+ const dispatcher = getDelegatedEventDispatcher(renderRuntime);
140
+ if (typeof prevHandler !== 'function' && typeof nextHandler === 'function') {
125
141
  if (++eventHandlerCounts[eventType] === 1) {
126
- document.addEventListener(eventType, dispatchDelegatedEvent);
142
+ document.addEventListener(eventType, dispatcher);
127
143
  }
144
+ return;
128
145
  }
129
- else {
146
+ if (typeof prevHandler === 'function' && typeof nextHandler !== 'function') {
130
147
  if (eventHandlerCounts[eventType] !== 0 && --eventHandlerCounts[eventType] === 0) {
131
- document.removeEventListener(eventType, dispatchDelegatedEvent);
148
+ document.removeEventListener(eventType, dispatcher);
132
149
  }
133
150
  }
134
151
  }
package/dom/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- import type { RefAttributes, SimpElement, SimpNode } from '../core/index.js';
1
+ import type { RefAttributes, SimpElement, SimpNode, SimpRenderRuntime } from '../core/index.js';
2
+ import type { HostAdapter } from '../core/internal.js';
2
3
  import type { Nullable } from '../shared/index.js';
3
4
 
4
5
  import type { PropertiesHyphen } from 'csstype';
@@ -16,9 +17,15 @@ export interface SimpRoot {
16
17
  unmount(): void;
17
18
  }
18
19
 
19
- declare function createRoot(container: Element | DocumentFragment): SimpRoot;
20
+ declare function createCreateRoot(
21
+ renderRuntime: SimpRenderRuntime
22
+ ): (container: Element | DocumentFragment) => SimpRoot;
20
23
 
21
- declare function render(element: SimpElement, parentReference: Nullable<HTMLElement>): void;
24
+ declare function createRenderer(
25
+ renderRuntime: SimpRenderRuntime
26
+ ): (element: SimpElement, parentReference: Nullable<HTMLElement>) => void;
27
+
28
+ declare const domAdapter: HostAdapter;
22
29
 
23
30
  export interface SimpReactHTMLElement<T extends HTMLElement>
24
31
  extends DetailedSimpReactHTMLElement<AllHTMLAttributes<T>, T> {}
@@ -227,8 +234,12 @@ export interface SyntheticEvent<C = Element, E = Event> {
227
234
  stopPropagation(): void;
228
235
  }
229
236
 
230
- export type EventHandler<E extends SyntheticEvent<any>> = { bivarianceHack(event: E): void }['bivarianceHack'];
231
- export type NativeEventHandler<E extends Event = Event> = { bivarianceHack(event: E): void }['bivarianceHack'];
237
+ export type EventHandler<E extends SyntheticEvent<any>> = {
238
+ bivarianceHack(event: E): void;
239
+ }['bivarianceHack'];
240
+ export type NativeEventHandler<E extends Event = Event> = {
241
+ bivarianceHack(event: E): void;
242
+ }['bivarianceHack'];
232
243
 
233
244
  export type ClipboardEventHandler = NativeEventHandler<ClipboardEvent>;
234
245
  export type CompositionEventHandler = NativeEventHandler<CompositionEvent>;
package/dom/index.js CHANGED
@@ -1,3 +1,4 @@
1
- import { createRoot, render } from './render.js';
2
- export { createRoot, render } from './render.js';
3
- export default { createRoot, render };
1
+ import { domAdapter } from './domAdapter.js';
2
+ import { createCreateRoot, createRenderer } from './render.js';
3
+ export { createCreateRoot, createRenderer, domAdapter };
4
+ export default { createCreateRoot, createRenderer, domAdapter };
@@ -1,7 +1,7 @@
1
- import type { SimpElement } from '../../../core/internal.js';
1
+ import type { SimpElement, SimpRenderRuntime } from '../../../core/internal.js';
2
2
  import type { Dict } from '../../../shared/index.js';
3
3
  export declare function isEventNameIgnored(element: SimpElement, eventName: string): boolean;
4
4
  export declare function isFormElementControlled(props: Dict): boolean;
5
- export declare function addControlledFormElementEventHandlers(element: SimpElement): void;
6
- export declare function removeControlledFormElementEventHandlers(element: SimpElement): void;
5
+ export declare function addControlledFormElementEventHandlers(element: SimpElement, renderRuntime: SimpRenderRuntime): void;
6
+ export declare function removeControlledFormElementEventHandlers(element: SimpElement, renderRuntime: SimpRenderRuntime): void;
7
7
  export declare function syncControlledFormElementPropsWithAttrs(element: SimpElement, props: Dict, mounting?: boolean): void;
@@ -16,26 +16,26 @@ export function isEventNameIgnored(element, eventName) {
16
16
  export function isFormElementControlled(props) {
17
17
  return props.value != null || props.checked != null;
18
18
  }
19
- export function addControlledFormElementEventHandlers(element) {
19
+ export function addControlledFormElementEventHandlers(element, renderRuntime) {
20
20
  if (element.type === 'input') {
21
- addControlledInputEventHandlers(element.reference);
21
+ addControlledInputEventHandlers(element.reference, renderRuntime);
22
22
  }
23
23
  else if (element.type === 'select') {
24
- addControlledSelectEventHandlers(element.reference);
24
+ addControlledSelectEventHandlers(element.reference, renderRuntime);
25
25
  }
26
26
  else if (element.type === 'textarea') {
27
- addControlledTextareaEventHandlers(element.reference);
27
+ addControlledTextareaEventHandlers(element.reference, renderRuntime);
28
28
  }
29
29
  }
30
- export function removeControlledFormElementEventHandlers(element) {
30
+ export function removeControlledFormElementEventHandlers(element, renderRuntime) {
31
31
  if (element.type === 'input') {
32
- removeControlledInputEventHandlers(element.reference);
32
+ removeControlledInputEventHandlers(element.reference, renderRuntime);
33
33
  }
34
34
  else if (element.type === 'select') {
35
- removeControlledSelectEventHandlers(element.reference);
35
+ removeControlledSelectEventHandlers(element.reference, renderRuntime);
36
36
  }
37
37
  else if (element.type === 'textarea') {
38
- removeControlledTextareaEventHandlers(element.reference);
38
+ removeControlledTextareaEventHandlers(element.reference, renderRuntime);
39
39
  }
40
40
  }
41
41
  export function syncControlledFormElementPropsWithAttrs(element, props, mounting = false) {
@@ -1,7 +1,7 @@
1
- import type { SimpElement } from '../../../core/internal.js';
1
+ import type { SimpElement, SimpRenderRuntime } from '../../../core/internal.js';
2
2
  import type { Dict } from '../../../shared/index.js';
3
3
  export declare function isCheckedType(type: string): boolean;
4
4
  export declare function isEventNameIgnored(props: Dict, eventName: string): boolean;
5
- export declare function addControlledInputEventHandlers(dom: HTMLInputElement): void;
6
- export declare function removeControlledInputEventHandlers(dom: HTMLInputElement): void;
5
+ export declare function addControlledInputEventHandlers(dom: HTMLInputElement, renderRuntime: SimpRenderRuntime): void;
6
+ export declare function removeControlledInputEventHandlers(dom: HTMLInputElement, renderRuntime: SimpRenderRuntime): void;
7
7
  export declare function syncControlledInputProps(element: SimpElement, props: Dict): void;
@@ -1,55 +1,78 @@
1
- import { batchingRerenderLocker } from '../../../core/internal.js';
2
- import { getElementFromDom } from '../../attach-element-to-dom.js';
1
+ import { withSyncRerender } from '../../../core/internal.js';
3
2
  export function isCheckedType(type) {
4
3
  return type === 'checkbox' || type === 'radio';
5
4
  }
6
5
  export function isEventNameIgnored(props, eventName) {
7
6
  return isCheckedType(props.type) ? eventName === 'onChange' : eventName === 'onInput';
8
7
  }
9
- function onControlledInputInput(event) {
10
- let element = getElementFromDom(event.target);
11
- if (!element || !element.props) {
12
- return;
13
- }
14
- if (element.props['onInput']) {
15
- batchingRerenderLocker.lock();
16
- element.props['onInput'](event);
17
- batchingRerenderLocker.flush();
18
- element = getElementFromDom(event.target);
19
- }
20
- if (element) {
21
- syncControlledInputProps(element, element.props);
22
- }
8
+ function createControlledInputInputHandler(renderRuntime) {
9
+ return event => {
10
+ let element = renderRuntime.hostAdapter.getElementFromReference(event.target, renderRuntime);
11
+ if (!element || !element.props) {
12
+ return;
13
+ }
14
+ const onInput = element.props['onInput'];
15
+ if (onInput) {
16
+ withSyncRerender(renderRuntime, () => {
17
+ onInput(event);
18
+ });
19
+ element = renderRuntime.hostAdapter.getElementFromReference(event.target, renderRuntime);
20
+ }
21
+ if (element) {
22
+ syncControlledInputProps(element, element.props);
23
+ }
24
+ };
23
25
  }
24
- function onControlledInputChange(event) {
25
- let element = getElementFromDom(event.target);
26
- if (!element || !element.props) {
27
- return;
26
+ const controlledInputInputHandlersByRuntime = new WeakMap();
27
+ function getControlledInputInputHandler(renderRuntime) {
28
+ let handler = controlledInputInputHandlersByRuntime.get(renderRuntime);
29
+ if (!handler) {
30
+ handler = createControlledInputInputHandler(renderRuntime);
31
+ controlledInputInputHandlersByRuntime.set(renderRuntime, handler);
28
32
  }
29
- if (element.props['onChange']) {
30
- batchingRerenderLocker.lock();
31
- element.props['onChange'](event);
32
- batchingRerenderLocker.flush();
33
- element = getElementFromDom(event.target);
34
- }
35
- if (element) {
36
- syncControlledInputProps(element, element.props);
33
+ return handler;
34
+ }
35
+ function createControlledInputChangeHandler(renderRuntime) {
36
+ return event => {
37
+ let element = renderRuntime.hostAdapter.getElementFromReference(event.target, renderRuntime);
38
+ if (!element || !element.props) {
39
+ return;
40
+ }
41
+ const onChange = element.props['onChange'];
42
+ if (onChange) {
43
+ withSyncRerender(renderRuntime, () => {
44
+ onChange(event);
45
+ });
46
+ element = renderRuntime.hostAdapter.getElementFromReference(event.target, renderRuntime);
47
+ }
48
+ if (element) {
49
+ syncControlledInputProps(element, element.props);
50
+ }
51
+ };
52
+ }
53
+ const controlledInputChangeHandlersByRuntime = new WeakMap();
54
+ function getControlledInputChangeHandler(renderRuntime) {
55
+ let handler = controlledInputChangeHandlersByRuntime.get(renderRuntime);
56
+ if (!handler) {
57
+ handler = createControlledInputChangeHandler(renderRuntime);
58
+ controlledInputChangeHandlersByRuntime.set(renderRuntime, handler);
37
59
  }
60
+ return handler;
38
61
  }
39
- export function addControlledInputEventHandlers(dom) {
62
+ export function addControlledInputEventHandlers(dom, renderRuntime) {
40
63
  if (isCheckedType(dom.type)) {
41
- dom.addEventListener('change', onControlledInputChange);
64
+ dom.addEventListener('change', getControlledInputChangeHandler(renderRuntime));
42
65
  }
43
66
  else {
44
- dom.addEventListener('input', onControlledInputInput);
67
+ dom.addEventListener('input', getControlledInputInputHandler(renderRuntime));
45
68
  }
46
69
  }
47
- export function removeControlledInputEventHandlers(dom) {
70
+ export function removeControlledInputEventHandlers(dom, renderRuntime) {
48
71
  if (isCheckedType(dom.type)) {
49
- dom.removeEventListener('change', onControlledInputChange);
72
+ dom.removeEventListener('change', getControlledInputChangeHandler(renderRuntime));
50
73
  }
51
74
  else {
52
- dom.removeEventListener('input', onControlledInputInput);
75
+ dom.removeEventListener('input', getControlledInputInputHandler(renderRuntime));
53
76
  }
54
77
  }
55
78
  export function syncControlledInputProps(element, props) {
@@ -1,6 +1,6 @@
1
- import type { SimpElement } from '../../../core/internal.js';
1
+ import type { SimpElement, SimpRenderRuntime } from '../../../core/internal.js';
2
2
  import type { Dict } from '../../../shared/index.js';
3
3
  export declare function isEventNameIgnored(eventName: string): boolean;
4
- export declare function addControlledSelectEventHandlers(dom: HTMLSelectElement): void;
5
- export declare function removeControlledSelectEventHandlers(dom: HTMLSelectElement): void;
4
+ export declare function addControlledSelectEventHandlers(dom: HTMLSelectElement, renderRuntime: SimpRenderRuntime): void;
5
+ export declare function removeControlledSelectEventHandlers(dom: HTMLSelectElement, renderRuntime: SimpRenderRuntime): void;
6
6
  export declare function syncControlledSelectProps(element: SimpElement, props: Dict, mounting?: boolean): void;
@@ -1,29 +1,40 @@
1
- import { batchingRerenderLocker } from '../../../core/internal.js';
1
+ import { SIMP_ELEMENT_CHILD_FLAG_ELEMENT, SIMP_ELEMENT_CHILD_FLAG_LIST, withSyncRerender } from '../../../core/internal.js';
2
2
  import { emptyObject } from '../../../shared/index.js';
3
- import { getElementFromDom } from '../../attach-element-to-dom.js';
4
3
  export function isEventNameIgnored(eventName) {
5
4
  return eventName === 'onChange';
6
5
  }
7
- function onControlledInputChange(event) {
8
- let element = getElementFromDom(event.target);
9
- if (!element || !element.props) {
10
- return;
11
- }
12
- if (element.props['onChange']) {
13
- batchingRerenderLocker.lock();
14
- element.props['onChange'](event);
15
- batchingRerenderLocker.flush();
16
- element = getElementFromDom(event.target);
17
- }
18
- if (element) {
19
- syncControlledSelectProps(element, element.props);
6
+ function createControlledInputChangeHandler(renderRuntime) {
7
+ return (event) => {
8
+ let element = renderRuntime.hostAdapter.getElementFromReference(event.target, renderRuntime);
9
+ if (!element || !element.props) {
10
+ return;
11
+ }
12
+ const onChange = element.props['onChange'];
13
+ if (onChange) {
14
+ withSyncRerender(renderRuntime, () => {
15
+ onChange(event);
16
+ });
17
+ element = renderRuntime.hostAdapter.getElementFromReference(event.target, renderRuntime);
18
+ }
19
+ if (element) {
20
+ syncControlledSelectProps(element, element.props);
21
+ }
22
+ };
23
+ }
24
+ const controlledSelectChangeHandlersByRuntime = new WeakMap();
25
+ function getControlledSelectChangeHandler(renderRuntime) {
26
+ let handler = controlledSelectChangeHandlersByRuntime.get(renderRuntime);
27
+ if (!handler) {
28
+ handler = createControlledInputChangeHandler(renderRuntime);
29
+ controlledSelectChangeHandlersByRuntime.set(renderRuntime, handler);
20
30
  }
31
+ return handler;
21
32
  }
22
- export function addControlledSelectEventHandlers(dom) {
23
- dom.addEventListener('change', onControlledInputChange);
33
+ export function addControlledSelectEventHandlers(dom, renderRuntime) {
34
+ dom.addEventListener('change', getControlledSelectChangeHandler(renderRuntime));
24
35
  }
25
- export function removeControlledSelectEventHandlers(dom) {
26
- dom.removeEventListener('change', onControlledInputChange);
36
+ export function removeControlledSelectEventHandlers(dom, renderRuntime) {
37
+ dom.removeEventListener('change', getControlledSelectChangeHandler(renderRuntime));
27
38
  }
28
39
  export function syncControlledSelectProps(element, props, mounting = false) {
29
40
  const multiple = Boolean(props.multiple);
@@ -50,13 +61,15 @@ function updateOptions(element, value) {
50
61
  return;
51
62
  }
52
63
  const children = element.children;
53
- if (Array.isArray(children)) {
54
- for (let i = 0, len = children.length; i < len; ++i) {
55
- updateOptions(children[i], value);
56
- }
57
- }
58
- else if (children) {
59
- updateOptions(children, value);
64
+ const childFlag = element.childFlag;
65
+ switch (childFlag) {
66
+ case SIMP_ELEMENT_CHILD_FLAG_LIST:
67
+ for (let i = 0, len = children.length; i < len; ++i) {
68
+ updateOptions(children[i], value);
69
+ }
70
+ break;
71
+ case SIMP_ELEMENT_CHILD_FLAG_ELEMENT:
72
+ updateOptions(children, value);
60
73
  }
61
74
  }
62
75
  function updateOption(element, value) {
@@ -1,6 +1,6 @@
1
- import type { SimpElement } from '../../../core/internal.js';
1
+ import type { SimpElement, SimpRenderRuntime } from '../../../core/internal.js';
2
2
  import type { Dict } from '../../../shared/index.js';
3
3
  export declare function isEventNameIgnored(eventName: string): boolean;
4
- export declare function addControlledTextareaEventHandlers(dom: HTMLTextAreaElement): void;
5
- export declare function removeControlledTextareaEventHandlers(dom: HTMLTextAreaElement): void;
4
+ export declare function addControlledTextareaEventHandlers(dom: HTMLTextAreaElement, renderRuntime: SimpRenderRuntime): void;
5
+ export declare function removeControlledTextareaEventHandlers(dom: HTMLTextAreaElement, renderRuntime: SimpRenderRuntime): void;
6
6
  export declare function syncControlledTextareaProps(element: SimpElement, props: Dict, mounting?: boolean): void;
@@ -1,45 +1,68 @@
1
- import { batchingRerenderLocker } from '../../../core/internal.js';
2
- import { getElementFromDom } from '../../attach-element-to-dom.js';
1
+ import { withSyncRerender } from '../../../core/internal.js';
3
2
  export function isEventNameIgnored(eventName) {
4
3
  return eventName === 'onChange' || eventName === 'onInput';
5
4
  }
6
- function onControlledTextareaChange(event) {
7
- let element = getElementFromDom(event.target);
8
- if (!element || !element.props) {
9
- return;
10
- }
11
- if (element.props['onChange']) {
12
- batchingRerenderLocker.lock();
13
- element.props['onChange'](event);
14
- batchingRerenderLocker.flush();
15
- element = getElementFromDom(event.target);
16
- }
17
- if (element) {
18
- syncControlledTextareaProps(element, element.props);
19
- }
5
+ function createControlledTextareaChangeHandler(renderRuntime) {
6
+ return (event) => {
7
+ let element = renderRuntime.hostAdapter.getElementFromReference(event.target, renderRuntime);
8
+ if (!element || !element.props) {
9
+ return;
10
+ }
11
+ const onChange = element.props['onChange'];
12
+ if (onChange) {
13
+ withSyncRerender(renderRuntime, () => {
14
+ onChange(event);
15
+ });
16
+ element = renderRuntime.hostAdapter.getElementFromReference(event.target, renderRuntime);
17
+ }
18
+ if (element) {
19
+ syncControlledTextareaProps(element, element.props);
20
+ }
21
+ };
20
22
  }
21
- function onControlledTextareaInput(event) {
22
- let element = getElementFromDom(event.target);
23
- if (!element || !element.props) {
24
- return;
23
+ const controlledTextareaChangeHandlersByRuntime = new WeakMap();
24
+ function getControlledTextareaChangeHandler(renderRuntime) {
25
+ let handler = controlledTextareaChangeHandlersByRuntime.get(renderRuntime);
26
+ if (!handler) {
27
+ handler = createControlledTextareaChangeHandler(renderRuntime);
28
+ controlledTextareaChangeHandlersByRuntime.set(renderRuntime, handler);
25
29
  }
26
- if (element.props['onInput']) {
27
- batchingRerenderLocker.lock();
28
- element.props['onInput'](event);
29
- batchingRerenderLocker.flush();
30
- element = getElementFromDom(event.target);
31
- }
32
- if (element) {
33
- syncControlledTextareaProps(element, element.props);
30
+ return handler;
31
+ }
32
+ function createControlledTextareaInputHandler(renderRuntime) {
33
+ return event => {
34
+ let element = renderRuntime.hostAdapter.getElementFromReference(event.target, renderRuntime);
35
+ if (!element || !element.props) {
36
+ return;
37
+ }
38
+ const onInput = element.props['onInput'];
39
+ if (onInput) {
40
+ withSyncRerender(renderRuntime, () => {
41
+ onInput(event);
42
+ });
43
+ element = renderRuntime.hostAdapter.getElementFromReference(event.target, renderRuntime);
44
+ }
45
+ if (element) {
46
+ syncControlledTextareaProps(element, element.props);
47
+ }
48
+ };
49
+ }
50
+ const controlledTextareaInputHandlersByRuntime = new WeakMap();
51
+ function getControlledTextareaInputHandler(renderRuntime) {
52
+ let handler = controlledTextareaInputHandlersByRuntime.get(renderRuntime);
53
+ if (!handler) {
54
+ handler = createControlledTextareaInputHandler(renderRuntime);
55
+ controlledTextareaInputHandlersByRuntime.set(renderRuntime, handler);
34
56
  }
57
+ return handler;
35
58
  }
36
- export function addControlledTextareaEventHandlers(dom) {
37
- dom.addEventListener('input', onControlledTextareaInput);
38
- dom.addEventListener('change', onControlledTextareaChange);
59
+ export function addControlledTextareaEventHandlers(dom, renderRuntime) {
60
+ dom.addEventListener('input', getControlledTextareaInputHandler(renderRuntime));
61
+ dom.addEventListener('change', getControlledTextareaChangeHandler(renderRuntime));
39
62
  }
40
- export function removeControlledTextareaEventHandlers(dom) {
41
- dom.removeEventListener('input', onControlledTextareaInput);
42
- dom.removeEventListener('change', onControlledTextareaChange);
63
+ export function removeControlledTextareaEventHandlers(dom, renderRuntime) {
64
+ dom.removeEventListener('input', getControlledTextareaInputHandler(renderRuntime));
65
+ dom.removeEventListener('change', getControlledTextareaChangeHandler(renderRuntime));
43
66
  }
44
67
  export function syncControlledTextareaProps(element, props, mounting = false) {
45
68
  const dom = element.reference;