pickem 0.2.0 → 1.0.1

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 (104) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/README.md +67 -68
  3. package/checkbox.d.ts.map +1 -1
  4. package/checkbox.js +10 -9
  5. package/checkbox.js.map +1 -1
  6. package/core/ansi.d.ts +16 -0
  7. package/core/ansi.d.ts.map +1 -0
  8. package/core/ansi.js +21 -0
  9. package/core/ansi.js.map +1 -0
  10. package/core/chrome.d.ts +37 -0
  11. package/core/chrome.d.ts.map +1 -0
  12. package/core/chrome.js +51 -0
  13. package/core/chrome.js.map +1 -0
  14. package/core/cleanup.d.ts +5 -0
  15. package/core/cleanup.d.ts.map +1 -0
  16. package/core/cleanup.js +31 -0
  17. package/core/cleanup.js.map +1 -0
  18. package/core/colors.d.ts +24 -0
  19. package/core/colors.d.ts.map +1 -0
  20. package/core/colors.js +67 -0
  21. package/core/colors.js.map +1 -0
  22. package/core/hooks.d.ts +26 -0
  23. package/core/hooks.d.ts.map +1 -0
  24. package/core/hooks.js +80 -0
  25. package/core/hooks.js.map +1 -0
  26. package/core/index.d.ts +9 -0
  27. package/core/index.d.ts.map +1 -0
  28. package/core/index.js +9 -0
  29. package/core/index.js.map +1 -0
  30. package/core/key-reader.d.ts +6 -0
  31. package/core/key-reader.d.ts.map +1 -0
  32. package/core/key-reader.js +29 -0
  33. package/core/key-reader.js.map +1 -0
  34. package/core/keys.d.ts +17 -0
  35. package/core/keys.d.ts.map +1 -0
  36. package/core/keys.js +17 -0
  37. package/core/keys.js.map +1 -0
  38. package/core/pagination.d.ts +14 -0
  39. package/core/pagination.d.ts.map +1 -0
  40. package/core/pagination.js +36 -0
  41. package/core/pagination.js.map +1 -0
  42. package/core/runtime.d.ts +20 -0
  43. package/core/runtime.d.ts.map +1 -0
  44. package/core/runtime.js +74 -0
  45. package/core/runtime.js.map +1 -0
  46. package/core/screen.d.ts +14 -0
  47. package/core/screen.d.ts.map +1 -0
  48. package/core/screen.js +50 -0
  49. package/core/screen.js.map +1 -0
  50. package/core/status-glyph.d.ts +10 -0
  51. package/core/status-glyph.d.ts.map +1 -0
  52. package/core/status-glyph.js +18 -0
  53. package/core/status-glyph.js.map +1 -0
  54. package/core/symbols.d.ts +27 -0
  55. package/core/symbols.d.ts.map +1 -0
  56. package/core/symbols.js +41 -0
  57. package/core/symbols.js.map +1 -0
  58. package/core/testing.d.ts +15 -0
  59. package/core/testing.d.ts.map +1 -0
  60. package/core/testing.js +47 -0
  61. package/core/testing.js.map +1 -0
  62. package/core/theme.d.ts +14 -0
  63. package/core/theme.d.ts.map +1 -0
  64. package/core/theme.js +10 -0
  65. package/core/theme.js.map +1 -0
  66. package/core/width.d.ts +7 -0
  67. package/core/width.d.ts.map +1 -0
  68. package/core/width.js +46 -0
  69. package/core/width.js.map +1 -0
  70. package/package.json +4 -13
  71. package/pickem.d.ts.map +1 -1
  72. package/pickem.js +6 -5
  73. package/pickem.js.map +1 -1
  74. package/prompts/checkbox.d.ts +14 -0
  75. package/prompts/checkbox.d.ts.map +1 -0
  76. package/prompts/checkbox.js +56 -0
  77. package/prompts/checkbox.js.map +1 -0
  78. package/prompts/confirm.d.ts +6 -0
  79. package/prompts/confirm.d.ts.map +1 -0
  80. package/prompts/confirm.js +32 -0
  81. package/prompts/confirm.js.map +1 -0
  82. package/prompts/input.d.ts +7 -0
  83. package/prompts/input.d.ts.map +1 -0
  84. package/prompts/input.js +52 -0
  85. package/prompts/input.js.map +1 -0
  86. package/prompts/search.d.ts +12 -0
  87. package/prompts/search.d.ts.map +1 -0
  88. package/prompts/search.js +67 -0
  89. package/prompts/search.js.map +1 -0
  90. package/prompts/searchable-checkbox.d.ts +14 -0
  91. package/prompts/searchable-checkbox.d.ts.map +1 -0
  92. package/prompts/searchable-checkbox.js +150 -0
  93. package/prompts/searchable-checkbox.js.map +1 -0
  94. package/prompts/select.d.ts +12 -0
  95. package/prompts/select.d.ts.map +1 -0
  96. package/prompts/select.js +40 -0
  97. package/prompts/select.js.map +1 -0
  98. package/wizard.d.ts.map +1 -1
  99. package/wizard.js +7 -5
  100. package/wizard.js.map +1 -1
  101. package/prompt/searchable-checkbox.d.ts +0 -26
  102. package/prompt/searchable-checkbox.d.ts.map +0 -1
  103. package/prompt/searchable-checkbox.js +0 -173
  104. package/prompt/searchable-checkbox.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -5,6 +5,46 @@ All notable changes to pickem will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.0.0] — 2026-05-31
