@nick-skriabin/glyph 0.1.22 → 0.1.24
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/index.cjs +394 -30
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.js +394 -30
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -536,6 +536,211 @@ var Terminal = class {
|
|
|
536
536
|
};
|
|
537
537
|
|
|
538
538
|
// src/runtime/input.ts
|
|
539
|
+
function getKeyNameFromCode(code) {
|
|
540
|
+
switch (code) {
|
|
541
|
+
// Standard ASCII
|
|
542
|
+
case 9:
|
|
543
|
+
return "tab";
|
|
544
|
+
case 13:
|
|
545
|
+
return "return";
|
|
546
|
+
case 27:
|
|
547
|
+
return "escape";
|
|
548
|
+
case 32:
|
|
549
|
+
return " ";
|
|
550
|
+
case 127:
|
|
551
|
+
return "backspace";
|
|
552
|
+
// Kitty protocol special keys
|
|
553
|
+
case 57358:
|
|
554
|
+
return "capslock";
|
|
555
|
+
case 57359:
|
|
556
|
+
return "scrolllock";
|
|
557
|
+
case 57360:
|
|
558
|
+
return "numlock";
|
|
559
|
+
case 57361:
|
|
560
|
+
return "printscreen";
|
|
561
|
+
case 57362:
|
|
562
|
+
return "pause";
|
|
563
|
+
case 57363:
|
|
564
|
+
return "menu";
|
|
565
|
+
// Function keys (kitty uses these codes)
|
|
566
|
+
case 57364:
|
|
567
|
+
return "f13";
|
|
568
|
+
case 57365:
|
|
569
|
+
return "f14";
|
|
570
|
+
case 57366:
|
|
571
|
+
return "f15";
|
|
572
|
+
case 57367:
|
|
573
|
+
return "f16";
|
|
574
|
+
case 57368:
|
|
575
|
+
return "f17";
|
|
576
|
+
case 57369:
|
|
577
|
+
return "f18";
|
|
578
|
+
case 57370:
|
|
579
|
+
return "f19";
|
|
580
|
+
case 57371:
|
|
581
|
+
return "f20";
|
|
582
|
+
case 57372:
|
|
583
|
+
return "f21";
|
|
584
|
+
case 57373:
|
|
585
|
+
return "f22";
|
|
586
|
+
case 57374:
|
|
587
|
+
return "f23";
|
|
588
|
+
case 57375:
|
|
589
|
+
return "f24";
|
|
590
|
+
case 57376:
|
|
591
|
+
return "f25";
|
|
592
|
+
// Keypad keys
|
|
593
|
+
case 57399:
|
|
594
|
+
return "kp0";
|
|
595
|
+
case 57400:
|
|
596
|
+
return "kp1";
|
|
597
|
+
case 57401:
|
|
598
|
+
return "kp2";
|
|
599
|
+
case 57402:
|
|
600
|
+
return "kp3";
|
|
601
|
+
case 57403:
|
|
602
|
+
return "kp4";
|
|
603
|
+
case 57404:
|
|
604
|
+
return "kp5";
|
|
605
|
+
case 57405:
|
|
606
|
+
return "kp6";
|
|
607
|
+
case 57406:
|
|
608
|
+
return "kp7";
|
|
609
|
+
case 57407:
|
|
610
|
+
return "kp8";
|
|
611
|
+
case 57408:
|
|
612
|
+
return "kp9";
|
|
613
|
+
case 57409:
|
|
614
|
+
return "kpdecimal";
|
|
615
|
+
case 57410:
|
|
616
|
+
return "kpdivide";
|
|
617
|
+
case 57411:
|
|
618
|
+
return "kpmultiply";
|
|
619
|
+
case 57412:
|
|
620
|
+
return "kpminus";
|
|
621
|
+
case 57413:
|
|
622
|
+
return "kpplus";
|
|
623
|
+
case 57414:
|
|
624
|
+
return "kpenter";
|
|
625
|
+
case 57415:
|
|
626
|
+
return "kpequal";
|
|
627
|
+
// Navigation (kitty protocol)
|
|
628
|
+
case 57416:
|
|
629
|
+
return "kpleft";
|
|
630
|
+
case 57417:
|
|
631
|
+
return "kpright";
|
|
632
|
+
case 57418:
|
|
633
|
+
return "kpup";
|
|
634
|
+
case 57419:
|
|
635
|
+
return "kpdown";
|
|
636
|
+
case 57420:
|
|
637
|
+
return "kppageup";
|
|
638
|
+
case 57421:
|
|
639
|
+
return "kppagedown";
|
|
640
|
+
case 57422:
|
|
641
|
+
return "kphome";
|
|
642
|
+
case 57423:
|
|
643
|
+
return "kpend";
|
|
644
|
+
case 57424:
|
|
645
|
+
return "kpinsert";
|
|
646
|
+
case 57425:
|
|
647
|
+
return "kpdelete";
|
|
648
|
+
// Media keys
|
|
649
|
+
case 57428:
|
|
650
|
+
return "mediaplaypause";
|
|
651
|
+
case 57429:
|
|
652
|
+
return "mediastop";
|
|
653
|
+
case 57430:
|
|
654
|
+
return "mediaprev";
|
|
655
|
+
case 57431:
|
|
656
|
+
return "medianext";
|
|
657
|
+
case 57432:
|
|
658
|
+
return "mediarewind";
|
|
659
|
+
case 57433:
|
|
660
|
+
return "mediafastforward";
|
|
661
|
+
case 57434:
|
|
662
|
+
return "mediamute";
|
|
663
|
+
case 57435:
|
|
664
|
+
return "volumedown";
|
|
665
|
+
case 57436:
|
|
666
|
+
return "volumeup";
|
|
667
|
+
default:
|
|
668
|
+
if (code >= 32 && code <= 126) {
|
|
669
|
+
return String.fromCharCode(code).toLowerCase();
|
|
670
|
+
}
|
|
671
|
+
return "unknown";
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
function getTildeKeyName(param) {
|
|
675
|
+
const baseParam = param.split(";")[0];
|
|
676
|
+
switch (baseParam) {
|
|
677
|
+
case "1":
|
|
678
|
+
return "home";
|
|
679
|
+
case "2":
|
|
680
|
+
return "insert";
|
|
681
|
+
case "3":
|
|
682
|
+
return "delete";
|
|
683
|
+
case "4":
|
|
684
|
+
return "end";
|
|
685
|
+
case "5":
|
|
686
|
+
return "pageup";
|
|
687
|
+
case "6":
|
|
688
|
+
return "pagedown";
|
|
689
|
+
case "7":
|
|
690
|
+
return "home";
|
|
691
|
+
case "8":
|
|
692
|
+
return "end";
|
|
693
|
+
case "11":
|
|
694
|
+
return "f1";
|
|
695
|
+
case "12":
|
|
696
|
+
return "f2";
|
|
697
|
+
case "13":
|
|
698
|
+
return "f3";
|
|
699
|
+
case "14":
|
|
700
|
+
return "f4";
|
|
701
|
+
case "15":
|
|
702
|
+
return "f5";
|
|
703
|
+
case "17":
|
|
704
|
+
return "f6";
|
|
705
|
+
case "18":
|
|
706
|
+
return "f7";
|
|
707
|
+
case "19":
|
|
708
|
+
return "f8";
|
|
709
|
+
case "20":
|
|
710
|
+
return "f9";
|
|
711
|
+
case "21":
|
|
712
|
+
return "f10";
|
|
713
|
+
case "23":
|
|
714
|
+
return "f11";
|
|
715
|
+
case "24":
|
|
716
|
+
return "f12";
|
|
717
|
+
case "25":
|
|
718
|
+
return "f13";
|
|
719
|
+
case "26":
|
|
720
|
+
return "f14";
|
|
721
|
+
case "28":
|
|
722
|
+
return "f15";
|
|
723
|
+
case "29":
|
|
724
|
+
return "f16";
|
|
725
|
+
case "31":
|
|
726
|
+
return "f17";
|
|
727
|
+
case "32":
|
|
728
|
+
return "f18";
|
|
729
|
+
case "33":
|
|
730
|
+
return "f19";
|
|
731
|
+
case "34":
|
|
732
|
+
return "f20";
|
|
733
|
+
default:
|
|
734
|
+
return "unknown";
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
function applyModifiers(key, mod) {
|
|
738
|
+
const m = mod - 1;
|
|
739
|
+
if (m & 1) key.shift = true;
|
|
740
|
+
if (m & 2) key.alt = true;
|
|
741
|
+
if (m & 4) key.ctrl = true;
|
|
742
|
+
if (m & 8) key.meta = true;
|
|
743
|
+
}
|
|
539
744
|
function parseKeySequence(data) {
|
|
540
745
|
const keys = [];
|
|
541
746
|
let i = 0;
|
|
@@ -551,9 +756,17 @@ function parseKeySequence(data) {
|
|
|
551
756
|
continue;
|
|
552
757
|
}
|
|
553
758
|
}
|
|
759
|
+
if (data[i + 1] === "O") {
|
|
760
|
+
const seq = parseSs3Sequence(data, i);
|
|
761
|
+
if (seq) {
|
|
762
|
+
keys.push(seq.key);
|
|
763
|
+
i = seq.end;
|
|
764
|
+
continue;
|
|
765
|
+
}
|
|
766
|
+
}
|
|
554
767
|
if (i + 1 < data.length && data.charCodeAt(i + 1) >= 32) {
|
|
555
768
|
keys.push({
|
|
556
|
-
name: data[i + 1],
|
|
769
|
+
name: data[i + 1].toLowerCase(),
|
|
557
770
|
sequence: data.substring(i, i + 2),
|
|
558
771
|
alt: true
|
|
559
772
|
});
|
|
@@ -588,6 +801,102 @@ function parseKeySequence(data) {
|
|
|
588
801
|
}
|
|
589
802
|
return keys;
|
|
590
803
|
}
|
|
804
|
+
function parseSs3Sequence(data, start) {
|
|
805
|
+
if (start + 2 >= data.length) return null;
|
|
806
|
+
const final = data[start + 2];
|
|
807
|
+
const sequence = data.substring(start, start + 3);
|
|
808
|
+
let key;
|
|
809
|
+
switch (final) {
|
|
810
|
+
// Arrow keys (some terminals)
|
|
811
|
+
case "A":
|
|
812
|
+
key = { name: "up", sequence };
|
|
813
|
+
break;
|
|
814
|
+
case "B":
|
|
815
|
+
key = { name: "down", sequence };
|
|
816
|
+
break;
|
|
817
|
+
case "C":
|
|
818
|
+
key = { name: "right", sequence };
|
|
819
|
+
break;
|
|
820
|
+
case "D":
|
|
821
|
+
key = { name: "left", sequence };
|
|
822
|
+
break;
|
|
823
|
+
// Home/End (some terminals)
|
|
824
|
+
case "H":
|
|
825
|
+
key = { name: "home", sequence };
|
|
826
|
+
break;
|
|
827
|
+
case "F":
|
|
828
|
+
key = { name: "end", sequence };
|
|
829
|
+
break;
|
|
830
|
+
// Function keys F1-F4
|
|
831
|
+
case "P":
|
|
832
|
+
key = { name: "f1", sequence };
|
|
833
|
+
break;
|
|
834
|
+
case "Q":
|
|
835
|
+
key = { name: "f2", sequence };
|
|
836
|
+
break;
|
|
837
|
+
case "R":
|
|
838
|
+
key = { name: "f3", sequence };
|
|
839
|
+
break;
|
|
840
|
+
case "S":
|
|
841
|
+
key = { name: "f4", sequence };
|
|
842
|
+
break;
|
|
843
|
+
// Keypad (application mode)
|
|
844
|
+
case "j":
|
|
845
|
+
key = { name: "kpmultiply", sequence };
|
|
846
|
+
break;
|
|
847
|
+
case "k":
|
|
848
|
+
key = { name: "kpplus", sequence };
|
|
849
|
+
break;
|
|
850
|
+
case "l":
|
|
851
|
+
key = { name: "kpcomma", sequence };
|
|
852
|
+
break;
|
|
853
|
+
case "m":
|
|
854
|
+
key = { name: "kpminus", sequence };
|
|
855
|
+
break;
|
|
856
|
+
case "n":
|
|
857
|
+
key = { name: "kpdecimal", sequence };
|
|
858
|
+
break;
|
|
859
|
+
case "o":
|
|
860
|
+
key = { name: "kpdivide", sequence };
|
|
861
|
+
break;
|
|
862
|
+
case "p":
|
|
863
|
+
key = { name: "kp0", sequence };
|
|
864
|
+
break;
|
|
865
|
+
case "q":
|
|
866
|
+
key = { name: "kp1", sequence };
|
|
867
|
+
break;
|
|
868
|
+
case "r":
|
|
869
|
+
key = { name: "kp2", sequence };
|
|
870
|
+
break;
|
|
871
|
+
case "s":
|
|
872
|
+
key = { name: "kp3", sequence };
|
|
873
|
+
break;
|
|
874
|
+
case "t":
|
|
875
|
+
key = { name: "kp4", sequence };
|
|
876
|
+
break;
|
|
877
|
+
case "u":
|
|
878
|
+
key = { name: "kp5", sequence };
|
|
879
|
+
break;
|
|
880
|
+
case "v":
|
|
881
|
+
key = { name: "kp6", sequence };
|
|
882
|
+
break;
|
|
883
|
+
case "w":
|
|
884
|
+
key = { name: "kp7", sequence };
|
|
885
|
+
break;
|
|
886
|
+
case "x":
|
|
887
|
+
key = { name: "kp8", sequence };
|
|
888
|
+
break;
|
|
889
|
+
case "y":
|
|
890
|
+
key = { name: "kp9", sequence };
|
|
891
|
+
break;
|
|
892
|
+
case "M":
|
|
893
|
+
key = { name: "kpenter", sequence };
|
|
894
|
+
break;
|
|
895
|
+
default:
|
|
896
|
+
return null;
|
|
897
|
+
}
|
|
898
|
+
return { key, end: start + 3 };
|
|
899
|
+
}
|
|
591
900
|
function parseCsiSequence(data, start) {
|
|
592
901
|
let i = start + 2;
|
|
593
902
|
let params = "";
|
|
@@ -606,6 +915,7 @@ function parseCsiSequence(data, start) {
|
|
|
606
915
|
i++;
|
|
607
916
|
let key;
|
|
608
917
|
switch (final) {
|
|
918
|
+
// Arrow keys
|
|
609
919
|
case "A":
|
|
610
920
|
key = { name: "up", sequence };
|
|
611
921
|
break;
|
|
@@ -618,43 +928,73 @@ function parseCsiSequence(data, start) {
|
|
|
618
928
|
case "D":
|
|
619
929
|
key = { name: "left", sequence };
|
|
620
930
|
break;
|
|
931
|
+
// Home/End
|
|
621
932
|
case "H":
|
|
622
933
|
key = { name: "home", sequence };
|
|
623
934
|
break;
|
|
624
935
|
case "F":
|
|
625
936
|
key = { name: "end", sequence };
|
|
626
937
|
break;
|
|
938
|
+
// Shift+Tab
|
|
627
939
|
case "Z":
|
|
628
940
|
key = { name: "tab", sequence, shift: true };
|
|
629
941
|
break;
|
|
942
|
+
// Function keys (some terminals)
|
|
943
|
+
case "P":
|
|
944
|
+
key = { name: "f1", sequence };
|
|
945
|
+
break;
|
|
946
|
+
case "Q":
|
|
947
|
+
key = { name: "f2", sequence };
|
|
948
|
+
break;
|
|
949
|
+
case "R":
|
|
950
|
+
key = { name: "f3", sequence };
|
|
951
|
+
break;
|
|
952
|
+
case "S":
|
|
953
|
+
key = { name: "f4", sequence };
|
|
954
|
+
break;
|
|
955
|
+
// ~ terminated sequences (VT-style)
|
|
630
956
|
case "~": {
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
default:
|
|
645
|
-
key = { name: "unknown", sequence };
|
|
957
|
+
if (params.startsWith("27;")) {
|
|
958
|
+
const modParts = params.split(";");
|
|
959
|
+
const mod = parseInt(modParts[1] ?? "1", 10);
|
|
960
|
+
const keyCode = parseInt(modParts[2] ?? "0", 10);
|
|
961
|
+
key = { name: getKeyNameFromCode(keyCode), sequence };
|
|
962
|
+
applyModifiers(key, mod);
|
|
963
|
+
break;
|
|
964
|
+
}
|
|
965
|
+
key = { name: getTildeKeyName(params), sequence };
|
|
966
|
+
if (params.includes(";")) {
|
|
967
|
+
const parts = params.split(";");
|
|
968
|
+
const mod = parseInt(parts[1] ?? "1", 10);
|
|
969
|
+
applyModifiers(key, mod);
|
|
646
970
|
}
|
|
647
971
|
break;
|
|
648
972
|
}
|
|
973
|
+
// Kitty keyboard protocol: CSI code;mod u
|
|
974
|
+
case "u": {
|
|
975
|
+
const parts = params.split(";");
|
|
976
|
+
const keyCode = parseInt(parts[0] ?? "0", 10);
|
|
977
|
+
const mod = parseInt(parts[1] ?? "1", 10);
|
|
978
|
+
key = { name: getKeyNameFromCode(keyCode), sequence };
|
|
979
|
+
applyModifiers(key, mod);
|
|
980
|
+
break;
|
|
981
|
+
}
|
|
982
|
+
// Focus events (if terminal reports them)
|
|
983
|
+
case "I":
|
|
984
|
+
key = { name: "focus", sequence };
|
|
985
|
+
break;
|
|
986
|
+
case "O":
|
|
987
|
+
key = { name: "blur", sequence };
|
|
988
|
+
break;
|
|
649
989
|
default:
|
|
650
990
|
key = { name: "unknown", sequence };
|
|
651
991
|
}
|
|
652
|
-
if (params.includes(";")) {
|
|
992
|
+
if (params.includes(";") && !["~", "u"].includes(final)) {
|
|
653
993
|
const parts = params.split(";");
|
|
654
|
-
const mod = parseInt(parts[1] ?? "1", 10)
|
|
655
|
-
if (mod
|
|
656
|
-
|
|
657
|
-
|
|
994
|
+
const mod = parseInt(parts[parts.length - 1] ?? "1", 10);
|
|
995
|
+
if (mod >= 1 && mod <= 16) {
|
|
996
|
+
applyModifiers(key, mod);
|
|
997
|
+
}
|
|
658
998
|
}
|
|
659
999
|
return { key, end: i };
|
|
660
1000
|
}
|
|
@@ -1591,12 +1931,17 @@ function render(element, opts = {}) {
|
|
|
1591
1931
|
const currentFb = new Framebuffer(terminal.columns, terminal.rows);
|
|
1592
1932
|
let fullRedraw = true;
|
|
1593
1933
|
const inputHandlers = /* @__PURE__ */ new Set();
|
|
1934
|
+
const priorityHandlers = /* @__PURE__ */ new Set();
|
|
1594
1935
|
const focusedInputHandlers = /* @__PURE__ */ new Map();
|
|
1595
1936
|
const inputContextValue = {
|
|
1596
1937
|
subscribe(handler) {
|
|
1597
1938
|
inputHandlers.add(handler);
|
|
1598
1939
|
return () => inputHandlers.delete(handler);
|
|
1599
1940
|
},
|
|
1941
|
+
subscribePriority(handler) {
|
|
1942
|
+
priorityHandlers.add(handler);
|
|
1943
|
+
return () => priorityHandlers.delete(handler);
|
|
1944
|
+
},
|
|
1600
1945
|
registerInputHandler(focusId, handler) {
|
|
1601
1946
|
focusedInputHandlers.set(focusId, handler);
|
|
1602
1947
|
return () => focusedInputHandlers.delete(focusId);
|
|
@@ -1842,7 +2187,13 @@ function render(element, opts = {}) {
|
|
|
1842
2187
|
continue;
|
|
1843
2188
|
}
|
|
1844
2189
|
let consumed = false;
|
|
1845
|
-
|
|
2190
|
+
for (const handler of priorityHandlers) {
|
|
2191
|
+
if (handler(key)) {
|
|
2192
|
+
consumed = true;
|
|
2193
|
+
break;
|
|
2194
|
+
}
|
|
2195
|
+
}
|
|
2196
|
+
if (!consumed && focusedId) {
|
|
1846
2197
|
const inputHandler = focusedInputHandlers.get(focusedId);
|
|
1847
2198
|
if (inputHandler) {
|
|
1848
2199
|
consumed = inputHandler(key);
|
|
@@ -2346,7 +2697,8 @@ function parseKeyDescriptor(descriptor) {
|
|
|
2346
2697
|
name,
|
|
2347
2698
|
ctrl: parts.includes("ctrl"),
|
|
2348
2699
|
alt: parts.includes("alt"),
|
|
2349
|
-
shift: parts.includes("shift")
|
|
2700
|
+
shift: parts.includes("shift"),
|
|
2701
|
+
meta: parts.includes("meta") || parts.includes("cmd") || parts.includes("super") || parts.includes("win")
|
|
2350
2702
|
};
|
|
2351
2703
|
}
|
|
2352
2704
|
function matchesKey(matcher, key) {
|
|
@@ -2354,12 +2706,14 @@ function matchesKey(matcher, key) {
|
|
|
2354
2706
|
if (matcher.ctrl !== !!key.ctrl) return false;
|
|
2355
2707
|
if (matcher.alt !== !!key.alt) return false;
|
|
2356
2708
|
if (matcher.shift !== !!key.shift) return false;
|
|
2709
|
+
if (matcher.meta !== !!key.meta) return false;
|
|
2357
2710
|
return true;
|
|
2358
2711
|
}
|
|
2359
2712
|
function Keybind({
|
|
2360
2713
|
keypress,
|
|
2361
2714
|
onPress,
|
|
2362
2715
|
whenFocused,
|
|
2716
|
+
priority,
|
|
2363
2717
|
disabled
|
|
2364
2718
|
}) {
|
|
2365
2719
|
const inputCtx = React15.useContext(InputContext);
|
|
@@ -2370,13 +2724,23 @@ function Keybind({
|
|
|
2370
2724
|
matcherRef.current = parseKeyDescriptor(keypress);
|
|
2371
2725
|
React15.useEffect(() => {
|
|
2372
2726
|
if (!inputCtx || disabled) return;
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2727
|
+
if (priority) {
|
|
2728
|
+
const handler = (key) => {
|
|
2729
|
+
if (!matchesKey(matcherRef.current, key)) return false;
|
|
2730
|
+
if (whenFocused && focusCtx?.focusedId !== whenFocused) return false;
|
|
2731
|
+
onPressRef.current();
|
|
2732
|
+
return true;
|
|
2733
|
+
};
|
|
2734
|
+
return inputCtx.subscribePriority(handler);
|
|
2735
|
+
} else {
|
|
2736
|
+
const handler = (key) => {
|
|
2737
|
+
if (!matchesKey(matcherRef.current, key)) return;
|
|
2738
|
+
if (whenFocused && focusCtx?.focusedId !== whenFocused) return;
|
|
2739
|
+
onPressRef.current();
|
|
2740
|
+
};
|
|
2741
|
+
return inputCtx.subscribe(handler);
|
|
2742
|
+
}
|
|
2743
|
+
}, [inputCtx, focusCtx, whenFocused, priority, disabled]);
|
|
2380
2744
|
return null;
|
|
2381
2745
|
}
|
|
2382
2746
|
function Portal({ children, zIndex = 1e3 }) {
|