@simpreact/simpreact 0.0.0-alpha.dd6f145 → 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 (71) hide show
  1. package/core/context.d.ts +18 -0
  2. package/core/context.js +18 -0
  3. package/core/createElement.d.ts +24 -15
  4. package/core/createElement.js +93 -27
  5. package/core/fragment.js +1 -2
  6. package/core/hostAdapter.d.ts +19 -8
  7. package/core/hostAdapter.js +4 -1
  8. package/core/index.d.ts +68 -2
  9. package/core/index.js +6 -2
  10. package/core/internal.d.ts +7 -3
  11. package/core/internal.js +7 -3
  12. package/core/lifecycleEventBus.d.ts +26 -0
  13. package/core/lifecycleEventBus.js +2 -0
  14. package/core/mounting.d.ts +11 -7
  15. package/core/mounting.js +104 -38
  16. package/core/patching.d.ts +8 -5
  17. package/core/patching.js +157 -161
  18. package/core/portal.d.ts +2 -0
  19. package/core/portal.js +9 -0
  20. package/core/ref.d.ts +17 -0
  21. package/core/ref.js +27 -0
  22. package/core/rerender.d.ts +11 -0
  23. package/core/rerender.js +61 -3
  24. package/core/unmounting.d.ts +4 -6
  25. package/core/unmounting.js +33 -39
  26. package/dom/attach-element-to-dom.d.ts +4 -0
  27. package/dom/attach-element-to-dom.js +9 -0
  28. package/dom/domAdapter.d.ts +3 -2
  29. package/dom/domAdapter.js +42 -115
  30. package/dom/events.d.ts +19 -0
  31. package/dom/events.js +129 -0
  32. package/dom/index.d.ts +1733 -1
  33. package/dom/index.js +2 -0
  34. package/dom/namespace.d.ts +2 -0
  35. package/dom/namespace.js +1 -0
  36. package/dom/props/controlled/index.d.ts +7 -0
  37. package/dom/props/controlled/index.js +51 -0
  38. package/dom/props/controlled/input.d.ts +7 -0
  39. package/dom/props/controlled/input.js +80 -0
  40. package/dom/props/controlled/select.d.ts +6 -0
  41. package/dom/props/controlled/select.js +76 -0
  42. package/dom/props/controlled/textarea.d.ts +6 -0
  43. package/dom/props/controlled/textarea.js +61 -0
  44. package/dom/props/dangerInnerHTML.d.ts +7 -0
  45. package/dom/props/dangerInnerHTML.js +24 -0
  46. package/dom/props/index.d.ts +1 -0
  47. package/dom/props/index.js +1 -0
  48. package/dom/props/props.d.ts +5 -0
  49. package/dom/props/props.js +197 -0
  50. package/dom/props/style.d.ts +1 -0
  51. package/dom/props/style.js +32 -0
  52. package/dom/render.d.ts +3 -3
  53. package/dom/render.js +31 -17
  54. package/hooks/index.d.ts +23 -10
  55. package/hooks/index.js +126 -32
  56. package/jsx-runtime/index.d.ts +247 -4
  57. package/jsx-runtime/index.js +3 -6
  58. package/package.json +22 -15
  59. package/shared/EventBus.js +1 -3
  60. package/shared/index.d.ts +19 -4
  61. package/shared/index.js +5 -4
  62. package/shared/lang.d.ts +3 -4
  63. package/shared/lang.js +3 -4
  64. package/shared/utils.d.ts +3 -3
  65. package/shared/utils.js +3 -7
  66. package/core/global.d.ts +0 -21
  67. package/core/global.js +0 -5
  68. package/core/jsx-runtime.d.ts +0 -2
  69. package/core/jsx-runtime.js +0 -2
  70. package/shared/types.d.ts +0 -8
  71. package/shared/types.js +0 -1
