Skip to content

Commit 8ed6d41

Browse files
committed
fix: use shift u/d instead of l/r
1 parent 2f720dc commit 8ed6d41

4 files changed

Lines changed: 61 additions & 45 deletions

File tree

packages/core/src/prompts/autocomplete.ts

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,15 @@ export default class AutocompletePrompt<T extends OptionLike> extends Prompt<
140140
const isUpKey = key.name === 'up';
141141
const isDownKey = key.name === 'down';
142142
const isReturnKey = key.name === 'return';
143-
const isLeft = key.name === 'left';
144-
const isRight = key.name === 'right';
145143

146144
// Start navigation mode with up/down arrows
147145
if (isUpKey || isDownKey) {
146+
// shift up/down behavior
147+
if (key.shift) {
148+
this.#handleShiftNavigation(isUpKey);
149+
return;
150+
}
151+
148152
this.#cursor = Math.max(
149153
0,
150154
Math.min(this.#cursor + (isUpKey ? -1 : 1), this.filteredOptions.length - 1)
@@ -163,15 +167,6 @@ export default class AutocompletePrompt<T extends OptionLike> extends Prompt<
163167
(key.name === 'tab' || (this.isNavigating && key.name === 'space'))
164168
) {
165169
this.toggleSelected(this.focusedValue);
166-
} else if (isLeft) {
167-
// set to none if all are selected
168-
if (this.selectedValues.length === this.filteredOptions.length) {
169-
this.deselectAll();
170-
} else {
171-
this.selectAll();
172-
}
173-
} else if (isRight) {
174-
this.invertSelected();
175170
} else {
176171
this.isNavigating = false;
177172
}
@@ -184,20 +179,43 @@ export default class AutocompletePrompt<T extends OptionLike> extends Prompt<
184179
}
185180
}
186181

187-
selectAll() {
182+
#handleShiftNavigation(isUpKey: boolean) {
183+
// invert if Shift + Down
184+
if (!isUpKey) {
185+
this.invertSelectedFiltered();
186+
return;
187+
}
188+
189+
// set to none if all are selected
190+
if (this.selectedValues.length === this.filteredOptions.length) {
191+
this.deselectAllFiltered();
192+
return;
193+
}
194+
195+
this.selectAllFiltered();
196+
return;
197+
}
198+
199+
selectAllFiltered() {
188200
this.selectedValues = this.filteredOptions.map((opt) => opt.value);
189201
}
190202

