@sascha384/tic 4.9.0 → 5.1.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.
Files changed (41) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/dist/auth/gitlab.js +12 -5
  3. package/dist/auth/gitlab.js.map +1 -1
  4. package/dist/commands.d.ts +28 -1
  5. package/dist/commands.js +677 -5
  6. package/dist/commands.js.map +1 -1
  7. package/dist/components/BranchList.js +326 -168
  8. package/dist/components/BranchList.js.map +1 -1
  9. package/dist/components/ColorPill.js +3 -3
  10. package/dist/components/ColorPill.js.map +1 -1
  11. package/dist/components/DetailPanel.js +2 -2
  12. package/dist/components/DetailPanel.js.map +1 -1
  13. package/dist/components/Header.js +6 -2
  14. package/dist/components/Header.js.map +1 -1
  15. package/dist/components/HelpScreen.d.ts +1 -9
  16. package/dist/components/HelpScreen.js +32 -227
  17. package/dist/components/HelpScreen.js.map +1 -1
  18. package/dist/components/IterationPicker.js +3 -2
  19. package/dist/components/IterationPicker.js.map +1 -1
  20. package/dist/components/PullRequestList.js +56 -16
  21. package/dist/components/PullRequestList.js.map +1 -1
  22. package/dist/components/Settings.js +36 -26
  23. package/dist/components/Settings.js.map +1 -1
  24. package/dist/components/StatusScreen.js +32 -20
  25. package/dist/components/StatusScreen.js.map +1 -1
  26. package/dist/components/WorkItemForm.js +20 -14
  27. package/dist/components/WorkItemForm.js.map +1 -1
  28. package/dist/components/WorkItemList.d.ts +0 -1
  29. package/dist/components/WorkItemList.js +97 -101
  30. package/dist/components/WorkItemList.js.map +1 -1
  31. package/dist/implement.js +7 -3
  32. package/dist/implement.js.map +1 -1
  33. package/dist/storage/index.js +14 -11
  34. package/dist/storage/index.js.map +1 -1
  35. package/dist/stores/backendDataStore.d.ts +1 -0
  36. package/dist/stores/backendDataStore.js +23 -1
  37. package/dist/stores/backendDataStore.js.map +1 -1
  38. package/dist/stores/uiStore.d.ts +12 -0
  39. package/dist/stores/uiStore.js.map +1 -1
  40. package/drizzle/meta/_journal.json +1 -1
  41. package/package.json +1 -1
package/dist/commands.js CHANGED
@@ -12,6 +12,11 @@ const commands = [
12
12
  label: 'Create item',
13
13
  category: 'Actions',
14
14
  shortcut: 'c',
15
+ keys: ['c'],
16
+ screen: 'list',
17
+ helpGroup: 'Actions',
18
+ footer: true,
19
+ footerLabel: 'create',
15
20
  when: (ctx) => ctx.screen === 'list',
16
21
  },
