@sascha384/tic 5.0.0 → 5.2.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 (44) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/dist/app.js +4 -1
  3. package/dist/app.js.map +1 -1
  4. package/dist/commands.d.ts +23 -1
  5. package/dist/commands.js +636 -16
  6. package/dist/commands.js.map +1 -1
  7. package/dist/components/BranchList.js +21 -20
  8. package/dist/components/BranchList.js.map +1 -1
  9. package/dist/components/Header.js +6 -2
  10. package/dist/components/Header.js.map +1 -1
  11. package/dist/components/HelpScreen.d.ts +1 -9
  12. package/dist/components/HelpScreen.js +32 -228
  13. package/dist/components/HelpScreen.js.map +1 -1
  14. package/dist/components/IterationPicker.js +3 -2
  15. package/dist/components/IterationPicker.js.map +1 -1
  16. package/dist/components/MarkdownEditor.d.ts +1 -0
  17. package/dist/components/MarkdownEditor.js +173 -0
  18. package/dist/components/MarkdownEditor.js.map +1 -0
  19. package/dist/components/PullRequestList.js +14 -13
  20. package/dist/components/PullRequestList.js.map +1 -1
  21. package/dist/components/Settings.js +31 -26
  22. package/dist/components/Settings.js.map +1 -1
  23. package/dist/components/StatusScreen.js +19 -15
  24. package/dist/components/StatusScreen.js.map +1 -1
  25. package/dist/components/WorkItemForm.js +26 -35
  26. package/dist/components/WorkItemForm.js.map +1 -1
  27. package/dist/components/WorkItemList.d.ts +0 -1
  28. package/dist/components/WorkItemList.js +84 -100
  29. package/dist/components/WorkItemList.js.map +1 -1
  30. package/dist/components/markdownHighlight.d.ts +20 -0
  31. package/dist/components/markdownHighlight.js +195 -0
  32. package/dist/components/markdownHighlight.js.map +1 -0
  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 +1 -0
  37. package/dist/stores/backendDataStore.js.map +1 -1
  38. package/dist/stores/editorStore.d.ts +53 -0
  39. package/dist/stores/editorStore.js +513 -0
  40. package/dist/stores/editorStore.js.map +1 -0
  41. package/dist/stores/navigationStore.d.ts +1 -1
  42. package/dist/stores/navigationStore.js +1 -1
  43. package/dist/stores/navigationStore.js.map +1 -1
  44. 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,9 +121,10 @@ const commands = [
83
121
  label: 'Go to help',
84
122
  category: 'Navigation',
85
123
  shortcut: '?',
86
- when: (ctx) => ctx.screen === 'list' ||
87
- ctx.screen === 'branch-list' ||
88
- ctx.screen === 'pr-list',
124
+ keys: ['?'],
125
+ screen: 'global',
126
+ footer: true,
127
+ footerLabel: 'help',
89
128
  },
90
129
  // Bulk
