11import { App , Modal , Setting } from 'obsidian' ;
22import { SelectModalElement } from './SelectModalElement' ;
3+ import { mod } from '../utils/Utils' ;
34
45export abstract class SelectModal < T > extends Modal {
56 allowMultiSelect : boolean ;
@@ -22,6 +23,17 @@ export abstract class SelectModal<T> extends Modal {
2223
2324 this . elements = elements ;
2425 this . selectModalElements = [ ] ;
26+
27+ this . scope . register ( [ ] , 'ArrowUp' , ( ) => {
28+ this . highlightUp ( ) ;
29+ } ) ;
30+ this . scope . register ( [ ] , 'ArrowDown' , ( ) => {
31+ this . highlightDown ( ) ;
32+ } ) ;
33+ this . scope . register ( [ ] , 'ArrowRight' , ( ) => {
34+ this . activateHighlighted ( ) ;
35+ } ) ;
36+ this . scope . register ( [ ] , 'Enter' , ( ) => this . submit ( ) ) ;
2537 }
2638
2739 abstract renderElement ( value : T , el : HTMLElement ) : any ;
@@ -38,6 +50,14 @@ export abstract class SelectModal<T> extends Modal {
3850 }
3951 }
4052
53+ deHighlightAllOtherElements ( elementId : number ) {
54+ for ( const selectModalElement of this . selectModalElements ) {
55+ if ( selectModalElement . id !== elementId ) {
56+ selectModalElement . setHighlighted ( false ) ;
57+ }
58+ }
59+ }
60+
4161 async onOpen ( ) {
4262 const { contentEl} = this ;
4363
@@ -72,4 +92,54 @@ export abstract class SelectModal<T> extends Modal {
7292 }
7393 bottomSetting . addButton ( btn => btn . setButtonText ( 'Ok' ) . setCta ( ) . onClick ( ( ) => this . submit ( ) ) ) ;
7494 }
95+
96+ activateHighlighted ( ) {
97+ for ( const selectModalElement of this . selectModalElements ) {
98+ if ( selectModalElement . isHighlighted ( ) ) {
99+ selectModalElement . setActive ( ! selectModalElement . isActive ( ) ) ;
100+ if ( ! this . allowMultiSelect ) {
101+ this . disableAllOtherElements ( selectModalElement . id ) ;
102+ }
103+ }
104+ }
105+ }
106+
107+ highlightUp ( ) {
108+ for ( const selectModalElement of this . selectModalElements ) {
109+ if ( selectModalElement . isHighlighted ( ) ) {
110+ this . getPreviousSelectModalElement ( selectModalElement ) . setHighlighted ( true ) ;
111+ return ;
112+ }
113+ }
114+
115+ // nothing is highlighted
116+ this . selectModalElements . last ( ) . setHighlighted ( true ) ;
117+ }
118+
119+ highlightDown ( ) {
120+ for ( const selectModalElement of this . selectModalElements ) {
121+ if ( selectModalElement . isHighlighted ( ) ) {
122+ this . getNextSelectModalElement ( selectModalElement ) . setHighlighted ( true ) ;
123+ return ;
124+ }
125+ }
126+
127+ // nothing is highlighted
128+ this . selectModalElements . first ( ) . setHighlighted ( true ) ;
129+ }
130+
131+ private getNextSelectModalElement ( selectModalElement : SelectModalElement < T > ) : SelectModalElement < T > {
132+ let nextId = selectModalElement . id + 1 ;
133+ nextId = mod ( nextId , this . selectModalElements . length ) ;
134+
135+ return this . selectModalElements . filter ( x => x . id === nextId ) . first ( ) ;
136+ }
137+
138+ private getPreviousSelectModalElement ( selectModalElement : SelectModalElement < T > ) : SelectModalElement < T > {
139+ let nextId = selectModalElement . id - 1 ;
140+ nextId = mod ( nextId , this . selectModalElements . length ) ;
141+
142+ return this . selectModalElements . filter ( x => x . id === nextId ) . first ( ) ;
143+ }
144+
75145}
0 commit comments