Skip to content

Commit 2f3bec7

Browse files
committed
React. FragmentInstance events
1 parent e6d83f7 commit 2f3bec7

File tree

4 files changed

+995
-2
lines changed

4 files changed

+995
-2
lines changed

build-logic/generatorlegacybuild/src/main/kotlin/karakum/browser/EventTypeMap.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,12 @@ internal val EVENT_CORRECTION_MAP = mapOf(
113113
"bufferedamountlow" to "buffered_amount_low",
114114
"canplay" to "can_play",
115115
"canplaythrough" to "can_play_through",
116+
"clipboardchange" to "clipboard_change",
116117
"compositionend" to "composition_end",
117118
"compositionstart" to "composition_start",
118119
"compositionupdate" to "composition_update",
119120
"connectionstatechange" to "connection_state_change",
121+
"contentvisibilityautostatechange" to "content_visibility_auto_state_change",
120122
"contextmenu" to "context_menu",
121123
"controllerchange" to "controller_change",
122124
"cuechange" to "cue_change",
@@ -245,5 +247,9 @@ internal val EVENT_CORRECTION_MAP = mapOf(
245247
"pagereveal" to "page_reveal",
246248
"pageswap" to "page_swap",
247249

248-
"prioritychange" to "priority_change"
250+
"prioritychange" to "priority_change",
251+
252+
"webglcontextcreationerror" to "webgl_context_creation_error",
253+
"webglcontextlost" to "webgl_context_lost",
254+
"webglcontextrestored" to "webgl_context_restored",
249255
)

build-logic/generatorlegacybuild/src/main/kotlin/karakum/events/EventDataRegistry.kt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,33 @@ object EventDataRegistry {
4646
}
4747
}
4848

