epiq 0.0.1 → 0.0.3
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/app.js +11 -4
- package/dist/board/components/Board.js +4 -12
- package/dist/board/components/CommandLine.d.ts +2 -0
- package/dist/board/components/CommandLine.js +19 -0
- package/dist/{components/Help.d.ts → board/components/ContextBar.d.ts} +1 -1
- package/dist/board/components/ContextBar.js +8 -0
- package/dist/board/components/Help.js +18 -11
- package/dist/board/components/Swimlane.js +6 -3
- package/dist/board/components/Swimlanes.js +1 -1
- package/dist/board/components/TextInput.d.ts +6 -0
- package/dist/board/components/TextInput.js +9 -0
- package/dist/board/components/TicketListItem.js +5 -4
- package/dist/board/components/TicketUI.js +6 -7
- package/dist/board/hints/hints.d.ts +7 -0
- package/dist/board/hints/hints.js +29 -0
- package/dist/board/mock/board.js +526 -457
- package/dist/cli.d.ts +2 -1
- package/dist/cli.js +37 -14
- package/dist/debug-logger.d.ts +2 -0
- package/dist/debug-logger.js +15 -0
- package/dist/navigation/actions/add/add-actions.d.ts +2 -0
- package/dist/navigation/actions/add/add-actions.js +25 -0
- package/dist/navigation/actions/add/add-item-actions.d.ts +2 -0
- package/dist/navigation/actions/add/add-item-actions.js +25 -0
- package/dist/navigation/actions/add-item/add-item-actions.d.ts +3 -0
- package/dist/navigation/actions/add-item/add-item-actions.js +35 -0
- package/dist/navigation/actions/board-action-map.d.ts +10 -0
- package/dist/navigation/actions/board-action-map.js +12 -0
- package/dist/{lib/utils/default-actions.d.ts → navigation/actions/default/default-action-utils.d.ts} +2 -2
- package/dist/{lib/utils → navigation/actions/default}/default-action-utils.js +11 -10
- package/dist/navigation/actions/default/default-actions.d.ts +2 -0
- package/dist/navigation/actions/default/default-actions.js +78 -0
- package/dist/navigation/actions/input/command-line-input.d.ts +2 -0
- package/dist/navigation/actions/input/command-line-input.js +18 -0
- package/dist/navigation/actions/input/input-actions-utils.d.ts +8 -0
- package/dist/navigation/actions/input/input-actions-utils.js +47 -0
- package/dist/navigation/actions/input/input-actions.d.ts +2 -0
- package/dist/navigation/actions/input/input-actions.js +43 -0
- package/dist/navigation/actions/move/move-actions-routes.d.ts +4 -0
- package/dist/navigation/actions/move/move-actions-routes.js +55 -0
- package/dist/{lib/actions → navigation/actions/move}/move-actions-utils.d.ts +1 -1
- package/dist/{board/actions/move-actions.js → navigation/actions/move/move-actions-utils.js} +13 -9
- package/dist/navigation/actions/move/move-actions.d.ts +4 -0
- package/dist/navigation/actions/move/move-actions.js +53 -0
- package/dist/{lib/utils/default-action-utils.d.ts → navigation/actions/navigate/navigation-action-utils.d.ts} +1 -1
- package/dist/navigation/actions/navigate/navigation-actions.d.ts +2 -0
- package/dist/navigation/actions/navigate/navigation-actions.js +78 -0
- package/dist/navigation/command-line/command-line-actions.d.ts +2 -0
- package/dist/navigation/command-line/command-line-actions.js +32 -0
- package/dist/navigation/command-line/command-line-intent.d.ts +7 -0
- package/dist/navigation/command-line/command-line-intent.js +29 -0
- package/dist/navigation/command-line/command-line-sequence-actions.d.ts +2 -0
- package/dist/navigation/command-line/command-line-sequence-actions.js +31 -0
- package/dist/navigation/command-line/command-line-sequence-intent.d.ts +7 -0
- package/dist/navigation/command-line/command-line-sequence-intent.js +29 -0
- package/dist/navigation/model/action-map.model.d.ts +17 -5
- package/dist/navigation/model/action-map.model.js +2 -0
- package/dist/navigation/model/navigation-ctx.model.d.ts +2 -2
- package/dist/navigation/model/navigation-tree.model.d.ts +1 -0
- package/dist/navigation/navigation.d.ts +1 -1
- package/dist/navigation/navigation.js +48 -34
- package/dist/navigation/state/command-line.state.d.ts +13 -0
- package/dist/navigation/state/command-line.state.js +43 -0
- package/dist/navigation/state/state.d.ts +7 -6
- package/dist/navigation/state/state.js +31 -2
- package/dist/navigation/utils/get-command-line-intent.d.ts +3 -0
- package/dist/navigation/utils/get-command-line-intent.js +17 -0
- package/dist/navigation/utils/getKeyIntent.d.ts +5 -0
- package/dist/navigation/utils/getKeyIntent.js +71 -0
- package/dist/navigation/utils/key-intent.d.ts +19 -10
- package/dist/navigation/utils/key-intent.js +103 -43
- package/package.json +2 -2
- package/dist/board/actions/board-action-map.d.ts +0 -11
- package/dist/board/actions/board-action-map.js +0 -11
- package/dist/board/actions/move-actions-routes.d.ts +0 -4
- package/dist/board/actions/move-actions-routes.js +0 -31
- package/dist/board/actions/move-actions.d.ts +0 -5
- package/dist/board/board-action-map.d.ts +0 -9
- package/dist/board/board-action-map.js +0 -7
- package/dist/board/move-actions-routes.d.ts +0 -4
- package/dist/board/move-actions-routes.js +0 -31
- package/dist/board/move-actions.d.ts +0 -5
- package/dist/board/move-actions.js +0 -49
- package/dist/components/Board.d.ts +0 -6
- package/dist/components/Board.js +0 -15
- package/dist/components/Help.js +0 -21
- package/dist/components/Swimlane.d.ts +0 -8
- package/dist/components/Swimlane.js +0 -10
- package/dist/components/TicketListItem.d.ts +0 -6
- package/dist/components/TicketListItem.js +0 -12
- package/dist/lib/actions/board-action-map.d.ts +0 -9
- package/dist/lib/actions/board-action-map.js +0 -7
- package/dist/lib/actions/move-actions-utils.js +0 -43
- package/dist/lib/actions/move-actions.d.ts +0 -4
- package/dist/lib/actions/move-actions.js +0 -31
- package/dist/lib/board/board-action-map.d.ts +0 -9
- package/dist/lib/board/board-action-map.js +0 -7
- package/dist/lib/board/move-actions-routes.d.ts +0 -4
- package/dist/lib/board/move-actions-routes.js +0 -31
- package/dist/lib/board/move-actions.d.ts +0 -5
- package/dist/lib/board/move-actions.js +0 -43
- package/dist/lib/board-utils.d.ts +0 -7
- package/dist/lib/board-utils.js +0 -33
- package/dist/lib/default-actions-routes.d.ts +0 -4
- package/dist/lib/default-actions-routes.js +0 -47
- package/dist/lib/default-actions.d.ts +0 -4
- package/dist/lib/default-actions.js +0 -47
- package/dist/lib/navigation-context.d.ts +0 -16
- package/dist/lib/navigation.d.ts +0 -10
- package/dist/lib/navigation.js +0 -74
- package/dist/lib/render-utils.d.ts +0 -10
- package/dist/lib/render-utils.js +0 -12
- package/dist/lib/state.d.ts +0 -8
- package/dist/lib/state.js +0 -8
- package/dist/lib/types/action-map.model.d.ts +0 -14
- package/dist/lib/types/action-map.model.js +0 -4
- package/dist/lib/types/board.model.d.ts +0 -21
- package/dist/lib/types/board.model.js +0 -5
- package/dist/lib/types/navigation.model.d.ts +0 -9
- package/dist/lib/utils/array-utils.d.ts +0 -5
- package/dist/lib/utils/array-utils.js +0 -7
- package/dist/lib/utils/default-actions.js +0 -50
- package/dist/lib/utils/key-intent.d.ts +0 -16
- package/dist/lib/utils/key-intent.js +0 -65
- package/dist/lib/utils.d.ts +0 -10
- package/dist/lib/utils.js +0 -12
- package/dist/mock/board.d.ts +0 -2
- package/dist/mock/board.js +0 -139
- package/dist/navigation/actions/default-actions-routes.d.ts +0 -4
- package/dist/navigation/actions/default-actions-routes.js +0 -47
- package/dist/navigation/actions/default-actions.d.ts +0 -7
- /package/dist/navigation/actions/{default-actions.js → navigate/navigation-action-utils.js} +0 -0
- /package/dist/{lib/navigation-context.js → navigation/navigation-ctx.d.ts} +0 -0
- /package/dist/{lib/types/navigation.model.js → navigation/navigation-ctx.js} +0 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { Mode } from '../../model/action-map.model.js';
|
|
2
|
+
import { patchState } from '../../state/state.js';
|
|
3
|
+
import { KeyIntent } from '../../utils/key-intent.js';
|
|
4
|
+
import { moveChildNextWithinParent, moveChildPreviousWithinParent, moveChildToNextParent, moveChildToPreviousParent, } from './move-actions-utils.js';
|
|
5
|
+
export const toggleMoveMode = [
|
|
6
|
+
{
|
|
7
|
+
intent: KeyIntent.ToggleMove,
|
|
8
|
+
mode: Mode.DEFAULT,
|
|
9
|
+
description: '[Y] Toggle move/yank mode',
|
|
10
|
+
action: () => {
|
|
11
|
+
patchState({
|
|
12
|
+
mode: Mode.MOVE,
|
|
13
|
+
});
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
intent: KeyIntent.ToggleMove,
|
|
18
|
+
mode: Mode.MOVE,
|
|
19
|
+
action: () => {
|
|
20
|
+
patchState({
|
|
21
|
+
mode: Mode.DEFAULT,
|
|
22
|
+
});
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
];
|
|
26
|
+
export const moveWithinParent = [
|
|
27
|
+
{
|
|
28
|
+
mode: Mode.MOVE,
|
|
29
|
+
description: '[Y, ARROW KEYS] Move item',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
intent: KeyIntent.MovePreviousItem,
|
|
33
|
+
mode: Mode.MOVE,
|
|
34
|
+
action: moveChildPreviousWithinParent,
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
intent: KeyIntent.MoveNextItem,
|
|
38
|
+
mode: Mode.MOVE,
|
|
39
|
+
action: moveChildNextWithinParent,
|
|
40
|
+
},
|
|
41
|
+
];
|
|
42
|
+
export const moveAcrossParents = [
|
|
43
|
+
{
|
|
44
|
+
intent: KeyIntent.MoveToNextContainer,
|
|
45
|
+
mode: Mode.MOVE,
|
|
46
|
+
action: moveChildToNextParent,
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
intent: KeyIntent.MoveToPreviousContainer,
|
|
50
|
+
mode: Mode.MOVE,
|
|
51
|
+
action: moveChildToPreviousParent,
|
|
52
|
+
},
|
|
53
|
+
];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { NavigateCtx } from '
|
|
1
|
+
import { NavigateCtx } from '../../model/navigation-ctx.model.js';
|
|
2
2
|
export declare const navigateToNextItem: (ctx: NavigateCtx) => void;
|
|
3
3
|
export declare const navigateToPreviousItem: (ctx: NavigateCtx) => void;
|
|
4
4
|
export declare const navigateToNextContainer: (ctx: NavigateCtx) => void;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { Mode } from '../../model/action-map.model.js';
|
|
2
|
+
import { patchState } from '../../state/state.js';
|
|
3
|
+
import { KeyIntent } from '../../utils/key-intent.js';
|
|
4
|
+
import { enterChildNode, exitToParentNode, navigateToNextContainer, navigateToNextItem, navigateToPreviousContainer, navigateToPreviousItem, } from './navigation-action-utils.js';
|
|
5
|
+
export const DefaultActions = [
|
|
6
|
+
{
|
|
7
|
+
intent: KeyIntent.ToggleCommandLine,
|
|
8
|
+
mode: Mode.DEFAULT,
|
|
9
|
+
description: '[:] Toggle command line',
|
|
10
|
+
action: () => patchState({
|
|
11
|
+
mode: Mode.COMMAND_LINE,
|
|
12
|
+
}),
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
intent: KeyIntent.ToggleCommandLine,
|
|
16
|
+
mode: Mode.COMMAND_LINE,
|
|
17
|
+
description: '[ESC] Toggle command line',
|
|
18
|
+
action: () => patchState({
|
|
19
|
+
mode: Mode.DEFAULT,
|
|
20
|
+
}),
|
|
21
|
+
},
|
|
22
|
+
// {
|
|
23
|
+
// intent: KeyIntent.ToggleHelp,
|
|
24
|
+
// mode: Mode.DEFAULT,
|
|
25
|
+
// description: '[F1] Toggle HELP menu',
|
|
26
|
+
// action: () =>
|
|
27
|
+
// setState(state => ({
|
|
28
|
+
// ...state,
|
|
29
|
+
// mode: Mode.HELP,
|
|
30
|
+
// })),
|
|
31
|
+
// },
|
|
32
|
+
// {
|
|
33
|
+
// intent: KeyIntent.ToggleHelp,
|
|
34
|
+
// mode: Mode.HELP,
|
|
35
|
+
// description: '[F1] Close HELP menu',
|
|
36
|
+
// action: () =>
|
|
37
|
+
// setState(state => ({
|
|
38
|
+
// ...state,
|
|
39
|
+
// mode: Mode.DEFAULT,
|
|
40
|
+
// })),
|
|
41
|
+
// },
|
|
42
|
+
{
|
|
43
|
+
intent: KeyIntent.Confirm,
|
|
44
|
+
mode: Mode.DEFAULT,
|
|
45
|
+
description: '[ENTER/E] Confirm/Enter context',
|
|
46
|
+
action: enterChildNode,
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
intent: KeyIntent.Exit,
|
|
50
|
+
mode: Mode.DEFAULT,
|
|
51
|
+
description: '[ESC/Q] Exit application',
|
|
52
|
+
action: exitToParentNode,
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
mode: Mode.DEFAULT,
|
|
56
|
+
description: '[ARROWS/HJKL] Navigate',
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
intent: KeyIntent.NavPreviousItem,
|
|
60
|
+
mode: Mode.DEFAULT,
|
|
61
|
+
action: navigateToPreviousItem,
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
intent: KeyIntent.NavNextItem,
|
|
65
|
+
mode: Mode.DEFAULT,
|
|
66
|
+
action: navigateToNextItem,
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
intent: KeyIntent.NavToPreviousContainer,
|
|
70
|
+
mode: Mode.DEFAULT,
|
|
71
|
+
action: navigateToPreviousContainer,
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
intent: KeyIntent.NavToNextContainer,
|
|
75
|
+
mode: Mode.DEFAULT,
|
|
76
|
+
action: navigateToNextContainer,
|
|
77
|
+
},
|
|
78
|
+
];
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { addSwimlaneAction, addTicketAction, } from '../actions/add-item/add-item-actions.js';
|
|
2
|
+
import { Mode } from '../model/action-map.model.js';
|
|
3
|
+
import { patchState } from '../state/state.js';
|
|
4
|
+
import { CommandLineIntent } from './command-line-sequence-intent.js';
|
|
5
|
+
export const commandLineActions = [
|
|
6
|
+
{
|
|
7
|
+
intent: CommandLineIntent.ViewHelp,
|
|
8
|
+
mode: Mode.COMMAND_LINE,
|
|
9
|
+
action: () => {
|
|
10
|
+
patchState({
|
|
11
|
+
mode: Mode.HELP,
|
|
12
|
+
commandLineInput: '',
|
|
13
|
+
});
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
intent: CommandLineIntent.AddSwimlane,
|
|
18
|
+
mode: Mode.COMMAND_LINE,
|
|
19
|
+
action: (...args) => {
|
|
20
|
+
addSwimlaneAction(...args);
|
|
21
|
+
patchState({ commandLineInput: '', mode: Mode.DEFAULT });
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
intent: CommandLineIntent.AddTicket,
|
|
26
|
+
mode: Mode.COMMAND_LINE,
|
|
27
|
+
action: (...args) => {
|
|
28
|
+
addTicketAction(...args);
|
|
29
|
+
patchState({ commandLineInput: '', mode: Mode.DEFAULT });
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
];
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const CommandLineIntent: {
|
|
2
|
+
readonly None: "none";
|
|
3
|
+
readonly AddSwimlane: "add-swimlane";
|
|
4
|
+
readonly AddTicket: "add-ticket";
|
|
5
|
+
readonly ViewHelp: "view-help";
|
|
6
|
+
};
|
|
7
|
+
export declare const getCommandLineIntent: (input: string) => (typeof CommandLineIntent)[keyof typeof CommandLineIntent];
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { BoardItemTypes } from '../../board/model/board.model.js';
|
|
2
|
+
import { navigationState } from '../state/state.js';
|
|
3
|
+
export const CommandLineIntent = {
|
|
4
|
+
None: 'none',
|
|
5
|
+
AddSwimlane: 'add-swimlane',
|
|
6
|
+
AddTicket: 'add-ticket',
|
|
7
|
+
ViewHelp: 'view-help',
|
|
8
|
+
};
|
|
9
|
+
export const getCommandLineIntent = (input) => {
|
|
10
|
+
const actionContext = navigationState?.currentNode?.actionContext;
|
|
11
|
+
if (!actionContext)
|
|
12
|
+
return CommandLineIntent.None;
|
|
13
|
+
switch (input) {
|
|
14
|
+
case 'help':
|
|
15
|
+
case 'he':
|
|
16
|
+
return CommandLineIntent.ViewHelp;
|
|
17
|
+
case 'add':
|
|
18
|
+
switch (actionContext) {
|
|
19
|
+
case BoardItemTypes.SWIMLANE:
|
|
20
|
+
return CommandLineIntent.AddSwimlane;
|
|
21
|
+
case BoardItemTypes.TICKET:
|
|
22
|
+
return CommandLineIntent.AddTicket;
|
|
23
|
+
default:
|
|
24
|
+
return CommandLineIntent.None;
|
|
25
|
+
}
|
|
26
|
+
default:
|
|
27
|
+
return CommandLineIntent.None;
|
|
28
|
+
}
|
|
29
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { addSwimlaneAction, addTicketAction, } from '../actions/add-item/add-item-actions.js';
|
|
2
|
+
import { Mode } from '../model/action-map.model.js';
|
|
3
|
+
import { patchState } from '../state/state.js';
|
|
4
|
+
import { CommandLineSequenceIntent } from './command-line-sequence-intent.js';
|
|
5
|
+
export const commandLineSequenceActions = [
|
|
6
|
+
{
|
|
7
|
+
intent: CommandLineSequenceIntent.ViewHelp,
|
|
8
|
+
mode: Mode.COMMAND_LINE,
|
|
9
|
+
action: () => {
|
|
10
|
+
patchState({
|
|
11
|
+
mode: Mode.HELP,
|
|
12
|
+
});
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
intent: CommandLineSequenceIntent.AddSwimlane,
|
|
17
|
+
mode: Mode.COMMAND_LINE,
|
|
18
|
+
action: (...args) => {
|
|
19
|
+
addSwimlaneAction(...args);
|
|
20
|
+
patchState({ mode: Mode.DEFAULT });
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
intent: CommandLineSequenceIntent.AddTicket,
|
|
25
|
+
mode: Mode.COMMAND_LINE,
|
|
26
|
+
action: (...args) => {
|
|
27
|
+
addTicketAction(...args);
|
|
28
|
+
patchState({ mode: Mode.DEFAULT });
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
];
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const CommandLineSequenceIntent: {
|
|
2
|
+
readonly None: "none";
|
|
3
|
+
readonly AddSwimlane: "add-swimlane";
|
|
4
|
+
readonly AddTicket: "add-ticket";
|
|
5
|
+
readonly ViewHelp: "view-help";
|
|
6
|
+
};
|
|
7
|
+
export declare const getCommandLineIntent: (command: string) => (typeof CommandLineSequenceIntent)[keyof typeof CommandLineSequenceIntent];
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { BoardItemTypes } from '../../board/model/board.model.js';
|
|
2
|
+
import { navigationState } from '../state/state.js';
|
|
3
|
+
export const CommandLineSequenceIntent = {
|
|
4
|
+
None: 'none',
|
|
5
|
+
AddSwimlane: 'add-swimlane',
|
|
6
|
+
AddTicket: 'add-ticket',
|
|
7
|
+
ViewHelp: 'view-help',
|
|
8
|
+
};
|
|
9
|
+
export const getCommandLineIntent = (command) => {
|
|
10
|
+
const actionContext = navigationState?.currentNode?.actionContext;
|
|
11
|
+
if (!actionContext)
|
|
12
|
+
return CommandLineSequenceIntent.None;
|
|
13
|
+
switch (command) {
|
|
14
|
+
case 'help':
|
|
15
|
+
case 'he':
|
|
16
|
+
return CommandLineSequenceIntent.ViewHelp;
|
|
17
|
+
case 'add':
|
|
18
|
+
switch (actionContext) {
|
|
19
|
+
case BoardItemTypes.SWIMLANE:
|
|
20
|
+
return CommandLineSequenceIntent.AddSwimlane;
|
|
21
|
+
case BoardItemTypes.TICKET:
|
|
22
|
+
return CommandLineSequenceIntent.AddTicket;
|
|
23
|
+
default:
|
|
24
|
+
return CommandLineSequenceIntent.None;
|
|
25
|
+
}
|
|
26
|
+
default:
|
|
27
|
+
return CommandLineSequenceIntent.None;
|
|
28
|
+
}
|
|
29
|
+
};
|
|
@@ -1,14 +1,26 @@
|
|
|
1
|
+
import { NavigateCtx } from './navigation-ctx.model.js';
|
|
2
|
+
import readline from 'readline';
|
|
1
3
|
export declare const Mode: {
|
|
2
4
|
readonly DEFAULT: "default";
|
|
3
5
|
readonly MOVE: "move";
|
|
6
|
+
readonly HELP: "help";
|
|
7
|
+
readonly COMMAND_LINE: "command-line";
|
|
4
8
|
};
|
|
5
|
-
export type
|
|
6
|
-
export type ActionEntry
|
|
9
|
+
export type ModeUnion = (typeof Mode)[keyof typeof Mode];
|
|
10
|
+
export type ActionEntry = {
|
|
7
11
|
intent?: string;
|
|
8
|
-
mode:
|
|
12
|
+
mode: ModeUnion | ModeUnion[];
|
|
9
13
|
description?: `[${string}] ${string}`;
|
|
10
|
-
action?: (...args:
|
|
14
|
+
action?: (...args: [NavigateCtx, ActionEntry, readline.Key]) => void | Promise<void>;
|
|
11
15
|
};
|
|
12
16
|
export type ActionMap<T extends Record<string, any[]>> = {
|
|
13
|
-
[K in keyof T]: ActionEntry
|
|
17
|
+
[K in keyof T]: ActionEntry[];
|
|
14
18
|
};
|
|
19
|
+
type CommandLineInput = {
|
|
20
|
+
value: string;
|
|
21
|
+
command: string;
|
|
22
|
+
};
|
|
23
|
+
export type CommandLineActionEntry = Omit<ActionEntry, 'action'> & {
|
|
24
|
+
action?: (...args: [NavigateCtx, CommandLineActionEntry, CommandLineInput]) => void | Promise<void>;
|
|
25
|
+
};
|
|
26
|
+
export {};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { NavigationTree } from './navigation-tree.model.js';
|
|
2
2
|
export interface NavigateCtx {
|
|
3
|
-
|
|
3
|
+
_selectionIndex: number;
|
|
4
4
|
breadCrumb: Array<NavigationTree<NavigationTree>>;
|
|
5
5
|
navigationNode: NavigationTree<NavigationTree>;
|
|
6
6
|
children: NavigationTree[];
|
|
7
7
|
getSelectedIndex(): number;
|
|
8
|
-
|
|
8
|
+
updateSelection(index: number): void;
|
|
9
9
|
selectNone(): void;
|
|
10
10
|
reInvokeNavigate(index: number, breadCrumb: NavigationTree<NavigationTree>[]): void;
|
|
11
11
|
render(): void;
|
|
@@ -3,6 +3,7 @@ export type NavigationTree<TMeta = Record<string, unknown>> = {
|
|
|
3
3
|
isSelected: boolean;
|
|
4
4
|
childrenRenderAxis: 'vertical' | 'horizontal';
|
|
5
5
|
name: string;
|
|
6
|
+
description?: string;
|
|
6
7
|
children: NavigationTree<unknown>[];
|
|
7
8
|
actionContext: string;
|
|
8
9
|
enableChildNavigationAcrossContainers?: boolean;
|
|
@@ -4,7 +4,7 @@ export declare function navigate<T extends NavigationTree>({ index, breadCrumb,
|
|
|
4
4
|
breadCrumb: Array<NavigationTree<NavigationTree>>;
|
|
5
5
|
callbacks: Partial<{
|
|
6
6
|
render: () => void;
|
|
7
|
-
onSelectChange: (s: T['children'][number], breadCrumb: T['children']) => void;
|
|
7
|
+
onSelectChange: (s: T['children'][number] | undefined, breadCrumb: T['children']) => void;
|
|
8
8
|
onConfirm: (s: T['children'][number]) => void;
|
|
9
9
|
}>;
|
|
10
10
|
}): void;
|
|
@@ -2,38 +2,51 @@ import readline from 'readline';
|
|
|
2
2
|
import { navigationState } from './state/state.js';
|
|
3
3
|
import { getKeyIntent } from './utils/key-intent.js';
|
|
4
4
|
export function navigate({ index = 0, breadCrumb, callbacks, }) {
|
|
5
|
-
const { render = () => { }, onSelectChange = () => { }, onConfirm = () => { }, } = callbacks;
|
|
6
5
|
const ctx = {
|
|
7
|
-
|
|
6
|
+
_selectionIndex: 0,
|
|
7
|
+
breadCrumb: breadCrumb,
|
|
8
|
+
render() {
|
|
9
|
+
callbacks.render?.();
|
|
10
|
+
},
|
|
8
11
|
get navigationNode() {
|
|
9
|
-
return this.breadCrumb
|
|
12
|
+
return this.breadCrumb?.at(-1) ?? breadCrumb[0];
|
|
10
13
|
},
|
|
11
14
|
get children() {
|
|
12
15
|
return this.navigationNode.children ?? [];
|
|
13
16
|
},
|
|
14
|
-
selectNone
|
|
15
|
-
ctx.
|
|
17
|
+
selectNone() {
|
|
18
|
+
ctx.updateSelection(-1);
|
|
16
19
|
},
|
|
17
|
-
_selectedIndex: 0,
|
|
18
20
|
getSelectedIndex() {
|
|
19
|
-
return this.
|
|
21
|
+
return this._selectionIndex;
|
|
22
|
+
},
|
|
23
|
+
updateSelection(idx) {
|
|
24
|
+
this._selectionIndex = idx;
|
|
25
|
+
const children = this.navigationNode.children ?? [];
|
|
26
|
+
children.forEach((c, i) => (c.isSelected = i === idx));
|
|
27
|
+
if (idx < 0 || idx >= children.length) {
|
|
28
|
+
callbacks.onSelectChange?.(undefined, breadCrumb);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
callbacks.onSelectChange?.(children[idx], breadCrumb);
|
|
20
32
|
},
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
33
|
+
reInvokeNavigate(idx, crumb) {
|
|
34
|
+
cleanup();
|
|
35
|
+
navigate({ index: idx, breadCrumb: [...crumb], callbacks });
|
|
24
36
|
},
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
return reInvokeNavigate(index, breadCrumb);
|
|
37
|
+
confirm(sel) {
|
|
38
|
+
return callbacks.onConfirm?.(sel);
|
|
28
39
|
},
|
|
29
|
-
|
|
30
|
-
exit: () => {
|
|
40
|
+
exit() {
|
|
31
41
|
cleanup();
|
|
32
42
|
process.exit(0);
|
|
33
43
|
},
|
|
34
|
-
enterChildNode
|
|
35
|
-
|
|
36
|
-
|
|
44
|
+
enterChildNode(childNode) {
|
|
45
|
+
this.updateSelection(-1); // Clear all on this level
|
|
46
|
+
this.reInvokeNavigate(0, [...breadCrumb, childNode]);
|
|
47
|
+
},
|
|
48
|
+
enterParentNode() {
|
|
49
|
+
ctx.updateSelection(-1); // Clear all on this level
|
|
37
50
|
if (breadCrumb.length < 2)
|
|
38
51
|
return; // Need at least grandparent + parent
|
|
39
52
|
const ancestors = breadCrumb;
|
|
@@ -42,33 +55,34 @@ export function navigate({ index = 0, breadCrumb, callbacks, }) {
|
|
|
42
55
|
if (!parent || !grandParent)
|
|
43
56
|
return;
|
|
44
57
|
const parentIndex = grandParent?.children.findIndex(x => parent.id === x.id);
|
|
45
|
-
reInvokeNavigate(parentIndex, breadCrumb.slice(0, -1)); // Go to parent level
|
|
58
|
+
this.reInvokeNavigate(parentIndex, breadCrumb.slice(0, -1)); // Go to parent level
|
|
46
59
|
},
|
|
47
60
|
};
|
|
48
|
-
ctx.
|
|
49
|
-
function onKeyPress(_, key) {
|
|
61
|
+
ctx.updateSelection(index);
|
|
62
|
+
async function onKeyPress(_, key) {
|
|
50
63
|
if (key.ctrl && key.name === 'c')
|
|
51
64
|
return ctx.exit();
|
|
52
65
|
const filteredActions = navigationState.availableActions.filter(x => x.mode === navigationState.mode);
|
|
53
|
-
const
|
|
54
|
-
const intent = getKeyIntent(key, ctx);
|
|
55
|
-
return intent ===
|
|
66
|
+
const actionMeta = filteredActions.find(actionMetaItem => {
|
|
67
|
+
const intent = getKeyIntent(key, ctx, navigationState.mode);
|
|
68
|
+
return intent === actionMetaItem.intent;
|
|
56
69
|
});
|
|
57
|
-
|
|
70
|
+
if (actionMeta?.action) {
|
|
71
|
+
try {
|
|
72
|
+
const res = actionMeta.action(ctx, actionMeta, key);
|
|
73
|
+
if (res instanceof Promise)
|
|
74
|
+
await res;
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
console.error(err);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
58
80
|
ctx.render();
|
|
59
81
|
}
|
|
60
82
|
const cleanup = () => process.stdin.removeListener('keypress', onKeyPress);
|
|
61
|
-
|
|
62
|
-
cleanup();
|
|
63
|
-
navigate({ index: idx, breadCrumb: [...crumb], callbacks });
|
|
64
|
-
};
|
|
65
|
-
render();
|
|
83
|
+
callbacks.render?.();
|
|
66
84
|
readline.emitKeypressEvents(process.stdin);
|
|
67
85
|
if (process.stdin.isTTY)
|
|
68
86
|
process.stdin.setRawMode(true);
|
|
69
87
|
process.stdin.on('keypress', onKeyPress);
|
|
70
88
|
}
|
|
71
|
-
function updateSelection({ children }, breadCrumb, idx, onSelectChange) {
|
|
72
|
-
children.forEach((c, i) => (c.isSelected = i === idx));
|
|
73
|
-
onSelectChange(children[idx], breadCrumb);
|
|
74
|
-
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type CommandLineState = {
|
|
2
|
+
value: string;
|
|
3
|
+
commandHistory: string[];
|
|
4
|
+
commandHistoryIndex: number;
|
|
5
|
+
};
|
|
6
|
+
export declare let commandLineState: CommandLineState;
|
|
7
|
+
export declare const updateCommandLineState: (cb: (old: CommandLineState) => CommandLineState) => void;
|
|
8
|
+
export declare const updateCommandLineInput: (cb: (previous: string) => string) => void;
|
|
9
|
+
export declare const updateCommandHistory: () => void;
|
|
10
|
+
export declare const getPrevCommand: () => void;
|
|
11
|
+
export declare const getNextCommand: () => void;
|
|
12
|
+
export declare const clearCommandLine: () => void;
|
|
13
|
+
export declare const getCommandLineInput: () => string;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export let commandLineState = {
|
|
2
|
+
commandHistory: [],
|
|
3
|
+
value: '',
|
|
4
|
+
commandHistoryIndex: -1,
|
|
5
|
+
};
|
|
6
|
+
export const updateCommandLineState = (cb) => {
|
|
7
|
+
bug(commandLineState);
|
|
8
|
+
commandLineState = cb(structuredClone(commandLineState));
|
|
9
|
+
};
|
|
10
|
+
export const updateCommandLineInput = (cb) => {
|
|
11
|
+
updateCommandLineState(state => ({
|
|
12
|
+
...state,
|
|
13
|
+
value: cb(state.value),
|
|
14
|
+
}));
|
|
15
|
+
};
|
|
16
|
+
export const updateCommandHistory = () => {
|
|
17
|
+
updateCommandLineState(state => ({
|
|
18
|
+
...state,
|
|
19
|
+
commandHistory: [state.value, ...state.commandHistory].slice(0, 20),
|
|
20
|
+
}));
|
|
21
|
+
};
|
|
22
|
+
export const getPrevCommand = () => {
|
|
23
|
+
updateCommandLineState(s => {
|
|
24
|
+
const nextIndex = Math.min(s.commandHistoryIndex + 1, s.commandHistory.length - 1);
|
|
25
|
+
return {
|
|
26
|
+
...s,
|
|
27
|
+
commandHistoryIndex: nextIndex,
|
|
28
|
+
value: s.commandHistory[nextIndex] ?? '',
|
|
29
|
+
};
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
export const getNextCommand = () => {
|
|
33
|
+
updateCommandLineState(s => {
|
|
34
|
+
const nextIndex = Math.min(s.commandHistoryIndex - 1, s.commandHistory.length - 1);
|
|
35
|
+
return {
|
|
36
|
+
...s,
|
|
37
|
+
commandHistoryIndex: nextIndex,
|
|
38
|
+
value: s.commandHistory[nextIndex] ?? '',
|
|
39
|
+
};
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
export const clearCommandLine = () => updateCommandLineInput(() => '');
|
|
43
|
+
export const getCommandLineInput = () => commandLineState.value;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { ActionEntry,
|
|
2
|
-
import { NavigateCtx } from '../model/navigation-ctx.model.js';
|
|
1
|
+
import { ActionEntry, ModeUnion } from '../model/action-map.model.js';
|
|
3
2
|
import { NavigationTree } from '../model/navigation-tree.model.js';
|
|
4
3
|
export declare let navigationState: {
|
|
5
|
-
mode:
|
|
6
|
-
availableActions: ActionEntry
|
|
7
|
-
|
|
4
|
+
mode: ModeUnion;
|
|
5
|
+
availableActions: ActionEntry[];
|
|
6
|
+
availableHints: readonly string[];
|
|
8
7
|
currentNode: NavigationTree<NavigationTree> | null;
|
|
9
8
|
breadCrumb: NavigationTree<NavigationTree>[];
|
|
10
9
|
};
|
|
11
|
-
export declare const
|
|
10
|
+
export declare const updateState: (cb: (oldState: typeof navigationState) => typeof navigationState) => void;
|
|
11
|
+
export declare const patchState: (patch: Partial<typeof navigationState>) => void;
|
|
12
|
+
export declare const flashHint: (hints: string[]) => Promise<void>;
|
|
@@ -1,10 +1,39 @@
|
|
|
1
|
+
import { Hints } from '../../board/hints/hints.js';
|
|
2
|
+
import { triggerRender } from '../../cli.js';
|
|
1
3
|
export let navigationState = {
|
|
2
4
|
mode: 'default',
|
|
3
5
|
availableActions: [],
|
|
4
|
-
|
|
6
|
+
availableHints: [],
|
|
5
7
|
currentNode: null,
|
|
6
8
|
breadCrumb: [],
|
|
7
9
|
};
|
|
8
|
-
export const
|
|
10
|
+
export const updateState = (cb) => {
|
|
9
11
|
navigationState = cb(navigationState);
|
|
10
12
|
};
|
|
13
|
+
export const patchState = (patch) => updateState(oldState => ({
|
|
14
|
+
...oldState,
|
|
15
|
+
...patch,
|
|
16
|
+
}));
|
|
17
|
+
// Utilities for updating specific parts of the state
|
|
18
|
+
export const flashHint = async (hints) => {
|
|
19
|
+
await new Promise(resolve => {
|
|
20
|
+
setTimeout(() => {
|
|
21
|
+
updateState(state => {
|
|
22
|
+
const { currentNode, mode } = state;
|
|
23
|
+
const contextualHints = (currentNode &&
|
|
24
|
+
Hints[currentNode.actionContext + mode]) ??
|
|
25
|
+
(currentNode && Hints[currentNode.actionContext]) ?? [''];
|
|
26
|
+
return {
|
|
27
|
+
...state,
|
|
28
|
+
availableHints: contextualHints,
|
|
29
|
+
};
|
|
30
|
+
});
|
|
31
|
+
triggerRender();
|
|
32
|
+
resolve();
|
|
33
|
+
}, 3000);
|
|
34
|
+
patchState({
|
|
35
|
+
availableHints: hints,
|
|
36
|
+
});
|
|
37
|
+
triggerRender();
|
|
38
|
+
});
|
|
39
|
+
};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { KeyIntent } from './key-intent.js';
|
|
2
|
+
import readline from 'readline';
|
|
3
|
+
export declare const getCommandLineIntent: (key: readline.Key) => KeyIntent.Confirm | KeyIntent.ToggleCommandLine | KeyIntent.CaptureInput | KeyIntent.EraseInput | KeyIntent.GetLastCommandFromHistory | KeyIntent.GetNextCommandFromHistory;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { KeyIntent } from './key-intent.js';
|
|
2
|
+
export const getCommandLineIntent = (key) => {
|
|
3
|
+
switch (key.name) {
|
|
4
|
+
case 'up':
|
|
5
|
+
return KeyIntent.GetLastCommandFromHistory;
|
|
6
|
+
case 'down':
|
|
7
|
+
return KeyIntent.GetNextCommandFromHistory;
|
|
8
|
+
case 'return':
|
|
9
|
+
return KeyIntent.Confirm;
|
|
10
|
+
case 'backspace':
|
|
11
|
+
return KeyIntent.EraseInput;
|
|
12
|
+
case 'escape':
|
|
13
|
+
return KeyIntent.ToggleCommandLine;
|
|
14
|
+
default:
|
|
15
|
+
return KeyIntent.CaptureInput;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import readline from 'readline';
|
|
2
|
+
import { ModeUnion } from '../model/action-map.model.js';
|
|
3
|
+
import { NavigateCtx } from '../model/navigation-ctx.model.js';
|
|
4
|
+
import { KeyIntent } from './key-intent.js';
|
|
5
|
+
export declare function getKeyIntent(key: readline.Key, ctx: NavigateCtx, mode: ModeUnion): KeyIntent | null;
|