9
+
10
+ The picker engine is now fully native. The public API
11
+ (`pickem`, `pickem.from`, `pickem.checkbox`, `wizard`, `defineSource`) is
12
+ **unchanged and backward compatible** — existing callers need no changes. The
13
+ major bump reflects the engine replacement, the dependency removal, and the
14
+ refreshed prompt visuals.
15
+
16
+ ### Changed
17
+
18
+ - **Native picker engine.** Replaced `@inquirer/prompts` and `@inquirer/core`
19
+ with a built-in hook-based picker runtime (`createPicker`). The only
20
+ remaining runtime dependency is `string-width`.
21
+ - Prompt visuals adopt the Claude Code selector aesthetic — a cyan `❯` cursor
22
+ rail with truecolor accents and synchronized-output rendering.
23
+
24
+ ### Added
25
+
26
+ - `src/core/*` — native engine: hook runtime, screen buffer, raw key reader,
27
+ pagination, chrome/border rendering, theme tokens, color/accent helpers,
28
+ glyphs, display-width measurement, ANSI primitives, status glyphs, and
29
+ terminal cleanup.
30
+ - `src/prompts/*` — native implementations of select, input, confirm,
31
+ checkbox, search, and searchable-checkbox.
32
+ - Release quality gates wired into `npm run release`: `npm audit` (prod deps),
33
+ manifest audit (`scripts/audit.js`), `publint --strict`, `attw --pack`, and
34
+ an `npm pack` dry-run.
35
+
36
+ ### Removed
37
+
38
+ - Runtime dependencies `@inquirer/prompts` and `@inquirer/core`.
39
+ - Dev dependency `@inquirer/testing` — native prompts are now tested via the
40
+ in-tree `renderTest` harness (`src/core/testing.ts`).
41
+
42
+ ### Fixed
43
+
44
+ - `package.json` `exports` now lists the `types` condition first (export
45
+ conditions are order-sensitive), so TypeScript resolves declarations
46
+ correctly.
47
+
8
48
  ## [0.2.0] — 2026-05-09
9
49
 
10
50
  ### Added
package/README.md CHANGED
@@ -1,37 +1,38 @@
1
1
  # pickem
2
2
 
3
- Usage-sorted searchable autocomplete for CLI tools. One dependency-light module that gives every CLI the same interactive picker pattern: discover items, sort by usage, search, select, track.
3
+ **Usage-sorted, searchable autocomplete for CLI tools.** Give every command-line tool the same fast, interactive picker: type to filter, arrow to choose and the options you reach for most float to the top on their own.
4
4
 