191-
deselectAll() {
192-
this.selectedValues = [];
203+
deselectAllFiltered() {
204+
this.selectedValues = this.filteredOptions
205+
.filter((opt) => !this.selectedValues.includes(opt.value))
206+
.map((opt) => opt.value);
193207
}
194208

195-
invertSelected() {
209+
invertSelectedFiltered() {
196210
this.selectedValues = this.filteredOptions
197211
.filter((opt) => !this.selectedValues.includes(opt.value))
198212
.map((opt) => opt.value);
199213
}
200214

215+
deselectAll() {
216+
this.selectedValues = [];
217+
}
218+
201219
toggleSelected(value: T['value']) {
202220
if (this.filteredOptions.length === 0) {
203221
return;

packages/prompts/src/autocomplete.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,6 @@ export const autocomplete = <Value>(opts: AutocompleteOptions<Value>) => {
9696
const placeholder = opts.placeholder;
9797
const showPlaceholder = valueAsString === '' && placeholder !== undefined;
9898

99-
console.log(this.state);
10099
// Handle different states
101100
switch (this.state) {
102101
case 'submit': {
@@ -276,7 +275,7 @@ export const autocompleteMultiselect = <Value>(opts: AutocompleteMultiSelectOpti
276275
// Instructions
277276
const instructions = [
278277
`${color.dim('↑/↓')} to navigate`,
279-
`${color.dim('←/→')} select all/inverse`,
278+
`${color.dim('Ctrl+↑/↓')} select all/inverse`,
280279
`${color.dim('Space:')} select`,
281280
`${color.dim('Enter:')} confirm`,
282281
`${color.dim('Type:')} to search`,

packages/prompts/test/__snapshots__/autocomplete.test.ts.snap

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ exports[`autocompleteMultiselect > all selection only applies to filtered option
298298
│ ◻ Cherry
299299
│ ◻ Grape
300300
│ ◻ Orange
301-
[36m│[39m [2m[2m↑/↓[22m[2m to navigate • [2m←/→[22m[2m select all/inverse • [2mSpace:[22m[2m select • [2mEnter:[22m[2m confirm • [2mType:[22m[2m to search[22m
301+
[36m│[39m [2m[2m↑/↓[22m[2m to navigate • [2mCtrl+↑/↓[22m[2m select all/inverse • [2mSpace:[22m[2m select • [2mEnter:[22m[2m confirm • [2mType:[22m[2m to search[22m
302302
└",
303303
"<cursor.backward count=999><cursor.up count=10>",
304304
"<cursor.down count=3>",
@@ -307,16 +307,15 @@ exports[`autocompleteMultiselect > all selection only applies to filtered option
307307
│ ◻ Cherry
308308
│ ◻ Grape
309309
│ ◻ Orange
310-
[36m│[39m [2m[2m↑/↓[22m[2m to navigate • [2m←/→[22m[2m select all/inverse • [2mSpace:[22m[2m select • [2mEnter:[22m[2m confirm • [2mType:[22m[2m to search[22m
310+
[36m│[39m [2m[2m↑/↓[22m[2m to navigate • [2mCtrl+↑/↓[22m[2m select all/inverse • [2mSpace:[22m[2m select • [2mEnter:[22m[2m confirm • [2mType:[22m[2m to search[22m
311311
└",
312312
"<cursor.backward count=999><cursor.up count=8>",
313-
"<cursor.down count=3>",
313+
"<cursor.down count=4>",
314314
"<erase.down>",
315-
"│ Search: r (3 matches)
316-
│ ◼ Cherry
315+
"│ ◼ Cherry
317316
│ ◼ Grape
318317
│ ◼ Orange
319-
[36m│[39m [2m[2m↑/↓[22m[2m to navigate • [2m←/→[22m[2m select all/inverse • [2mSpace:[22m[2m select • [2mEnter:[22m[2m confirm • [2mType:[22m[2m to search[22m
318+
[36m│[39m [2m[2m↑/↓[22m[2m to navigate • [2mCtrl+↑/↓[22m[2m select all/inverse • [2mSpace:[22m[2m select • [2mEnter:[22m[2m confirm • [2mType:[22m[2m to search[22m
320319
└",
321320
"<cursor.backward count=999><cursor.up count=8>",
322321
"<cursor.down count=1>",
@@ -341,7 +340,7 @@ exports[`autocompleteMultiselect > can be aborted by a signal 1`] = `
341340
│ ◻ Cherry
342341
│ ◻ Grape
343342
│ ◻ Orange
344-
[36m│[39m [2m[2m↑/↓[22m[2m to navigate • [2m←/→[22m[2m select all/inverse • [2mSpace:[22m[2m select • [2mEnter:[22m[2m confirm • [2mType:[22m[2m to search[22m
343+
[36m│[39m [2m[2m↑/↓[22m[2m to navigate • [2mCtrl+↑/↓[22m[2m select all/inverse • [2mSpace:[22m[2m select • [2mEnter:[22m[2m confirm • [2mType:[22m[2m to search[22m
345344
└",
346345
"
347346
",
@@ -361,7 +360,7 @@ exports[`autocompleteMultiselect > everything can be selected with left arrow 1`
361360
│ ◻ Cherry
362361
│ ◻ Grape
363362
│ ◻ Orange
364-
[36m│[39m [2m[2m↑/↓[22m[2m to navigate • [2m←/→[22m[2m select all/inverse • [2mSpace:[22m[2m select • [2mEnter:[22m[2m confirm • [2mType:[22m[2m to search[22m
363+
[36m│[39m [2m[2m↑/↓[22m[2m to navigate • [2mCtrl+↑/↓[22m[2m select all/inverse • [2mSpace:[22m[2m select • [2mEnter:[22m[2m confirm • [2mType:[22m[2m to search[22m
365364
└",
366365
"<cursor.backward count=999><cursor.up count=10>",
367366
"<cursor.down count=4>",
@@ -371,7 +370,7 @@ exports[`autocompleteMultiselect > everything can be selected with left arrow 1`
371370
│ ◼ Cherry
372371
│ ◼ Grape
373372
│ ◼ Orange
374-
[36m│[39m [2m[2m↑/↓[22m[2m to navigate • [2m←/→[22m[2m select all/inverse • [2mSpace:[22m[2m select • [2mEnter:[22m[2m confirm • [2mType:[22m[2m to search[22m
373+
[36m│[39m [2m[2m↑/↓[22m[2m to navigate • [2mCtrl+↑/↓[22m[2m select all/inverse • [2mSpace:[22m[2m select • [2mEnter:[22m[2m confirm • [2mType:[22m[2m to search[22m
375374
└",
376375
"<cursor.backward count=999><cursor.up count=10>",
377376
"<cursor.down count=1>",
@@ -396,7 +395,7 @@ exports[`autocompleteMultiselect > everything is deselected if left is pressed a
396395
│ ◻ Cherry
397396
│ ◻ Grape
398397
│ ◻ Orange
399-
[36m│[39m [2m[2m↑/↓[22m[2m to navigate • [2m←/→[22m[2m select all/inverse • [2mSpace:[22m[2m select • [2mEnter:[22m[2m confirm • [2mType:[22m[2m to search[22m
398+
[36m│[39m [2m[2m↑/↓[22m[2m to navigate • [2mCtrl+↑/↓[22m[2m select all/inverse • [2mSpace:[22m[2m select • [2mEnter:[22m[2m confirm • [2mType:[22m[2m to search[22m
400399
└",
401400
"<cursor.backward count=999><cursor.up count=10>",
402401
"<cursor.down count=4>",
@@ -406,7 +405,7 @@ exports[`autocompleteMultiselect > everything is deselected if left is pressed a
406405
│ ◼ Cherry
407406
│ ◼ Grape
408407
│ ◼ Orange
409-
[36m│[39m [2m[2m↑/↓[22m[2m to navigate • [2m←/→[22m[2m select all/inverse • [2mSpace:[22m[2m select • [2mEnter:[22m[2m confirm • [2mType:[22m[2m to search[22m
408+
[36m│[39m [2m[2m↑/↓[22m[2m to navigate • [2mCtrl+↑/↓[22m[2m select all/inverse • [2mSpace:[22m[2m select • [2mEnter:[22m[2m confirm • [2mType:[22m[2m to search[22m
410409
└",
411410
"<cursor.backward count=999><cursor.up count=10>",
412411
"<cursor.down count=4>",
@@ -416,7 +415,7 @@ exports[`autocompleteMultiselect > everything is deselected if left is pressed a
416415
│ ◻ Cherry
417416
│ ◻ Grape
418417
│ ◻ Orange
419-
[36m│[39m [2m[2m↑/↓[22m[2m to navigate • [2m←/→[22m[2m select all/inverse • [2mSpace:[22m[2m select • [2mEnter:[22m[2m confirm • [2mType:[22m[2m to search[22m
418+
[36m│[39m [2m[2m↑/↓[22m[2m to navigate • [2mCtrl+↑/↓[22m[2m select all/inverse • [2mSpace:[22m[2m select • [2mEnter:[22m[2m confirm • [2mType:[22m[2m to search[22m
420419
└",
421420
"<cursor.backward count=999><cursor.up count=10>",
422421
"<cursor.down count=1>",
@@ -441,7 +440,7 @@ exports[`autocompleteMultiselect > inverse can be selected with right arrow 1`]
441440
│ ◻ Cherry
442441
│ ◻ Grape
443442
│ ◻ Orange
444-
[36m│[39m [2m[2m↑/↓[22m[2m to navigate • [2m←/→[22m[2m select all/inverse • [2mSpace:[22m[2m select • [2mEnter:[22m[2m confirm • [2mType:[22m[2m to search[22m
443+
[36m│[39m [2m[2m↑/↓[22m[2m to navigate • [2mCtrl+↑/↓[22m[2m select all/inverse • [2mSpace:[22m[2m select • [2mEnter:[22m[2m confirm • [2mType:[22m[2m to search[22m
445444
└",
446445
"<cursor.backward count=999><cursor.up count=10>",
447446
"<cursor.down count=3>",
@@ -452,7 +451,7 @@ exports[`autocompleteMultiselect > inverse can be selected with right arrow 1`]
452451
│ ◻ Cherry
453452
│ ◻ Grape
454453
│ ◻ Orange
455-
[36m│[39m [2m[2m↑/↓[22m[2m to navigate • [2m←/→[22m[2m select all/inverse • [2mSpace:[22m[2m select • [2mEnter:[22m[2m confirm • [2mType:[22m[2m to search[22m
454+
[36m│[39m [2m[2m↑/↓[22m[2m to navigate • [2mCtrl+↑/↓[22m[2m select all/inverse • [2mSpace:[22m[2m select • [2mEnter:[22m[2m confirm • [2mType:[22m[2m to search[22m
456455
└",
457456
"<cursor.backward count=999><cursor.up count=10>",
458457
"<cursor.down count=5>",
@@ -467,7 +466,7 @@ exports[`autocompleteMultiselect > inverse can be selected with right arrow 1`]
467466
│ ◼ Cherry
468467
│ ◼ Grape
469468
│ ◼ Orange
470-
[36m│[39m [2m[2m↑/↓[22m[2m to navigate • [2m←/→[22m[2m select all/inverse • [2mSpace:[22m[2m select • [2mEnter:[22m[2m confirm • [2mType:[22m[2m to search[22m
469+
[36m│[39m [2m[2m↑/↓[22m[2m to navigate • [2mCtrl+↑/↓[22m[2m select all/inverse • [2mSpace:[22m[2m select • [2mEnter:[22m[2m confirm • [2mType:[22m[2m to search[22m
471470
└",
472471
"<cursor.backward count=999><cursor.up count=10>",
473472
"<cursor.down count=1>",
@@ -492,7 +491,7 @@ exports[`autocompleteMultiselect > inversion only applies to filtered options 1`
492491
│ ◻ Cherry
493492
│ ◻ Grape
494493
│ ◻ Orange
495-
[36m│[39m [2m[2m↑/↓[22m[2m to navigate • [2m←/→[22m[2m select all/inverse • [2mSpace:[22m[2m select • [2mEnter:[22m[2m confirm • [2mType:[22m[2m to search[22m
494+
[36m│[39m [2m[2m↑/↓[22m[2m to navigate • [2mCtrl+↑/↓[22m[2m select all/inverse • [2mSpace:[22m[2m select • [2mEnter:[22m[2m confirm • [2mType:[22m[2m to search[22m
496495
└",
497496
"<cursor.backward count=999><cursor.up count=10>",
498497
"<cursor.down count=3>",
@@ -501,7 +500,7 @@ exports[`autocompleteMultiselect > inversion only applies to filtered options 1`
501500
│ ◻ Cherry
502501
│ ◻ Grape
503502
│ ◻ Orange
504-
[36m│[39m [2m[2m↑/↓[22m[2m to navigate • [2m←/→[22m[2m select all/inverse • [2mSpace:[22m[2m select • [2mEnter:[22m[2m confirm • [2mType:[22m[2m to search[22m
503+
[36m│[39m [2m[2m↑/↓[22m[2m to navigate • [2mCtrl+↑/↓[22m[2m select all/inverse • [2mSpace:[22m[2m select • [2mEnter:[22m[2m confirm • [2mType:[22m[2m to search[22m
505504
└",
506505
"<cursor.backward count=999><cursor.up count=8>",
507506
"<cursor.down count=3>",
@@ -510,7 +509,7 @@ exports[`autocompleteMultiselect > inversion only applies to filtered options 1`
510509
│ ◻ Cherry
511510
│ ◻ Grape
512511
│ ◻ Orange
513-
[36m│[39m [2m[2m↑/↓[22m[2m to navigate • [2m←/→[22m[2m select all/inverse • [2mSpace:[22m[2m select • [2mEnter:[22m[2m confirm • [2mType:[22m[2m to search[22m
512+
[36m│[39m [2m[2m↑/↓[22m[2m to navigate • [2mCtrl+↑/↓[22m[2m select all/inverse • [2mSpace:[22m[2m select • [2mEnter:[22m[2m confirm • [2mType:[22m[2m to search[22m
514513
└",
515514
"<cursor.backward count=999><cursor.up count=8>",
516515
"<cursor.down count=5>",
@@ -523,7 +522,7 @@ exports[`autocompleteMultiselect > inversion only applies to filtered options 1`
523522
"│ ◼ Cherry
524523
│ ◻ Grape
525524
│ ◼ Orange
526-
[36m│[39m [2m[2m↑/↓[22m[2m to navigate • [2m←/→[22m[2m select all/inverse • [2mSpace:[22m[2m select • [2mEnter:[22m[2m confirm • [2mType:[22m[2m to search[22m
525+
[36m│[39m [2m[2m↑/↓[22m[2m to navigate • [2mCtrl+↑/↓[22m[2m select all/inverse • [2mSpace:[22m[2m select • [2mEnter:[22m[2m confirm • [2mType:[22m[2m to search[22m
527526
└",
528527
"<cursor.backward count=999><cursor.up count=8>",
529528
"<cursor.down count=1>",
@@ -548,7 +547,7 @@ exports[`autocompleteMultiselect > renders error when empty selection & required
548547
│ ◻ Cherry
549548
│ ◻ Grape
550549
│ ◻ Orange
551-
[36m│[39m [2m[2m↑/↓[22m[2m to navigate • [2m←/→[22m[2m select all/inverse • [2mSpace:[22m[2m select • [2mEnter:[22m[2m confirm • [2mType:[22m[2m to search[22m
550+
[36m│[39m [2m[2m↑/↓[22m[2m to navigate • [2mCtrl+↑/↓[22m[2m select all/inverse • [2mSpace:[22m[2m select • [2mEnter:[22m[2m confirm • [2mType:[22m[2m to search[22m
552551
└",
553552
"<cursor.backward count=999><cursor.up count=10>",
554553
"<cursor.down count=1>",
@@ -562,7 +561,7 @@ exports[`autocompleteMultiselect > renders error when empty selection & required
562561
│ ◻ Cherry
563562
│ ◻ Grape
564563
│ ◻ Orange
565-
[36m│[39m [2m[2m↑/↓[22m[2m to navigate • [2m←/→[22m[2m select all/inverse • [2mSpace:[22m[2m select • [2mEnter:[22m[2m confirm • [2mType:[22m[2m to search[22m
564+
[36m│[39m [2m[2m↑/↓[22m[2m to navigate • [2mCtrl+↑/↓[22m[2m select all/inverse • [2mSpace:[22m[2m select • [2mEnter:[22m[2m confirm • [2mType:[22m[2m to search[22m
566565
└",
567566
"<cursor.backward count=999><cursor.up count=11>",
568567
"<cursor.down count=1>",
@@ -575,7 +574,7 @@ exports[`autocompleteMultiselect > renders error when empty selection & required
575574
│ ◻ Cherry
576575
│ ◻ Grape
577576
│ ◻ Orange
578-
[36m│[39m [2m[2m↑/↓[22m[2m to navigate • [2m←/→[22m[2m select all/inverse • [2mSpace:[22m[2m select • [2mEnter:[22m[2m confirm • [2mType:[22m[2m to search[22m
577+
[36m│[39m [2m[2m↑/↓[22m[2m to navigate • [2mCtrl+↑/↓[22m[2m select all/inverse • [2mSpace:[22m[2m select • [2mEnter:[22m[2m confirm • [2mType:[22m[2m to search[22m
579578
└",
580579
"<cursor.backward count=999><cursor.up count=10>",
581580
"<cursor.down count=1>",

packages/prompts/test/autocomplete.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ describe('autocompleteMultiselect', () => {
230230
output,
231231
});
232232

233-
input.emit('keypress', '', { name: 'left' });
233+
input.emit('keypress', '', { name: 'up', shift: true });
234234
input.emit('keypress', '', { name: 'return' });
235235
await result;
236236
expect(output.buffer).toMatchSnapshot();
@@ -245,8 +245,8 @@ describe('autocompleteMultiselect', () => {
245245
output,
246246
});
247247

248-
input.emit('keypress', '', { name: 'left' });
249-
input.emit('keypress', '', { name: 'left' });
248+
input.emit('keypress', '', { name: 'up', shift: true });
249+
input.emit('keypress', '', { name: 'up', shift: true });
250250
input.emit('keypress', '', { name: 'return' });
251251
await result;
252252
expect(output.buffer).toMatchSnapshot();
@@ -263,7 +263,7 @@ describe('autocompleteMultiselect', () => {
263263

264264
input.emit('keypress', '', { name: 'down' });
265265
input.emit('keypress', '', { name: 'space' });
266-
input.emit('keypress', '', { name: 'right' });
266+
input.emit('keypress', '', { name: 'down', shift: true });
267267
input.emit('keypress', '', { name: 'return' });
268268
await result;
269269
expect(output.buffer).toMatchSnapshot();
@@ -279,7 +279,7 @@ describe('autocompleteMultiselect', () => {
279279
});
280280

281281
input.emit('keypress', 'r', { name: 'r' });
282-
input.emit('keypress', '', { name: 'left' });
282+
input.emit('keypress', '', { name: 'up', shift: true });
283283
input.emit('keypress', '', { name: 'return' });
284284
await result;
285285
expect(output.buffer).toMatchSnapshot();
@@ -297,7 +297,7 @@ describe('autocompleteMultiselect', () => {
297297
input.emit('keypress', 'r', { name: 'r' });
298298
input.emit('keypress', '', { name: 'down' });
299299
input.emit('keypress', '', { name: 'space' });
300-
input.emit('keypress', '', { name: 'right' });
300+
input.emit('keypress', '', { name: 'down', shift: true });
301301
input.emit('keypress', '', { name: 'return' });
302302
await result;
303303
expect(output.buffer).toMatchSnapshot();

0 commit comments

Comments
 (0)