@tanstack/hotkeys-devtools 0.2.0 → 0.3.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.
@@ -1,12 +1,30 @@
1
1
  import { For, Show, createMemo } from 'solid-js'
2
- import { formatForDisplay } from '@tanstack/hotkeys'
2
+ import { formatForDisplay, formatHotkeySequence } from '@tanstack/hotkeys'
3
3
  import { useStyles } from '../styles/use-styles'
4
4
  import { useHotkeysDevtoolsState } from '../HotkeysContextProvider'
5
5
  import { ActionButtons } from './ActionButtons'
6
- import type { ConflictBehavior, HotkeyRegistration } from '@tanstack/hotkeys'
6
+ import type {
7
+ ConflictBehavior,
8
+ HotkeyRegistration,
9
+ HotkeySequence,
10
+ SequenceRegistrationView,
11
+ } from '@tanstack/hotkeys'
12
+
13
+ function sequenceKey(sequence: Array<string>): string {
14
+ return sequence.join('|')
15
+ }
16
+
17
+ function isSequenceRegistration(
18
+ reg: HotkeyRegistration | SequenceRegistrationView,
19
+ ): reg is SequenceRegistrationView {
20
+ return 'sequence' in reg && Array.isArray(reg.sequence)
21
+ }
7
22
 
8
23
  type DetailsPanelProps = {
9
- selectedRegistration: () => HotkeyRegistration | null
24
+ selectedRegistration: () =>
25
+ | HotkeyRegistration
26
+ | SequenceRegistrationView
27
+ | null
10
28
  }
11
29
 
12
30
  function getTargetDescription(target: HTMLElement | Document | Window): string {
@@ -53,6 +71,32 @@ function findScopeConflicts(
53
71
  )
54
72
  }
55
73
 