package/core/ref.js ADDED
@@ -0,0 +1,27 @@
1
+ export function unmountRef(element) {
2
+ if (element.ref == null) {
3
+ return;
4
+ }
5
+ if (typeof element.ref.cleanup === 'function') {
6
+ element.ref.cleanup();
7
+ }
8
+ if (typeof element.ref.value !== 'function') {
9
+ element.ref.value.current = null;
10
+ }
11
+ }
12
+ export function applyRef(element) {
13
+ if (element.ref == null) {
14
+ return;
15
+ }
16
+ if (typeof element.ref.cleanup === 'function') {
17
+ element.ref.cleanup();
18
+ }
19
+ if (typeof element.ref.value === 'function') {
20
+ let cleanup;
21
+ if ((cleanup = element.ref.value(element.reference))) {
22
+ element.ref.cleanup = cleanup;
23
+ }
24
+ return;
25
+ }
26
+ element.ref.value.current = element.reference;
27
+ }
@@ -1,2 +1,13 @@
1
1
  import type { SimpElement } from './createElement';
2
2
  export declare function rerender(element: SimpElement): void;
3
+ interface IRendererLocker {
4
+ _isLocked: boolean;
5
+ _elements: Set<SimpElement>;
6
+ isLocked: boolean;
7
+ lock(): void;
8
+ track(element: SimpElement): void;
9
+ flush(): void;
10
+ }
11
+ export declare const syncRerenderLocker: IRendererLocker;
12
+ export declare const asyncRerenderLocker: IRendererLocker;
13
+ export {};
package/core/rerender.js CHANGED
@@ -1,5 +1,63 @@
1
- import { findHostReferenceFromElement, updateFunctionalComponent } from './patching';
2
- import { GLOBAL } from './global';
1
+ import { findParentReferenceFromElement, updateFunctionalComponent } from './patching';
3
2
  export function rerender(element) {
4
- updateFunctionalComponent(element, GLOBAL.hostAdapter.findParentReference(findHostReferenceFromElement(element, true)), null);
3
+ if (element.flag !== 'FC') {
4
+ throw new TypeError('Re-rendering is only supported for FC elements.');
5
+ }
6
+ if (element.unmounted) {
7
+ console.warn('The component unmounted.');
8
+ }
9
+ if (syncRerenderLocker.isLocked) {
10
+ syncRerenderLocker.track(element);
11
+ return;
12
+ }
13
+ else if (asyncRerenderLocker.isLocked) {
14
+ asyncRerenderLocker.track(element);
15
+ }
16
+ else {
17
+ asyncRerenderLocker.lock();
18
+ updateFunctionalComponent(element, findParentReferenceFromElement(element), null, element.contextMap || null, element.store.hostNamespace);
19
+ asyncRerenderLocker.flush();
20
+ }
5
21
  }
22
+ export const syncRerenderLocker = {
23
+ _isLocked: false,
24
+ _elements: new Set(),
25
+ get isLocked() {
26
+ return this._isLocked;
27
+ },
28
+ lock() {
29
+ this._isLocked = true;
30
+ },
31
+ track(element) {
32
+ this._elements.add(element);
33
+ },
34
+ flush() {
35
+ this._isLocked = false;
36
+ for (const element of this._elements) {
37
+ this._elements.delete(element);
38
+ rerender(element.store.latestElement);
39
+ }
40
+ },
41
+ };
42
+ export const asyncRerenderLocker = {
43
+ _isLocked: false,
44
+ _elements: new Set(),
45
+ get isLocked() {
46
+ return this._isLocked;
47
+ },
48
+ lock() {
49
+ this._isLocked = true;
50
+ },
51
+ track(element) {
52
+ this._elements.add(element);
53
+ },
54
+ flush() {
55
+ this._isLocked = false;
56
+ queueMicrotask(() => {
57
+ for (const element of this._elements) {
58
+ this._elements.delete(element);
59
+ rerender(element.store.latestElement);
60
+ }
61
+ });
62
+ },
63
+ };
@@ -1,8 +1,6 @@
1
+ import type { Many, Maybe } from '../shared';
1
2
  import type { SimpElement } from './createElement';