5
- ## Install
6
-
7
- ```bash
8
- npm install pickem
9
- ```
5
+ ![npm version](https://img.shields.io/npm/v/pickem) ![node](https://img.shields.io/node/v/pickem) ![license](https://img.shields.io/npm/l/pickem)
10
6
 
11
- ## Demo
7
+ - **Search as you type** — filter on labels, descriptions, or any field you name
8
+ - **Usage-aware ordering** — frequently chosen items sort to the top automatically
9
+ - **Single- and multi-select** — with optional free-text entry for ad-hoc values
10
+ - **Wizard flows** — chain prompts with branching and conditional steps
11
+ - **Light and fully typed** — one runtime dependency, ESM, ships with types
12
12
 
13
- An interactive tour of every feature ships with the repo:
13
+ ## Install
14
14
 
15
15
  ```bash
16
- git clone https://github.com/calebogden/pickem
17
- cd pickem && npm install && npm run demo
16
+ npm install pickem
18
17
  ```
19
18
 
20
- ## Quick Start
19
+ ## Quick start
21
20
 
22
21
  ```typescript
23
22
  import { pickem } from 'pickem'
24
23
 
25
24
  const choice = await pickem([
26
25
  { label: 'Deploy', value: 'deploy', description: 'Push to production' },
27
- { label: 'Test', value: 'test', description: 'Run test suite' },
28
- { label: 'Lint', value: 'lint', description: 'Check formatting' },
26
+ { label: 'Test', value: 'test', description: 'Run test suite' },
27
+ { label: 'Lint', value: 'lint', description: 'Check formatting' },
29
28
  ])
30
29
  ```
31
30
 
32
- ## Multi-select (checkbox)
31
+ Type to filter, arrow keys to move, Enter to choose. The selected value is returned.
33
32
 
34
- `pickem.checkbox(items, opts)` returns `string[]` — the values of every checked item.
33
+ ## Multi-select
34
+
35
+ `pickem.checkbox(items, opts)` returns the values of every checked item.
35
36
 
36
37
  ```typescript
37
38
  import { pickem } from 'pickem'
@@ -44,35 +45,37 @@ const choices = await pickem.checkbox([
44
45
  // => ['deploy', 'test']
45
46
  ```
46
47
 
47
- Key bindings: Space toggles a selection, Enter submits, type to filter, Esc clears the filter, Backspace removes filter characters.
48
+ Space toggles a selection, Enter submits, type to filter, Esc clears the filter, Backspace removes filter characters.
48
49
 
49
- Pass `searchable: false` to fall back to the standard `@inquirer/prompts` checkbox (no search bar):
50
+ Pass `searchable: false` to fall back to a plain checkbox list with no search bar:
50
51
 
51
52
  ```typescript
52
53
  const choices = await pickem.checkbox(items, { searchable: false })
53
54
  ```
54
55
 
55
- Pass `{ allowFreeText: true }` to let the user add ad-hoc entries: type text that doesn't match any item, press Enter, and the typed text is appended to the list as a checked item. The filter clears and the prompt stays open so they can keep toggling or add more.
56
+ Pass `allowFreeText: true` to let users add ad-hoc entries: type text that matches nothing, press Enter, and it's appended to the list as a checked item the filter clears and the picker stays open so they can keep going.
56
57
 
57
58
  ```typescript
58
59
  const tags = await pickem.checkbox(KNOWN_TAGS, { allowFreeText: true })
59
60
  ```
60
61
 
61
- ## Usage Tracking
62
+ ## Usage-aware ordering
62
63
 
63
- Items sort by how often they're used. Enable with `track: true`:
64
+ Items sort by how often they've been chosen, so the picker adapts to how each user actually works. Enable it with `track: true`:
64
65
 
65
66
  ```typescript
66
67
  const choice = await pickem(items, {
67
- track: true, // Uses ~/.pickem/usage.json
68
- // or:
68
+ track: true, // stored in ~/.pickem/usage.json
69
+ // or point it somewhere of your own:
69
70
  track: { storePath: '~/.myapp/usage.json' },
70
71
  })
71
72
  ```
72
73
 
73
- 3-tier sort: count desc, lastUsed desc, alphabetical.
74
+ Ordering is a 3-tier sort: usage count, then most-recently-used, then alphabetical.
75
+
76
+ ## Multiple sources
74
77
 
75
- ## Multiple Sources
78
+ Pull items from several places at once — they load in parallel and merge into one picker.
76
79
 
77
80
  ```typescript
78
81
  import { pickem, defineSource } from 'pickem'
@@ -84,45 +87,45 @@ const scripts = defineSource('scripts', async () => [
84
87
 
85
88
  const npm = defineSource('npm', async () => [
86
89
  { label: 'build', value: 'npm run build' },
87
- { label: 'test', value: 'npm test' },
90
+ { label: 'test', value: 'npm test' },
88
91
  ])
89
92
 
90
93
  const choice = await pickem.from([scripts, npm], { track: true })
91
- // Items get group badges when badgeStyle is set: [scripts], [npm]
94
+ // Set badgeStyle to label each item by source, e.g. [scripts], [npm]
92
95
  ```
93
96
 
94
- ## Wizard Flows
97
+ ## Wizard flows
95
98
 
96
- Chain multiple prompts with branching logic:
99
+ Chain multiple prompts together, with branching and conditional steps.
97
100
 
98
101
  ```typescript
99
102
  import { wizard } from 'pickem'
100
103
 
101
104
  const result = await wizard([
102
- { id: 'action', type: 'pick', message: 'What to do?', items: allScripts },
103
- { id: 'env', type: 'select', message: 'Environment:', choices: [
105
+ { id: 'action', type: 'pick', message: 'What to do?', items: allScripts },
106
+ { id: 'env', type: 'select', message: 'Environment:', choices: [
104
107
  { label: 'Production', value: 'prod' },
105
- { label: 'Staging', value: 'staging' },
108
+ { label: 'Staging', value: 'staging' },
106
109
  ], when: ctx => ctx.action === 'deploy' },
107
110
  { id: 'confirm', type: 'confirm', message: 'Are you sure?' },
108
- { id: 'route', type: 'branch', on: ctx => ctx.confirm ? 'done' : 'action' },
111
+ { id: 'route', type: 'branch', on: ctx => ctx.confirm ? 'done' : 'action' },
109
112
  ])
110
113
  ```
111
114
 
112
- ### Step types
113
-
114
- | Type | Purpose |
115
- |------|---------|
116
- | `pick` | Searchable usage-sorted selection |
115
+ | Step type | Purpose |
116
+ |------------|---------|
117
+ | `pick` | Searchable, usage-sorted selection |
117
118
  | `checkbox` | Searchable multi-select, returns an array |
118
- | `select` | Simple choice list |
119
- | `input` | Free text entry |
120
- | `confirm` | Yes/no |
121
- | `branch` | Route to a step ID or inject dynamic steps |
119
+ | `select` | Simple choice list |
120
+ | `input` | Free text entry |
121
+ | `confirm` | Yes / no |
122
+ | `branch` | Route to a step ID or inject steps dynamically |
123
+
124
+ Every step supports `when` (run conditionally) and `before` (a pre-step hook).
122
125
 
123
- Each step supports `when` (conditional) and `before` (pre-step hook).
126
+ ## Standalone usage tracker
124
127
 
125
- ## Standalone Usage Tracker
128
+ The usage tracker works on its own, too — handy for ranking anything by frequency.
126
129
 
127
130
  ```typescript
128
131
  import { UsageTracker } from 'pickem'
@@ -132,26 +135,26 @@ await tracker.track('deploy')
132
135
  await tracker.track('deploy')
133
136
 
134
137
  const sorted = await tracker.sortItems(items)
135
- const top = await tracker.getTop(10)
136
- const stats = await tracker.getStats('deploy') // { count: 2, lastUsed: ... }
138
+ const top = await tracker.getTop(10)
139
+ const stats = await tracker.getStats('deploy') // { count: 2, lastUsed: ... }
137
140
  ```
138
141
 
139
142
  ## Options
140
143
 
141
144
  ```typescript
142
145
  await pickem(items, {
143
- message: 'Pick one:', // Prompt message
144
- pageSize: 15, // Visible items
145
- track: true | TrackOptions, // Enable usage tracking
146
- searchable: true, // Set false to skip the search bar (falls back to select)
147
- searchFields: ['label', 'description'], // Fields to search (dot-notation for meta)
148
- search: (item, term) => boolean, // Custom search function
149
- format: (item, stats) => string, // Custom display formatter
150
- badgeStyle: 'none' | 'bracket' | 'dot' | fn, // Group badge style (default: 'none')
151
- badgeColors: { npm: 'red' }, // Badge color overrides
152
- sort: (a, b) => number, // Tiebreaker after usage sort
153
- onSelect: (item) => {}, // Post-selection callback
154
- allowFreeText: true, // Surface unmatched input as a selectable option
146
+ message: 'Pick one:', // Prompt message
147
+ pageSize: 15, // Visible items per page
148
+ track: true, // Enable usage tracking (true | TrackOptions)
149
+ searchable: true, // false skips the search bar
150
+ searchFields: ['label', 'description'], // Fields to search (dot-notation for nested meta)
151
+ search: (item, term) => boolean, // Custom match function
152
+ format: (item, stats) => string, // Custom row formatter
153
+ badgeStyle: 'none', // Group badge style: 'none' | 'bracket' | 'dot' | fn
154
+ badgeColors: { npm: 'red' }, // Per-group badge colors
155
+ sort: (a, b) => number, // Tiebreaker applied after usage sort
156
+ onSelect: (item) => {}, // Callback fired on selection
157
+ allowFreeText: false, // Surface unmatched input as a selectable option
155
158
  })
156
159
  ```
157
160
 
@@ -160,20 +163,16 @@ await pickem(items, {
160
163
  ```typescript
161
164
  await pickem.checkbox(items, {
162
165
  required: false, // Require at least one selection before Enter submits
163
- defaultChecked: ['test'], // Pre-checked values
164
- allowFreeText: true, // Type unmatched text + Enter to add as a checked item
166
+ defaultChecked: ['test'], // Values checked on open
167
+ allowFreeText: true, // Type unmatched text + Enter to add it as a checked item
165
168
  })
166
169
  ```
167
170
 
168
- ### `badgeStyle` default changed in v0.2.0
169
-
170
- The default `badgeStyle` is now `'none'` — group labels are hidden unless you opt in. This is a breaking change if your code relied on the old default of `'bracket'`. To restore the previous behavior:
171
-
172
- ```typescript
173
- await pickem(items, { badgeStyle: 'bracket' })
174
- ```
175
-
176
171
  ## Requirements
177
172
 
178
- - Node >= 18
173
+ - Node.js >= 18
179
174
  - ESM only
175
+
176
+ ## License
177
+
178
+ MIT
package/checkbox.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"checkbox.d.ts","sourceRoot":"","sources":["../src/checkbox.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAc,MAAM,YAAY,CAAA;AAQvE,wBAAsB,QAAQ,CAAC,CAAC,GAAG,MAAM,EACvC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,EACpB,OAAO,GAAE,eAAe,CAAC,CAAC,CAAM,GAC/B,OAAO,CAAC,CAAC,EAAE,CAAC,CAuEd"}
1
+ {"version":3,"file":"checkbox.d.ts","sourceRoot":"","sources":["../src/checkbox.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAc,MAAM,YAAY,CAAA;AAQvE,wBAAsB,QAAQ,CAAC,CAAC,GAAG,MAAM,EACvC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,EACpB,OAAO,GAAE,eAAe,CAAC,CAAC,CAAM,GAC/B,OAAO,CAAC,CAAC,EAAE,CAAC,CAwEd"}
package/checkbox.js CHANGED
@@ -1,9 +1,9 @@
1
- import { checkbox as standardCheckbox } from '@inquirer/prompts';
1
+ import { checkboxPicker as standardCheckbox } from './prompts/checkbox.js';
2
2
  import { UsageTracker } from './usage/tracker.js';
3
3
  import { createFormatter } from './display/format.js';
4
4
  import { createSearchFn } from './search/search.js';
5
5
  import { resolveTrackOptions } from './internal/track.js';
6
- import { searchableCheckbox } from './prompt/searchable-checkbox.js';
6
+ import { searchableCheckbox } from './prompts/searchable-checkbox.js';
7
7
  export async function checkbox(items, options = {}) {
8
8
  const trackOpts = resolveTrackOptions(options.track);
9
9
  const tracker = trackOpts ? new UsageTracker(trackOpts) : null;
@@ -35,21 +35,22 @@ export async function checkbox(items, options = {}) {
35
35
  const useSearchable = options.searchable !== false;
36
36
  let result;
37
37
  if (useSearchable) {
38
- result = await searchableCheckbox({
38
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
39
+ result = (await searchableCheckbox({
39
40
  message: options.message ?? 'Pick:',
40
41
  items: sorted,
41
42
  pageSize: options.pageSize ?? 15,
42
43
  required: options.required ?? false,
43
- defaultChecked: options.defaultChecked ?? [],
44
+ defaultChecked: (options.defaultChecked ?? []),
44
45
  allowFreeText: options.allowFreeText ?? false,
45
- searchFn,
46
- formatFn,
46
+ searchFn: searchFn,
47
+ formatFn: formatFn,
47
48
  usageStats: tracker ? statsMap : null,
48
- });
49
+ }));
49
50
  }
50
51
  else {
51
52
  const defaultCheckedSet = new Set(options.defaultChecked ?? []);
52
- result = await standardCheckbox({
53
+ result = (await standardCheckbox({
53
54
  message: options.message ?? 'Pick:',
54
55
  pageSize: options.pageSize ?? 15,
55
56
  required: options.required ?? false,
@@ -59,7 +60,7 @@ export async function checkbox(items, options = {}) {
59
60
  checked: defaultCheckedSet.has(item.value),
60
61
  description: undefined, // We handle description in formatFn
61
62
  })),
62
- });
63
+ }));
63
64
  }
64
65
  // Single combined pass — track usage and fire onSelect for each selected item
65
66
  for (const v of result) {
package/checkbox.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"checkbox.js","sourceRoot":"","sources":["../src/checkbox.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"checkbox.js","sourceRoot":"","sources":["../src/checkbox.ts"],"names":[],"mappings":"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"}
package/core/ansi.d.ts ADDED
@@ -0,0 +1,16 @@
1
+ export declare const ansi: {
2
+ readonly cursorUp: (n?: number) => string;
3
+ readonly cursorDown: (n?: number) => string;
4
+ readonly cursorTo: (col: number) => string;
5
+ readonly hideCursor: "\u001B[?25l";
6
+ readonly showCursor: "\u001B[?25h";
7
+ readonly eraseLine: "\u001B[2K";
8
+ readonly eraseDown: "\u001B[0J";
9
+ readonly eraseScreen: "\u001B[2J";
10
+ readonly beginSync: "\u001B[?2026h";
11
+ readonly endSync: "\u001B[?2026l";
12
+ readonly enterAltScreen: "\u001B[?1049h";
13
+ readonly exitAltScreen: "\u001B[?1049l";
14
+ readonly link: (url: string, text: string) => string;
15
+ };
16
+ //# sourceMappingURL=ansi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ansi.d.ts","sourceRoot":"","sources":["../../src/core/ansi.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,IAAI;;;6BAGC,MAAM;;;;;;;;;;yBAYV,MAAM,QAAQ,MAAM;CACxB,CAAA"}
package/core/ansi.js ADDED
@@ -0,0 +1,21 @@
1
+ // src/core/ansi.ts
2
+ const ESC = '\x1b';
3
+ const CSI = `${ESC}[`;
4
+ export const ansi = {
5
+ cursorUp: (n = 1) => `${CSI}${n}A`,
6
+ cursorDown: (n = 1) => `${CSI}${n}B`,
7
+ cursorTo: (col) => `${CSI}${col + 1}G`, // 0-based → 1-based column
8
+ hideCursor: `${CSI}?25l`,
9
+ showCursor: `${CSI}?25h`,
10
+ eraseLine: `${CSI}2K`,
11
+ eraseDown: `${CSI}0J`,
12
+ eraseScreen: `${CSI}2J`,
13
+ // DEC private mode 2026 — atomic frame repaint (anti-flicker); ignored if unsupported
14
+ beginSync: `${CSI}?2026h`,
15
+ endSync: `${CSI}?2026l`,
16
+ enterAltScreen: `${CSI}?1049h`,
17
+ exitAltScreen: `${CSI}?1049l`,
18
+ // OSC-8 hyperlink — degrades to plain text on unsupporting terminals
19
+ link: (url, text) => `${ESC}]8;;${url}\x07${text}${ESC}]8;;\x07`,
20
+ };
21
+ //# sourceMappingURL=ansi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ansi.js","sourceRoot":"","sources":["../../src/core/ansi.ts"],"names":[],"mappings":"AAAA,mBAAmB;AACnB,MAAM,GAAG,GAAG,MAAM,CAAA;AAClB,MAAM,GAAG,GAAG,GAAG,GAAG,GAAG,CAAA;AAErB,MAAM,CAAC,MAAM,IAAI,GAAG;IAClB,QAAQ,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG;IAClC,UAAU,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG;IACpC,QAAQ,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,EAAE,2BAA2B;IAC3E,UAAU,EAAE,GAAG,GAAG,MAAM;IACxB,UAAU,EAAE,GAAG,GAAG,MAAM;IACxB,SAAS,EAAE,GAAG,GAAG,IAAI;IACrB,SAAS,EAAE,GAAG,GAAG,IAAI;IACrB,WAAW,EAAE,GAAG,GAAG,IAAI;IACvB,sFAAsF;IACtF,SAAS,EAAE,GAAG,GAAG,QAAQ;IACzB,OAAO,EAAE,GAAG,GAAG,QAAQ;IACvB,cAAc,EAAE,GAAG,GAAG,QAAQ;IAC9B,aAAa,EAAE,GAAG,GAAG,QAAQ;IAC7B,qEAAqE;IACrE,IAAI,EAAE,CAAC,GAAW,EAAE,IAAY,EAAE,EAAE,CAAC,GAAG,GAAG,OAAO,GAAG,OAAO,IAAI,GAAG,GAAG,UAAU;CACxE,CAAA"}
@@ -0,0 +1,37 @@
1
+ import type { Colors } from './colors.js';
2
+ import type { Symbols } from './symbols.js';
3
+ export interface ChromeDeps {
4
+ colors: Colors;
5
+ symbols: Symbols;
6
+ }
7
+ export interface RowArgs {
8
+ label: string;
9
+ meta?: string[];
10
+ active?: boolean;
11
+ glyph?: string;
12
+ state?: string;
13
+ maxWidth?: number;
14
+ }
15
+ export interface SearchBoxArgs {
16
+ value: string;
17
+ placeholder?: string;
18
+ focused?: boolean;
19
+ width?: number;
20
+ }
21
+ export interface FooterArgs {
22
+ moreAbove?: number;
23
+ moreBelow?: number;
24
+ summary?: string;
25
+ }
26
+ export declare function makeChrome({ colors, symbols }: ChromeDeps): {
27
+ /** Accent+bold title, then a dim "·"-joined hint line. */
28
+ header(title: string, hints?: string[]): string;
29
+ /** Rounded boxed search input (searchable pickers only). */
30
+ searchBox({ value, placeholder, focused, width }: SearchBoxArgs): string;
31
+ /** One columnar list row: pointer [glyph] [state] name · dim-meta. */
32
+ row({ label, meta, active, glyph, state, maxWidth }: RowArgs): string;
33
+ /** Dim pagination/summary footer. */
34
+ footer({ moreAbove, moreBelow, summary }: FooterArgs): string;
35
+ };
36
+ export type Chrome = ReturnType<typeof makeChrome>;
37
+ //# sourceMappingURL=chrome.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chrome.d.ts","sourceRoot":"","sources":["../../src/core/chrome.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAG3C,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAOD,wBAAgB,UAAU,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,UAAU;IAKtD,0DAA0D;kBAC5C,MAAM,UAAS,MAAM,EAAE,GAAQ,MAAM;IAMnD,4DAA4D;sDACO,aAAa,GAAG,MAAM;IAYzF,sEAAsE;yDACW,OAAO,GAAG,MAAM;IASjG,qCAAqC;8CACkB,UAAU,GAAG,MAAM;EAQ7E;AAED,MAAM,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAA"}
package/core/chrome.js ADDED
@@ -0,0 +1,51 @@
1
+ import { displayWidth, truncateToWidth } from './width.js';
2
+ function padToWidth(str, width) {
3
+ const w = displayWidth(str);
4
+ return w >= width ? str : str + ' '.repeat(width - w);
5
+ }
6
+ export function makeChrome({ colors, symbols }) {
7
+ const dot = colors.dim(' · ');
8
+ const accent = colors.accent;
9
+ return {
10
+ /** Accent+bold title, then a dim "·"-joined hint line. */
11
+ header(title, hints = []) {
12
+ const head = colors.bold(accent(title));
13
+ if (hints.length === 0)
14
+ return head;
15
+ return `${head}\n${colors.dim(hints.join(' · '))}`;
16
+ },
17
+ /** Rounded boxed search input (searchable pickers only). */
18
+ searchBox({ value, placeholder = '', focused = true, width = 40 }) {
19
+ const w = Math.max(20, Math.min(width, 60));
20
+ const cursor = focused ? colors.inverse(' ') : '';
21
+ const text = value.length ? value + cursor : colors.dim(placeholder) + cursor;
22
+ const content = `${colors.dim(symbols.search)} ${text}`;
23
+ const inner = padToWidth(content, w);
24
+ const top = colors.dim(symbols.cornerTL + symbols.line.repeat(w + 1) + symbols.cornerTR);
25
+ const mid = `${colors.dim(symbols.boxV)} ${inner}${colors.dim(symbols.boxV)}`;
26
+ const bot = colors.dim(symbols.cornerBL + symbols.line.repeat(w + 1) + symbols.cornerBR);
27
+ return `${top}\n${mid}\n${bot}`;
28
+ },
29
+ /** One columnar list row: pointer [glyph] [state] name · dim-meta. */
30
+ row({ label, meta = [], active = false, glyph = '', state = '', maxWidth = 80 }) {
31
+ const pointer = active ? accent(symbols.pointer) : ' ';
32
+ const g = glyph ? `${glyph} ` : '';
33
+ const s = state ? `${colors.dim(state)} ` : '';
34
+ const name = active ? accent(truncateToWidth(label, maxWidth)) : truncateToWidth(label, maxWidth);
35
+ const m = meta.length ? dot + colors.dim(meta.join(' · ')) : '';
36
+ return `${pointer} ${g}${s}${name}${m}`;
37
+ },
38
+ /** Dim pagination/summary footer. */
39
+ footer({ moreAbove = 0, moreBelow = 0, summary = '' }) {
40
+ const bits = [];
41
+ if (moreAbove)
42
+ bits.push(colors.dim(`${symbols.moreAbove} ${moreAbove} more above`));
43
+ if (moreBelow)
44
+ bits.push(colors.dim(`${symbols.moreBelow} ${moreBelow} more below`));
45
+ if (summary)
46
+ bits.push(colors.dim(summary));
47
+ return bits.join(' ');
48
+ },
49
+ };
50
+ }
51
+ //# sourceMappingURL=chrome.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chrome.js","sourceRoot":"","sources":["../../src/core/chrome.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ type Handler = () => void;
2
+ /** Register a terminal-restore handler that runs on any process exit path. */
3
+ export declare function onExit(fn: Handler): () => void;
4
+ export {};
5
+ //# sourceMappingURL=cleanup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cleanup.d.ts","sourceRoot":"","sources":["../../src/core/cleanup.ts"],"names":[],"mappings":"AAAA,KAAK,OAAO,GAAG,MAAM,IAAI,CAAA;AA0BzB,8EAA8E;AAC9E,wBAAgB,MAAM,CAAC,EAAE,EAAE,OAAO,GAAG,MAAM,IAAI,CAI9C"}
@@ -0,0 +1,31 @@
1
+ const handlers = new Set();
2
+ let installed = false;
3
+ function fireAll() {
4
+ for (const h of [...handlers]) {
5
+ try {
6
+ h();
7
+ }
8
+ catch {
9
+ /* never throw during teardown */
10
+ }
11
+ }
12
+ }
13
+ function install() {
14
+ if (installed)
15
+ return;
16
+ installed = true;
17
+ process.once('exit', fireAll);
18
+ for (const sig of ['SIGINT', 'SIGTERM', 'SIGHUP']) {
19
+ process.once(sig, () => {
20
+ fireAll();
21
+ process.exit(sig === 'SIGINT' ? 130 : 1);
22
+ });
23
+ }
24
+ }
25
+ /** Register a terminal-restore handler that runs on any process exit path. */
26
+ export function onExit(fn) {
27
+ install();
28
+ handlers.add(fn);
29
+ return () => handlers.delete(fn);
30
+ }
31
+ //# sourceMappingURL=cleanup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cleanup.js","sourceRoot":"","sources":["../../src/core/cleanup.ts"],"names":[],"mappings":"AACA,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAW,CAAA;AACnC,IAAI,SAAS,GAAG,KAAK,CAAA;AAErB,SAAS,OAAO;IACd,KAAK,MAAM,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC;QAC9B,IAAI,CAAC;YACH,CAAC,EAAE,CAAA;QACL,CAAC;QAAC,MAAM,CAAC;YACP,iCAAiC;QACnC,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,OAAO;IACd,IAAI,SAAS;QAAE,OAAM;IACrB,SAAS,GAAG,IAAI,CAAA;IAChB,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC7B,KAAK,MAAM,GAAG,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAU,EAAE,CAAC;QAC3D,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE;YACrB,OAAO,EAAE,CAAA;YACT,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QAC1C,CAAC,CAAC,CAAA;IACJ,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,MAAM,CAAC,EAAW;IAChC,OAAO,EAAE,CAAA;IACT,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IAChB,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;AAClC,CAAC"}
@@ -0,0 +1,24 @@
1
+ export interface ColorOptions {
2
+ level?: 0 | 1 | 2 | 3;
3
+ env?: NodeJS.ProcessEnv;
4
+ isTTY?: boolean;
5
+ }
6
+ export declare function detectLevel(env: NodeJS.ProcessEnv, isTTY: boolean): 0 | 1 | 2 | 3;
7
+ export declare function makeColors(opts?: ColorOptions): {
8
+ level: 0 | 1 | 2 | 3;
9
+ bold: (s: string) => string;
10
+ dim: (s: string) => string;
11
+ italic: (s: string) => string;
12
+ underline: (s: string) => string;
13
+ inverse: (s: string) => string;
14
+ cyan: (s: string) => string;
15
+ green: (s: string) => string;
16
+ red: (s: string) => string;
17
+ yellow: (s: string) => string;
18
+ gray: (s: string) => string;
19
+ accent: (s: string) => string;
20
+ rgb: (r: number, g: number, b: number) => (s: string) => string;
21
+ gradient: (from: [number, number, number], to: [number, number, number]) => (s: string) => string;
22
+ };
23
+ export type Colors = ReturnType<typeof makeColors>;
24
+ //# sourceMappingURL=colors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"colors.d.ts","sourceRoot":"","sources":["../../src/core/colors.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;IACvB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,EAAE,KAAK,EAAE,OAAO,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAajF;AAQD,wBAAgB,UAAU,CAAC,IAAI,GAAE,YAAiB;;cAEb,MAAM;aAAN,MAAM;gBAAN,MAAM;mBAAN,MAAM;iBAAN,MAAM;cAAN,MAAM;eAAN,MAAM;aAAN,MAAM;gBAAN,MAAM;cAAN,MAAM;gBACY,MAAM;aAA3C,MAAM,KAAK,MAAM,KAAK,MAAM,MAAM,GAAG,MAAM;qBAMnC,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,GAAG,MAAM;EA6B9F;AAED,MAAM,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAA"}