@tanstack/hotkeys-devtools 0.2.0 → 0.3.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.
- package/dist/HotkeysContextProvider.js +11 -1
- package/dist/HotkeysContextProvider.js.map +1 -1
- package/dist/components/ActionButtons.js +7 -2
- package/dist/components/ActionButtons.js.map +1 -1
- package/dist/components/DetailsPanel.js +458 -215
- package/dist/components/DetailsPanel.js.map +1 -1
- package/dist/components/HotkeyList.js +294 -139
- package/dist/components/HotkeyList.js.map +1 -1
- package/dist/components/Shell.js +3 -1
- package/dist/components/Shell.js.map +1 -1
- package/package.json +2 -2
- package/src/HotkeysContextProvider.tsx +31 -3
- package/src/components/ActionButtons.tsx +18 -5
- package/src/components/DetailsPanel.tsx +500 -204
- package/src/components/HotkeyList.tsx +195 -2
- package/src/components/Shell.tsx +4 -1
|
@@ -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 {
|
|
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: () =>
|
|
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
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
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
|
)
|