@remix-run/ui 0.6.0 → 0.8.0

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/README.md +86 -20
  2. package/dist/animation/demos/drag-release.js +5 -7
  3. package/dist/animation/demos/drag-release.js.map +1 -1
  4. package/dist/index.d.ts +2 -2
  5. package/dist/index.js +1 -1
  6. package/dist/index.js.map +1 -1
  7. package/dist/runtime/component.d.ts +2 -1
  8. package/dist/runtime/component.js.map +1 -1
  9. package/dist/runtime/diff-dom.js +8 -3
  10. package/dist/runtime/diff-dom.js.map +1 -1
  11. package/dist/runtime/dom.d.ts +21 -11
  12. package/dist/runtime/event-types.d.ts +14 -0
  13. package/dist/runtime/event-types.js +2 -0
  14. package/dist/runtime/event-types.js.map +1 -0
  15. package/dist/runtime/frame-resolution.js +8 -0
  16. package/dist/runtime/frame-resolution.js.map +1 -1
  17. package/dist/runtime/frame.d.ts +5 -2
  18. package/dist/runtime/frame.js +107 -49
  19. package/dist/runtime/frame.js.map +1 -1
  20. package/dist/runtime/mixins/link-mixin.js +4 -4
  21. package/dist/runtime/mixins/link-mixin.js.map +1 -1
  22. package/dist/runtime/mixins/mixin.d.ts +9 -3
  23. package/dist/runtime/mixins/mixin.js.map +1 -1
  24. package/dist/runtime/mixins/on-mixin.d.ts +1 -1
  25. package/dist/runtime/module-preloader.js +3 -3
  26. package/dist/runtime/module-preloader.js.map +1 -1
  27. package/dist/runtime/navigation.d.ts +1 -2
  28. package/dist/runtime/navigation.js +115 -36
  29. package/dist/runtime/navigation.js.map +1 -1
  30. package/dist/runtime/reconcile.js +9 -3
  31. package/dist/runtime/reconcile.js.map +1 -1
  32. package/dist/runtime/run.d.ts +3 -3
  33. package/dist/runtime/run.js +43 -3
  34. package/dist/runtime/run.js.map +1 -1
  35. package/dist/runtime/scheduler.js +37 -11
  36. package/dist/runtime/scheduler.js.map +1 -1
  37. package/dist/runtime/spa-response.d.ts +30 -0
  38. package/dist/runtime/spa-response.js +47 -0
  39. package/dist/runtime/spa-response.js.map +1 -0
  40. package/dist/runtime/typed-event-target.d.ts +0 -4
  41. package/dist/runtime/typed-event-target.js.map +1 -1
  42. package/dist/server/stream.js +21 -5
  43. package/dist/server/stream.js.map +1 -1
  44. package/dist/style/stylesheet.js +2 -2
  45. package/dist/style/stylesheet.js.map +1 -1
  46. package/package.json +1 -1
  47. package/src/animation/demos/drag-release.ts +5 -7
  48. package/src/index.ts +2 -2
  49. package/src/runtime/component.ts +2 -1
  50. package/src/runtime/demos/readme.demo.tsx +7 -17
  51. package/src/runtime/diff-dom.ts +6 -3
  52. package/src/runtime/dom.ts +21 -11
  53. package/src/runtime/event-types.ts +27 -0
  54. package/src/runtime/frame-resolution.ts +9 -0
  55. package/src/runtime/frame.ts +112 -50
  56. package/src/runtime/mixins/link-mixin.ts +4 -4
  57. package/src/runtime/mixins/mixin.ts +26 -4
  58. package/src/runtime/mixins/on-mixin.ts +1 -1
  59. package/src/runtime/module-preloader.ts +3 -3
  60. package/src/runtime/navigation.ts +127 -34
  61. package/src/runtime/reconcile.ts +11 -4
  62. package/src/runtime/run.ts +53 -6
  63. package/src/runtime/scheduler.ts +53 -13
  64. package/src/runtime/spa-response.ts +56 -0
  65. package/src/runtime/typed-event-target.ts +1 -6
  66. package/src/server/stream.ts +28 -5
  67. package/src/style/stylesheet.ts +3 -3
  68. package/dist/runtime/event-listeners.d.ts +0 -50
  69. package/dist/runtime/event-listeners.js +0 -31
  70. package/dist/runtime/event-listeners.js.map +0 -1
  71. package/src/runtime/event-listeners.ts +0 -171