2
- import type { Maybe } from '../shared';
3
3
  import type { HostReference } from './hostAdapter';
4
- export declare function unmount(element: SimpElement): void;
5
- export declare function unmountAllChildren(children: SimpElement[]): void;
6
- export declare function clearElementHostReference<HostRef = HostReference>(element: Maybe<SimpElement>, parentHostReference: HostRef): void;
7
- export declare function removeAllChildren<HostRef = HostReference>(hostReference: HostRef, element: SimpElement, children: SimpElement[]): void;
8
- export declare function remove<HostRef = HostReference>(element: SimpElement, parentReference: HostRef): void;
4
+ export declare function unmount(element: Many<SimpElement>): void;
5
+ export declare function clearElementHostReference(element: Maybe<SimpElement>, parentHostReference: HostReference): void;
6
+ export declare function remove(element: SimpElement, parentReference: HostReference): void;
@@ -1,69 +1,63 @@
1
- import { isArray } from '../shared';
2
- import { GLOBAL } from './global';
1
+ import { hostAdapter } from './hostAdapter';
2
+ import { unmountRef } from './ref';
3
+ import { lifecycleEventBus } from './lifecycleEventBus';
3
4
  export function unmount(element) {
4
- if (element.flag === 'HOST') {
5
- if (isArray(element.children)) {
6
- for (const child of element.children) {
7
- unmount(child);
8
- }
5
+ if (Array.isArray(element)) {
6
+ for (const child of element) {
7
+ unmount(child);
9
8
  }
10
- else if (element.children != null) {
9
+ return;
10
+ }
11
+ if (element.flag === 'FC') {
12
+ // FC element always has Maybe<SimpElement> due to normalization.
13
+ if (element.children) {
11
14
  unmount(element.children);
12
15
  }
16
+ element.unmounted = true;
17
+ lifecycleEventBus.publish({ type: 'unmounted', element });
18
+ return;
13
19
  }
14
- else if (element.flag === 'FC') {
15
- unmount(element.children);
16
- GLOBAL.eventBus.publish({ type: 'unmounted', element });
20
+ if (element.flag === 'TEXT') {
21
+ return;
17
22
  }
18
- else if (element.flag === 'FRAGMENT') {
19
- if (isArray(element.children)) {
20
- for (const child of element.children) {
21
- unmount(child);
22
- }
23
- }
24
- else if (element.children != null) {
25
- unmount(element.children);
26
- }
23
+ if (element.flag === 'PORTAL') {
24
+ remove(element.children, element.ref);
25
+ return;
27
26
  }
28
- }
29
- export function unmountAllChildren(children) {
30
- for (const child of children) {
31
- unmount(child);
27
+ // Only FRAGMENT, PROVIDER, CONSUMER, and HOST elements remain,
28
+ // with Maybe<Many<SimpElement>> children due to normalization.
29
+ if (element.children) {
30
+ unmount(element.children);
31
+ }
32
+ if (element.flag === 'HOST') {
33
+ unmountRef(element);
34
+ hostAdapter.unmountProps(element.reference, element);
32
35
  }
33
36
  }
34
37
  export function clearElementHostReference(element, parentHostReference) {
35
38
  while (element != null) {
36
- if (element.flag === 'HOST' || element.flag === 'TEXT') {
37
- GLOBAL.hostAdapter.removeChild(parentHostReference, element.reference);
39
+ if (element.flag === 'HOST' || element.flag === 'TEXT' || element.flag === 'PORTAL') {
40
+ hostAdapter.removeChild(parentHostReference, element.reference);
38
41
  return;
39
42
  }
40
43
  const children = element.children;
41
- if (element.flag === 'FC') {
44
+ if (element.flag === 'FC' || element.flag === 'CONSUMER') {
42
45
  element = children;
43
46
  continue;
44
47
  }
45
- if (element.flag === 'FRAGMENT') {
46
- if (isArray(children)) {
48
+ if (element.flag === 'FRAGMENT' || element.flag === 'PROVIDER') {
49
+ if (Array.isArray(children)) {
47
50
  for (let i = 0, len = children.length; i < len; ++i) {
48
51
  clearElementHostReference(children[i], parentHostReference);
49
52
  }
50
53
  return;
51
54
  }
52
- else if (children != null) {
55
+ else if (children) {
53
56
  element = children;
54
57
  }
55
58
  }
56
59
  }
57
60
  }
58
- export function removeAllChildren(hostReference, element, children) {
59
- unmountAllChildren(children);
60
- if (element.flag === 'FRAGMENT') {
61
- clearElementHostReference(element, hostReference);
62
- }
63
- else {
64
- GLOBAL.hostAdapter.setTextContent(hostReference, '');
65
- }
66
- }
67
61
  export function remove(element, parentReference) {
68
62
  unmount(element);
69
63
  clearElementHostReference(element, parentReference);
@@ -0,0 +1,4 @@
1
+ import type { Nullable } from '../shared';
2
+ import type { SimpElement } from '../core/internal.js';
3
+ export declare function attachElementToDom(element: SimpElement, dom: Node): void;
4
+ export declare function getElementFromDom(target: Nullable<EventTarget>): Nullable<SimpElement>;
@@ -0,0 +1,9 @@
1
+ const elementPropertyName = '__SIMP_ELEMENT__';
2
+ export function attachElementToDom(element, dom) {
3
+ if (dom.nodeType !== Node.TEXT_NODE) {
4
+ Object.defineProperty(dom, elementPropertyName, { value: element, writable: true });
5
+ }
6
+ }
7
+ export function getElementFromDom(target) {
8
+ return target?.[elementPropertyName] ?? null;
9
+ }
@@ -1,2 +1,3 @@
1
- import type { HostAdapter } from '../core/internal';
2
- export declare const domAdapter: HostAdapter<HTMLElement, Text>;
1
+ import type { HostAdapter } from '../core/internal.js';
2
+ import type { Namespace } from './namespace';
3
+ export declare const domAdapter: HostAdapter<HTMLElement | SVGElement, Text, Namespace>;
package/dom/domAdapter.js CHANGED
@@ -1,20 +1,34 @@
1
+ import { attachElementToDom } from './attach-element-to-dom';
2
+ import { mountProps, patchProps, unmountProps } from './props';
3
+ import { defaultNamespace } from './namespace';
1
4
  export const domAdapter = {
2
- createReference(type) {
3
- return document.createElement(type);
5
+ createReference(type, namespace) {
6
+ if (namespace) {
7
+ return document.createElementNS(namespace, type);
8
+ }
9
+ else {
10
+ return document.createElement(type);
11
+ }
4
12
  },
5
13
  createTextReference(text) {
6
14
  return document.createTextNode(text);
7
15
  },
8
- mountProps(reference, props) {
9
- mountProps(props, reference);
16
+ mountProps(dom, element, namespace) {
17
+ mountProps(dom, element, namespace || defaultNamespace);
10
18
  },
11
- patchProp(reference, propName, prevValue, nextValue) {
12
- patchProp(propName, prevValue, nextValue, reference);
19
+ patchProps(dom, prevElement, nextElement, namespace) {
20
+ patchProps(dom, prevElement, nextElement, namespace || defaultNamespace);
13
21
  },
14
- setClassname(reference, className) {
22
+ unmountProps(dom, element) {
23
+ unmountProps(dom, element);
24
+ },
25
+ setClassname(reference, className, namespace) {
15
26
  if (!className) {
16
27
  reference.removeAttribute('class');
17
28
  }
29
+ else if (namespace === 'http://www.w3.org/2000/svg') {
30
+ reference.setAttribute('class', className);
31
+ }
18
32
  else {
19
33
  reference.className = className;
20
34
  }
@@ -39,118 +53,31 @@ export const domAdapter = {
39
53
  removeChild(parent, child) {
40
54
  parent.removeChild(child);
41
55
  },
42
- replaceChild(parent, replacer, child) {
43
- parent.replaceChild(child, replacer);
56
+ replaceChild(parent, replacer, toBeReplaced) {
57
+ parent.replaceChild(replacer, toBeReplaced);
44
58
  },
45
59
  findParentReference(reference) {
46
60
  return reference.parentElement;
47
61
  },
48
- };
49
- function mountProps(props, reference) {
50
- for (const propsKey in props) {
51
- patchProp(propsKey, null, props[propsKey], reference);
52
- }
53
- }
54
- function patchProp(propName, prevValue, nextValue, dom) {
55
- switch (propName) {
56
- case 'children':
57
- case 'childrenType':
58
- case 'className':
59
- case 'defaultValue':
60
- case 'key':
61
- case 'multiple':
62
- case 'ref':
63
- case 'selectedIndex':
64
- break;
65
- case 'autoFocus':
66
- dom.autofocus = !!nextValue;
67
- break;
68
- case 'allowfullscreen':
69
- case 'autoplay':
70
- case 'capture':
71
- case 'checked':
72
- case 'controls':
73
- case 'default':
74
- case 'disabled':
75
- case 'hidden':
76
- case 'indeterminate':
77
- case 'loop':
78
- case 'muted':
79
- case 'novalidate':
80
- case 'open':
81
- case 'readOnly':
82
- case 'required':
83
- case 'reversed':
84
- case 'scoped':
85
- case 'seamless':
86
- case 'selected':
87
- dom[propName] = !!nextValue;
88
- break;
89
- case 'defaultChecked':
90
- case 'value':
91
- case 'volume':
92
- patchDomProp(nextValue, dom, propName);
93
- break;
94
- case 'style':
95
- patchStyle(prevValue, nextValue, dom);
96
- break;
97
- default:
98
- if (propName.charCodeAt(0) === 111 && propName.charCodeAt(1) === 110) {
99
- patchEvent(propName, prevValue, nextValue, dom);
100
- }
101
- else if (nextValue == null) {
102
- dom.removeAttribute(propName);
103
- }
104
- else {
105
- dom.setAttribute(propName, nextValue);
106
- }
107
- break;
108
- }
109
- }
110
- function patchDomProp(nextValue, dom, propKey) {
111
- const value = nextValue == null ? '' : nextValue;
112
- if (dom[propKey] !== value) {
113
- dom[propKey] = value;
114
- }
115
- }
116
- function patchStyle(lastAttrValue, nextAttrValue, dom) {
117
- if (nextAttrValue == null) {
118
- dom.removeAttribute('style');
119
- return;
120
- }
121
- const domStyle = dom.style;
122
- let style;
123
- let value;
124
- if (typeof nextAttrValue === 'string') {
125
- domStyle.cssText = nextAttrValue;
126
- return;
127
- }
128
- if (lastAttrValue != null && typeof lastAttrValue !== 'string') {
129
- for (style in nextAttrValue) {
130
- value = nextAttrValue[style];
131
- if (value !== lastAttrValue[style]) {
132
- domStyle.setProperty(style, value);
133
- }
62
+ findNextSiblingReference(reference) {
63
+ return reference.nextSibling;
64
+ },
65
+ clearNode(reference) {
66
+ reference.textContent = '';
67
+ },
68
+ attachElementToReference(element, reference) {
69
+ attachElementToDom(element, reference);
70
+ },
71
+ getHostNamespaces(element, currentNamespace) {
72
+ if (element.type === 'svg') {
73
+ return { self: 'http://www.w3.org/2000/svg', children: 'http://www.w3.org/2000/svg' };
134
74
  }
135
- for (style in lastAttrValue) {
136
- if (nextAttrValue[style] == null) {
137
- domStyle.removeProperty(style);
138
- }
75
+ if (element.type === 'foreignObject') {
76
+ return { self: 'http://www.w3.org/2000/svg', children: null };
139
77
  }
140
- }
141
- else {
142
- for (style in nextAttrValue) {
143
- value = nextAttrValue[style];
144
- domStyle.setProperty(style, value);
78
+ if (currentNamespace && currentNamespace !== 'http://www.w3.org/1999/xhtml') {
79
+ return { self: currentNamespace, children: currentNamespace };
145
80
  }
146
- }
147
- }
148
- function patchEvent(name, lastValue, nextValue, dom) {
149
- name = name.toLowerCase().substring(2);
150
- if (typeof lastValue === 'function') {
151
- dom.removeEventListener(name, lastValue);
152
- }
153
- if (typeof nextValue === 'function') {
154
- dom.addEventListener(name, nextValue);
155
- }
156
- }
81
+ return null;
82
+ },
83
+ };
@@ -0,0 +1,19 @@
1
+ import type { Nullable } from '../shared';
2
+ type DelegatedEventType = 'click' | 'dblclick' | 'mousedown' | 'mouseup' | 'mousemove' | 'pointerdown' | 'pointerup' | 'pointermove' | 'touchstart' | 'touchmove' | 'touchend' | 'keydown' | 'keyup' | 'focusin' | 'focusout';
3
+ export declare class SyntheticEvent {
4
+ nativeEvent: Event;
5
+ currentTarget: Nullable<EventTarget>;
6
+ isPropagationStopped: boolean;
7
+ isDefaultPrevented: boolean;
8
+ constructor(event: Event);
9
+ get target(): EventTarget | null;
10
+ get type(): string;
11
+ stopPropagation(): void;
12
+ preventDefault(): void;
13
+ }
14
+ export declare function dispatchDelegatedEvent(event: Event): void;
15
+ export declare function patchEvent(name: string, prevValue: any, nextValue: any, dom: Element): void;
16
+ export declare function patchDelegatedEvent(eventType: DelegatedEventType, handler: any, eventHandlerCounts: Record<DelegatedEventType, number>): void;
17
+ export declare function patchNormalEvent(eventType: string, prevValue: any, nextValue: any, dom: Element, capture: boolean): void;
18
+ export declare function isPropNameEventName(name: string): boolean;
19
+ export {};
package/dom/events.js ADDED
@@ -0,0 +1,129 @@
1
+ import { syncRerenderLocker } from '../core/internal.js';
2
+ import { getElementFromDom } from './attach-element-to-dom';
3
+ const eventNameByTypes = {
4
+ click: 'onClick',
5
+ dblclick: 'onDblClick',
6
+ mousedown: 'onMouseDown',
7
+ mouseup: 'onMouseUp',
8
+ mousemove: 'onMouseMove',
9
+ pointerdown: 'onPointerDown',
10
+ pointerup: 'onPointerUp',
11
+ pointermove: 'onPointerMove',
12
+ touchstart: 'onTouchStart',
13
+ touchmove: 'onTouchMove',
14
+ touchend: 'onTouchEnd',
15
+ keydown: 'onKeyDown',
16
+ keyup: 'onKeyUp',
17
+ focusin: 'onFocusIn',
18
+ focusout: 'onFocusOut',
19
+ };
20
+ const delegatedEventTypes = new Set(Object.keys(eventNameByTypes));
21
+ const eventHandlerCounts = {
22
+ click: 0,
23
+ dblclick: 0,
24
+ mousedown: 0,
25
+ mouseup: 0,
26
+ mousemove: 0,
27
+ pointerdown: 0,
28
+ pointerup: 0,
29
+ pointermove: 0,
30
+ touchstart: 0,
31
+ touchmove: 0,
32
+ touchend: 0,
33
+ keydown: 0,
34
+ keyup: 0,
35
+ focusin: 0,
36
+ focusout: 0,
37
+ };
38
+ export class SyntheticEvent {
39
+ nativeEvent;
40
+ currentTarget = null;
41
+ isPropagationStopped = false;
42
+ isDefaultPrevented = false;
43
+ constructor(event) {
44
+ this.nativeEvent = event;
45
+ }
46
+ get target() {
47
+ return this.nativeEvent.target;
48
+ }
49
+ get type() {
50
+ return this.nativeEvent.type;
51
+ }
52
+ stopPropagation() {
53
+ this.isPropagationStopped = true;
54
+ this.nativeEvent.stopPropagation();
55
+ }
56
+ preventDefault() {
57
+ this.isDefaultPrevented = true;
58
+ this.nativeEvent.preventDefault();
59
+ }
60
+ }
61
+ export function dispatchDelegatedEvent(event) {
62
+ syncRerenderLocker.lock();
63
+ const syntheticEvent = new SyntheticEvent(event);
64
+ const captureHandlers = [];
65
+ const bubbleHandlers = [];
66
+ let element = getElementFromDom(event.target);
67
+ while (element) {
68
+ if (element.flag === 'HOST') {
69
+ const captureHandler = element.props?.[eventNameByTypes[event.type] + 'Capture'];
70
+ const bubbleHandler = element.props?.[eventNameByTypes[event.type]];
71
+ if (captureHandler) {
72
+ captureHandlers.push({ element, handler: captureHandler });
73
+ }
74
+ if (bubbleHandler) {
75
+ bubbleHandlers.push({ element, handler: bubbleHandler });
76
+ }
77
+ }
78
+ element = element.parent;
79
+ }
80
+ for (const { handler, element } of captureHandlers.reverse()) {
81
+ syntheticEvent.currentTarget = element.reference;
82
+ handler(syntheticEvent);
83
+ if (syntheticEvent.isPropagationStopped) {
84
+ return;
85
+ }
86
+ }
87
+ for (const { element, handler } of bubbleHandlers) {
88
+ syntheticEvent.currentTarget = element.reference;
89
+ handler(syntheticEvent);
90
+ if (syntheticEvent.isPropagationStopped) {
91
+ return;
92
+ }
93
+ }
94
+ syncRerenderLocker.flush();
95
+ }
96
+ const captureRegex = /Capture/;
97
+ export function patchEvent(name, prevValue, nextValue, dom) {
98
+ const isCapture = captureRegex.test(name);
99
+ name = name.replace(captureRegex, '').substring(2).toLowerCase();
100
+ if (delegatedEventTypes.has(name)) {
101
+ patchDelegatedEvent(name, nextValue, eventHandlerCounts);
102
+ }
103
+ else {
104
+ patchNormalEvent(name, prevValue, nextValue, dom, isCapture);
105
+ }
106
+ }
107
+ export function patchDelegatedEvent(eventType, handler, eventHandlerCounts) {
108
+ if (typeof handler === 'function') {
109
+ if (++eventHandlerCounts[eventType] === 1) {
110
+ document.addEventListener(eventType, dispatchDelegatedEvent);
111
+ }
112
+ }
113
+ else {
114
+ if (eventHandlerCounts[eventType] !== 0 && --eventHandlerCounts[eventType] === 0) {
115
+ document.removeEventListener(eventType, dispatchDelegatedEvent);
116
+ }
117
+ }
118
+ }
119
+ export function patchNormalEvent(eventType, prevValue, nextValue, dom, capture) {
120
+ if (typeof prevValue === 'function') {
121
+ dom.removeEventListener(eventType, prevValue, { capture });
122
+ }
123
+ if (typeof nextValue === 'function') {
124
+ dom.addEventListener(eventType, nextValue, { capture });
125
+ }
126
+ }
127
+ export function isPropNameEventName(name) {
128
+ return name.charCodeAt(0) === 111 && name.charCodeAt(1) === 110;
129
+ }