91
130
  {
@@ -93,6 +132,9 @@ const commands = [
93
132
  label: 'Mark/unmark item',
94
133
  category: 'Bulk',
95
134
  shortcut: 'm',
135
+ keys: ['m'],
136
+ screen: 'list',
137
+ helpGroup: 'Actions',
96
138
  when: (ctx) => ctx.screen === 'list' && ctx.hasSelectedItem,
97
139
  },
98
140
  {
@@ -100,12 +142,19 @@ const commands = [
100
142
  label: 'Clear all marks',
101
143
  category: 'Bulk',
102
144
  shortcut: 'M',
145
+ keys: ['M'],
146
+ screen: 'list',
147
+ helpGroup: 'Bulk',
103
148
  when: (ctx) => ctx.screen === 'list' && ctx.markedCount > 0,
104
149
  },
105
150
  {
106
151
  id: 'set-priority',
107
152
  label: 'Set priority',
108
153
  category: 'Bulk',
154
+ shortcut: 'y',
155
+ keys: ['y'],
156
+ screen: 'list',
157
+ helpGroup: 'Bulk',
109
158
  when: (ctx) => ctx.screen === 'list' &&
110
159
  ctx.capabilities.fields.priority &&
111
160
  (ctx.hasSelectedItem || ctx.markedCount > 0),
@@ -115,6 +164,9 @@ const commands = [
115
164
  label: 'Set assignee',
116
165
  category: 'Bulk',
117
166
  shortcut: 'a',
167
+ keys: ['a'],
168
+ screen: 'list',
169
+ helpGroup: 'Actions',
118
170
  when: (ctx) => ctx.screen === 'list' &&
119
171
  ctx.capabilities.fields.assignee &&
120
172
  (ctx.hasSelectedItem || ctx.markedCount > 0),
@@ -124,6 +176,9 @@ const commands = [
124
176
  label: 'Set labels',
125
177
  category: 'Bulk',
126
178
  shortcut: 'l',
179
+ keys: ['l'],
180
+ screen: 'list',
181
+ helpGroup: 'Actions',
127
182
  when: (ctx) => ctx.screen === 'list' &&
128
183
  ctx.capabilities.fields.labels &&
129
184
  (ctx.hasSelectedItem || ctx.markedCount > 0),
@@ -133,6 +188,9 @@ const commands = [
133
188
  label: 'Set type',
134
189
  category: 'Bulk',
135
190
  shortcut: 't',
191
+ keys: ['t'],
192
+ screen: 'list',
193
+ helpGroup: 'Bulk',
136
194
  when: (ctx) => ctx.screen === 'list' &&
137
195
  ctx.capabilities.customTypes &&
138
196
  (ctx.hasSelectedItem || ctx.markedCount > 0),
@@ -141,14 +199,19 @@ const commands = [
141
199
  id: 'bulk-menu',
142
200
  label: 'Bulk actions menu',
143
201
  category: 'Bulk',
144
- shortcut: 'B',
145
- when: (ctx) => ctx.screen === 'list' && ctx.markedCount > 0,
202
+ shortcut: 'x',
203
+ keys: ['x'],
204
+ screen: 'list',
205
+ helpGroup: 'Bulk',
146
206
  },
147
207
  {
148
208
  id: 'filter',
149
209
  label: 'Filter...',
150
210
  category: 'Actions',
151
211
  shortcut: 'F',
212
+ keys: ['F'],
213
+ screen: 'list',
214
+ helpGroup: 'Actions',
152
215
  when: (ctx) => ctx.screen === 'list',
153
216
  },
154
217
  {
@@ -156,6 +219,9 @@ const commands = [
156
219
  label: 'Clear filters',
157
220
  category: 'Actions',
158
221
  shortcut: 'X',
222
+ keys: ['X'],
223
+ screen: 'list',
224
+ helpGroup: 'Actions',
159
225
  when: (ctx) => ctx.screen === 'list' && ctx.hasActiveFilters,
160
226
  },
161
227
  {
@@ -163,26 +229,224 @@ const commands = [
163
229
  label: 'Load view...',
164
230
  category: 'Actions',
165
231
  shortcut: 'V',
232
+ keys: ['V'],
233
+ screen: 'list',
234
+ helpGroup: 'Actions',
166
235
  when: (ctx) => ctx.screen === 'list',
167
236
  },
168
237
  {
169
238
  id: 'save-view',
170
239
  label: 'Save current view...',
171
240
  category: 'Actions',
241
+ screen: 'list',
172
242
  when: (ctx) => ctx.screen === 'list' && ctx.hasActiveFilters,
173
243
  },
174
244
  {
175
245
  id: 'delete-view',
176
246
  label: 'Delete view...',
177
247
  category: 'Actions',
248
+ screen: 'list',
178
249
  when: (ctx) => ctx.screen === 'list' && ctx.hasSavedViews,
179
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
+ },
180
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
+ },
181
440
  {
182
441
  id: 'branch-switch',
183
442
  label: 'Switch to branch',
184
443
  category: 'Actions',
185
444
  shortcut: 'enter',
445
+ keys: [{ special: 'return' }],
446
+ screen: 'branch-list',
447
+ helpGroup: 'Actions',
448
+ footer: true,
449
+ footerLabel: 'switch',
186
450
  when: (ctx) => ctx.screen === 'branch-list' &&
187
451
  ctx.hasSelectedBranch &&
188
452
  !ctx.isCurrentBranch,
@@ -192,6 +456,11 @@ const commands = [
192
456
  label: 'Create new branch',
193
457
  category: 'Actions',
194
458
  shortcut: 'c',
459
+ keys: ['c'],
460
+ screen: 'branch-list',
461
+ helpGroup: 'Actions',
462
+ footer: true,
463
+ footerLabel: 'new',
195
464
  when: (ctx) => ctx.screen === 'branch-list',
196
465
  },
197
466
  {
@@ -199,6 +468,11 @@ const commands = [
199
468
  label: 'Delete branch',
200
469
  category: 'Actions',
201
470
  shortcut: 'd',
471
+ keys: ['d'],
472
+ screen: 'branch-list',
473
+ helpGroup: 'Actions',
474
+ footer: true,
475
+ footerLabel: 'delete',
202
476
  when: (ctx) => ctx.screen === 'branch-list' &&
203
477
  ctx.hasSelectedBranch &&
204
478
  !ctx.isCurrentBranch,
@@ -208,6 +482,11 @@ const commands = [
208
482
  label: 'Merge into current',
209
483
  category: 'Actions',
210
484
  shortcut: 'm',
485
+ keys: ['m'],
486
+ screen: 'branch-list',
487
+ helpGroup: 'Actions',
488
+ footer: true,
489
+ footerLabel: 'merge',
211
490
  when: (ctx) => ctx.screen === 'branch-list' &&
212
491
  ctx.hasSelectedBranch &&
213
492
  !ctx.isCurrentBranch,
@@ -217,6 +496,11 @@ const commands = [
217
496
  label: 'Push to remote',
218
497
  category: 'Actions',
219
498
  shortcut: 'P',
499
+ keys: ['P'],
500
+ screen: 'branch-list',
501
+ helpGroup: 'Actions',
502
+ footer: true,
503
+ footerLabel: 'push',
220
504
  when: (ctx) => ctx.screen === 'branch-list' && ctx.hasSelectedBranch,
221
505
  },
222
506
  {
@@ -224,6 +508,9 @@ const commands = [
224
508
  label: 'Create PR for branch',
225
509
  category: 'Actions',
226
510
  shortcut: 'p',
511
+ keys: ['p'],
512
+ screen: 'branch-list',
513
+ helpGroup: 'Actions',
227
514
  when: (ctx) => ctx.screen === 'branch-list' &&
228
515
  ctx.hasSelectedBranch &&
229
516
  ctx.hasPrCreateCapability,
@@ -233,6 +520,11 @@ const commands = [
233
520
  label: 'Open worktree shell',
234
521
  category: 'Actions',
235
522
  shortcut: 'w',
523
+ keys: ['w'],
524
+ screen: 'branch-list',
525
+ helpGroup: 'Actions',
526
+ footer: true,
527
+ footerLabel: 'worktree',
236
528
  when: (ctx) => ctx.screen === 'branch-list' && ctx.hasSelectedBranch && ctx.hasWorktree,
237
529
  },
238
530
  {
@@ -240,29 +532,223 @@ const commands = [
240
532
  label: 'Refresh branches',
241
533
  category: 'Actions',
242
534
  shortcut: 'r',
535
+ keys: ['r'],
536
+ screen: 'branch-list',
537
+ helpGroup: 'Actions',
538
+ footer: true,
539
+ footerLabel: 'refresh',
243
540
  when: (ctx) => ctx.screen === 'branch-list',
244
541
  },
542
+ // PR list actions
245
543
  {
246
- id: 'branch-back',
247
- label: 'Back to items',
544
+ id: 'pr-navigate',
545
+ label: 'Navigate pull requests',
248
546
  category: 'Navigation',
249
- shortcut: 'esc',
250
- when: (ctx) => ctx.screen === 'branch-list',
547
+ shortcut: 'j/k',
548
+ keys: [{ special: 'upArrow' }, { special: 'downArrow' }],
549
+ screen: 'pr-list',
550
+ helpGroup: 'Navigation',
551
+ footer: true,
552
+ footerLabel: 'navigate',
251
553
  },
252
- // PR list actions
253
554
  {
254
555
  id: 'pr-open',
255
556
  label: 'Open in browser',
256
557
  category: 'Actions',
257
- shortcut: 'enter',
558
+ shortcut: 'enter/o',
559
+ keys: ['o', { special: 'return' }],
560
+ screen: 'pr-list',
561
+ helpGroup: 'Actions',
562
+ footer: true,
563
+ footerLabel: 'open',
258
564
  when: (ctx) => ctx.screen === 'pr-list' && ctx.hasSelectedPr,
259
565
  },
260
566
  {
261
- id: 'pr-back',
262
- label: 'Back to items',
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',
263
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',
264
600
  shortcut: 'esc',
265
- when: (ctx) => ctx.screen === 'pr-list',
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,
266
752
  },
267
753
  // Other
268
754
  {
@@ -270,6 +756,9 @@ const commands = [
270
756
  label: 'Toggle detail panel',
271
757
  category: 'Other',
272
758
  shortcut: 'v',
759
+ keys: ['v'],
760
+ screen: 'list',
761
+ helpGroup: 'Other',
273
762
  when: (ctx) => ctx.screen === 'list',
274
763
  },
275
764
  {
@@ -277,8 +766,69 @@ const commands = [
277
766
  label: 'Quit',
278
767
  category: 'Other',
279
768
  shortcut: 'q',
769
+ keys: ['q'],
770
+ screen: 'global',
771
+ helpGroup: 'Other',
280
772
  when: () => true,
281
773
  },
774
+ // Editor commands
775
+ {
776
+ id: 'editor-save',
777
+ label: 'Save and return',
778
+ category: 'Actions',
779
+ shortcut: 'Ctrl+S',
780
+ keys: [],
781
+ screen: 'editor',
782
+ helpGroup: 'Editor',
783
+ },
784
+ {
785
+ id: 'editor-cancel',
786
+ label: 'Cancel and return',
787
+ category: 'Navigation',
788
+ shortcut: 'Esc',
789
+ keys: [],
790
+ screen: 'editor',
791
+ helpGroup: 'Editor',
792
+ },
793
+ {
794
+ id: 'editor-undo',
795
+ label: 'Undo',
796
+ category: 'Actions',
797
+ shortcut: 'Ctrl+Z',
798
+ keys: [],
799
+ screen: 'editor',
800
+ helpGroup: 'Editor',
801
+ },
802
+ {
803
+ id: 'editor-redo',
804
+ label: 'Redo',
805
+ category: 'Actions',
806
+ shortcut: 'Ctrl+Shift+Z',
807
+ keys: [],
808
+ screen: 'editor',
809
+ helpGroup: 'Editor',
810
+ },
811
+ // Help screen commands
812
+ {
813
+ id: 'help-scroll',
814
+ label: 'Scroll help',
815
+ category: 'Navigation',
816
+ keys: [{ special: 'upArrow' }, { special: 'downArrow' }],
817
+ shortcut: '↑/↓',
818
+ screen: 'help',
819
+ helpGroup: 'Navigation',
820
+ },
821
+ {
822
+ id: 'help-back',
823
+ label: 'Go back',
824
+ category: 'Navigation',
825
+ keys: [{ special: 'escape' }],
826
+ shortcut: 'esc',
827
+ screen: 'help',
828
+ helpGroup: 'Navigation',
829
+ footer: true,
830
+ footerLabel: 'back',
831
+ },
282
832
  ];
283
833
  export function filterCommands(commands, query) {
284
834
  if (query.trim() === '')
@@ -297,7 +847,7 @@ export function groupCommandsByCategory(commands) {
297
847
  return groups;
298
848
  }
299
849
  export function getVisibleCommands(ctx) {
300
- const visible = commands.filter((cmd) => cmd.when(ctx));
850
+ const visible = commands.filter((cmd) => !cmd.when || cmd.when(ctx));
301
851
  // Add dynamic switch-type commands
302
852
  if (ctx.screen === 'list' && ctx.capabilities.customTypes) {
303
853
  for (const type of ctx.types) {
@@ -309,10 +859,80 @@ export function getVisibleCommands(ctx) {
309
859
  label: `Switch to ${plural}`,
310
860
  category: 'Switching',
311
861
  shortcut: 'tab',
862
+ screen: 'list',
312
863
  when: () => true,
313
864
  });
314
865
  }
315
866
  }
316
867
  return visible;
317
868
  }
869
+ export function findCommand(id) {
870
+ return commands.find((cmd) => cmd.id === id);
871
+ }
872
+ export function getCommandsForScreen(screen, ctx) {
873
+ return commands.filter((cmd) => {
874
+ const screens = cmd.screen;
875
+ if (screens === 'global') {
876
+ // global matches all
877
+ }
878
+ else if (Array.isArray(screens)) {
879
+ if (!screens.includes(screen))
880
+ return false;
881
+ }
882
+ else {
883
+ if (screens !== screen)
884
+ return false;
885
+ }
886
+ if (cmd.when && !cmd.when(ctx))
887
+ return false;
888
+ return true;
889
+ });
890
+ }
891
+ export function getFooterCommands(screen, ctx) {
892
+ return getCommandsForScreen(screen, ctx).filter((cmd) => cmd.footer);
893
+ }
894
+ export function buildFooterHints(screen, ctx, availableWidth) {
895
+ const footerCmds = getFooterCommands(screen, ctx);
896
+ const sep = ' ';
897
+ let result = '';
898
+ for (const cmd of footerCmds) {
899
+ if (!cmd.shortcut)
900
+ continue;
901
+ const label = cmd.footerLabel ?? cmd.label;
902
+ const entry = `${cmd.shortcut} ${label}`;
903
+ const candidate = result ? result + sep + entry : entry;
904
+ if (candidate.length > availableWidth)
905
+ break;
906
+ result = candidate;
907
+ }
908
+ return result;
909
+ }
910
+ export function matchesCommand(id, input, key) {
911
+ const cmd = findCommand(id);
912
+ if (!cmd?.keys)
913
+ return false;
914
+ return cmd.keys.some((k) => {
915
+ if (typeof k === 'string')
916
+ return input === k;
917
+ if (k.modifier === 'shift')
918
+ return key[k.special] && key['shift'];
919
+ return key[k.special] && !key['shift'];
920
+ });
921
+ }
922
+ export function groupByHelpGroup(commands) {
923
+ const groups = [];
924
+ const seen = new Map();
925
+ for (const cmd of commands) {
926
+ if (!cmd.helpGroup || !cmd.shortcut)
927
+ continue;
928
+ let group = seen.get(cmd.helpGroup);
929
+ if (!group) {
930
+ group = { label: cmd.helpGroup, shortcuts: [] };
931
+ seen.set(cmd.helpGroup, group);
932
+ groups.push(group);
933
+ }
934
+ group.shortcuts.push({ key: cmd.shortcut, description: cmd.label });
935
+ }
936
+ return groups;
937
+ }
318
938
  //# sourceMappingURL=commands.js.map