17
22
  {
@@ -19,6 +24,11 @@ const commands = [
19
24
  label: 'Edit item',
20
25
  category: 'Actions',
21
26
  shortcut: 'enter',
27
+ keys: [{ special: 'return' }],
28
+ screen: 'list',
29
+ helpGroup: 'Actions',
30
+ footer: true,
31
+ footerLabel: 'edit',
22
32
  when: (ctx) => ctx.screen === 'list' && ctx.hasSelectedItem,
23
33
  },
24
34
  {
@@ -26,6 +36,11 @@ const commands = [
26
36
  label: 'Delete item',
27
37
  category: 'Actions',
28
38
  shortcut: 'd',
39
+ keys: ['d'],
40
+ screen: 'list',
41
+ helpGroup: 'Actions',
42
+ footer: true,
43
+ footerLabel: 'delete',
29
44
  when: (ctx) => ctx.screen === 'list' && ctx.hasSelectedItem,
30
45
  },
31
46
  {
@@ -33,6 +48,9 @@ const commands = [
33
48
  label: 'Open in browser',
34
49
  category: 'Actions',
35
50
  shortcut: 'o',
51
+ keys: ['o'],
52
+ screen: 'list',
53
+ helpGroup: 'Actions',
36
54
  when: (ctx) => ctx.screen === 'list' && ctx.hasSelectedItem,
37
55
  },
38
56
  {
@@ -40,6 +58,9 @@ const commands = [
40
58
  label: 'Create branch/worktree',
41
59
  category: 'Actions',
42
60
  shortcut: 'b',
61
+ keys: ['b'],
62
+ screen: 'list',
63
+ helpGroup: 'Other',
43
64
  when: (ctx) => ctx.screen === 'list' && ctx.hasSelectedItem && ctx.gitAvailable,
44
65
  },
45
66
  {
@@ -47,6 +68,9 @@ const commands = [
47
68
  label: 'Refresh/sync',
48
69
  category: 'Actions',
49
70
  shortcut: 'r',
71
+ keys: ['r'],
72
+ screen: 'list',
73
+ helpGroup: 'Other',
50
74
  when: (ctx) => ctx.screen === 'list' && ctx.hasSyncManager,
51
75
  },
52
76
  {
@@ -54,6 +78,9 @@ const commands = [
54
78
  label: 'Order by...',
55
79
  category: 'Actions',
56
80
  shortcut: 'O',
81
+ keys: ['O'],
82
+ screen: 'list',
83
+ helpGroup: 'Actions',
57
84
  when: (ctx) => ctx.screen === 'list',
58
85
  },
59
86
  // Navigation
@@ -62,6 +89,9 @@ const commands = [
62
89
  label: 'Go to iterations',
63
90
  category: 'Navigation',
64
91
  shortcut: 'i',
92
+ keys: ['i'],
93
+ screen: 'list',
94
+ helpGroup: 'Switching',
65
95
  when: (ctx) => ctx.screen === 'list' && ctx.capabilities.iterations,
66
96
  },
67
97
  {
@@ -69,13 +99,21 @@ const commands = [
69
99
  label: 'Go to settings',
70
100
  category: 'Navigation',
71
101
  shortcut: ',',
102
+ keys: [','],
103
+ screen: 'list',
104
+ helpGroup: 'Switching',
105
+ footer: true,
106
+ footerLabel: 'settings',
72
107
  when: (ctx) => ctx.screen === 'list',
73
108
  },
74
109
  {
75
110
  id: 'status',
76
111
  label: 'Go to status',
77
112
  category: 'Navigation',
78
- shortcut: 's',
113
+ shortcut: 'S',
114
+ keys: ['S'],
115
+ screen: 'list',
116
+ helpGroup: 'Switching',
79
117
  when: (ctx) => ctx.screen === 'list',
80
118
  },
81
119
  {
@@ -83,7 +121,10 @@ const commands = [
83
121
  label: 'Go to help',
84
122
  category: 'Navigation',
85
123
  shortcut: '?',
86
- when: (ctx) => ctx.screen === 'list',
124
+ keys: ['?'],
125
+ screen: 'global',
126
+ footer: true,
127
+ footerLabel: 'help',
87
128
  },
88
129
  // Bulk
89
130
  {
@@ -91,6 +132,9 @@ const commands = [
91
132
  label: 'Mark/unmark item',
92
133
  category: 'Bulk',
93
134
  shortcut: 'm',
135
+ keys: ['m'],
136
+ screen: 'list',
137
+ helpGroup: 'Actions',
94
138
  when: (ctx) => ctx.screen === 'list' && ctx.hasSelectedItem,
95
139
  },
96
140
  {
@@ -98,12 +142,19 @@ const commands = [
98
142
  label: 'Clear all marks',
99
143
  category: 'Bulk',
100
144
  shortcut: 'M',
145
+ keys: ['M'],
146
+ screen: 'list',
147
+ helpGroup: 'Bulk',
101
148
  when: (ctx) => ctx.screen === 'list' && ctx.markedCount > 0,
102
149
  },
103
150
  {
104
151
  id: 'set-priority',
105
152
  label: 'Set priority',
106
153
  category: 'Bulk',
154
+ shortcut: 'y',
155
+ keys: ['y'],
156
+ screen: 'list',
157
+ helpGroup: 'Bulk',
107
158
  when: (ctx) => ctx.screen === 'list' &&
108
159
  ctx.capabilities.fields.priority &&
109
160
  (ctx.hasSelectedItem || ctx.markedCount > 0),
@@ -113,6 +164,9 @@ const commands = [
113
164
  label: 'Set assignee',
114
165
  category: 'Bulk',
115
166
  shortcut: 'a',
167
+ keys: ['a'],
168
+ screen: 'list',
169
+ helpGroup: 'Actions',
116
170
  when: (ctx) => ctx.screen === 'list' &&
117
171
  ctx.capabilities.fields.assignee &&
118
172
  (ctx.hasSelectedItem || ctx.markedCount > 0),
@@ -122,6 +176,9 @@ const commands = [
122
176
  label: 'Set labels',
123
177
  category: 'Bulk',
124
178
  shortcut: 'l',
179
+ keys: ['l'],
180
+ screen: 'list',
181
+ helpGroup: 'Actions',
125
182
  when: (ctx) => ctx.screen === 'list' &&
126
183
  ctx.capabilities.fields.labels &&
127
184
  (ctx.hasSelectedItem || ctx.markedCount > 0),
@@ -131,6 +188,9 @@ const commands = [
131
188
  label: 'Set type',
132
189
  category: 'Bulk',
133
190
  shortcut: 't',
191
+ keys: ['t'],
192
+ screen: 'list',
193
+ helpGroup: 'Bulk',
134
194
  when: (ctx) => ctx.screen === 'list' &&
135
195
  ctx.capabilities.customTypes &&
136
196
  (ctx.hasSelectedItem || ctx.markedCount > 0),
@@ -139,14 +199,19 @@ const commands = [
139
199
  id: 'bulk-menu',
140
200
  label: 'Bulk actions menu',
141
201
  category: 'Bulk',
142
- shortcut: 'B',
143
- when: (ctx) => ctx.screen === 'list' && ctx.markedCount > 0,
202
+ shortcut: 'x',
203
+ keys: ['x'],
204
+ screen: 'list',
205
+ helpGroup: 'Bulk',
144
206
  },
145
207
  {
146
208
  id: 'filter',
147
209
  label: 'Filter...',
148
210
  category: 'Actions',
149
211
  shortcut: 'F',
212
+ keys: ['F'],
213
+ screen: 'list',
214
+ helpGroup: 'Actions',
150
215
  when: (ctx) => ctx.screen === 'list',
151
216
  },
152
217
  {
@@ -154,6 +219,9 @@ const commands = [
154
219
  label: 'Clear filters',
155
220
  category: 'Actions',
156
221
  shortcut: 'X',
222
+ keys: ['X'],
223
+ screen: 'list',
224
+ helpGroup: 'Actions',
157
225
  when: (ctx) => ctx.screen === 'list' && ctx.hasActiveFilters,
158
226
  },
159
227
  {
@@ -161,26 +229,536 @@ const commands = [
161
229
  label: 'Load view...',
162
230
  category: 'Actions',
163
231
  shortcut: 'V',
232
+ keys: ['V'],
233
+ screen: 'list',
234
+ helpGroup: 'Actions',
164
235
  when: (ctx) => ctx.screen === 'list',
165
236
  },
166
237
  {
167
238
  id: 'save-view',
168
239
  label: 'Save current view...',
169
240
  category: 'Actions',
241
+ screen: 'list',
170
242
  when: (ctx) => ctx.screen === 'list' && ctx.hasActiveFilters,
171
243
  },
172
244
  {
173
245
  id: 'delete-view',
174
246
  label: 'Delete view...',
175
247
  category: 'Actions',
248
+ screen: 'list',
176
249
  when: (ctx) => ctx.screen === 'list' && ctx.hasSavedViews,
177
250
  },
251
+ // List-screen navigation
252
+ {
253
+ id: 'list-navigate',
254
+ label: 'Navigate items',
255
+ category: 'Navigation',
256
+ shortcut: '↑/↓',
257
+ keys: [{ special: 'upArrow' }, { special: 'downArrow' }],
258
+ screen: 'list',
259
+ helpGroup: 'Navigation',
260
+ footer: true,
261
+ footerLabel: 'navigate',
262
+ },
263
+ {
264
+ id: 'list-page',
265
+ label: 'Page up / page down',
266
+ category: 'Navigation',
267
+ shortcut: 'pgup/pgdn',
268
+ keys: [{ special: 'pageUp' }, { special: 'pageDown' }],
269
+ screen: 'list',
270
+ helpGroup: 'Navigation',
271
+ },
272
+ {
273
+ id: 'list-home-end',
274
+ label: 'Jump to first / last item',
275
+ category: 'Navigation',
276
+ shortcut: 'home/end',
277
+ keys: [{ special: 'home' }, { special: 'end' }],
278
+ screen: 'list',
279
+ helpGroup: 'Navigation',
280
+ },
281
+ {
282
+ id: 'list-collapse',
283
+ label: 'Collapse or jump to parent',
284
+ category: 'Navigation',
285
+ shortcut: '←',
286
+ keys: [{ special: 'leftArrow' }],
287
+ screen: 'list',
288
+ helpGroup: 'Navigation',
289
+ when: (ctx) => ctx.capabilities.relationships,
290
+ },
291
+ {
292
+ id: 'list-expand',
293
+ label: 'Expand children',
294
+ category: 'Navigation',
295
+ shortcut: '→',
296
+ keys: [{ special: 'rightArrow' }],
297
+ screen: 'list',
298
+ helpGroup: 'Navigation',
299
+ when: (ctx) => ctx.capabilities.relationships,
300
+ },
301
+ // List-screen actions missing from registry
302
+ {
303
+ id: 'list-undo',
304
+ label: 'Undo last action',
305
+ category: 'Actions',
306
+ shortcut: 'u',
307
+ keys: ['u'],
308
+ screen: 'list',
309
+ helpGroup: 'Actions',
310
+ footer: true,
311
+ footerLabel: 'undo',
312
+ },
313
+ {
314
+ id: 'list-status',
315
+ label: 'Set status',
316
+ category: 'Actions',
317
+ shortcut: 's',
318
+ keys: ['s'],
319
+ screen: 'list',
320
+ helpGroup: 'Actions',
321
+ },
322
+ {
323
+ id: 'list-parent',
324
+ label: 'Set parent',
325
+ category: 'Actions',
326
+ shortcut: 'g',
327
+ keys: ['g'],
328
+ screen: 'list',
329
+ helpGroup: 'Actions',
330
+ when: (ctx) => ctx.capabilities.fields.parent,
331
+ },
332
+ {
333
+ id: 'list-pr-create',
334
+ label: 'Create pull request',
335
+ category: 'Actions',
336
+ shortcut: 'p',
337
+ keys: ['p'],
338
+ screen: 'list',
339
+ helpGroup: 'Actions',
340
+ },
341
+ {
342
+ id: 'list-pr-list',
343
+ label: 'Pull requests',
344
+ category: 'Navigation',
345
+ shortcut: 'P',
346
+ keys: ['P'],
347
+ screen: 'list',
348
+ helpGroup: 'Actions',
349
+ },
350
+ {
351
+ id: 'list-branch-manage',
352
+ label: 'Branch management',
353
+ category: 'Navigation',
354
+ shortcut: 'B',
355
+ keys: ['B'],
356
+ screen: 'list',
357
+ helpGroup: 'Actions',
358
+ when: (ctx) => ctx.gitAvailable,
359
+ },
360
+ {
361
+ id: 'list-range-select',
362
+ label: 'Range select',
363
+ category: 'Bulk',
364
+ shortcut: 'shift+↑↓',
365
+ keys: [
366
+ { special: 'upArrow', modifier: 'shift' },
367
+ { special: 'downArrow', modifier: 'shift' },
368
+ ],
369
+ screen: 'list',
370
+ helpGroup: 'Actions',
371
+ },
372
+ {
373
+ id: 'list-tab',
374
+ label: 'Cycle work item type',
375
+ category: 'Switching',
376
+ shortcut: 'tab',
377
+ keys: [{ special: 'tab' }],
378
+ screen: 'list',
379
+ helpGroup: 'Switching',
380
+ when: (ctx) => ctx.capabilities.customTypes,
381
+ },
382
+ {
383
+ id: 'list-toggle-description',
384
+ label: 'Toggle full description',
385
+ category: 'Other',
386
+ shortcut: 'space',
387
+ keys: [' '],
388
+ screen: 'list',
389
+ helpGroup: 'Other',
390
+ },
391
+ {
392
+ id: 'list-command-bar',
393
+ label: 'Command bar',
394
+ category: 'Actions',
395
+ shortcut: '/',
396
+ keys: ['/'],
397
+ screen: 'list',
398
+ helpGroup: 'Actions',
399
+ footer: true,
400
+ footerLabel: 'commands',
401
+ },
402
+ // Navigation shared across sub-screens
403
+ {
404
+ id: 'nav-back',
405
+ label: 'Back to list',
406
+ category: 'Navigation',
407
+ shortcut: 'esc',
408
+ keys: [{ special: 'escape' }],
409
+ screen: ['pr-list', 'branch-list', 'iteration-picker'],
410
+ helpGroup: 'Navigation',
411
+ footer: true,
412
+ footerLabel: 'back',
413
+ when: (ctx) => ctx.screen === 'pr-list' ||
414
+ ctx.screen === 'branch-list' ||
415
+ ctx.screen === 'iteration-picker',
416
+ },
417
+ // Branch list actions
418
+ {
419
+ id: 'branch-navigate',
420
+ label: 'Navigate branches',
421
+ category: 'Navigation',
422
+ shortcut: 'j/k',
423
+ keys: [{ special: 'upArrow' }, { special: 'downArrow' }],
424
+ screen: 'branch-list',
425
+ helpGroup: 'Navigation',
426
+ footer: true,
427
+ footerLabel: 'navigate',
428
+ },
429
+ {
430
+ id: 'branch-search',
431
+ label: 'Search branches',
432
+ category: 'Actions',
433
+ shortcut: '/',
434
+ keys: ['/'],
435
+ screen: 'branch-list',
436
+ helpGroup: 'Actions',
437
+ footer: true,
438
+ footerLabel: 'search',
439
+ },
440
+ {
441
+ id: 'branch-switch',
442
+ label: 'Switch to branch',
443
+ category: 'Actions',
444
+ shortcut: 'enter',
445
+ keys: [{ special: 'return' }],
446
+ screen: 'branch-list',
447
+ helpGroup: 'Actions',
448
+ footer: true,
449
+ footerLabel: 'switch',
450
+ when: (ctx) => ctx.screen === 'branch-list' &&
451
+ ctx.hasSelectedBranch &&
452
+ !ctx.isCurrentBranch,
453
+ },
454
+ {
455
+ id: 'branch-create',
456
+ label: 'Create new branch',
457
+ category: 'Actions',
458
+ shortcut: 'c',
459
+ keys: ['c'],
460
+ screen: 'branch-list',
461
+ helpGroup: 'Actions',
462
+ footer: true,
463
+ footerLabel: 'new',
464
+ when: (ctx) => ctx.screen === 'branch-list',
465
+ },
466
+ {
467
+ id: 'branch-delete',
468
+ label: 'Delete branch',
469
+ category: 'Actions',
470
+ shortcut: 'd',
471
+ keys: ['d'],
472
+ screen: 'branch-list',
473
+ helpGroup: 'Actions',
474
+ footer: true,
475
+ footerLabel: 'delete',
476
+ when: (ctx) => ctx.screen === 'branch-list' &&
477
+ ctx.hasSelectedBranch &&
478
+ !ctx.isCurrentBranch,
479
+ },
480
+ {
481
+ id: 'branch-merge',
482
+ label: 'Merge into current',
483
+ category: 'Actions',
484
+ shortcut: 'm',
485
+ keys: ['m'],
486
+ screen: 'branch-list',
487
+ helpGroup: 'Actions',
488
+ footer: true,
489
+ footerLabel: 'merge',
490
+ when: (ctx) => ctx.screen === 'branch-list' &&
491
+ ctx.hasSelectedBranch &&
492
+ !ctx.isCurrentBranch,
493
+ },
494
+ {
495
+ id: 'branch-push',
496
+ label: 'Push to remote',
497
+ category: 'Actions',
498
+ shortcut: 'P',
499
+ keys: ['P'],
500
+ screen: 'branch-list',
501
+ helpGroup: 'Actions',
502
+ footer: true,
503
+ footerLabel: 'push',
504
+ when: (ctx) => ctx.screen === 'branch-list' && ctx.hasSelectedBranch,
505
+ },
506
+ {
507
+ id: 'branch-create-pr',
508
+ label: 'Create PR for branch',
509
+ category: 'Actions',
510
+ shortcut: 'p',
511
+ keys: ['p'],
512
+ screen: 'branch-list',
513
+ helpGroup: 'Actions',
514
+ when: (ctx) => ctx.screen === 'branch-list' &&
515
+ ctx.hasSelectedBranch &&
516
+ ctx.hasPrCreateCapability,
517
+ },
518
+ {
519
+ id: 'branch-worktree',
520
+ label: 'Open worktree shell',
521
+ category: 'Actions',
522
+ shortcut: 'w',
523
+ keys: ['w'],
524
+ screen: 'branch-list',
525
+ helpGroup: 'Actions',
526
+ footer: true,
527
+ footerLabel: 'worktree',
528
+ when: (ctx) => ctx.screen === 'branch-list' && ctx.hasSelectedBranch && ctx.hasWorktree,
529
+ },
530
+ {
531
+ id: 'branch-refresh',
532
+ label: 'Refresh branches',
533
+ category: 'Actions',
534
+ shortcut: 'r',
535
+ keys: ['r'],
536
+ screen: 'branch-list',
537
+ helpGroup: 'Actions',
538
+ footer: true,
539
+ footerLabel: 'refresh',
540
+ when: (ctx) => ctx.screen === 'branch-list',
541
+ },
542
+ // PR list actions
543
+ {
544
+ id: 'pr-navigate',
545
+ label: 'Navigate pull requests',
546
+ category: 'Navigation',
547
+ shortcut: 'j/k',
548
+ keys: [{ special: 'upArrow' }, { special: 'downArrow' }],
549
+ screen: 'pr-list',
550
+ helpGroup: 'Navigation',
551
+ footer: true,
552
+ footerLabel: 'navigate',
553
+ },
554
+ {
555
+ id: 'pr-open',
556
+ label: 'Open in browser',
557
+ category: 'Actions',
558
+ shortcut: 'enter/o',
559
+ keys: ['o', { special: 'return' }],
560
+ screen: 'pr-list',
561
+ helpGroup: 'Actions',
562
+ footer: true,
563
+ footerLabel: 'open',
564
+ when: (ctx) => ctx.screen === 'pr-list' && ctx.hasSelectedPr,
565
+ },
566
+ {
567
+ id: 'pr-search',
568
+ label: 'Search pull requests',
569
+ category: 'Actions',
570
+ shortcut: '/',
571
+ keys: ['/'],
572
+ screen: 'pr-list',
573
+ helpGroup: 'Actions',
574
+ footer: true,
575
+ footerLabel: 'search',
576
+ },
577
+ // Form commands
578
+ {
579
+ id: 'form-navigate',
580
+ label: 'Move between fields',
581
+ category: 'Navigation',
582
+ shortcut: '↑/↓',
583
+ keys: [{ special: 'upArrow' }, { special: 'downArrow' }],
584
+ screen: 'form',
585
+ helpGroup: 'Navigation',
586
+ },
587
+ {
588
+ id: 'form-edit',
589
+ label: 'Edit field / open $EDITOR (description) / navigate to related item',
590
+ category: 'Actions',
591
+ shortcut: 'enter',
592
+ keys: [{ special: 'return' }],
593
+ screen: 'form',
594
+ helpGroup: 'Editing',
595
+ },
596
+ {
597
+ id: 'form-revert',
598
+ label: 'Revert field to previous value (in edit mode)',
599
+ category: 'Actions',
600
+ shortcut: 'esc',
601
+ keys: [{ special: 'escape' }],
602
+ screen: 'form',
603
+ helpGroup: 'Editing',
604
+ },
605
+ {
606
+ id: 'form-confirm',
607
+ label: 'Confirm field value',
608
+ category: 'Actions',
609
+ shortcut: 'enter/select',
610
+ screen: 'form',
611
+ helpGroup: 'Editing',
612
+ },
613
+ {
614
+ id: 'form-save',
615
+ label: 'Save and go back',
616
+ category: 'Actions',
617
+ shortcut: 's',
618
+ keys: ['s'],
619
+ screen: 'form',
620
+ helpGroup: 'Save & Exit',
621
+ },
622
+ {
623
+ id: 'form-back',
624
+ label: 'Go back (prompts to save/discard if unsaved changes)',
625
+ category: 'Navigation',
626
+ shortcut: 'esc',
627
+ keys: [{ special: 'escape' }],
628
+ screen: 'form',
629
+ helpGroup: 'Save & Exit',
630
+ },
631
+ // Iteration picker commands
632
+ {
633
+ id: 'iter-navigate',
634
+ label: 'Navigate iterations',
635
+ category: 'Navigation',
636
+ shortcut: '↑/↓',
637
+ keys: [{ special: 'upArrow' }, { special: 'downArrow' }],
638
+ screen: 'iteration-picker',
639
+ helpGroup: 'Navigation',
640
+ },
641
+ {
642
+ id: 'iter-select',
643
+ label: 'Select iteration',
644
+ category: 'Actions',
645
+ shortcut: 'enter',
646
+ keys: [{ special: 'return' }],
647
+ screen: 'iteration-picker',
648
+ helpGroup: 'Navigation',
649
+ },
650
+ // Settings commands
651
+ {
652
+ id: 'settings-navigate',
653
+ label: 'Navigate options',
654
+ category: 'Navigation',
655
+ shortcut: '↑/↓',
656
+ keys: [{ special: 'upArrow' }, { special: 'downArrow' }],
657
+ screen: 'settings',
658
+ helpGroup: 'Navigation',
659
+ },
660
+ {
661
+ id: 'settings-select',
662
+ label: 'Select or edit',
663
+ category: 'Actions',
664
+ shortcut: 'enter',
665
+ keys: [{ special: 'return' }],
666
+ screen: 'settings',
667
+ helpGroup: 'Navigation',
668
+ },
669
+ {
670
+ id: 'settings-back',
671
+ label: 'Go back',
672
+ category: 'Navigation',
673
+ shortcut: 'esc/,',
674
+ keys: [{ special: 'escape' }, ','],
675
+ screen: 'settings',
676
+ helpGroup: 'Navigation',
677
+ },
678
+ {
679
+ id: 'settings-edit',
680
+ label: 'Edit field value',
681
+ category: 'Actions',
682
+ shortcut: 'type',
683
+ screen: 'settings',
684
+ helpGroup: 'Editing',
685
+ },
686
+ {
687
+ id: 'settings-confirm',
688
+ label: 'Confirm',
689
+ category: 'Actions',
690
+ shortcut: 'enter/esc',
691
+ screen: 'settings',
692
+ helpGroup: 'Editing',
693
+ },
694
+ {
695
+ id: 'settings-create-template',
696
+ label: 'Create template',
697
+ category: 'Actions',
698
+ shortcut: 'c',
699
+ keys: ['c'],
700
+ screen: 'settings',
701
+ helpGroup: 'Templates',
702
+ when: (ctx) => ctx.capabilities.templates,
703
+ },
704
+ {
705
+ id: 'settings-delete-template',
706
+ label: 'Delete template',
707
+ category: 'Actions',
708
+ shortcut: 'd',
709
+ keys: ['d'],
710
+ screen: 'settings',
711
+ helpGroup: 'Templates',
712
+ when: (ctx) => ctx.capabilities.templates,
713
+ },
714
+ {
715
+ id: 'settings-edit-template',
716
+ label: 'Edit template',
717
+ category: 'Actions',
718
+ shortcut: 'enter',
719
+ keys: [{ special: 'return' }],
720
+ screen: 'settings',
721
+ helpGroup: 'Templates',
722
+ when: (ctx) => ctx.capabilities.templates,
723
+ },
724
+ // Status screen commands
725
+ {
726
+ id: 'status-scroll',
727
+ label: 'Scroll errors',
728
+ category: 'Navigation',
729
+ shortcut: '↑/↓',
730
+ keys: [{ special: 'upArrow' }, { special: 'downArrow' }],
731
+ screen: 'status',
732
+ helpGroup: 'Navigation',
733
+ },
734
+ {
735
+ id: 'status-back',
736
+ label: 'Go back',
737
+ category: 'Navigation',
738
+ shortcut: 'esc/q',
739
+ keys: [{ special: 'escape' }, 'q'],
740
+ screen: 'status',
741
+ helpGroup: 'Navigation',
742
+ },
743
+ {
744
+ id: 'status-retry',
745
+ label: 'Retry failed sync operations',
746
+ category: 'Actions',
747
+ shortcut: 'r',
748
+ keys: ['r'],
749
+ screen: 'status',
750
+ helpGroup: 'Actions',
751
+ when: (ctx) => ctx.hasSyncManager,
752
+ },
178
753
  // Other
179
754
  {
180
755
  id: 'toggle-detail-panel',
181
756
  label: 'Toggle detail panel',
182
757
  category: 'Other',
183
758
  shortcut: 'v',
759
+ keys: ['v'],
760
+ screen: 'list',
761
+ helpGroup: 'Other',
184
762
  when: (ctx) => ctx.screen === 'list',
185
763
  },
186
764
  {
@@ -188,8 +766,32 @@ const commands = [
188
766
  label: 'Quit',
189
767
  category: 'Other',
190
768
  shortcut: 'q',
769
+ keys: ['q'],
770
+ screen: 'global',
771
+ helpGroup: 'Other',
191
772
  when: () => true,
192
773
  },
774
+ // Help screen commands
775
+ {
776
+ id: 'help-scroll',
777
+ label: 'Scroll help',
778
+ category: 'Navigation',
779
+ keys: [{ special: 'upArrow' }, { special: 'downArrow' }],
780
+ shortcut: '↑/↓',
781
+ screen: 'help',
782
+ helpGroup: 'Navigation',
783
+ },
784
+ {
785
+ id: 'help-back',
786
+ label: 'Go back',
787
+ category: 'Navigation',
788
+ keys: [{ special: 'escape' }],
789
+ shortcut: 'esc',
790
+ screen: 'help',
791
+ helpGroup: 'Navigation',
792
+ footer: true,
793
+ footerLabel: 'back',
794
+ },
193
795
  ];
194
796
  export function filterCommands(commands, query) {
195
797
  if (query.trim() === '')
@@ -208,7 +810,7 @@ export function groupCommandsByCategory(commands) {
208
810
  return groups;
209
811
  }
210
812
  export function getVisibleCommands(ctx) {
211
- const visible = commands.filter((cmd) => cmd.when(ctx));
813
+ const visible = commands.filter((cmd) => !cmd.when || cmd.when(ctx));
212
814
  // Add dynamic switch-type commands
213
815
  if (ctx.screen === 'list' && ctx.capabilities.customTypes) {
214
816
  for (const type of ctx.types) {
@@ -220,10 +822,80 @@ export function getVisibleCommands(ctx) {
220
822
  label: `Switch to ${plural}`,
221
823
  category: 'Switching',
222
824
  shortcut: 'tab',
825
+ screen: 'list',
223
826
  when: () => true,
224
827
  });
225
828
  }
226
829
  }
227
830
  return visible;
228
831
  }
832
+ export function findCommand(id) {
833
+ return commands.find((cmd) => cmd.id === id);
834
+ }
835
+ export function getCommandsForScreen(screen, ctx) {
836
+ return commands.filter((cmd) => {
837
+ const screens = cmd.screen;
838
+ if (screens === 'global') {
839
+ // global matches all
840
+ }
841
+ else if (Array.isArray(screens)) {
842
+ if (!screens.includes(screen))
843
+ return false;
844
+ }
845
+ else {
846
+ if (screens !== screen)
847
+ return false;
848
+ }
849
+ if (cmd.when && !cmd.when(ctx))
850
+ return false;
851
+ return true;
852
+ });
853
+ }
854
+ export function getFooterCommands(screen, ctx) {
855
+ return getCommandsForScreen(screen, ctx).filter((cmd) => cmd.footer);
856
+ }
857
+ export function buildFooterHints(screen, ctx, availableWidth) {
858
+ const footerCmds = getFooterCommands(screen, ctx);
859
+ const sep = ' ';
860
+ let result = '';
861
+ for (const cmd of footerCmds) {
862
+ if (!cmd.shortcut)
863
+ continue;
864
+ const label = cmd.footerLabel ?? cmd.label;
865
+ const entry = `${cmd.shortcut} ${label}`;
866
+ const candidate = result ? result + sep + entry : entry;
867
+ if (candidate.length > availableWidth)
868
+ break;
869
+ result = candidate;
870
+ }
871
+ return result;
872
+ }
873
+ export function matchesCommand(id, input, key) {
874
+ const cmd = findCommand(id);
875
+ if (!cmd?.keys)
876
+ return false;
877
+ return cmd.keys.some((k) => {
878
+ if (typeof k === 'string')
879
+ return input === k;
880
+ if (k.modifier === 'shift')
881
+ return key[k.special] && key['shift'];
882
+ return key[k.special] && !key['shift'];
883
+ });
884
+ }
885
+ export function groupByHelpGroup(commands) {
886
+ const groups = [];
887
+ const seen = new Map();
888
+ for (const cmd of commands) {
889
+ if (!cmd.helpGroup || !cmd.shortcut)
890
+ continue;
891
+ let group = seen.get(cmd.helpGroup);
892
+ if (!group) {
893
+ group = { label: cmd.helpGroup, shortcuts: [] };
894
+ seen.set(cmd.helpGroup, group);
895
+ groups.push(group);
896
+ }
897
+ group.shortcuts.push({ key: cmd.shortcut, description: cmd.label });
898
+ }
899
+ return groups;
900
+ }
229
901
  //# sourceMappingURL=commands.js.map