@@ -492,7 +492,7 @@ function buildFrameSegment(
492
492
  framePromise.catch(() => {})
493
493
  context.pendingFrames.push({ frameId, promise: framePromise })
494
494
  } else {
495
- seg.pending = Promise.resolve(
495
+ let framePromise = Promise.resolve(
496
496
  context.resolveFrame(props.src, props.name, resolveFrameContext),
497
497
  ).then(async (resolved) => {
498
498
  let { html, tail } = await resolveFrameHtml(resolved)
@@ -502,6 +502,9 @@ function buildFrameSegment(
502
502
  context.blockingFrameTails.push(tail)
503
503
  }
504
504
  })
505
+ // An earlier blocking frame may reject before this promise is awaited.
506
+ framePromise.catch(() => {})
507
+ seg.pending = framePromise
505
508
  }
506
509
 
507
510
  return seg
@@ -535,6 +538,16 @@ function buildElementSegment(
535
538
  return staticSeg(`<${tag}${attrs}>${props.innerHTML}</${tag}>`)
536
539
  }
537
540
 
541
+ if (tag === 'script') {
542
+ if (typeof props.children === 'string') {
543
+ return staticSeg(`<${tag}${attrs}>${escapeScriptTextContent(props.children)}</${tag}>`)
544
+ }
545
+ if (props.children != null) {
546
+ console.error(new Error('script elements with children must have a single string child'))
547
+ }
548
+ return staticSeg(`<${tag}${attrs}></${tag}>`)
549
+ }
550
+
538
551
  let open = staticSeg(`<${tag}${attrs}>`)
539
552
  // Adjust svg context for children: foreignObject switches back to HTML
540
553
  let previousInsideSvg = context.insideSvg
@@ -1174,6 +1187,16 @@ function escapeTemplateContent(html: string): string {
1174
1187
  return html.replace(/<\/template/gi, '<\\/template')
1175
1188
  }
1176
1189
 
1190
+ const SCRIPT_TAG_PATTERN = /(<\/|<)(s)(cript)/gi
1191
+
1192
+ function escapeScriptTextContent(value: string): string {
1193
+ return value.replace(
1194
+ SCRIPT_TAG_PATTERN,
1195
+ (_match, prefix: string, firstLetter: string, suffix: string) =>
1196
+ `${prefix}${firstLetter === 's' ? '\\u0073' : '\\u0053'}${suffix}`,
1197
+ )
1198
+ }
1199
+
1177
1200
  function transformAttributeName(name: string, isSvg: boolean): string {
1178
1201
  return normalizeAttributeName(name, isSvg).attr
1179
1202
  }
@@ -1232,7 +1255,7 @@ function finalizeHtml(html: string, context: RenderContext): string {
1232
1255
 
1233
1256
  const FRAME_HEAD_OPEN_TAG = '<head>'
1234
1257
  const FRAME_HEAD_CLOSE_TAG = '</head>'
1235
- const MARKED_MODULE_PRELOAD_START = '<link data-rmx rel="modulepreload" href="'
1258
+ const MARKED_MODULE_PRELOAD_START = '<link data-rmx-module-preload rel="modulepreload" href="'
1236
1259
  const MODULE_PRELOAD_END = '" />'
1237
1260
 
1238
1261
  function createModulePreloadTag(href: string): string {
@@ -1322,12 +1345,12 @@ function renderStyleTag(
1322
1345
  ): string {
1323
1346
  let wrappedCss = wrapStyleForLayer(selector, css, layer)
1324
1347
  if (!wrappedCss) return ''
1325
- return `<style data-rmx="${escapeHtml(selector)}">${escapeStyleText(wrappedCss)}</style>`
1348
+ return `<style data-rmx-style="${escapeHtml(selector)}">${escapeStyleText(wrappedCss)}</style>`
1326
1349
  }
1327
1350
 
1328
1351
  function escapeStyleText(css: string): string {
1329
- // A literal "</style" closes an HTML style element even when it appears inside a CSS string.
1330
- return css.replace(/</g, '\\3C ')
1352
+ // Only neutralize literal style end tags. Escaping every '<' breaks valid range media queries.
1353
+ return css.replace(/<\/style/gi, '\\3C/style')
1331
1354
  }
1332
1355
 
1333
1356
  function buildRmxDataScript(context: RenderContext): string {
@@ -7,7 +7,7 @@ import { REMIX_UI_STYLE_LAYER } from './layers.ts'
7
7
  // never become *wrong* — only unused. That observation drives a two-tier
8
8
  // lifetime model on a single document-level registry:
9
9
  //
10
- // - **Server-adopted rules are pinned.** Once a `<style data-rmx>` tag is
10
+ // - **Server-adopted rules are pinned.** Once a `<style data-rmx-style>` tag is
11
11
  // adopted, its rule stays for the life of the manager. Frame reloads,
12
12
  // island hydration, and streamed templates never need to agree on which
13
13
  // scope "owns" a shared rule — adoption is additive and idempotent, and the
@@ -34,7 +34,7 @@ export interface StyleManager {
34
34
  dispose(): void
35
35
  }
36
36
 
37
- const SERVER_STYLE_SELECTOR = 'style[data-rmx]'
37
+ const SERVER_STYLE_SELECTOR = 'style[data-rmx-style]'
38
38
 
39
39
  function getStyleLayerName(className: string, layer: string = REMIX_UI_STYLE_LAYER): string {
40
40
  return `${layer}.${className}`
@@ -95,7 +95,7 @@ function isHtmlStyleElement(node: unknown): node is HTMLStyleElement {
95
95
  }
96
96
 
97
97
  function getStyleSelector(styleEl: HTMLStyleElement): string | null {
98
- let selector = styleEl.getAttribute('data-rmx')?.trim()
98
+ let selector = styleEl.getAttribute('data-rmx-style')?.trim()
99
99
  return selector ? selector : null
100
100
  }
101
101
 
@@ -1,50 +0,0 @@
1
- /**
2
- * Event type with `currentTarget` narrowed to the dispatched target.
3
- */
4
- export type Dispatched<event extends Event, target extends EventTarget> = Omit<event, 'currentTarget'> & {
5
- currentTarget: target;
6
- };
7
- /**
8
- * Narrows non-event values to `never` and preserves dispatched event typing otherwise.
9
- */
10
- export type EnsureEvent<event, target extends EventTarget> = event extends Event ? Dispatched<event, target> : never;
11
- /**
12
- * Union of event type names supported by the given target.
13
- */
14
- export type EventType<target extends EventTarget> = target extends {
15
- __eventMap?: infer eventMap;
16
- } ? keyof eventMap : keyof EventMap<target>;
17
- type NavigationTarget = Window extends {
18
- navigation: infer navigation;
19
- } ? navigation : never;
20
- type NavigationTargetEvent = NavigationTarget extends {
21
- onnavigate: ((event: infer navigateEvent) => unknown) | null;
22
- } ? navigateEvent : Event;
23
- type NavigationTargetEventMap = {
24
- navigate: NavigationTargetEvent;
25
- };
26
- /**
27
- * Listener function type for a specific target and event name.
28
- */
29
- export type ListenerFor<target extends EventTarget, type extends EventType<target>> = (event: EnsureEvent<EventMap<target>[type], target>, signal: AbortSignal) => void;
30
- /**
31
- * Partial map of event listeners keyed by event type.
32
- */
33
- export type EventListeners<target extends EventTarget> = Partial<{
34
- [k in EventType<target>]: ListenerFor<target, k>;
35
- }>;
36
- /**
37
- * Event map resolved for the given DOM or custom event target.
38
- */
39
- export type EventMap<target extends EventTarget> = (target extends {
40
- __eventMap?: infer eventMap;
41
- } ? eventMap : target extends HTMLElement ? HTMLElementEventMap : target extends SVGSVGElement ? SVGSVGElementEventMap : target extends SVGElement ? SVGElementEventMap : target extends Element ? ElementEventMap : target extends Window ? WindowEventMap : target extends Document ? DocumentEventMap : target extends AbortSignal ? AbortSignalEventMap : target extends Animation ? AnimationEventMap : target extends AudioDecoder ? AudioDecoderEventMap : target extends AudioEncoder ? AudioEncoderEventMap : target extends AudioNode ? GlobalEventHandlersEventMap : target extends BaseAudioContext ? BaseAudioContextEventMap : target extends BroadcastChannel ? BroadcastChannelEventMap : target extends Clipboard ? GlobalEventHandlersEventMap : target extends EventSource ? EventSourceEventMap : target extends FileReader ? FileReaderEventMap : target extends FontFaceSet ? FontFaceSetEventMap : target extends IDBDatabase ? IDBDatabaseEventMap : target extends IDBTransaction ? IDBTransactionEventMap : target extends MIDIAccess ? MIDIAccessEventMap : target extends MIDIPort ? MIDIPortEventMap : target extends MediaDevices ? MediaDevicesEventMap : target extends MediaKeySession ? MediaKeySessionEventMap : target extends MediaQueryList ? MediaQueryListEventMap : target extends MediaRecorder ? MediaRecorderEventMap : target extends MediaSource ? MediaSourceEventMap : target extends MediaStream ? MediaStreamEventMap : target extends MediaStreamTrack ? MediaStreamTrackEventMap : target extends MessagePort ? MessagePortEventMap : target extends NavigationTarget ? NavigationTargetEventMap : target extends Node ? GlobalEventHandlersEventMap : target extends Notification ? NotificationEventMap : target extends OffscreenCanvas ? OffscreenCanvasEventMap : target extends PaymentRequest ? PaymentRequestEventMap : target extends PaymentResponse ? PaymentResponseEventMap : target extends Performance ? PerformanceEventMap : target extends PermissionStatus ? PermissionStatusEventMap : target extends PictureInPictureWindow ? PictureInPictureWindowEventMap : target extends RTCDTMFSender ? RTCDTMFSenderEventMap : target extends RTCDataChannel ? RTCDataChannelEventMap : target extends RTCDtlsTransport ? RTCDtlsTransportEventMap : target extends RTCIceTransport ? RTCIceTransportEventMap : target extends RTCPeerConnection ? RTCPeerConnectionEventMap : target extends RTCSctpTransport ? RTCSctpTransportEventMap : target extends RemotePlayback ? RemotePlaybackEventMap : target extends ScreenOrientation ? ScreenOrientationEventMap : target extends ServiceWorkerContainer ? ServiceWorkerContainerEventMap : target extends ServiceWorkerRegistration ? ServiceWorkerRegistrationEventMap : target extends ServiceWorker ? AbstractWorkerEventMap : target extends SharedWorker ? AbstractWorkerEventMap : target extends SourceBuffer ? SourceBufferEventMap : target extends SourceBufferList ? SourceBufferListEventMap : target extends SpeechSynthesis ? SpeechSynthesisEventMap : target extends SpeechSynthesisUtterance ? SpeechSynthesisUtteranceEventMap : target extends TextTrack ? TextTrackEventMap : target extends TextTrackCue ? TextTrackCueEventMap : target extends TextTrackList ? TextTrackListEventMap : target extends VideoDecoder ? VideoDecoderEventMap : target extends VideoEncoder ? VideoEncoderEventMap : target extends VisualViewport ? VisualViewportEventMap : target extends WakeLockSentinel ? WakeLockSentinelEventMap : target extends WebSocket ? WebSocketEventMap : target extends Window ? (WindowEventMap & GlobalEventHandlersEventMap) : target extends Worker ? AbstractWorkerEventMap : target extends XMLHttpRequestEventTarget ? XMLHttpRequestEventTargetEventMap : GlobalEventHandlersEventMap & Record<string, Event>);
42
- /**
43
- * Adds typed event listeners and reentry abort signals to a target.
44
- *
45
- * @param target Event target to attach listeners to.
46
- * @param signal Lifetime signal used to remove all listeners.
47
- * @param listeners Listener map keyed by event type.
48
- */
49
- export declare function addEventListeners<target extends EventTarget>(target: target, signal: AbortSignal, listeners: EventListeners<target>): void;
50
- export {};
@@ -1,31 +0,0 @@
1
- /**
2
- * Adds typed event listeners and reentry abort signals to a target.
3
- *
4
- * @param target Event target to attach listeners to.
5
- * @param signal Lifetime signal used to remove all listeners.
6
- * @param listeners Listener map keyed by event type.
7
- */
8
- export function addEventListeners(target, signal, listeners) {
9
- for (let type in listeners) {
10
- let listener = listeners[type];
11
- if (!listener)
12
- continue;
13
- let reentry = null;
14
- signal.addEventListener('abort', () => {
15
- reentry?.abort();
16
- });
17
- target.addEventListener(type, (event) => {
18
- reentry?.abort();
19
- let dispatchedEvent = event;
20
- if (listener.length < 2) {
21
- reentry = null;
22
- listener(dispatchedEvent);
23
- }
24
- else {
25
- reentry = new AbortController();
26
- listener(dispatchedEvent, reentry.signal);
27
- }
28
- }, { signal });
29
- }
30
- }
31
- //# sourceMappingURL=event-listeners.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"event-listeners.js","sourceRoot":"","sources":["../../src/runtime/event-listeners.ts"],"names":[],"mappings":"AAiIA;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAC/B,MAAc,EACd,MAAmB,EACnB,SAAiC;IAKjC,KAAK,IAAI,IAAI,IAAI,SAAS,EAAE,CAAC;QAC3B,IAAI,QAAQ,GAAG,SAAS,CAAC,IAAyB,CAAa,CAAA;QAC/D,IAAI,CAAC,QAAQ;YAAE,SAAQ;QACvB,IAAI,OAAO,GAA2B,IAAI,CAAA;QAE1C,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE;YACpC,OAAO,EAAE,KAAK,EAAE,CAAA;QAClB,CAAC,CAAC,CAAA;QAEF,MAAM,CAAC,gBAAgB,CACrB,IAAI,EACJ,CAAC,KAAK,EAAE,EAAE;YACR,OAAO,EAAE,KAAK,EAAE,CAAA;YAChB,IAAI,eAAe,GAAG,KAAiB,CAAA;YAEvC,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACxB,OAAO,GAAG,IAAI,CAAA;gBACd,QAAQ,CAAC,eAAe,CAAC,CAAA;YAC3B,CAAC;iBAAM,CAAC;gBACN,OAAO,GAAG,IAAI,eAAe,EAAE,CAAA;gBAC/B,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC,MAAM,CAAC,CAAA;YAC3C,CAAC;QACH,CAAC,EACD,EAAE,MAAM,EAAE,CACX,CAAA;IACH,CAAC;AACH,CAAC"}
@@ -1,171 +0,0 @@
1
- /**
2
- * Event type with `currentTarget` narrowed to the dispatched target.
3
- */
4
- export type Dispatched<event extends Event, target extends EventTarget> = Omit<
5
- event,
6
- 'currentTarget'
7
- > & {
8
- currentTarget: target
9
- }
10
-
11
- /**
12
- * Narrows non-event values to `never` and preserves dispatched event typing otherwise.
13
- */
14
- export type EnsureEvent<event, target extends EventTarget> = event extends Event
15
- ? Dispatched<event, target>
16
- : never
17
-
18
- /**
19
- * Union of event type names supported by the given target.
20
- */
21
- export type EventType<target extends EventTarget> = target extends { __eventMap?: infer eventMap }
22
- ? keyof eventMap
23
- : keyof EventMap<target>
24
-
25
- type NavigationTarget = Window extends { navigation: infer navigation } ? navigation : never
26
- type NavigationTargetEvent = NavigationTarget extends {
27
- onnavigate: ((event: infer navigateEvent) => unknown) | null
28
- }
29
- ? navigateEvent
30
- : Event
31
- type NavigationTargetEventMap = {
32
- navigate: NavigationTargetEvent
33
- }
34
-
35
- /**
36
- * Listener function type for a specific target and event name.
37
- */
38
- export type ListenerFor<target extends EventTarget, type extends EventType<target>> = (
39
- event: EnsureEvent<EventMap<target>[type], target>,
40
- signal: AbortSignal,
41
- ) => void
42
-
43
- /**
44
- * Partial map of event listeners keyed by event type.
45
- */
46
- export type EventListeners<target extends EventTarget> = Partial<{
47
- [k in EventType<target>]: ListenerFor<target, k>
48
- }>
49
-
50
- // oxfmt-ignore
51
- /**
52
- * Event map resolved for the given DOM or custom event target.
53
- */
54
- export type EventMap<target extends EventTarget> = (
55
- // TypedEventTarget
56
- target extends { __eventMap?: infer eventMap } ? eventMap :
57
-
58
- // elements
59
- target extends HTMLElement ? HTMLElementEventMap :
60
- target extends SVGSVGElement ? SVGSVGElementEventMap :
61
- target extends SVGElement ? SVGElementEventMap :
62
- target extends Element ? ElementEventMap :
63
- target extends Window ? WindowEventMap :
64
- target extends Document ? DocumentEventMap :
65
-
66
- // everything else
67
- target extends AbortSignal ? AbortSignalEventMap :
68
- target extends Animation ? AnimationEventMap :
69
- target extends AudioDecoder ? AudioDecoderEventMap :
70
- target extends AudioEncoder ? AudioEncoderEventMap :
71
- target extends AudioNode ? GlobalEventHandlersEventMap :
72
- target extends BaseAudioContext ? BaseAudioContextEventMap :
73
- target extends BroadcastChannel ? BroadcastChannelEventMap :
74
- target extends Clipboard ? GlobalEventHandlersEventMap :
75
- target extends EventSource ? EventSourceEventMap :
76
- target extends FileReader ? FileReaderEventMap :
77
- target extends FontFaceSet ? FontFaceSetEventMap :
78
- target extends IDBDatabase ? IDBDatabaseEventMap :
79
- target extends IDBTransaction ? IDBTransactionEventMap :
80
- target extends MIDIAccess ? MIDIAccessEventMap :
81
- target extends MIDIPort ? MIDIPortEventMap :
82
- target extends MediaDevices ? MediaDevicesEventMap :
83
- target extends MediaKeySession ? MediaKeySessionEventMap :
84
- target extends MediaQueryList ? MediaQueryListEventMap :
85
- target extends MediaRecorder ? MediaRecorderEventMap :
86
- target extends MediaSource ? MediaSourceEventMap :
87
- target extends MediaStream ? MediaStreamEventMap :
88
- target extends MediaStreamTrack ? MediaStreamTrackEventMap :
89
- target extends MessagePort ? MessagePortEventMap :
90
- target extends NavigationTarget ? NavigationTargetEventMap :
91
- target extends Node ? GlobalEventHandlersEventMap :
92
- target extends Notification ? NotificationEventMap :
93
- target extends OffscreenCanvas ? OffscreenCanvasEventMap :
94
- target extends PaymentRequest ? PaymentRequestEventMap :
95
- target extends PaymentResponse ? PaymentResponseEventMap :
96
- target extends Performance ? PerformanceEventMap :
97
- target extends PermissionStatus ? PermissionStatusEventMap :
98
- target extends PictureInPictureWindow ? PictureInPictureWindowEventMap :
99
- target extends RTCDTMFSender ? RTCDTMFSenderEventMap :
100
- target extends RTCDataChannel ? RTCDataChannelEventMap :
101
- target extends RTCDtlsTransport ? RTCDtlsTransportEventMap :
102
- target extends RTCIceTransport ? RTCIceTransportEventMap :
103
- target extends RTCPeerConnection ? RTCPeerConnectionEventMap :
104
- target extends RTCSctpTransport ? RTCSctpTransportEventMap :
105
- target extends RemotePlayback ? RemotePlaybackEventMap :
106
- target extends ScreenOrientation ? ScreenOrientationEventMap :
107
- target extends ServiceWorkerContainer ? ServiceWorkerContainerEventMap :
108
- target extends ServiceWorkerRegistration ? ServiceWorkerRegistrationEventMap :
109
- target extends ServiceWorker ? AbstractWorkerEventMap :
110
- target extends SharedWorker ? AbstractWorkerEventMap :
111
- target extends SourceBuffer ? SourceBufferEventMap :
112
- target extends SourceBufferList ? SourceBufferListEventMap :
113
- target extends SpeechSynthesis ? SpeechSynthesisEventMap :
114
- target extends SpeechSynthesisUtterance ? SpeechSynthesisUtteranceEventMap :
115
- target extends TextTrack ? TextTrackEventMap :
116
- target extends TextTrackCue ? TextTrackCueEventMap :
117
- target extends TextTrackList ? TextTrackListEventMap :
118
- target extends VideoDecoder ? VideoDecoderEventMap :
119
- target extends VideoEncoder ? VideoEncoderEventMap :
120
- target extends VisualViewport ? VisualViewportEventMap :
121
- target extends WakeLockSentinel ? WakeLockSentinelEventMap :
122
- target extends WebSocket ? WebSocketEventMap :
123
- target extends Window ? (WindowEventMap & GlobalEventHandlersEventMap) :
124
- target extends Worker ? AbstractWorkerEventMap :
125
- target extends XMLHttpRequestEventTarget ? XMLHttpRequestEventTargetEventMap :
126
- // default
127
- GlobalEventHandlersEventMap & Record<string, Event>
128
- )
129
-
130
- /**
131
- * Adds typed event listeners and reentry abort signals to a target.
132
- *
133
- * @param target Event target to attach listeners to.
134
- * @param signal Lifetime signal used to remove all listeners.
135
- * @param listeners Listener map keyed by event type.
136
- */
137
- export function addEventListeners<target extends EventTarget>(
138
- target: target,
139
- signal: AbortSignal,
140
- listeners: EventListeners<target>,
141
- ) {
142
- type AnyEvent = EnsureEvent<EventMap<target>[EventType<target>], target>
143
- type Listener = (event: AnyEvent, signal?: AbortSignal) => void
144
-
145
- for (let type in listeners) {
146
- let listener = listeners[type as EventType<target>] as Listener
147
- if (!listener) continue
148
- let reentry: AbortController | null = null
149
-
150
- signal.addEventListener('abort', () => {
151
- reentry?.abort()
152
- })
153
-
154
- target.addEventListener(
155
- type,
156
- (event) => {
157
- reentry?.abort()
158
- let dispatchedEvent = event as AnyEvent
159
-
160
- if (listener.length < 2) {
161
- reentry = null
162
- listener(dispatchedEvent)
163
- } else {
164
- reentry = new AbortController()
165
- listener(dispatchedEvent, reentry.signal)
166
- }
167
- },
168
- { signal },
169
- )
170
- }
171
- }