74
+ function findSequenceTargetConflicts(
75
+ registration: SequenceRegistrationView,
76
+ all: Array<SequenceRegistrationView>,
77
+ ): Array<SequenceRegistrationView> {
78
+ return all.filter(
79
+ (other) =>
80
+ other.id !== registration.id &&
81
+ sequenceKey(other.sequence) === sequenceKey(registration.sequence) &&
82
+ other.options.eventType === registration.options.eventType &&
83
+ other.target === registration.target,
84
+ )
85
+ }
86
+
87
+ function findSequenceScopeConflicts(
88
+ registration: SequenceRegistrationView,
89
+ all: Array<SequenceRegistrationView>,
90
+ ): Array<SequenceRegistrationView> {
91
+ return all.filter(
92
+ (other) =>
93
+ other.id !== registration.id &&
94
+ sequenceKey(other.sequence) === sequenceKey(registration.sequence) &&
95
+ other.options.eventType === registration.options.eventType &&
96
+ other.target !== registration.target,
97
+ )
98
+ }
99
+
56
100
  function getConflictItemStyle(
57
101
  behavior: ConflictBehavior,
58
102
  isSameTarget: boolean,
@@ -78,6 +122,427 @@ function getConflictLabel(
78
122
  return 'warning'
79
123
  }
80
124
 
125
+ function HotkeyDetails(props: {
126
+ registration: HotkeyRegistration
127
+ state: ReturnType<typeof useHotkeysDevtoolsState>
128
+ getTargetDescription: (t: HTMLElement | Document | Window) => string
129
+ findTargetConflicts: (
130
+ r: HotkeyRegistration,
131
+ all: Array<HotkeyRegistration>,
132
+ ) => Array<HotkeyRegistration>
133
+ findScopeConflicts: (
134
+ r: HotkeyRegistration,
135
+ all: Array<HotkeyRegistration>,
136
+ ) => Array<HotkeyRegistration>
137
+ getConflictItemStyle: (
138
+ b: ConflictBehavior,
139
+ same: boolean,
140
+ ) =>
141
+ | 'conflictItem'
142
+ | 'conflictItemAllow'
143
+ | 'conflictItemError'
144
+ | 'conflictItemScope'
145
+ getConflictLabel: (b: ConflictBehavior, same: boolean) => string
146
+ formatForDisplay: (hotkey: string) => string
147
+ styles: ReturnType<typeof useStyles>
148
+ }) {
149
+ const reg = () => props.registration
150
+ const parsed = () => reg().parsedHotkey
151
+ const targetConflicts = createMemo(() =>
152
+ props.findTargetConflicts(reg(), props.state.registrations()),
153
+ )
154
+ const scopeConflicts = createMemo(() =>
155
+ props.findScopeConflicts(reg(), props.state.registrations()),
156
+ )
157
+ const allConflicts = createMemo(() => [
158
+ ...targetConflicts(),
159
+ ...scopeConflicts(),
160
+ ])
161
+ const conflictBehavior = (): ConflictBehavior =>
162
+ reg().options.conflictBehavior ?? 'warn'
163
+
164
+ const keyParts = createMemo(() => {
165
+ const parts: Array<string> = []
166
+ const p = parsed()
167
+ if (p.ctrl) parts.push('Ctrl')
168
+ if (p.shift) parts.push('Shift')
169
+ if (p.alt) parts.push('Alt')
170
+ if (p.meta) parts.push('Meta')
171
+ parts.push(p.key)
172
+ return parts
173
+ })
174
+
175
+ const styles = props.styles
176
+
177
+ return (
178
+ <>
179
+ <div class={styles().stateHeader}>
180
+ <div class={styles().stateTitle}>
181
+ {props.formatForDisplay(reg().hotkey)}
182
+ </div>
183
+ <div class={styles().infoGrid}>
184
+ <div class={styles().infoLabel}>ID</div>
185
+ <div class={styles().infoValueMono}>{reg().id}</div>
186
+ <div class={styles().infoLabel}>Raw</div>
187
+ <div class={styles().infoValueMono}>{reg().hotkey}</div>
188
+ <div class={styles().infoLabel}>Target</div>
189
+ <div class={styles().infoValueMono}>
190
+ {props.getTargetDescription(reg().target)}
191
+ </div>
192
+ </div>
193
+ </div>
194
+
195
+ <div class={styles().detailsGrid}>
196
+ <div class={styles().detailSection}>
197
+ <div class={styles().detailSectionHeader}>Key Breakdown</div>
198
+ <div class={styles().keyBreakdown}>
199
+ <For each={keyParts()}>
200
+ {(part, i) => (
201
+ <>
202
+ <Show when={i() > 0}>
203
+ <span class={styles().keyBreakdownPlus}>+</span>
204
+ </Show>
205
+ <span class={styles().keyCapLarge}>{part}</span>
206
+ </>
207
+ )}
208
+ </For>
209
+ </div>
210
+ </div>
211
+
212
+ <div class={styles().detailSection}>
213
+ <div class={styles().detailSectionHeader}>Actions</div>
214
+ <ActionButtons registration={reg()} />
215
+ </div>
216
+
217
+ <div class={styles().detailSection}>
218
+ <div class={styles().detailSectionHeader}>Options</div>
219
+ <div>
220
+ <div class={styles().optionRow}>
221
+ <span class={styles().optionLabel}>enabled</span>
222
+ <span
223
+ class={
224
+ reg().options.enabled !== false
225
+ ? styles().optionValueTrue
226
+ : styles().optionValueFalse
227
+ }
228
+ >
229
+ {String(reg().options.enabled !== false)}
230
+ </span>
231
+ </div>
232
+ <div class={styles().optionRow}>
233
+ <span class={styles().optionLabel}>eventType</span>
234
+ <span class={styles().optionValue}>
235
+ {reg().options.eventType ?? 'keydown'}
236
+ </span>
237
+ </div>
238
+ <div class={styles().optionRow}>
239
+ <span class={styles().optionLabel}>preventDefault</span>
240
+ <span
241
+ class={
242
+ reg().options.preventDefault
243
+ ? styles().optionValueTrue
244
+ : styles().optionValueFalse
245
+ }
246
+ >
247
+ {String(!!reg().options.preventDefault)}
248
+ </span>
249
+ </div>
250
+ <div class={styles().optionRow}>
251
+ <span class={styles().optionLabel}>stopPropagation</span>
252
+ <span
253
+ class={
254
+ reg().options.stopPropagation
255
+ ? styles().optionValueTrue
256
+ : styles().optionValueFalse
257
+ }
258
+ >
259
+ {String(!!reg().options.stopPropagation)}
260
+ </span>
261
+ </div>
262
+ <div class={styles().optionRow}>
263
+ <span class={styles().optionLabel}>ignoreInputs</span>
264
+ <span
265
+ class={
266
+ reg().options.ignoreInputs !== false
267
+ ? styles().optionValueTrue
268
+ : styles().optionValueFalse
269
+ }
270
+ >
271
+ {String(reg().options.ignoreInputs !== false)}
272
+ </span>
273
+ </div>
274
+ <div class={styles().optionRow}>
275
+ <span class={styles().optionLabel}>requireReset</span>
276
+ <span
277
+ class={
278
+ reg().options.requireReset
279
+ ? styles().optionValueTrue
280
+ : styles().optionValueFalse
281
+ }
282
+ >
283
+ {String(!!reg().options.requireReset)}
284
+ </span>
285
+ </div>
286
+ <div class={styles().optionRow}>
287
+ <span class={styles().optionLabel}>conflictBehavior</span>
288
+ <span class={styles().optionValue}>{conflictBehavior()}</span>
289
+ </div>
290
+ <div class={styles().optionRow}>
291
+ <span class={styles().optionLabel}>hasFired</span>
292
+ <span
293
+ class={
294
+ reg().hasFired
295
+ ? styles().optionValueTrue
296
+ : styles().optionValueFalse
297
+ }
298
+ >
299
+ {String(reg().hasFired)}
300
+ </span>
301
+ </div>
302
+ </div>
303
+ </div>
304
+
305
+ <Show when={allConflicts().length > 0}>
306
+ <div class={styles().detailSection}>
307
+ <div class={styles().detailSectionHeader}>
308
+ Conflicts ({allConflicts().length})
309
+ </div>
310
+ <div class={styles().conflictList}>
311
+ <For each={targetConflicts()}>
312
+ {(conflict) => {
313
+ const itemStyle = () =>
314
+ props.getConflictItemStyle(conflictBehavior(), true)
315
+ const label = () =>
316
+ props.getConflictLabel(conflictBehavior(), true)
317
+ return (
318
+ <div class={styles()[itemStyle()]}>
319
+ <span>{label()}</span> {conflict.id}:{' '}
320
+ {props.formatForDisplay(conflict.hotkey)} (
321
+ {conflict.options.eventType ?? 'keydown'}) on{' '}
322
+ {props.getTargetDescription(conflict.target)}
323
+ </div>
324
+ )
325
+ }}
326
+ </For>
327
+ <For each={scopeConflicts()}>
328
+ {(conflict) => (
329
+ <div class={styles().conflictItemScope}>
330
+ <span>scope</span> {conflict.id}:{' '}
331
+ {props.formatForDisplay(conflict.hotkey)} (
332
+ {conflict.options.eventType ?? 'keydown'}) on{' '}
333
+ {props.getTargetDescription(conflict.target)}
334
+ </div>
335
+ )}
336
+ </For>
337
+ </div>
338
+ </div>
339
+ </Show>
340
+ </div>
341
+ </>
342
+ )
343
+ }
344
+
345
+ function SequenceDetails(props: {
346
+ registration: SequenceRegistrationView
347
+ state: ReturnType<typeof useHotkeysDevtoolsState>
348
+ getTargetDescription: (t: HTMLElement | Document | Window) => string
349
+ findSequenceTargetConflicts: (
350
+ r: SequenceRegistrationView,
351
+ all: Array<SequenceRegistrationView>,
352
+ ) => Array<SequenceRegistrationView>
353
+ findSequenceScopeConflicts: (
354
+ r: SequenceRegistrationView,
355
+ all: Array<SequenceRegistrationView>,
356
+ ) => Array<SequenceRegistrationView>
357
+ getConflictItemStyle: (
358
+ b: ConflictBehavior,
359
+ same: boolean,
360
+ ) =>
361
+ | 'conflictItem'
362
+ | 'conflictItemAllow'
363
+ | 'conflictItemError'
364
+ | 'conflictItemScope'
365
+ getConflictLabel: (b: ConflictBehavior, same: boolean) => string
366
+ formatHotkeySequence: (seq: HotkeySequence) => string
367
+ formatForDisplay: (hotkey: string) => string
368
+ styles: ReturnType<typeof useStyles>
369
+ }) {
370
+ const reg = () => props.registration
371
+ const targetConflicts = createMemo(() =>
372
+ props.findSequenceTargetConflicts(
373
+ reg(),
374
+ props.state.sequenceRegistrations(),
375
+ ),
376
+ )
377
+ const scopeConflicts = createMemo(() =>
378
+ props.findSequenceScopeConflicts(
379
+ reg(),
380
+ props.state.sequenceRegistrations(),
381
+ ),
382
+ )
383
+ const allConflicts = createMemo(() => [
384
+ ...targetConflicts(),
385
+ ...scopeConflicts(),
386
+ ])
387
+ const conflictBehavior = (): ConflictBehavior =>
388
+ reg().options.conflictBehavior ?? 'warn'
389
+
390
+ const styles = props.styles
391
+
392
+ return (
393
+ <>
394
+ <div class={styles().stateHeader}>
395
+ <div class={styles().stateTitle}>
396
+ {props.formatHotkeySequence(reg().sequence)}
397
+ </div>
398
+ <div class={styles().infoGrid}>
399
+ <div class={styles().infoLabel}>ID</div>
400
+ <div class={styles().infoValueMono}>{reg().id}</div>
401
+ <div class={styles().infoLabel}>Sequence</div>
402
+ <div class={styles().infoValueMono}>
403
+ {props.formatHotkeySequence(reg().sequence)}
404
+ </div>
405
+ <div class={styles().infoLabel}>Target</div>
406
+ <div class={styles().infoValueMono}>
407
+ {props.getTargetDescription(reg().target)}
408
+ </div>
409
+ </div>
410
+ </div>
411
+
412
+ <div class={styles().detailsGrid}>
413
+ <div class={styles().detailSection}>
414
+ <div class={styles().detailSectionHeader}>Key Breakdown</div>
415
+ <div class={styles().keyBreakdown}>
416
+ <For each={reg().sequence}>
417
+ {(step, i) => (
418
+ <>
419
+ <Show when={i() > 0}>
420
+ <span class={styles().keyBreakdownPlus}>→</span>
421
+ </Show>
422
+ <span class={styles().keyCapLarge}>
423
+ {props.formatForDisplay(step)}
424
+ </span>
425
+ </>
426
+ )}
427
+ </For>
428
+ </div>
429
+ </div>
430
+
431
+ <div class={styles().detailSection}>
432
+ <div class={styles().detailSectionHeader}>Actions</div>
433
+ <ActionButtons registration={reg()} />
434
+ </div>
435
+
436
+ <div class={styles().detailSection}>
437
+ <div class={styles().detailSectionHeader}>Options</div>
438
+ <div>
439
+ <div class={styles().optionRow}>
440
+ <span class={styles().optionLabel}>enabled</span>
441
+ <span
442
+ class={
443
+ reg().options.enabled !== false
444
+ ? styles().optionValueTrue
445
+ : styles().optionValueFalse
446
+ }
447
+ >
448
+ {String(reg().options.enabled !== false)}
449
+ </span>
450
+ </div>
451
+ <div class={styles().optionRow}>
452
+ <span class={styles().optionLabel}>eventType</span>
453
+ <span class={styles().optionValue}>
454
+ {reg().options.eventType ?? 'keydown'}
455
+ </span>
456
+ </div>
457
+ <div class={styles().optionRow}>
458
+ <span class={styles().optionLabel}>timeout</span>
459
+ <span class={styles().optionValue}>
460
+ {reg().options.timeout ?? 1000}ms
461
+ </span>
462
+ </div>
463
+ <div class={styles().optionRow}>
464
+ <span class={styles().optionLabel}>preventDefault</span>
465
+ <span
466
+ class={
467
+ reg().options.preventDefault
468
+ ? styles().optionValueTrue
469
+ : styles().optionValueFalse
470
+ }
471
+ >
472
+ {String(!!reg().options.preventDefault)}
473
+ </span>
474
+ </div>
475
+ <div class={styles().optionRow}>
476
+ <span class={styles().optionLabel}>stopPropagation</span>
477
+ <span
478
+ class={
479
+ reg().options.stopPropagation
480
+ ? styles().optionValueTrue
481
+ : styles().optionValueFalse
482
+ }
483
+ >
484
+ {String(!!reg().options.stopPropagation)}
485
+ </span>
486
+ </div>
487
+ <div class={styles().optionRow}>
488
+ <span class={styles().optionLabel}>ignoreInputs</span>
489
+ <span
490
+ class={
491
+ reg().options.ignoreInputs !== false
492
+ ? styles().optionValueTrue
493
+ : styles().optionValueFalse
494
+ }
495
+ >
496
+ {String(reg().options.ignoreInputs !== false)}
497
+ </span>
498
+ </div>
499
+ <div class={styles().optionRow}>
500
+ <span class={styles().optionLabel}>conflictBehavior</span>
501
+ <span class={styles().optionValue}>{conflictBehavior()}</span>
502
+ </div>
503
+ </div>
504
+ </div>
505
+
506
+ <Show when={allConflicts().length > 0}>
507
+ <div class={styles().detailSection}>
508
+ <div class={styles().detailSectionHeader}>
509
+ Conflicts ({allConflicts().length})
510
+ </div>
511
+ <div class={styles().conflictList}>
512
+ <For each={targetConflicts()}>
513
+ {(conflict) => {
514
+ const itemStyle = () =>
515
+ props.getConflictItemStyle(conflictBehavior(), true)
516
+ const label = () =>
517
+ props.getConflictLabel(conflictBehavior(), true)
518
+ return (
519
+ <div class={styles()[itemStyle()]}>
520
+ <span>{label()}</span> {conflict.id}:{' '}
521
+ {props.formatHotkeySequence(conflict.sequence)} (
522
+ {conflict.options.eventType ?? 'keydown'}) on{' '}
523
+ {props.getTargetDescription(conflict.target)}
524
+ </div>
525
+ )
526
+ }}
527
+ </For>
528
+ <For each={scopeConflicts()}>
529
+ {(conflict) => (
530
+ <div class={styles().conflictItemScope}>
531
+ <span>scope</span> {conflict.id}:{' '}
532
+ {props.formatHotkeySequence(conflict.sequence)} (
533
+ {conflict.options.eventType ?? 'keydown'}) on{' '}
534
+ {props.getTargetDescription(conflict.target)}
535
+ </div>
536
+ )}
537
+ </For>
538
+ </div>
539
+ </div>
540
+ </Show>
541
+ </div>
542
+ </>
543
+ )
544
+ }
545
+
81
546
  export function DetailsPanel(props: DetailsPanelProps) {
82
547
  const styles = useStyles()
83
548
  const state = useHotkeysDevtoolsState()
@@ -88,210 +553,41 @@ export function DetailsPanel(props: DetailsPanelProps) {
88
553
  when={props.selectedRegistration()}
89
554
  fallback={
90
555
  <div class={styles().noSelection}>
91
- Select a hotkey from the list to view its details
556
+ Select a hotkey or sequence from the list to view its details
92
557
  </div>
93
558
  }
94
559
  >
95
- {(reg) => {
96
- const parsed = () => reg().parsedHotkey
97
- const targetConflicts = createMemo(() =>
98
- findTargetConflicts(reg(), state.registrations()),
99
- )
100
- const scopeConflicts = createMemo(() =>
101
- findScopeConflicts(reg(), state.registrations()),
102
- )
103
- const allConflicts = createMemo(() => [
104
- ...targetConflicts(),
105
- ...scopeConflicts(),
106
- ])
107
- const conflictBehavior = (): ConflictBehavior =>
108
- reg().options.conflictBehavior ?? 'warn'
109
-
110
- // Build key parts for visual breakdown
111
- const keyParts = createMemo(() => {
112
- const parts: Array<string> = []
113
- const p = parsed()
114
- if (p.ctrl) parts.push('Ctrl')
115
- if (p.shift) parts.push('Shift')
116
- if (p.alt) parts.push('Alt')
117
- if (p.meta) parts.push('Meta')
118
- parts.push(p.key)
119
- return parts
120
- })
121
-
122
- return (
123
- <>
124
- <div class={styles().stateHeader}>
125
- <div class={styles().stateTitle}>
126
- {formatForDisplay(reg().hotkey)}
127
- </div>
128
- <div class={styles().infoGrid}>
129
- <div class={styles().infoLabel}>ID</div>
130
- <div class={styles().infoValueMono}>{reg().id}</div>
131
- <div class={styles().infoLabel}>Raw</div>
132
- <div class={styles().infoValueMono}>{reg().hotkey}</div>
133
- <div class={styles().infoLabel}>Target</div>
134
- <div class={styles().infoValueMono}>
135
- {getTargetDescription(reg().target)}
136
- </div>
137
- </div>
138
- </div>
139
-
140
- <div class={styles().detailsGrid}>
141
- {/* Key Breakdown */}
142
- <div class={styles().detailSection}>
143
- <div class={styles().detailSectionHeader}>Key Breakdown</div>
144
- <div class={styles().keyBreakdown}>
145
- <For each={keyParts()}>
146
- {(part, i) => (
147
- <>
148
- <Show when={i() > 0}>
149
- <span class={styles().keyBreakdownPlus}>+</span>
150
- </Show>
151
- <span class={styles().keyCapLarge}>{part}</span>
152
- </>
153
- )}
154
- </For>
155
- </div>
156
- </div>
157
-
158
- {/* Actions */}
159
- <div class={styles().detailSection}>
160
- <div class={styles().detailSectionHeader}>Actions</div>
161
- <ActionButtons registration={reg()} />
162
- </div>
163
-
164
- {/* Options */}
165
- <div class={styles().detailSection}>
166
- <div class={styles().detailSectionHeader}>Options</div>
167
- <div>
168
- <div class={styles().optionRow}>
169
- <span class={styles().optionLabel}>enabled</span>
170
- <span
171
- class={
172
- reg().options.enabled !== false
173
- ? styles().optionValueTrue
174
- : styles().optionValueFalse
175
- }
176
- >
177
- {String(reg().options.enabled !== false)}
178
- </span>
179
- </div>
180
- <div class={styles().optionRow}>
181
- <span class={styles().optionLabel}>eventType</span>
182
- <span class={styles().optionValue}>
183
- {reg().options.eventType ?? 'keydown'}
184
- </span>
185
- </div>
186
- <div class={styles().optionRow}>
187
- <span class={styles().optionLabel}>preventDefault</span>
188
- <span
189
- class={
190
- reg().options.preventDefault
191
- ? styles().optionValueTrue
192
- : styles().optionValueFalse
193
- }
194
- >
195
- {String(!!reg().options.preventDefault)}
196
- </span>
197
- </div>
198
- <div class={styles().optionRow}>
199
- <span class={styles().optionLabel}>stopPropagation</span>
200
- <span
201
- class={
202
- reg().options.stopPropagation
203
- ? styles().optionValueTrue
204
- : styles().optionValueFalse
205
- }
206
- >
207
- {String(!!reg().options.stopPropagation)}
208
- </span>
209
- </div>
210
- <div class={styles().optionRow}>
211
- <span class={styles().optionLabel}>ignoreInputs</span>
212
- <span
213
- class={
214
- reg().options.ignoreInputs !== false
215
- ? styles().optionValueTrue
216
- : styles().optionValueFalse
217
- }
218
- >
219
- {String(reg().options.ignoreInputs !== false)}
220
- </span>
221
- </div>
222
- <div class={styles().optionRow}>
223
- <span class={styles().optionLabel}>requireReset</span>
224
- <span
225
- class={
226
- reg().options.requireReset
227
- ? styles().optionValueTrue
228
- : styles().optionValueFalse
229
- }
230
- >
231
- {String(!!reg().options.requireReset)}
232
- </span>
233
- </div>
234
- <div class={styles().optionRow}>
235
- <span class={styles().optionLabel}>conflictBehavior</span>
236
- <span class={styles().optionValue}>
237
- {conflictBehavior()}
238
- </span>
239
- </div>
240
- <div class={styles().optionRow}>
241
- <span class={styles().optionLabel}>hasFired</span>
242
- <span
243
- class={
244
- reg().hasFired
245
- ? styles().optionValueTrue
246
- : styles().optionValueFalse
247
- }
248
- >
249
- {String(reg().hasFired)}
250
- </span>
251
- </div>
252
- </div>
253
- </div>
254
-
255
- {/* Conflicts */}
256
- <Show when={allConflicts().length > 0}>
257
- <div class={styles().detailSection}>
258
- <div class={styles().detailSectionHeader}>
259
- Conflicts ({allConflicts().length})
260
- </div>
261
- <div class={styles().conflictList}>
262
- <For each={targetConflicts()}>
263
- {(conflict) => {
264
- const itemStyle = () =>
265
- getConflictItemStyle(conflictBehavior(), true)
266
- const label = () =>
267
- getConflictLabel(conflictBehavior(), true)
268
- return (
269
- <div class={styles()[itemStyle()]}>
270
- <span>{label()}</span> {conflict.id}:{' '}
271
- {formatForDisplay(conflict.hotkey)} (
272
- {conflict.options.eventType ?? 'keydown'}) on{' '}
273
- {getTargetDescription(conflict.target)}
274
- </div>
275
- )
276
- }}
277
- </For>
278
- <For each={scopeConflicts()}>
279
- {(conflict) => (
280
- <div class={styles().conflictItemScope}>
281
- <span>scope</span> {conflict.id}:{' '}
282
- {formatForDisplay(conflict.hotkey)} (
283
- {conflict.options.eventType ?? 'keydown'}) on{' '}
284
- {getTargetDescription(conflict.target)}
285
- </div>
286
- )}
287
- </For>
288
- </div>
289
- </div>
290
- </Show>
291
- </div>
292
- </>
293
- )
294
- }}
560
+ {(reg) => (
561
+ <Show
562
+ when={isSequenceRegistration(reg())}
563
+ fallback={
564
+ <HotkeyDetails
565
+ registration={reg() as HotkeyRegistration}
566
+ state={state}
567
+ getTargetDescription={getTargetDescription}
568
+ findTargetConflicts={findTargetConflicts}
569
+ findScopeConflicts={findScopeConflicts}
570
+ getConflictItemStyle={getConflictItemStyle}
571
+ getConflictLabel={getConflictLabel}
572
+ formatForDisplay={formatForDisplay}
573
+ styles={styles}
574
+ />
575
+ }
576
+ >
577
+ <SequenceDetails
578
+ registration={reg() as SequenceRegistrationView}
579
+ state={state}
580
+ getTargetDescription={getTargetDescription}
581
+ findSequenceTargetConflicts={findSequenceTargetConflicts}
582
+ findSequenceScopeConflicts={findSequenceScopeConflicts}
583
+ getConflictItemStyle={getConflictItemStyle}
584
+ getConflictLabel={getConflictLabel}
585
+ formatHotkeySequence={formatHotkeySequence}
586
+ formatForDisplay={formatForDisplay}
587
+ styles={styles}
588
+ />
589
+ </Show>
590
+ )}
295
591
  </Show>
296
592
  </div>
297
593
  )