@compilr-dev/cli 0.4.0 → 0.5.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.
- package/README.md +30 -12
- package/dist/agent.d.ts +74 -1
- package/dist/agent.js +259 -76
- package/dist/anchors/index.d.ts +9 -0
- package/dist/anchors/index.js +9 -0
- package/dist/anchors/project-anchors.d.ts +79 -0
- package/dist/anchors/project-anchors.js +202 -0
- package/dist/commands/handler-types.d.ts +68 -0
- package/dist/commands/handler-types.js +8 -0
- package/dist/commands/handlers/agent-commands.d.ts +13 -0
- package/dist/commands/handlers/agent-commands.js +305 -0
- package/dist/commands/handlers/design-commands.d.ts +15 -0
- package/dist/commands/handlers/design-commands.js +334 -0
- package/dist/commands/handlers/index.d.ts +20 -0
- package/dist/commands/handlers/index.js +43 -0
- package/dist/commands/handlers/overlay-commands.d.ts +21 -0
- package/dist/commands/handlers/overlay-commands.js +287 -0
- package/dist/commands/handlers/project-commands.d.ts +11 -0
- package/dist/commands/handlers/project-commands.js +167 -0
- package/dist/commands/handlers/simple-commands.d.ts +19 -0
- package/dist/commands/handlers/simple-commands.js +144 -0
- package/dist/commands/index.d.ts +2 -1
- package/dist/commands/registry.d.ts +50 -0
- package/dist/commands/registry.js +75 -0
- package/dist/commands-v2/handlers/context.d.ts +13 -0
- package/dist/commands-v2/handlers/context.js +348 -0
- package/dist/commands-v2/handlers/core.d.ts +13 -0
- package/dist/commands-v2/handlers/core.js +165 -0
- package/dist/commands-v2/handlers/debug.d.ts +11 -0
- package/dist/commands-v2/handlers/debug.js +159 -0
- package/dist/commands-v2/handlers/index.d.ts +12 -0
- package/dist/commands-v2/handlers/index.js +24 -0
- package/dist/commands-v2/handlers/project.d.ts +22 -0
- package/dist/commands-v2/handlers/project.js +814 -0
- package/dist/commands-v2/handlers/settings.d.ts +15 -0
- package/dist/commands-v2/handlers/settings.js +235 -0
- package/dist/commands-v2/index.d.ts +13 -0
- package/dist/commands-v2/index.js +15 -0
- package/dist/commands-v2/registry.d.ts +37 -0
- package/dist/commands-v2/registry.js +80 -0
- package/dist/commands-v2/types.d.ts +75 -0
- package/dist/commands-v2/types.js +7 -0
- package/dist/commands.js +110 -7
- package/dist/index.js +288 -29
- package/dist/input-handlers/index.d.ts +7 -0
- package/dist/input-handlers/index.js +7 -0
- package/dist/input-handlers/memory-handler.d.ts +26 -0
- package/dist/input-handlers/memory-handler.js +68 -0
- package/dist/repl-helpers.d.ts +63 -0
- package/dist/repl-helpers.js +318 -0
- package/dist/repl-v2.d.ts +155 -0
- package/dist/repl-v2.js +774 -0
- package/dist/repl.d.ts +32 -4
- package/dist/repl.js +250 -977
- package/dist/settings/index.d.ts +23 -0
- package/dist/settings/index.js +48 -0
- package/dist/settings/paths.d.ts +110 -0
- package/dist/settings/paths.js +264 -0
- package/dist/templates/compilr-md.js +7 -4
- package/dist/templates/index.js +3 -4
- package/dist/themes/colors.js +3 -1
- package/dist/themes/registry.d.ts +5 -36
- package/dist/themes/registry.js +11 -95
- package/dist/themes/types.d.ts +3 -38
- package/dist/themes/types.js +2 -2
- package/dist/tools/anchor-tools.d.ts +31 -0
- package/dist/tools/anchor-tools.js +255 -0
- package/dist/tools/backlog-wrappers.d.ts +54 -0
- package/dist/tools/backlog-wrappers.js +338 -0
- package/dist/tools/backlog.js +1 -1
- package/dist/tools/db-tools.d.ts +65 -0
- package/dist/tools/db-tools.js +19 -0
- package/dist/tools/document-db.d.ts +43 -0
- package/dist/tools/document-db.js +220 -0
- package/dist/tools/project-db.d.ts +102 -0
- package/dist/tools/project-db.js +370 -0
- package/dist/tools/workitem-db.d.ts +103 -0
- package/dist/tools/workitem-db.js +549 -0
- package/dist/tools.js +13 -3
- package/dist/ui/agents-overlay-v2.d.ts +43 -0
- package/dist/ui/agents-overlay-v2.js +809 -0
- package/dist/ui/agents-overlay.d.ts +5 -5
- package/dist/ui/agents-overlay.js +782 -420
- package/dist/ui/anchors-overlay.d.ts +12 -0
- package/dist/ui/anchors-overlay.js +775 -0
- package/dist/ui/arch-type-overlay.d.ts +1 -6
- package/dist/ui/arch-type-overlay.js +175 -203
- package/dist/ui/ask-user-overlay-v2.d.ts +26 -0
- package/dist/ui/ask-user-overlay-v2.js +555 -0
- package/dist/ui/ask-user-overlay.d.ts +2 -2
- package/dist/ui/ask-user-overlay.js +443 -535
- package/dist/ui/ask-user-simple-overlay-v2.d.ts +25 -0
- package/dist/ui/ask-user-simple-overlay-v2.js +215 -0
- package/dist/ui/ask-user-simple-overlay.d.ts +2 -2
- package/dist/ui/ask-user-simple-overlay.js +182 -209
- package/dist/ui/backlog-overlay.d.ts +16 -1
- package/dist/ui/backlog-overlay.js +525 -659
- package/dist/ui/base/index.d.ts +26 -0
- package/dist/ui/base/index.js +33 -0
- package/dist/ui/base/inline-overlay-utils.d.ts +217 -0
- package/dist/ui/base/inline-overlay-utils.js +320 -0
- package/dist/ui/base/inline-overlay.d.ts +159 -0
- package/dist/ui/base/inline-overlay.js +257 -0
- package/dist/ui/base/key-utils.d.ts +15 -0
- package/dist/ui/base/key-utils.js +30 -0
- package/dist/ui/base/overlay-base-v2.d.ts +193 -0
- package/dist/ui/base/overlay-base-v2.js +246 -0
- package/dist/ui/base/overlay-base.d.ts +156 -0
- package/dist/ui/base/overlay-base.js +238 -0
- package/dist/ui/base/overlay-lifecycle.d.ts +65 -0
- package/dist/ui/base/overlay-lifecycle.js +159 -0
- package/dist/ui/base/overlay-types.d.ts +185 -0
- package/dist/ui/base/overlay-types.js +7 -0
- package/dist/ui/base/render-utils.d.ts +8 -0
- package/dist/ui/base/render-utils.js +11 -0
- package/dist/ui/base/screen-stack.d.ts +148 -0
- package/dist/ui/base/screen-stack.js +184 -0
- package/dist/ui/base/tabbed-list-overlay-v2.d.ts +103 -0
- package/dist/ui/base/tabbed-list-overlay-v2.js +317 -0
- package/dist/ui/base/tabbed-list-overlay.d.ts +153 -0
- package/dist/ui/base/tabbed-list-overlay.js +369 -0
- package/dist/ui/commands-overlay-v2.d.ts +33 -0
- package/dist/ui/commands-overlay-v2.js +441 -0
- package/dist/ui/commands-overlay.d.ts +7 -2
- package/dist/ui/commands-overlay.js +384 -355
- package/dist/ui/config-overlay.d.ts +5 -4
- package/dist/ui/config-overlay.js +243 -513
- package/dist/ui/conversation.d.ts +75 -4
- package/dist/ui/conversation.js +374 -161
- package/dist/ui/docs-overlay.d.ts +17 -0
- package/dist/ui/docs-overlay.js +303 -0
- package/dist/ui/ephemeral.d.ts +1 -1
- package/dist/ui/ephemeral.js +1 -1
- package/dist/ui/features/index.d.ts +34 -0
- package/dist/ui/features/index.js +34 -0
- package/dist/ui/features/input-feature.d.ts +85 -0
- package/dist/ui/features/input-feature.js +238 -0
- package/dist/ui/features/list-feature.d.ts +155 -0
- package/dist/ui/features/list-feature.js +244 -0
- package/dist/ui/features/pagination-feature.d.ts +154 -0
- package/dist/ui/features/pagination-feature.js +238 -0
- package/dist/ui/features/search-feature.d.ts +148 -0
- package/dist/ui/features/search-feature.js +185 -0
- package/dist/ui/features/tab-feature.d.ts +194 -0
- package/dist/ui/features/tab-feature.js +307 -0
- package/dist/ui/footer-v2.d.ts +222 -0
- package/dist/ui/footer-v2.js +1349 -0
- package/dist/ui/footer.d.ts +107 -0
- package/dist/ui/footer.js +359 -67
- package/dist/ui/guardrail-overlay.d.ts +29 -0
- package/dist/ui/guardrail-overlay.js +145 -0
- package/dist/ui/help-overlay-v2.d.ts +34 -0
- package/dist/ui/help-overlay-v2.js +309 -0
- package/dist/ui/help-overlay.d.ts +16 -0
- package/dist/ui/help-overlay.js +316 -0
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/index.js +1 -3
- package/dist/ui/init-overlay-v2.d.ts +34 -0
- package/dist/ui/init-overlay-v2.js +600 -0
- package/dist/ui/init-overlay.d.ts +12 -2
- package/dist/ui/init-overlay.js +349 -270
- package/dist/ui/input-prompt-v2.d.ts +1 -0
- package/dist/ui/input-prompt-v2.js +14 -6
- package/dist/ui/input-prompt.d.ts +116 -33
- package/dist/ui/input-prompt.js +536 -337
- package/dist/ui/iteration-limit-overlay-v2.d.ts +21 -0
- package/dist/ui/iteration-limit-overlay-v2.js +114 -0
- package/dist/ui/iteration-limit-overlay.d.ts +2 -2
- package/dist/ui/iteration-limit-overlay.js +92 -128
- package/dist/ui/keys-overlay-v2.d.ts +41 -0
- package/dist/ui/keys-overlay-v2.js +248 -0
- package/dist/ui/keys-overlay.d.ts +1 -0
- package/dist/ui/keys-overlay.js +203 -141
- package/dist/ui/line-utils.d.ts +88 -0
- package/dist/ui/line-utils.js +150 -0
- package/dist/ui/live-region.d.ts +161 -0
- package/dist/ui/live-region.js +387 -0
- package/dist/ui/mascot/expressions.d.ts +32 -0
- package/dist/ui/mascot/expressions.js +213 -0
- package/dist/ui/mascot/index.d.ts +8 -0
- package/dist/ui/mascot/index.js +8 -0
- package/dist/ui/mascot/renderer.d.ts +19 -0
- package/dist/ui/mascot/renderer.js +97 -0
- package/dist/ui/mascot-overlay-v2.d.ts +41 -0
- package/dist/ui/mascot-overlay-v2.js +138 -0
- package/dist/ui/mascot-overlay.d.ts +21 -0
- package/dist/ui/mascot-overlay.js +146 -0
- package/dist/ui/model-overlay-v2.d.ts +49 -0
- package/dist/ui/model-overlay-v2.js +118 -0
- package/dist/ui/model-overlay.d.ts +27 -0
- package/dist/ui/model-overlay.js +221 -0
- package/dist/ui/model-warning-overlay.js +3 -5
- package/dist/ui/new-overlay.d.ts +34 -0
- package/dist/ui/new-overlay.js +604 -0
- package/dist/ui/overlay/impl/agents-overlay-v2.d.ts +45 -0
- package/dist/ui/overlay/impl/agents-overlay-v2.js +825 -0
- package/dist/ui/overlay/impl/anchors-overlay-v2.d.ts +47 -0
- package/dist/ui/overlay/impl/anchors-overlay-v2.js +783 -0
- package/dist/ui/overlay/impl/arch-type-overlay-v2.d.ts +37 -0
- package/dist/ui/overlay/impl/arch-type-overlay-v2.js +240 -0
- package/dist/ui/overlay/impl/ask-user-overlay-v2.d.ts +72 -0
- package/dist/ui/overlay/impl/ask-user-overlay-v2.js +584 -0
- package/dist/ui/overlay/impl/ask-user-simple-overlay-v2.d.ts +46 -0
- package/dist/ui/overlay/impl/ask-user-simple-overlay-v2.js +204 -0
- package/dist/ui/overlay/impl/backlog-overlay-v2.d.ts +49 -0
- package/dist/ui/overlay/impl/backlog-overlay-v2.js +642 -0
- package/dist/ui/overlay/impl/commands-overlay-v2.d.ts +33 -0
- package/dist/ui/overlay/impl/commands-overlay-v2.js +441 -0
- package/dist/ui/overlay/impl/config-overlay-v2.d.ts +100 -0
- package/dist/ui/overlay/impl/config-overlay-v2.js +654 -0
- package/dist/ui/overlay/impl/dashboard-overlay-v2.d.ts +55 -0
- package/dist/ui/overlay/impl/dashboard-overlay-v2.js +359 -0
- package/dist/ui/overlay/impl/docs-overlay-v2.d.ts +45 -0
- package/dist/ui/overlay/impl/docs-overlay-v2.js +114 -0
- package/dist/ui/overlay/impl/document-detail-overlay-v2.d.ts +77 -0
- package/dist/ui/overlay/impl/document-detail-overlay-v2.js +1071 -0
- package/dist/ui/overlay/impl/guardrail-overlay-v2.d.ts +43 -0
- package/dist/ui/overlay/impl/guardrail-overlay-v2.js +114 -0
- package/dist/ui/overlay/impl/help-overlay-v2.d.ts +34 -0
- package/dist/ui/overlay/impl/help-overlay-v2.js +309 -0
- package/dist/ui/overlay/impl/init-overlay-v2.d.ts +77 -0
- package/dist/ui/overlay/impl/init-overlay-v2.js +593 -0
- package/dist/ui/overlay/impl/init-setup-overlay-v2.d.ts +25 -0
- package/dist/ui/overlay/impl/init-setup-overlay-v2.js +97 -0
- package/dist/ui/overlay/impl/iteration-limit-overlay-v2.d.ts +35 -0
- package/dist/ui/overlay/impl/iteration-limit-overlay-v2.js +105 -0
- package/dist/ui/overlay/impl/keys-overlay-v2.d.ts +41 -0
- package/dist/ui/overlay/impl/keys-overlay-v2.js +248 -0
- package/dist/ui/overlay/impl/mascot-overlay-v2.d.ts +41 -0
- package/dist/ui/overlay/impl/mascot-overlay-v2.js +138 -0
- package/dist/ui/overlay/impl/model-overlay-v2.d.ts +49 -0
- package/dist/ui/overlay/impl/model-overlay-v2.js +118 -0
- package/dist/ui/overlay/impl/model-warning-overlay-v2.d.ts +46 -0
- package/dist/ui/overlay/impl/model-warning-overlay-v2.js +132 -0
- package/dist/ui/overlay/impl/new-overlay-v2.d.ts +77 -0
- package/dist/ui/overlay/impl/new-overlay-v2.js +593 -0
- package/dist/ui/overlay/impl/permission-overlay-v2.d.ts +36 -0
- package/dist/ui/overlay/impl/permission-overlay-v2.js +380 -0
- package/dist/ui/overlay/impl/projects-overlay-v2.d.ts +36 -0
- package/dist/ui/overlay/impl/projects-overlay-v2.js +499 -0
- package/dist/ui/overlay/impl/theme-overlay-v2.d.ts +42 -0
- package/dist/ui/overlay/impl/theme-overlay-v2.js +135 -0
- package/dist/ui/overlay/impl/tools-overlay-v2.d.ts +47 -0
- package/dist/ui/overlay/impl/tools-overlay-v2.js +218 -0
- package/dist/ui/overlay/impl/tutorial-overlay-v2.d.ts +31 -0
- package/dist/ui/overlay/impl/tutorial-overlay-v2.js +1035 -0
- package/dist/ui/overlay/impl/workflow-overlay-v2.d.ts +80 -0
- package/dist/ui/overlay/impl/workflow-overlay-v2.js +637 -0
- package/dist/ui/overlay/index.d.ts +33 -0
- package/dist/ui/overlay/index.js +35 -0
- package/dist/ui/overlay/key-utils.d.ts +6 -0
- package/dist/ui/overlay/key-utils.js +6 -0
- package/dist/ui/overlay/overlay-types.d.ts +128 -0
- package/dist/ui/overlay/overlay-types.js +22 -0
- package/dist/ui/overlay/types.d.ts +135 -0
- package/dist/ui/overlay/types.js +22 -0
- package/dist/ui/overlays/help-overlay-v2.d.ts +28 -0
- package/dist/ui/overlays/help-overlay-v2.js +198 -0
- package/dist/ui/overlays/index.d.ts +11 -0
- package/dist/ui/overlays/index.js +11 -0
- package/dist/ui/overlays.d.ts +0 -4
- package/dist/ui/overlays.js +0 -444
- package/dist/ui/permission-overlay-v2.d.ts +36 -0
- package/dist/ui/permission-overlay-v2.js +380 -0
- package/dist/ui/permission-overlay.d.ts +1 -1
- package/dist/ui/permission-overlay.js +186 -298
- package/dist/ui/projects-overlay.d.ts +19 -0
- package/dist/ui/projects-overlay.js +484 -0
- package/dist/ui/providers/types.d.ts +178 -0
- package/dist/ui/providers/types.js +9 -0
- package/dist/ui/render-modes.d.ts +36 -0
- package/dist/ui/render-modes.js +44 -0
- package/dist/ui/startup-menu.d.ts +36 -0
- package/dist/ui/startup-menu.js +236 -0
- package/dist/ui/subagent-renderer.d.ts +117 -0
- package/dist/ui/subagent-renderer.js +334 -0
- package/dist/ui/terminal-codes.d.ts +94 -0
- package/dist/ui/terminal-codes.js +124 -0
- package/dist/ui/terminal-renderer.d.ts +221 -0
- package/dist/ui/terminal-renderer.js +751 -0
- package/dist/ui/terminal-ui.d.ts +463 -0
- package/dist/ui/terminal-ui.js +2296 -0
- package/dist/ui/terminal.d.ts +20 -0
- package/dist/ui/terminal.js +72 -0
- package/dist/ui/theme-overlay-v2.d.ts +42 -0
- package/dist/ui/theme-overlay-v2.js +135 -0
- package/dist/ui/theme-overlay.d.ts +24 -0
- package/dist/ui/theme-overlay.js +127 -0
- package/dist/ui/todo-zone.js +53 -25
- package/dist/ui/tool-formatters.d.ts +16 -0
- package/dist/ui/tool-formatters.js +516 -0
- package/dist/ui/tools-overlay-v2.d.ts +47 -0
- package/dist/ui/tools-overlay-v2.js +218 -0
- package/dist/ui/tools-overlay.d.ts +10 -2
- package/dist/ui/tools-overlay.js +172 -220
- package/dist/ui/tutorial-overlay-v2.d.ts +31 -0
- package/dist/ui/tutorial-overlay-v2.js +1035 -0
- package/dist/ui/tutorial-overlay.d.ts +1 -0
- package/dist/ui/tutorial-overlay.js +400 -302
- package/dist/ui/workflow-overlay.d.ts +22 -0
- package/dist/ui/workflow-overlay.js +636 -0
- package/dist/utils/debug-log.d.ts +28 -0
- package/dist/utils/debug-log.js +57 -0
- package/dist/utils/model-tiers.js +1 -1
- package/dist/utils/path-safety.d.ts +56 -0
- package/dist/utils/path-safety.js +239 -0
- package/dist/workflow/guided-mode-injector.d.ts +42 -0
- package/dist/workflow/guided-mode-injector.js +191 -0
- package/dist/workflow/index.d.ts +8 -0
- package/dist/workflow/index.js +8 -0
- package/dist/workflow/step-criteria.d.ts +62 -0
- package/dist/workflow/step-criteria.js +150 -0
- package/dist/workflow/step-tracker.d.ts +92 -0
- package/dist/workflow/step-tracker.js +141 -0
- package/package.json +12 -5
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pagination Feature
|
|
3
|
+
*
|
|
4
|
+
* Composable feature for paginated list navigation.
|
|
5
|
+
* Handles page up/down, scroll offset tracking, and visibility.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* ```typescript
|
|
9
|
+
* interface MyState extends OverlayState, PaginationState {
|
|
10
|
+
* items: string[];
|
|
11
|
+
* }
|
|
12
|
+
*
|
|
13
|
+
* class MyScreen extends BaseScreen {
|
|
14
|
+
* private pagination = new PaginationFeature({ pageSize: 12 });
|
|
15
|
+
*
|
|
16
|
+
* handleKey(data: Buffer): ScreenResult {
|
|
17
|
+
* const result = this.pagination.handleKey(data, this.state, this.state.items.length);
|
|
18
|
+
* if (result?.handled) {
|
|
19
|
+
* return result.action === 'render' ? stay() : stay(false);
|
|
20
|
+
* }
|
|
21
|
+
* // ... other key handling
|
|
22
|
+
* }
|
|
23
|
+
*
|
|
24
|
+
* render(): string[] {
|
|
25
|
+
* const visible = this.pagination.getVisibleItems(this.state, this.state.items);
|
|
26
|
+
* // render visible items...
|
|
27
|
+
* return [
|
|
28
|
+
* ...itemLines,
|
|
29
|
+
* this.pagination.renderIndicator(this.state, this.state.items.length, styles)
|
|
30
|
+
* ];
|
|
31
|
+
* }
|
|
32
|
+
* }
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
/**
|
|
36
|
+
* State interface for pagination.
|
|
37
|
+
* Overlay state should extend this.
|
|
38
|
+
*/
|
|
39
|
+
export interface PaginationState {
|
|
40
|
+
/** Currently selected index (0-based) */
|
|
41
|
+
selectedIndex: number;
|
|
42
|
+
/** First visible item index */
|
|
43
|
+
scrollOffset: number;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Configuration for PaginationFeature.
|
|
47
|
+
*/
|
|
48
|
+
export interface PaginationConfig {
|
|
49
|
+
/** Number of items visible per page */
|
|
50
|
+
pageSize: number;
|
|
51
|
+
/**
|
|
52
|
+
* Whether left/right arrows trigger page navigation.
|
|
53
|
+
* Default: true
|
|
54
|
+
*/
|
|
55
|
+
useArrowsForPaging?: boolean;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Result from handling a key.
|
|
59
|
+
*/
|
|
60
|
+
export interface PaginationKeyResult {
|
|
61
|
+
/** Whether the key was handled */
|
|
62
|
+
handled: boolean;
|
|
63
|
+
/** Action to take */
|
|
64
|
+
action?: 'render' | 'none';
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Feature for paginated list navigation.
|
|
68
|
+
*
|
|
69
|
+
* Handles:
|
|
70
|
+
* - Up/Down arrows and j/k for item navigation
|
|
71
|
+
* - Left/Right arrows and h/l for page navigation
|
|
72
|
+
* - Page Up/Page Down for page navigation
|
|
73
|
+
* - Scroll offset tracking
|
|
74
|
+
* - Visibility management (ensure selected item is visible)
|
|
75
|
+
*/
|
|
76
|
+
export declare class PaginationFeature {
|
|
77
|
+
private readonly pageSize;
|
|
78
|
+
private readonly useArrowsForPaging;
|
|
79
|
+
constructor(config: PaginationConfig);
|
|
80
|
+
/**
|
|
81
|
+
* Handle a key press.
|
|
82
|
+
*
|
|
83
|
+
* @param data - Raw key buffer
|
|
84
|
+
* @param state - State containing selectedIndex and scrollOffset
|
|
85
|
+
* @param totalItems - Total number of items in the list
|
|
86
|
+
* @returns Result if handled, null otherwise
|
|
87
|
+
*/
|
|
88
|
+
handleKey(data: Buffer, state: PaginationState, totalItems: number): PaginationKeyResult | null;
|
|
89
|
+
/**
|
|
90
|
+
* Ensure the selected item is visible by adjusting scrollOffset.
|
|
91
|
+
*
|
|
92
|
+
* @param state - State to adjust
|
|
93
|
+
* @param totalItems - Total number of items
|
|
94
|
+
*/
|
|
95
|
+
ensureVisible(state: PaginationState, totalItems: number): void;
|
|
96
|
+
/**
|
|
97
|
+
* Get the visible slice of items.
|
|
98
|
+
*
|
|
99
|
+
* @param state - State containing scrollOffset
|
|
100
|
+
* @param items - All items
|
|
101
|
+
* @returns Visible items
|
|
102
|
+
*/
|
|
103
|
+
getVisibleItems<T>(state: PaginationState, items: T[]): T[];
|
|
104
|
+
/**
|
|
105
|
+
* Get the visible range info.
|
|
106
|
+
*
|
|
107
|
+
* @param state - State containing scrollOffset
|
|
108
|
+
* @param totalItems - Total number of items
|
|
109
|
+
* @returns Object with start, end, total, canScrollUp, canScrollDown
|
|
110
|
+
*/
|
|
111
|
+
getVisibleRange(state: PaginationState, totalItems: number): {
|
|
112
|
+
start: number;
|
|
113
|
+
end: number;
|
|
114
|
+
total: number;
|
|
115
|
+
canScrollUp: boolean;
|
|
116
|
+
canScrollDown: boolean;
|
|
117
|
+
};
|
|
118
|
+
/**
|
|
119
|
+
* Render a scroll indicator line.
|
|
120
|
+
*
|
|
121
|
+
* @param state - State containing scrollOffset
|
|
122
|
+
* @param totalItems - Total number of items
|
|
123
|
+
* @param styles - Theme styles with muted() function
|
|
124
|
+
* @returns Formatted indicator string (empty if no pagination needed)
|
|
125
|
+
*/
|
|
126
|
+
renderIndicator(state: PaginationState, totalItems: number, styles: {
|
|
127
|
+
muted: (s: string) => string;
|
|
128
|
+
}): string;
|
|
129
|
+
/**
|
|
130
|
+
* Render navigation hints for the footer.
|
|
131
|
+
*
|
|
132
|
+
* @param includeArrows - Whether to include ←→/hl hints
|
|
133
|
+
* @returns Hint string
|
|
134
|
+
*/
|
|
135
|
+
renderHints(includeArrows?: boolean): string;
|
|
136
|
+
/**
|
|
137
|
+
* Get the page size.
|
|
138
|
+
*/
|
|
139
|
+
getPageSize(): number;
|
|
140
|
+
/**
|
|
141
|
+
* Reset pagination state to beginning.
|
|
142
|
+
*
|
|
143
|
+
* @param state - State to reset
|
|
144
|
+
*/
|
|
145
|
+
reset(state: PaginationState): void;
|
|
146
|
+
/**
|
|
147
|
+
* Jump to a specific index and ensure it's visible.
|
|
148
|
+
*
|
|
149
|
+
* @param state - State to update
|
|
150
|
+
* @param index - Target index
|
|
151
|
+
* @param totalItems - Total number of items
|
|
152
|
+
*/
|
|
153
|
+
jumpTo(state: PaginationState, index: number, totalItems: number): void;
|
|
154
|
+
}
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pagination Feature
|
|
3
|
+
*
|
|
4
|
+
* Composable feature for paginated list navigation.
|
|
5
|
+
* Handles page up/down, scroll offset tracking, and visibility.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* ```typescript
|
|
9
|
+
* interface MyState extends OverlayState, PaginationState {
|
|
10
|
+
* items: string[];
|
|
11
|
+
* }
|
|
12
|
+
*
|
|
13
|
+
* class MyScreen extends BaseScreen {
|
|
14
|
+
* private pagination = new PaginationFeature({ pageSize: 12 });
|
|
15
|
+
*
|
|
16
|
+
* handleKey(data: Buffer): ScreenResult {
|
|
17
|
+
* const result = this.pagination.handleKey(data, this.state, this.state.items.length);
|
|
18
|
+
* if (result?.handled) {
|
|
19
|
+
* return result.action === 'render' ? stay() : stay(false);
|
|
20
|
+
* }
|
|
21
|
+
* // ... other key handling
|
|
22
|
+
* }
|
|
23
|
+
*
|
|
24
|
+
* render(): string[] {
|
|
25
|
+
* const visible = this.pagination.getVisibleItems(this.state, this.state.items);
|
|
26
|
+
* // render visible items...
|
|
27
|
+
* return [
|
|
28
|
+
* ...itemLines,
|
|
29
|
+
* this.pagination.renderIndicator(this.state, this.state.items.length, styles)
|
|
30
|
+
* ];
|
|
31
|
+
* }
|
|
32
|
+
* }
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
import { isNavigateUp, isNavigateDown, isNavigateLeft, isNavigateRight, isPageUp, isPageDown, } from '../base/key-utils.js';
|
|
36
|
+
// =============================================================================
|
|
37
|
+
// PaginationFeature Class
|
|
38
|
+
// =============================================================================
|
|
39
|
+
/**
|
|
40
|
+
* Feature for paginated list navigation.
|
|
41
|
+
*
|
|
42
|
+
* Handles:
|
|
43
|
+
* - Up/Down arrows and j/k for item navigation
|
|
44
|
+
* - Left/Right arrows and h/l for page navigation
|
|
45
|
+
* - Page Up/Page Down for page navigation
|
|
46
|
+
* - Scroll offset tracking
|
|
47
|
+
* - Visibility management (ensure selected item is visible)
|
|
48
|
+
*/
|
|
49
|
+
export class PaginationFeature {
|
|
50
|
+
pageSize;
|
|
51
|
+
useArrowsForPaging;
|
|
52
|
+
constructor(config) {
|
|
53
|
+
this.pageSize = config.pageSize;
|
|
54
|
+
this.useArrowsForPaging = config.useArrowsForPaging ?? true;
|
|
55
|
+
}
|
|
56
|
+
// ===========================================================================
|
|
57
|
+
// Key Handling
|
|
58
|
+
// ===========================================================================
|
|
59
|
+
/**
|
|
60
|
+
* Handle a key press.
|
|
61
|
+
*
|
|
62
|
+
* @param data - Raw key buffer
|
|
63
|
+
* @param state - State containing selectedIndex and scrollOffset
|
|
64
|
+
* @param totalItems - Total number of items in the list
|
|
65
|
+
* @returns Result if handled, null otherwise
|
|
66
|
+
*/
|
|
67
|
+
handleKey(data, state, totalItems) {
|
|
68
|
+
if (totalItems === 0) {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
// Navigate up (single item)
|
|
72
|
+
if (isNavigateUp(data)) {
|
|
73
|
+
if (state.selectedIndex > 0) {
|
|
74
|
+
state.selectedIndex--;
|
|
75
|
+
this.ensureVisible(state, totalItems);
|
|
76
|
+
return { handled: true, action: 'render' };
|
|
77
|
+
}
|
|
78
|
+
return { handled: true, action: 'none' };
|
|
79
|
+
}
|
|
80
|
+
// Navigate down (single item)
|
|
81
|
+
if (isNavigateDown(data)) {
|
|
82
|
+
if (state.selectedIndex < totalItems - 1) {
|
|
83
|
+
state.selectedIndex++;
|
|
84
|
+
this.ensureVisible(state, totalItems);
|
|
85
|
+
return { handled: true, action: 'render' };
|
|
86
|
+
}
|
|
87
|
+
return { handled: true, action: 'none' };
|
|
88
|
+
}
|
|
89
|
+
// Page up (PgUp or ←/h if enabled)
|
|
90
|
+
const isPageUpKey = isPageUp(data) || (this.useArrowsForPaging && isNavigateLeft(data));
|
|
91
|
+
if (isPageUpKey) {
|
|
92
|
+
const newIndex = Math.max(0, state.selectedIndex - this.pageSize);
|
|
93
|
+
if (newIndex !== state.selectedIndex) {
|
|
94
|
+
state.selectedIndex = newIndex;
|
|
95
|
+
this.ensureVisible(state, totalItems);
|
|
96
|
+
return { handled: true, action: 'render' };
|
|
97
|
+
}
|
|
98
|
+
return { handled: true, action: 'none' };
|
|
99
|
+
}
|
|
100
|
+
// Page down (PgDn or →/l if enabled)
|
|
101
|
+
const isPageDownKey = isPageDown(data) || (this.useArrowsForPaging && isNavigateRight(data));
|
|
102
|
+
if (isPageDownKey) {
|
|
103
|
+
const newIndex = Math.min(totalItems - 1, state.selectedIndex + this.pageSize);
|
|
104
|
+
if (newIndex !== state.selectedIndex) {
|
|
105
|
+
state.selectedIndex = newIndex;
|
|
106
|
+
this.ensureVisible(state, totalItems);
|
|
107
|
+
return { handled: true, action: 'render' };
|
|
108
|
+
}
|
|
109
|
+
return { handled: true, action: 'none' };
|
|
110
|
+
}
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
// ===========================================================================
|
|
114
|
+
// Visibility Management
|
|
115
|
+
// ===========================================================================
|
|
116
|
+
/**
|
|
117
|
+
* Ensure the selected item is visible by adjusting scrollOffset.
|
|
118
|
+
*
|
|
119
|
+
* @param state - State to adjust
|
|
120
|
+
* @param totalItems - Total number of items
|
|
121
|
+
*/
|
|
122
|
+
ensureVisible(state, totalItems) {
|
|
123
|
+
// Clamp selectedIndex first
|
|
124
|
+
if (state.selectedIndex < 0) {
|
|
125
|
+
state.selectedIndex = 0;
|
|
126
|
+
}
|
|
127
|
+
else if (state.selectedIndex >= totalItems) {
|
|
128
|
+
state.selectedIndex = Math.max(0, totalItems - 1);
|
|
129
|
+
}
|
|
130
|
+
// Adjust scrollOffset to keep selection visible
|
|
131
|
+
if (state.selectedIndex < state.scrollOffset) {
|
|
132
|
+
state.scrollOffset = state.selectedIndex;
|
|
133
|
+
}
|
|
134
|
+
else if (state.selectedIndex >= state.scrollOffset + this.pageSize) {
|
|
135
|
+
state.scrollOffset = state.selectedIndex - this.pageSize + 1;
|
|
136
|
+
}
|
|
137
|
+
// Clamp scrollOffset
|
|
138
|
+
const maxOffset = Math.max(0, totalItems - this.pageSize);
|
|
139
|
+
if (state.scrollOffset > maxOffset) {
|
|
140
|
+
state.scrollOffset = maxOffset;
|
|
141
|
+
}
|
|
142
|
+
if (state.scrollOffset < 0) {
|
|
143
|
+
state.scrollOffset = 0;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// ===========================================================================
|
|
147
|
+
// Item Access
|
|
148
|
+
// ===========================================================================
|
|
149
|
+
/**
|
|
150
|
+
* Get the visible slice of items.
|
|
151
|
+
*
|
|
152
|
+
* @param state - State containing scrollOffset
|
|
153
|
+
* @param items - All items
|
|
154
|
+
* @returns Visible items
|
|
155
|
+
*/
|
|
156
|
+
getVisibleItems(state, items) {
|
|
157
|
+
return items.slice(state.scrollOffset, state.scrollOffset + this.pageSize);
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Get the visible range info.
|
|
161
|
+
*
|
|
162
|
+
* @param state - State containing scrollOffset
|
|
163
|
+
* @param totalItems - Total number of items
|
|
164
|
+
* @returns Object with start, end, total, canScrollUp, canScrollDown
|
|
165
|
+
*/
|
|
166
|
+
getVisibleRange(state, totalItems) {
|
|
167
|
+
const start = state.scrollOffset + 1; // 1-based for display
|
|
168
|
+
const end = Math.min(state.scrollOffset + this.pageSize, totalItems);
|
|
169
|
+
return {
|
|
170
|
+
start,
|
|
171
|
+
end,
|
|
172
|
+
total: totalItems,
|
|
173
|
+
canScrollUp: state.scrollOffset > 0,
|
|
174
|
+
canScrollDown: state.scrollOffset + this.pageSize < totalItems,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
// ===========================================================================
|
|
178
|
+
// Rendering Helpers
|
|
179
|
+
// ===========================================================================
|
|
180
|
+
/**
|
|
181
|
+
* Render a scroll indicator line.
|
|
182
|
+
*
|
|
183
|
+
* @param state - State containing scrollOffset
|
|
184
|
+
* @param totalItems - Total number of items
|
|
185
|
+
* @param styles - Theme styles with muted() function
|
|
186
|
+
* @returns Formatted indicator string (empty if no pagination needed)
|
|
187
|
+
*/
|
|
188
|
+
renderIndicator(state, totalItems, styles) {
|
|
189
|
+
if (totalItems <= this.pageSize) {
|
|
190
|
+
return ''; // No pagination needed
|
|
191
|
+
}
|
|
192
|
+
const range = this.getVisibleRange(state, totalItems);
|
|
193
|
+
const info = `${String(range.start)}-${String(range.end)} of ${String(range.total)}`;
|
|
194
|
+
const arrows = (range.canScrollUp ? '↑' : ' ') + (range.canScrollDown ? '↓' : ' ');
|
|
195
|
+
return ` ${styles.muted(info)} ${styles.muted(arrows)}`;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Render navigation hints for the footer.
|
|
199
|
+
*
|
|
200
|
+
* @param includeArrows - Whether to include ←→/hl hints
|
|
201
|
+
* @returns Hint string
|
|
202
|
+
*/
|
|
203
|
+
renderHints(includeArrows = true) {
|
|
204
|
+
if (includeArrows) {
|
|
205
|
+
return '↑↓/jk Navigate · ←→/hl Page';
|
|
206
|
+
}
|
|
207
|
+
return '↑↓/jk Navigate · PgUp/PgDn Page';
|
|
208
|
+
}
|
|
209
|
+
// ===========================================================================
|
|
210
|
+
// Utilities
|
|
211
|
+
// ===========================================================================
|
|
212
|
+
/**
|
|
213
|
+
* Get the page size.
|
|
214
|
+
*/
|
|
215
|
+
getPageSize() {
|
|
216
|
+
return this.pageSize;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Reset pagination state to beginning.
|
|
220
|
+
*
|
|
221
|
+
* @param state - State to reset
|
|
222
|
+
*/
|
|
223
|
+
reset(state) {
|
|
224
|
+
state.selectedIndex = 0;
|
|
225
|
+
state.scrollOffset = 0;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Jump to a specific index and ensure it's visible.
|
|
229
|
+
*
|
|
230
|
+
* @param state - State to update
|
|
231
|
+
* @param index - Target index
|
|
232
|
+
* @param totalItems - Total number of items
|
|
233
|
+
*/
|
|
234
|
+
jumpTo(state, index, totalItems) {
|
|
235
|
+
state.selectedIndex = Math.max(0, Math.min(index, totalItems - 1));
|
|
236
|
+
this.ensureVisible(state, totalItems);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Search Feature
|
|
3
|
+
*
|
|
4
|
+
* Composable feature for search/filter text input in overlays.
|
|
5
|
+
* Handles typing, backspace, and escape to clear.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* ```typescript
|
|
9
|
+
* interface MyState extends OverlayState, SearchState {
|
|
10
|
+
* items: string[];
|
|
11
|
+
* }
|
|
12
|
+
*
|
|
13
|
+
* class MyScreen extends BaseScreen {
|
|
14
|
+
* private search = new SearchFeature({
|
|
15
|
+
* onSearch: (query) => this.filterItems(query),
|
|
16
|
+
* });
|
|
17
|
+
*
|
|
18
|
+
* handleKey(data: Buffer): ScreenResult {
|
|
19
|
+
* const result = this.search.handleKey(data, this.state);
|
|
20
|
+
* if (result?.handled) {
|
|
21
|
+
* return result.action === 'render' ? stay() : stay(false);
|
|
22
|
+
* }
|
|
23
|
+
* // ... other key handling
|
|
24
|
+
* }
|
|
25
|
+
*
|
|
26
|
+
* render(): string[] {
|
|
27
|
+
* return [
|
|
28
|
+
* this.search.renderSearchBox(this.state, styles, { label: 'Search' }),
|
|
29
|
+
* ...filteredItemLines,
|
|
30
|
+
* ];
|
|
31
|
+
* }
|
|
32
|
+
* }
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
/**
|
|
36
|
+
* State interface for search.
|
|
37
|
+
* Overlay state should extend this.
|
|
38
|
+
*/
|
|
39
|
+
export interface SearchState {
|
|
40
|
+
/** Current search query */
|
|
41
|
+
searchQuery: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Configuration for SearchFeature.
|
|
45
|
+
*/
|
|
46
|
+
export interface SearchConfig {
|
|
47
|
+
/**
|
|
48
|
+
* Callback when search query changes.
|
|
49
|
+
* Use this to trigger filtering/re-rendering.
|
|
50
|
+
*/
|
|
51
|
+
onSearch?: (query: string) => void;
|
|
52
|
+
/**
|
|
53
|
+
* Whether Escape clears the search (default: true).
|
|
54
|
+
* If false, Escape is not handled by this feature.
|
|
55
|
+
*/
|
|
56
|
+
escapeClearsSearch?: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Placeholder text when search is empty.
|
|
59
|
+
*/
|
|
60
|
+
placeholder?: string;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Result from handling a key.
|
|
64
|
+
*/
|
|
65
|
+
export interface SearchKeyResult {
|
|
66
|
+
/** Whether the key was handled */
|
|
67
|
+
handled: boolean;
|
|
68
|
+
/** Action to take */
|
|
69
|
+
action?: 'render' | 'none';
|
|
70
|
+
/** Whether the search was cleared (Escape pressed) */
|
|
71
|
+
cleared?: boolean;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Options for rendering the search box.
|
|
75
|
+
*/
|
|
76
|
+
export interface SearchBoxOptions {
|
|
77
|
+
/** Label before the search box (default: 'Search') */
|
|
78
|
+
label?: string;
|
|
79
|
+
/** Whether to show cursor (default: true) */
|
|
80
|
+
showCursor?: boolean;
|
|
81
|
+
/** Prefix before the input (default: ' ') */
|
|
82
|
+
prefix?: string;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Feature for search/filter text input.
|
|
86
|
+
*
|
|
87
|
+
* Handles:
|
|
88
|
+
* - Printable character input
|
|
89
|
+
* - Backspace to delete
|
|
90
|
+
* - Escape to clear (optional)
|
|
91
|
+
*/
|
|
92
|
+
export declare class SearchFeature {
|
|
93
|
+
private readonly config;
|
|
94
|
+
constructor(config?: SearchConfig);
|
|
95
|
+
/**
|
|
96
|
+
* Handle a key press.
|
|
97
|
+
*
|
|
98
|
+
* @param data - Raw key buffer
|
|
99
|
+
* @param state - State containing searchQuery
|
|
100
|
+
* @returns Result if handled, null otherwise
|
|
101
|
+
*/
|
|
102
|
+
handleKey(data: Buffer, state: SearchState): SearchKeyResult | null;
|
|
103
|
+
/**
|
|
104
|
+
* Render a search box with optional cursor.
|
|
105
|
+
*
|
|
106
|
+
* @param state - State containing searchQuery
|
|
107
|
+
* @param styles - Theme styles
|
|
108
|
+
* @param options - Rendering options
|
|
109
|
+
* @returns Formatted search box string
|
|
110
|
+
*/
|
|
111
|
+
renderSearchBox(state: SearchState, styles: {
|
|
112
|
+
muted: (s: string) => string;
|
|
113
|
+
primary?: (s: string) => string;
|
|
114
|
+
}, options?: SearchBoxOptions): string;
|
|
115
|
+
/**
|
|
116
|
+
* Render search hints for the footer.
|
|
117
|
+
*
|
|
118
|
+
* @param hasQuery - Whether there's an active search query
|
|
119
|
+
* @returns Hint string
|
|
120
|
+
*/
|
|
121
|
+
renderHints(hasQuery?: boolean): string;
|
|
122
|
+
/**
|
|
123
|
+
* Check if there's an active search query.
|
|
124
|
+
*/
|
|
125
|
+
hasQuery(state: SearchState): boolean;
|
|
126
|
+
/**
|
|
127
|
+
* Get the current search query.
|
|
128
|
+
*/
|
|
129
|
+
getQuery(state: SearchState): string;
|
|
130
|
+
/**
|
|
131
|
+
* Clear the search query.
|
|
132
|
+
*/
|
|
133
|
+
clear(state: SearchState): void;
|
|
134
|
+
/**
|
|
135
|
+
* Set the search query programmatically.
|
|
136
|
+
*/
|
|
137
|
+
setQuery(state: SearchState, query: string): void;
|
|
138
|
+
/**
|
|
139
|
+
* Filter items based on search query.
|
|
140
|
+
* Generic helper that works with any item type.
|
|
141
|
+
*
|
|
142
|
+
* @param items - Items to filter
|
|
143
|
+
* @param state - State containing searchQuery
|
|
144
|
+
* @param getSearchableText - Function to extract searchable text from item
|
|
145
|
+
* @returns Filtered items
|
|
146
|
+
*/
|
|
147
|
+
filterItems<T>(items: T[], state: SearchState, getSearchableText: (item: T) => string): T[];
|
|
148
|
+
}
|