49+
fun isDomNodeTarget(
50+
target: String,
51+
): Boolean =
52+
when {
53+
target == "Text" -> true
54+
target == "Element" -> true
55+
target == "MathMLElement" -> true
56+
57+
// TEMP
58+
target == "HTMLPortalElement" -> false
59+
60+
!target.endsWith("Element") -> false
61+
else -> target.startsWith("HTML") || target.startsWith("SVG")
62+
}
63+
64+
fun getMergedDomDataList(): List<EventData> {
65+
return dataList.asSequence()
66+
.filter { !it.type.startsWith("DOM") }
67+
.filter { it.`interface` !in EXCLUDED_EVENTS }
68+
.filter { data ->
69+
data.targets.asSequence()
70+
.map { it.target }
71+
.any(::isDomNodeTarget)
72+
}
73+
.toList()
74+
}
75+
4976
private fun Target.targetWithAliases(
5077
eventType: String,
5178
): Sequence<String> {
Lines changed: 137 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,144 @@
11
package karakum.react
22

3+
import karakum.browser.EVENT_CORRECTION_MAP
4+
import karakum.browser.EVENT_INSTANCE
5+
import karakum.common.snakeToCamel
6+
import karakum.events.EventDataRegistry
7+
import karakum.events.EventDataRegistry.isDomNodeTarget
8+
39
internal fun FragmentInstanceEvents(): ConversionResult =
410
ConversionResult(
511
name = "FragmentInstance.events",
6-
body = "",
12+
body = events(),
713
pkg = Package.REACT,
814
)
15+
16+
private data class EventData(
17+
val type: String,
18+
val eventType: String,
19+
val currentTarget: String,
20+
val target: String,
21+
val docTarget: String = currentTarget,
22+
)
23+
24+
private fun events(): String {
25+
val list = EventDataRegistry.getMergedDomDataList()
26+
.flatMap { data ->
27+
data.targets
28+
.filter { isDomNodeTarget(it.target) }
29+
.map { current ->
30+
val currentTarget = current.target
31+
val target = EventDataRegistry.getTarget(
32+
currentTarget = currentTarget,
33+
eventType = data.type,
34+
defaultTarget = currentTarget,
35+
)
36+
37+
EventData(
38+
type = data.type,
39+
eventType = data.`interface`,
40+
currentTarget = currentTarget,
41+
target = target,
42+
)
43+
}
44+
}
45+
.sortedBy { it.type }
46+
.groupBy { it.type }
47+
.values
48+
.map { list ->
49+
list.singleOrNull()
50+
?: EventData(
51+
type = list.first().type,
52+
eventType = list.map { it.eventType }.distinct().single(),
53+
currentTarget = getTarget(list.map { it.currentTarget }.distinct()),
54+
target = getTarget(list.map { it.target }.distinct()),
55+
docTarget = getDocTarget(list.map { it.docTarget }.distinct()),
56+
)
57+
}
58+
59+
val events = list.joinToString("\n\n") { data ->
60+
val memberName = EVENT_CORRECTION_MAP
61+
.getOrDefault(data.type, data.type)
62+
.snakeToCamel()
63+
64+
"""
65+
/**
66+
* [MDN Reference](https://developer.mozilla.org/docs/Web/API/${data.docTarget}/${data.type}_event)
67+
*/
68+
@ReactCanary
69+
inline val FragmentInstance.${memberName}Event: $EVENT_INSTANCE<${data.eventType}, ${data.currentTarget}, ${data.target}>
70+
get() = $EVENT_INSTANCE(this, "${data.type}")
71+
""".trimIndent()
72+
}
73+
74+
return IMPORTS + "\n\n" + events
75+
}
76+
77+
private fun getTarget(
78+
targets: List<String>,
79+
): String {
80+
return targets.singleOrNull()
81+
?: TARGET_MAP.getValue(targets.toSet())
82+
}
83+
84+
private fun getDocTarget(
85+
targets: List<String>,
86+
): String {
87+
val target = getTarget(targets)
88+
return if (target in targets) {
89+
target
90+
} else {
91+
targets.minOf { it }
92+
}
93+
}
94+
95+
private val TARGET_MAP = mapOf(
96+
setOf("Element", "HTMLMediaElement") to "Element",
97+
setOf("HTMLElement", "MathMLElement", "SVGElement") to "Element",
98+
setOf("HTMLDialogElement", "HTMLInputElement") to "HTMLElement",
99+
setOf("HTMLDialogElement", "Node") to "Node",
100+
setOf("HTMLInputElement", "HTMLSelectElement") to "HTMLElement",
101+
setOf("HTMLElement", "MathMLElement", "SVGElement", "Text") to "Node",
102+
setOf("Element", "HTMLMediaElement", "HTMLSourceElement", "HTMLTrackElement") to "Element",
103+
setOf("HTMLButtonElement", "HTMLInputElement", "HTMLSelectElement", "HTMLTextAreaElement") to "HTMLElement",
104+
setOf("Element", "HTMLInputElement", "HTMLTextAreaElement") to "Element",
105+
setOf("Element", "HTMLTrackElement") to "Element",
106+
)
107+
108+
private val IMPORTS = """
109+
import react.canary.ReactCanary
110+
import web.animations.AnimationEvent
111+
import web.clipboard.ClipboardEvent
112+
import web.command.CommandEvent
113+
import web.components.HTMLSlotElement
114+
import web.cssom.ContentVisibilityAutoStateChangeEvent
115+
import web.cssom.TransitionEvent
116+
import web.dnd.DragEvent
117+
import web.dom.Element
118+
import web.dom.Node
119+
import web.events.Event
120+
import web.events.EventInstance
121+
import web.focus.FocusEvent
122+
import web.form.FormDataEvent
123+
import web.form.SubmitEvent
124+
import web.gl.WebGLContextEvent
125+
import web.html.HTMLCanvasElement
126+
import web.html.HTMLDetailsElement
127+
import web.html.HTMLDialogElement
128+
import web.html.HTMLElement
129+
import web.html.HTMLFormElement
130+
import web.html.HTMLMediaElement
131+
import web.html.HTMLTrackElement
132+
import web.html.HTMLVideoElement
133+
import web.html.MediaEncryptedEvent
134+
import web.input.CompositionEvent
135+
import web.input.InputEvent
136+
import web.keyboard.KeyboardEvent
137+
import web.messaging.MessageEvent
138+
import web.mouse.MouseEvent
139+
import web.mouse.WheelEvent
140+
import web.pip.PictureInPictureEvent
141+
import web.pointer.PointerEvent
142+
import web.popover.ToggleEvent
143+
import web.touch.TouchEvent
144+
""".trimIndent()

0 commit comments

Comments
 (0)