use-kbd 0.3.0 → 0.4.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/README.md +35 -36
- package/dist/index.cjs +1374 -285
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +405 -56
- package/dist/index.d.ts +405 -56
- package/dist/index.js +1339 -281
- package/dist/index.js.map +1 -1
- package/package.json +6 -8
- package/src/styles.css +255 -65
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "use-kbd",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Keyboard-first UX for React: action registration, shortcuts modal, omnibar, and sequences",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -48,19 +48,17 @@
|
|
|
48
48
|
"react": "^18.3.1",
|
|
49
49
|
"tsup": "^8.3.5",
|
|
50
50
|
"typescript": "^5.7.2",
|
|
51
|
-
"typescript-eslint": "^8.50.1"
|
|
52
|
-
"vitest": "^2.1.8"
|
|
51
|
+
"typescript-eslint": "^8.50.1"
|
|
53
52
|
},
|
|
54
53
|
"peerDependencies": {
|
|
55
|
-
"react": ">=18.0.0"
|
|
56
|
-
|
|
57
|
-
"dependencies": {
|
|
58
|
-
"@rdub/base": "^0.8.1"
|
|
54
|
+
"react": ">=18.0.0",
|
|
55
|
+
"react-dom": ">=18.0.0"
|
|
59
56
|
},
|
|
57
|
+
"dependencies": {},
|
|
60
58
|
"scripts": {
|
|
61
59
|
"build": "tsup",
|
|
62
60
|
"dev": "tsup --watch",
|
|
63
|
-
"test": "
|
|
61
|
+
"test": "pnpm -C site test",
|
|
64
62
|
"lint": "eslint src"
|
|
65
63
|
}
|
|
66
64
|
}
|
package/src/styles.css
CHANGED
|
@@ -9,37 +9,44 @@
|
|
|
9
9
|
* }
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
/* === CSS Custom Properties === */
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
--kbd-bg:
|
|
17
|
-
--kbd-
|
|
18
|
-
--kbd-text:
|
|
19
|
-
--kbd-
|
|
20
|
-
--kbd-
|
|
21
|
-
--kbd-accent:
|
|
22
|
-
--kbd-accent-hover: var(--kbd-accent-hover, #2563eb);
|
|
12
|
+
/* === CSS Custom Properties (defaults) === */
|
|
13
|
+
:root {
|
|
14
|
+
/* Colors - light mode defaults */
|
|
15
|
+
--kbd-bg: #ffffff;
|
|
16
|
+
--kbd-bg-secondary: #f9fafb;
|
|
17
|
+
--kbd-text: #1f2937;
|
|
18
|
+
--kbd-text-secondary: #6b7280;
|
|
19
|
+
--kbd-border: #e5e7eb;
|
|
20
|
+
--kbd-accent: #3b82f6;
|
|
21
|
+
--kbd-accent-hover: #2563eb;
|
|
23
22
|
|
|
24
23
|
/* Conflict/warning colors */
|
|
25
|
-
--kbd-conflict:
|
|
26
|
-
--kbd-conflict-bg:
|
|
27
|
-
--kbd-warning:
|
|
28
|
-
--kbd-warning-bg:
|
|
24
|
+
--kbd-conflict: #ef4444;
|
|
25
|
+
--kbd-conflict-bg: #fef2f2;
|
|
26
|
+
--kbd-warning: #f59e0b;
|
|
27
|
+
--kbd-warning-bg: #fef3c7;
|
|
28
|
+
|
|
29
|
+
/* Timeout bar */
|
|
30
|
+
--kbd-timeout-bar: #10b981;
|
|
29
31
|
|
|
30
32
|
/* Kbd element */
|
|
31
|
-
--kbd-kbd-bg:
|
|
32
|
-
--kbd-kbd-border:
|
|
33
|
-
--kbd-kbd-text:
|
|
33
|
+
--kbd-kbd-bg: #f3f4f6;
|
|
34
|
+
--kbd-kbd-border: #d1d5db;
|
|
35
|
+
--kbd-kbd-text: #374151;
|
|
34
36
|
|
|
35
37
|
/* Spacing & sizing */
|
|
36
|
-
--kbd-radius:
|
|
37
|
-
--kbd-radius-sm:
|
|
38
|
-
--kbd-gap:
|
|
39
|
-
--kbd-padding:
|
|
38
|
+
--kbd-radius: 8px;
|
|
39
|
+
--kbd-radius-sm: 4px;
|
|
40
|
+
--kbd-gap: 8px;
|
|
41
|
+
--kbd-padding: 16px;
|
|
40
42
|
|
|
41
43
|
/* Animation */
|
|
42
|
-
--kbd-transition:
|
|
44
|
+
--kbd-transition: 150ms ease;
|
|
45
|
+
|
|
46
|
+
/* Sequence modal */
|
|
47
|
+
--kbd-sequence-max-height: 300px;
|
|
48
|
+
--kbd-sequence-row-padding: 8px 12px;
|
|
49
|
+
--kbd-sequence-row-gap: 8px;
|
|
43
50
|
}
|
|
44
51
|
|
|
45
52
|
/* === Backdrop === */
|
|
@@ -79,12 +86,34 @@
|
|
|
79
86
|
font-weight: 600;
|
|
80
87
|
}
|
|
81
88
|
|
|
89
|
+
.kbd-modal-header-buttons {
|
|
90
|
+
display: flex;
|
|
91
|
+
align-items: center;
|
|
92
|
+
gap: 8px;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.kbd-reset-btn {
|
|
96
|
+
background: none;
|
|
97
|
+
border: 1px solid var(--kbd-border);
|
|
98
|
+
border-radius: var(--kbd-radius-sm);
|
|
99
|
+
padding: 4px 10px;
|
|
100
|
+
font-size: 0.875rem;
|
|
101
|
+
cursor: pointer;
|
|
102
|
+
color: var(--kbd-text-secondary);
|
|
103
|
+
transition: all var(--kbd-transition);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.kbd-reset-btn:hover {
|
|
107
|
+
color: var(--kbd-text);
|
|
108
|
+
border-color: var(--kbd-text-secondary);
|
|
109
|
+
}
|
|
110
|
+
|
|
82
111
|
.kbd-modal-close {
|
|
83
112
|
background: none;
|
|
84
113
|
border: none;
|
|
85
|
-
font-size: 1.
|
|
114
|
+
font-size: 1.25rem;
|
|
86
115
|
cursor: pointer;
|
|
87
|
-
padding: 4px;
|
|
116
|
+
padding: 4px 8px;
|
|
88
117
|
line-height: 1;
|
|
89
118
|
color: var(--kbd-text-secondary);
|
|
90
119
|
transition: color var(--kbd-transition);
|
|
@@ -136,6 +165,7 @@
|
|
|
136
165
|
|
|
137
166
|
/* === Kbd element === */
|
|
138
167
|
.kbd-kbd {
|
|
168
|
+
position: relative;
|
|
139
169
|
display: inline-flex;
|
|
140
170
|
align-items: center;
|
|
141
171
|
gap: 2px;
|
|
@@ -202,12 +232,47 @@
|
|
|
202
232
|
flex-shrink: 0;
|
|
203
233
|
}
|
|
204
234
|
|
|
235
|
+
/* === Key icons (arrows, enter, etc.) === */
|
|
236
|
+
.kbd-key-icon {
|
|
237
|
+
width: 14px;
|
|
238
|
+
height: 14px;
|
|
239
|
+
flex-shrink: 0;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/* === Digit placeholder (for \d and \d+ patterns) === */
|
|
243
|
+
.kbd-placeholder {
|
|
244
|
+
font-family: monospace;
|
|
245
|
+
font-weight: 600;
|
|
246
|
+
color: var(--kbd-text);
|
|
247
|
+
background: var(--kbd-bg-secondary);
|
|
248
|
+
border: 1px solid var(--kbd-border);
|
|
249
|
+
border-radius: var(--kbd-radius-sm);
|
|
250
|
+
padding: 0 3px;
|
|
251
|
+
margin: 0 1px;
|
|
252
|
+
}
|
|
253
|
+
|
|
205
254
|
/* === Sequence separator === */
|
|
206
255
|
.kbd-sequence-sep {
|
|
207
256
|
color: var(--kbd-text-secondary);
|
|
208
257
|
margin: 0 1px;
|
|
209
258
|
}
|
|
210
259
|
|
|
260
|
+
/* === Clickable kbd === */
|
|
261
|
+
.kbd-clickable {
|
|
262
|
+
cursor: pointer;
|
|
263
|
+
transition: all var(--kbd-transition);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
.kbd-clickable:hover {
|
|
267
|
+
background: var(--kbd-accent);
|
|
268
|
+
color: white;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
.kbd-clickable:focus-visible {
|
|
272
|
+
outline: 2px solid var(--kbd-accent);
|
|
273
|
+
outline-offset: 2px;
|
|
274
|
+
}
|
|
275
|
+
|
|
211
276
|
/* === Add binding button === */
|
|
212
277
|
.kbd-add-btn {
|
|
213
278
|
background: none;
|
|
@@ -227,23 +292,39 @@
|
|
|
227
292
|
|
|
228
293
|
/* === Remove binding button === */
|
|
229
294
|
.kbd-remove-btn {
|
|
230
|
-
|
|
295
|
+
position: absolute;
|
|
296
|
+
top: -6px;
|
|
297
|
+
right: -6px;
|
|
298
|
+
display: flex;
|
|
299
|
+
align-items: center;
|
|
300
|
+
justify-content: center;
|
|
301
|
+
background: var(--kbd-conflict, #dc2626);
|
|
231
302
|
border: none;
|
|
303
|
+
border-radius: 50%;
|
|
232
304
|
padding: 0;
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
305
|
+
width: 16px;
|
|
306
|
+
height: 16px;
|
|
307
|
+
font-size: 12px;
|
|
308
|
+
font-weight: bold;
|
|
309
|
+
line-height: 1;
|
|
310
|
+
color: #fff;
|
|
236
311
|
cursor: pointer;
|
|
237
312
|
opacity: 0;
|
|
238
|
-
|
|
313
|
+
transform: scale(0.8);
|
|
314
|
+
transition:
|
|
315
|
+
opacity var(--kbd-transition),
|
|
316
|
+
transform var(--kbd-transition),
|
|
317
|
+
background var(--kbd-transition);
|
|
239
318
|
}
|
|
240
319
|
|
|
241
|
-
.kbd-kbd:hover .kbd-remove-btn
|
|
320
|
+
.kbd-kbd:hover .kbd-remove-btn,
|
|
321
|
+
.kbd-kbd:focus-within .kbd-remove-btn {
|
|
242
322
|
opacity: 1;
|
|
323
|
+
transform: scale(1);
|
|
243
324
|
}
|
|
244
325
|
|
|
245
326
|
.kbd-remove-btn:hover {
|
|
246
|
-
|
|
327
|
+
background: #b91c1c;
|
|
247
328
|
}
|
|
248
329
|
|
|
249
330
|
/* === Timeout bar === */
|
|
@@ -251,8 +332,8 @@
|
|
|
251
332
|
position: absolute;
|
|
252
333
|
bottom: 0;
|
|
253
334
|
left: 0;
|
|
254
|
-
height:
|
|
255
|
-
background-color: var(--kbd-
|
|
335
|
+
height: 3px;
|
|
336
|
+
background-color: var(--kbd-timeout-bar);
|
|
256
337
|
animation: kbd-timeout linear forwards;
|
|
257
338
|
}
|
|
258
339
|
|
|
@@ -362,18 +443,6 @@
|
|
|
362
443
|
}
|
|
363
444
|
|
|
364
445
|
.kbd-sequence {
|
|
365
|
-
/* Inherit CSS custom properties */
|
|
366
|
-
--kbd-bg: var(--kbd-bg, #ffffff);
|
|
367
|
-
--kbd-bg-secondary: var(--kbd-bg-secondary, #f9fafb);
|
|
368
|
-
--kbd-text: var(--kbd-text, #1f2937);
|
|
369
|
-
--kbd-text-secondary: var(--kbd-text-secondary, #6b7280);
|
|
370
|
-
--kbd-border: var(--kbd-border, #e5e7eb);
|
|
371
|
-
--kbd-kbd-bg: var(--kbd-kbd-bg, #f3f4f6);
|
|
372
|
-
--kbd-kbd-border: var(--kbd-kbd-border, #d1d5db);
|
|
373
|
-
--kbd-kbd-text: var(--kbd-kbd-text, #374151);
|
|
374
|
-
--kbd-radius: var(--kbd-radius, 8px);
|
|
375
|
-
--kbd-accent: var(--kbd-accent, #3b82f6);
|
|
376
|
-
|
|
377
446
|
background-color: var(--kbd-bg);
|
|
378
447
|
border: 1px solid var(--kbd-border);
|
|
379
448
|
border-radius: 12px;
|
|
@@ -447,8 +516,8 @@
|
|
|
447
516
|
padding: 12px 16px;
|
|
448
517
|
display: flex;
|
|
449
518
|
flex-direction: column;
|
|
450
|
-
gap:
|
|
451
|
-
max-height:
|
|
519
|
+
gap: var(--kbd-sequence-row-gap);
|
|
520
|
+
max-height: var(--kbd-sequence-max-height);
|
|
452
521
|
overflow-y: auto;
|
|
453
522
|
}
|
|
454
523
|
|
|
@@ -456,14 +525,19 @@
|
|
|
456
525
|
display: flex;
|
|
457
526
|
align-items: center;
|
|
458
527
|
gap: 8px;
|
|
459
|
-
padding:
|
|
460
|
-
background-color: var(--kbd-bg-secondary);
|
|
528
|
+
padding: var(--kbd-sequence-row-padding);
|
|
461
529
|
border-radius: 6px;
|
|
462
530
|
transition: background-color 0.1s ease;
|
|
463
531
|
}
|
|
464
532
|
|
|
465
533
|
.kbd-sequence-completion:hover {
|
|
466
|
-
background-color: var(--kbd-bg);
|
|
534
|
+
background-color: var(--kbd-bg-secondary);
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
.kbd-sequence-completion:first-child {
|
|
538
|
+
background-color: var(--kbd-bg-secondary);
|
|
539
|
+
outline: 2px solid var(--kbd-accent);
|
|
540
|
+
outline-offset: -2px;
|
|
467
541
|
}
|
|
468
542
|
|
|
469
543
|
.kbd-sequence-arrow {
|
|
@@ -508,19 +582,135 @@
|
|
|
508
582
|
text-align: center;
|
|
509
583
|
}
|
|
510
584
|
|
|
585
|
+
/* === Lookup Modal === */
|
|
586
|
+
.kbd-lookup-backdrop {
|
|
587
|
+
position: fixed;
|
|
588
|
+
inset: 0;
|
|
589
|
+
display: flex;
|
|
590
|
+
align-items: flex-start;
|
|
591
|
+
justify-content: center;
|
|
592
|
+
padding-top: 15vh;
|
|
593
|
+
z-index: 9999;
|
|
594
|
+
background-color: rgba(0, 0, 0, 0.5);
|
|
595
|
+
animation: kbd-fade-in 0.1s ease;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
.kbd-lookup {
|
|
599
|
+
background-color: var(--kbd-bg);
|
|
600
|
+
border-radius: var(--kbd-radius);
|
|
601
|
+
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
|
|
602
|
+
width: 90vw;
|
|
603
|
+
max-width: 500px;
|
|
604
|
+
max-height: 70vh;
|
|
605
|
+
display: flex;
|
|
606
|
+
flex-direction: column;
|
|
607
|
+
overflow: hidden;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
.kbd-lookup-header {
|
|
611
|
+
padding: 12px 16px;
|
|
612
|
+
border-bottom: 1px solid var(--kbd-border);
|
|
613
|
+
display: flex;
|
|
614
|
+
flex-direction: column;
|
|
615
|
+
gap: 8px;
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
.kbd-lookup-search {
|
|
619
|
+
display: flex;
|
|
620
|
+
align-items: center;
|
|
621
|
+
min-height: 32px;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
.kbd-lookup-placeholder {
|
|
625
|
+
color: var(--kbd-text-secondary);
|
|
626
|
+
font-size: 0.875rem;
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
.kbd-lookup-hint {
|
|
630
|
+
font-size: 0.75rem;
|
|
631
|
+
color: var(--kbd-text-secondary);
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
.kbd-lookup-results {
|
|
635
|
+
flex: 1;
|
|
636
|
+
overflow-y: auto;
|
|
637
|
+
padding: 8px;
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
.kbd-lookup-result {
|
|
641
|
+
display: flex;
|
|
642
|
+
align-items: center;
|
|
643
|
+
gap: 12px;
|
|
644
|
+
padding: 8px 12px;
|
|
645
|
+
border-radius: 6px;
|
|
646
|
+
cursor: pointer;
|
|
647
|
+
transition: background-color 0.1s ease;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
.kbd-lookup-result:hover,
|
|
651
|
+
.kbd-lookup-result.selected {
|
|
652
|
+
background-color: var(--kbd-bg-secondary);
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
.kbd-lookup-result.selected {
|
|
656
|
+
outline: 2px solid var(--kbd-accent);
|
|
657
|
+
outline-offset: -2px;
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
.kbd-lookup-labels {
|
|
661
|
+
flex: 1;
|
|
662
|
+
font-size: 0.875rem;
|
|
663
|
+
color: var(--kbd-text);
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
.kbd-lookup-empty {
|
|
667
|
+
padding: 24px;
|
|
668
|
+
text-align: center;
|
|
669
|
+
color: var(--kbd-text-secondary);
|
|
670
|
+
font-size: 0.875rem;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
.kbd-lookup-continuations {
|
|
674
|
+
padding: 8px 16px;
|
|
675
|
+
border-top: 1px solid var(--kbd-border);
|
|
676
|
+
display: flex;
|
|
677
|
+
align-items: center;
|
|
678
|
+
gap: 8px;
|
|
679
|
+
flex-wrap: wrap;
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
.kbd-lookup-continuations-label {
|
|
683
|
+
font-size: 0.75rem;
|
|
684
|
+
color: var(--kbd-text-secondary);
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
.kbd-kbd.kbd-small {
|
|
688
|
+
font-size: 0.7rem;
|
|
689
|
+
padding: 2px 5px;
|
|
690
|
+
}
|
|
691
|
+
|
|
511
692
|
/* === Dark mode preset === */
|
|
512
|
-
[data-theme="dark"]
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
--kbd-
|
|
519
|
-
--kbd-
|
|
520
|
-
--kbd-
|
|
521
|
-
--kbd-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
693
|
+
[data-theme="dark"],
|
|
694
|
+
.dark {
|
|
695
|
+
--kbd-bg: #1f2937;
|
|
696
|
+
--kbd-bg-secondary: #374151;
|
|
697
|
+
--kbd-text: #f3f4f6;
|
|
698
|
+
--kbd-text-secondary: #9ca3af;
|
|
699
|
+
--kbd-border: #4b5563;
|
|
700
|
+
--kbd-kbd-bg: #374151;
|
|
701
|
+
--kbd-kbd-border: #4b5563;
|
|
702
|
+
--kbd-kbd-text: #e5e7eb;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
@media (prefers-color-scheme: dark) {
|
|
706
|
+
:root:not([data-theme="light"]):not(.light) {
|
|
707
|
+
--kbd-bg: #1f2937;
|
|
708
|
+
--kbd-bg-secondary: #374151;
|
|
709
|
+
--kbd-text: #f3f4f6;
|
|
710
|
+
--kbd-text-secondary: #9ca3af;
|
|
711
|
+
--kbd-border: #4b5563;
|
|
712
|
+
--kbd-kbd-bg: #374151;
|
|
713
|
+
--kbd-kbd-border: #4b5563;
|
|
714
|
+
--kbd-kbd-text: #e5e7eb;
|
|
715
|
+
}
|
|
526
716
|
}
|