pickem 0.1.0 → 1.0.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/CHANGELOG.md +89 -0
- package/README.md +64 -3
- package/checkbox.d.ts +3 -0
- package/checkbox.d.ts.map +1 -0
- package/checkbox.js +77 -0
- package/checkbox.js.map +1 -0
- package/core/ansi.d.ts +16 -0
- package/core/ansi.d.ts.map +1 -0
- package/core/ansi.js +21 -0
- package/core/ansi.js.map +1 -0
- package/core/chrome.d.ts +37 -0
- package/core/chrome.d.ts.map +1 -0
- package/core/chrome.js +51 -0
- package/core/chrome.js.map +1 -0
- package/core/cleanup.d.ts +5 -0
- package/core/cleanup.d.ts.map +1 -0
- package/core/cleanup.js +31 -0
- package/core/cleanup.js.map +1 -0
- package/core/colors.d.ts +24 -0
- package/core/colors.d.ts.map +1 -0
- package/core/colors.js +67 -0
- package/core/colors.js.map +1 -0
- package/core/hooks.d.ts +26 -0
- package/core/hooks.d.ts.map +1 -0
- package/core/hooks.js +80 -0
- package/core/hooks.js.map +1 -0
- package/core/index.d.ts +9 -0
- package/core/index.d.ts.map +1 -0
- package/core/index.js +9 -0
- package/core/index.js.map +1 -0
- package/core/key-reader.d.ts +6 -0
- package/core/key-reader.d.ts.map +1 -0
- package/core/key-reader.js +29 -0
- package/core/key-reader.js.map +1 -0
- package/core/keys.d.ts +17 -0
- package/core/keys.d.ts.map +1 -0
- package/core/keys.js +17 -0
- package/core/keys.js.map +1 -0
- package/core/pagination.d.ts +14 -0
- package/core/pagination.d.ts.map +1 -0
- package/core/pagination.js +36 -0
- package/core/pagination.js.map +1 -0
- package/core/runtime.d.ts +20 -0
- package/core/runtime.d.ts.map +1 -0
- package/core/runtime.js +74 -0
- package/core/runtime.js.map +1 -0
- package/core/screen.d.ts +14 -0
- package/core/screen.d.ts.map +1 -0
- package/core/screen.js +50 -0
- package/core/screen.js.map +1 -0
- package/core/status-glyph.d.ts +10 -0
- package/core/status-glyph.d.ts.map +1 -0
- package/core/status-glyph.js +18 -0
- package/core/status-glyph.js.map +1 -0
- package/core/symbols.d.ts +27 -0
- package/core/symbols.d.ts.map +1 -0
- package/core/symbols.js +41 -0
- package/core/symbols.js.map +1 -0
- package/core/testing.d.ts +15 -0
- package/core/testing.d.ts.map +1 -0
- package/core/testing.js +47 -0
- package/core/testing.js.map +1 -0
- package/core/theme.d.ts +14 -0
- package/core/theme.d.ts.map +1 -0
- package/core/theme.js +10 -0
- package/core/theme.js.map +1 -0
- package/core/width.d.ts +7 -0
- package/core/width.d.ts.map +1 -0
- package/core/width.js +46 -0
- package/core/width.js.map +1 -0
- package/display/format.d.ts +1 -3
- package/display/format.d.ts.map +1 -1
- package/display/format.js +4 -1
- package/display/format.js.map +1 -1
- package/index.d.ts +1 -1
- package/index.d.ts.map +1 -1
- package/internal/track.d.ts +3 -0
- package/internal/track.d.ts.map +1 -0
- package/internal/track.js +8 -0
- package/internal/track.js.map +1 -0
- package/package.json +17 -4
- package/pickem.d.ts +2 -0
- package/pickem.d.ts.map +1 -1
- package/pickem.js +37 -32
- package/pickem.js.map +1 -1
- package/prompts/checkbox.d.ts +14 -0
- package/prompts/checkbox.d.ts.map +1 -0
- package/prompts/checkbox.js +56 -0
- package/prompts/checkbox.js.map +1 -0
- package/prompts/confirm.d.ts +6 -0
- package/prompts/confirm.d.ts.map +1 -0
- package/prompts/confirm.js +32 -0
- package/prompts/confirm.js.map +1 -0
- package/prompts/input.d.ts +7 -0
- package/prompts/input.d.ts.map +1 -0
- package/prompts/input.js +52 -0
- package/prompts/input.js.map +1 -0
- package/prompts/search.d.ts +12 -0
- package/prompts/search.d.ts.map +1 -0
- package/prompts/search.js +67 -0
- package/prompts/search.js.map +1 -0
- package/prompts/searchable-checkbox.d.ts +14 -0
- package/prompts/searchable-checkbox.d.ts.map +1 -0
- package/prompts/searchable-checkbox.js +150 -0
- package/prompts/searchable-checkbox.js.map +1 -0
- package/prompts/select.d.ts +12 -0
- package/prompts/select.d.ts.map +1 -0
- package/prompts/select.js +40 -0
- package/prompts/select.js.map +1 -0
- package/types.d.ts +25 -2
- package/types.d.ts.map +1 -1
- package/wizard.d.ts.map +1 -1
- package/wizard.js +17 -5
- package/wizard.js.map +1 -1
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to pickem will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
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
|
+
|
|
48
|
+
## [0.2.0] — 2026-05-09
|
|
49
|
+
|
|
50
|
+
### Added
|
|
51
|
+
|
|
52
|
+
- `pickem.checkbox(items, opts) → Promise<V[]>` — multi-select with built-in
|
|
53
|
+
filter-as-you-type. Built on `@inquirer/core`. Space toggles, Enter submits,
|
|
54
|
+
Backspace removes filter chars, Esc clears the filter. Pinned items respect
|
|
55
|
+
the filter (stay pinned within filtered set). Checked items remain in the
|
|
56
|
+
result even if the filter hides them. Result is in source order, matching
|
|
57
|
+
`@inquirer/prompts/checkbox` semantics.
|
|
58
|
+
- `searchable?: boolean` option on both `pickem()` and `pickem.checkbox()`.
|
|
59
|
+
Default `true`. When `false`, falls back to the non-search prompts
|
|
60
|
+
(`@inquirer/prompts/select` and `/checkbox` respectively).
|
|
61
|
+
- `'checkbox'` step type for `wizard()`. `ctx[step.id]` receives `string[]`.
|
|
62
|
+
- `allowFreeText?: boolean` on `pickem.checkbox()`. When `true`, typing text
|
|
63
|
+
that matches nothing and pressing Enter appends the typed text to the list
|
|
64
|
+
as a checked item; the filter clears and the prompt stays open.
|
|
65
|
+
- `npm run demo` — interactive tour of every feature using `tsx`.
|
|
66
|
+
Uses `MemoryStorage` so demo runs don't pollute `~/.pickem/usage.json`.
|
|
67
|
+
- New direct dep: `@inquirer/core ^10.3.2` (was already pulled transitively
|
|
68
|
+
by `@inquirer/prompts`).
|
|
69
|
+
- New devDeps: `@inquirer/testing ^3.3.5` (custom prompt smoke-tests),
|
|
70
|
+
`tsx ^4.21.0` (demo runner).
|
|
71
|
+
- Public type exports: `CheckboxOptions`, `CheckboxStep`.
|
|
72
|
+
|
|
73
|
+
### Changed
|
|
74
|
+
|
|
75
|
+
- **BREAKING**: default `badgeStyle` changed from `'bracket'` to `'none'`.
|
|
76
|
+
Items with a `group` no longer render `[group]` badges by default. Pass
|
|
77
|
+
`{ badgeStyle: 'bracket' }` or `{ badgeStyle: 'dot' }` to opt back in.
|
|
78
|
+
- `searchableCheckbox` toggle glyphs upgraded from `[ ]`/`[x]` to filled
|
|
79
|
+
circles (`○`/`●`, green when checked) with a cyan `❯` cursor. Matches
|
|
80
|
+
the Apple/iOS and `@inquirer/prompts` default visual style.
|
|
81
|
+
- `pickem()` single-select stats lookup no longer reaches into the tracker's
|
|
82
|
+
private `cache` field — uses the public `getStats()` method instead.
|
|
83
|
+
Fixes a latent issue when the tracker hadn't been loaded yet.
|
|
84
|
+
- `BadgeStyle` union now includes `'none'`.
|
|
85
|
+
|
|
86
|
+
### Internal
|
|
87
|
+
|
|
88
|
+
- Extracted `resolveTrackOptions` to `src/internal/track.ts` (shared between
|
|
89
|
+
`pickem.ts` and `checkbox.ts`).
|
package/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# pickem
|
|
2
2
|
|
|
3
|
-
Usage-sorted searchable autocomplete for CLI tools. One dependency
|
|
3
|
+
Usage-sorted searchable autocomplete for CLI tools. One near-zero-dependency module that gives every CLI the same interactive picker pattern: discover items, sort by usage, search, select, track.
|
|
4
|
+
|
|
5
|
+
pickem runs on its **own native picker engine** — no `@inquirer`, no prompt-library dependency. The only runtime dependency is [`string-width`](https://github.com/sindresorhus/string-width) (for correct CJK/emoji column width). The look is a Claude Code `/skills`-style selector: an accent title, a dim hint line, a rounded search box, columnar rows with a `❯` chevron on the active item, and a `↓ N more below` footer — truecolor with graceful 256/ASCII fallbacks. See [`docs/standards/selector-ui.md`](docs/standards/selector-ui.md) and [`docs/architecture/picker-engine.md`](docs/architecture/picker-engine.md).
|
|
4
6
|
|
|
5
7
|
## Install
|
|
6
8
|
|
|
@@ -8,6 +10,15 @@ Usage-sorted searchable autocomplete for CLI tools. One dependency-light module
|
|
|
8
10
|
npm install pickem
|
|
9
11
|
```
|
|
10
12
|
|
|
13
|
+
## Demo
|
|
14
|
+
|
|
15
|
+
An interactive tour of every feature ships with the repo:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
git clone https://github.com/calebogden/pickem
|
|
19
|
+
cd pickem && npm install && npm run demo
|
|
20
|
+
```
|
|
21
|
+
|
|
11
22
|
## Quick Start
|
|
12
23
|
|
|
13
24
|
```typescript
|
|
@@ -20,6 +31,35 @@ const choice = await pickem([
|
|
|
20
31
|
])
|
|
21
32
|
```
|
|
22
33
|
|
|
34
|
+
## Multi-select (checkbox)
|
|
35
|
+
|
|
36
|
+
`pickem.checkbox(items, opts)` returns `string[]` — the values of every checked item.
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
import { pickem } from 'pickem'
|
|
40
|
+
|
|
41
|
+
const choices = await pickem.checkbox([
|
|
42
|
+
{ label: 'Deploy', value: 'deploy' },
|
|
43
|
+
{ label: 'Test', value: 'test' },
|
|
44
|
+
{ label: 'Lint', value: 'lint' },
|
|
45
|
+
], { message: 'Which steps?', defaultChecked: ['test'] })
|
|
46
|
+
// => ['deploy', 'test']
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Key bindings: Space toggles a selection, Enter submits, type to filter, Esc clears the filter, Backspace removes filter characters.
|
|
50
|
+
|
|
51
|
+
Pass `searchable: false` to fall back to the plain native checkbox picker (no search bar):
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
const choices = await pickem.checkbox(items, { searchable: false })
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
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.
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
const tags = await pickem.checkbox(KNOWN_TAGS, { allowFreeText: true })
|
|
61
|
+
```
|
|
62
|
+
|
|
23
63
|
## Usage Tracking
|
|
24
64
|
|
|
25
65
|
Items sort by how often they're used. Enable with `track: true`:
|
|
@@ -50,7 +90,7 @@ const npm = defineSource('npm', async () => [
|
|
|
50
90
|
])
|
|
51
91
|
|
|
52
92
|
const choice = await pickem.from([scripts, npm], { track: true })
|
|
53
|
-
// Items get group badges: [scripts], [npm]
|
|
93
|
+
// Items get group badges when badgeStyle is set: [scripts], [npm]
|
|
54
94
|
```
|
|
55
95
|
|
|
56
96
|
## Wizard Flows
|
|
@@ -76,6 +116,7 @@ const result = await wizard([
|
|
|
76
116
|
| Type | Purpose |
|
|
77
117
|
|------|---------|
|
|
78
118
|
| `pick` | Searchable usage-sorted selection |
|
|
119
|
+
| `checkbox` | Searchable multi-select, returns an array |
|
|
79
120
|
| `select` | Simple choice list |
|
|
80
121
|
| `input` | Free text entry |
|
|
81
122
|
| `confirm` | Yes/no |
|
|
@@ -104,16 +145,36 @@ await pickem(items, {
|
|
|
104
145
|
message: 'Pick one:', // Prompt message
|
|
105
146
|
pageSize: 15, // Visible items
|
|
106
147
|
track: true | TrackOptions, // Enable usage tracking
|
|
148
|
+
searchable: true, // Set false to skip the search bar (falls back to select)
|
|
107
149
|
searchFields: ['label', 'description'], // Fields to search (dot-notation for meta)
|
|
108
150
|
search: (item, term) => boolean, // Custom search function
|
|
109
151
|
format: (item, stats) => string, // Custom display formatter
|
|
110
|
-
badgeStyle: 'bracket' | 'dot' | fn,
|
|
152
|
+
badgeStyle: 'none' | 'bracket' | 'dot' | fn, // Group badge style (default: 'none')
|
|
111
153
|
badgeColors: { npm: 'red' }, // Badge color overrides
|
|
112
154
|
sort: (a, b) => number, // Tiebreaker after usage sort
|
|
113
155
|
onSelect: (item) => {}, // Post-selection callback
|
|
156
|
+
allowFreeText: true, // Surface unmatched input as a selectable option
|
|
157
|
+
})
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
`pickem.checkbox` accepts the same options, plus:
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
await pickem.checkbox(items, {
|
|
164
|
+
required: false, // Require at least one selection before Enter submits
|
|
165
|
+
defaultChecked: ['test'], // Pre-checked values
|
|
166
|
+
allowFreeText: true, // Type unmatched text + Enter to add as a checked item
|
|
114
167
|
})
|
|
115
168
|
```
|
|
116
169
|
|
|
170
|
+
### `badgeStyle` default changed in v0.2.0
|
|
171
|
+
|
|
172
|
+
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:
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
await pickem(items, { badgeStyle: 'bracket' })
|
|
176
|
+
```
|
|
177
|
+
|
|
117
178
|
## Requirements
|
|
118
179
|
|
|
119
180
|
- Node >= 18
|
package/checkbox.d.ts
ADDED
|
@@ -0,0 +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,CAwEd"}
|
package/checkbox.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { checkboxPicker as standardCheckbox } from './prompts/checkbox.js';
|
|
2
|
+
import { UsageTracker } from './usage/tracker.js';
|
|
3
|
+
import { createFormatter } from './display/format.js';
|
|
4
|
+
import { createSearchFn } from './search/search.js';
|
|
5
|
+
import { resolveTrackOptions } from './internal/track.js';
|
|
6
|
+
import { searchableCheckbox } from './prompts/searchable-checkbox.js';
|
|
7
|
+
export async function checkbox(items, options = {}) {
|
|
8
|
+
const trackOpts = resolveTrackOptions(options.track);
|
|
9
|
+
const tracker = trackOpts ? new UsageTracker(trackOpts) : null;
|
|
10
|
+
const keyFn = trackOpts?.key ?? ((item) => item.label);
|
|
11
|
+
let sorted;
|
|
12
|
+
if (tracker) {
|
|
13
|
+
sorted = await tracker.sortItems(items, keyFn, options.sort);
|
|
14
|
+
}
|
|
15
|
+
else if (options.sort) {
|
|
16
|
+
sorted = [...items].sort(options.sort);
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
sorted = items;
|
|
20
|
+
}
|
|
21
|
+
const formatFn = options.format ??
|
|
22
|
+
createFormatter({
|
|
23
|
+
badgeStyle: options.badgeStyle,
|
|
24
|
+
badgeColors: options.badgeColors,
|
|
25
|
+
});
|
|
26
|
+
const searchFn = options.search ?? createSearchFn(options.searchFields);
|
|
27
|
+
const statsMap = new Map();
|
|
28
|
+
if (tracker) {
|
|
29
|
+
for (const item of sorted) {
|
|
30
|
+
statsMap.set(item.value, await tracker.getStats(keyFn(item)));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
// Build a value→item map once for O(n) post-submit lookups
|
|
34
|
+
const valueToItem = new Map(sorted.map((item) => [item.value, item]));
|
|
35
|
+
const useSearchable = options.searchable !== false;
|
|
36
|
+
let result;
|
|
37
|
+
if (useSearchable) {
|
|
38
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
39
|
+
result = (await searchableCheckbox({
|
|
40
|
+
message: options.message ?? 'Pick:',
|
|
41
|
+
items: sorted,
|
|
42
|
+
pageSize: options.pageSize ?? 15,
|
|
43
|
+
required: options.required ?? false,
|
|
44
|
+
defaultChecked: (options.defaultChecked ?? []),
|
|
45
|
+
allowFreeText: options.allowFreeText ?? false,
|
|
46
|
+
searchFn: searchFn,
|
|
47
|
+
formatFn: formatFn,
|
|
48
|
+
usageStats: tracker ? statsMap : null,
|
|
49
|
+
}));
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
const defaultCheckedSet = new Set(options.defaultChecked ?? []);
|
|
53
|
+
result = (await standardCheckbox({
|
|
54
|
+
message: options.message ?? 'Pick:',
|
|
55
|
+
pageSize: options.pageSize ?? 15,
|
|
56
|
+
required: options.required ?? false,
|
|
57
|
+
choices: sorted.map((item) => ({
|
|
58
|
+
name: formatFn(item, statsMap.get(item.value) ?? null),
|
|
59
|
+
value: item.value,
|
|
60
|
+
checked: defaultCheckedSet.has(item.value),
|
|
61
|
+
description: undefined, // We handle description in formatFn
|
|
62
|
+
})),
|
|
63
|
+
}));
|
|
64
|
+
}
|
|
65
|
+
// Single combined pass — track usage and fire onSelect for each selected item
|
|
66
|
+
for (const v of result) {
|
|
67
|
+
const item = valueToItem.get(v);
|
|
68
|
+
if (!item)
|
|
69
|
+
continue;
|
|
70
|
+
if (tracker)
|
|
71
|
+
await tracker.track(keyFn(item), trackOpts?.source);
|
|
72
|
+
if (options.onSelect)
|
|
73
|
+
await options.onSelect(item);
|
|
74
|
+
}
|
|
75
|
+
return result;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=checkbox.js.map
|
package/checkbox.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
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
|
package/core/ansi.js.map
ADDED
|
@@ -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"}
|
package/core/chrome.d.ts
ADDED
|
@@ -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 @@
|
|
|
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"}
|
package/core/cleanup.js
ADDED
|
@@ -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"}
|
package/core/colors.d.ts
ADDED
|
@@ -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"}
|
package/core/colors.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
export function detectLevel(env, isTTY) {
|
|
2
|
+
if ('NO_COLOR' in env && env.NO_COLOR !== '')
|
|
3
|
+
return 0;
|
|
4
|
+
if (env.FORCE_COLOR != null) {
|
|
5
|
+
const n = Number(env.FORCE_COLOR);
|
|
6
|
+
return (Number.isNaN(n) ? 1 : Math.max(0, Math.min(3, n)));
|
|
7
|
+
}
|
|
8
|
+
if (!isTTY)
|
|
9
|
+
return 0;
|
|
10
|
+
const ct = env.COLORTERM ?? '';
|
|
11
|
+
if (ct === 'truecolor' || ct === '24bit')
|
|
12
|
+
return 3;
|
|
13
|
+
const term = env.TERM ?? '';
|
|
14
|
+
if (/-256(color)?$/.test(term))
|
|
15
|
+
return 2;
|
|
16
|
+
if (term && term !== 'dumb')
|
|
17
|
+
return 1;
|
|
18
|
+
return 0;
|
|
19
|
+
}
|
|
20
|
+
// Map an 8-bit RGB triple to the closest xterm-256 cube index.
|
|
21
|
+
function rgbTo256(r, g, b) {
|
|
22
|
+
const q = (v) => (v < 48 ? 0 : v < 115 ? 1 : Math.round((v - 35) / 40));
|
|
23
|
+
return 16 + 36 * q(r) + 6 * q(g) + q(b);
|
|
24
|
+
}
|
|
25
|
+
export function makeColors(opts = {}) {
|
|
26
|
+
const level = opts.level ?? detectLevel(opts.env ?? process.env, opts.isTTY ?? !!process.stdout.isTTY);
|
|
27
|
+
const wrap = (open) => (s) => (level === 0 ? s : `\x1b[${open}m${s}\x1b[0m`);
|
|
28
|
+
const rgb = (r, g, b) => (s) => {
|
|
29
|
+
if (level === 0)
|
|
30
|
+
return s;
|
|
31
|
+
if (level >= 3)
|
|
32
|
+
return `\x1b[38;2;${r};${g};${b}m${s}\x1b[0m`;
|
|
33
|
+
return `\x1b[38;5;${rgbTo256(r, g, b)}m${s}\x1b[0m`;
|
|
34
|
+
};
|
|
35
|
+
// Per-character truecolor interpolation (the Vite/Astro banner look).
|
|
36
|
+
const gradient = (from, to) => (s) => {
|
|
37
|
+
if (level === 0)
|
|
38
|
+
return s;
|
|
39
|
+
const chars = [...s];
|
|
40
|
+
return chars
|
|
41
|
+
.map((ch, i) => {
|
|
42
|
+
const t = chars.length <= 1 ? 0 : i / (chars.length - 1);
|
|
43
|
+
const c = [0, 1, 2].map((k) => Math.round(from[k] + (to[k] - from[k]) * t));
|
|
44
|
+
return rgb(c[0], c[1], c[2])(ch);
|
|
45
|
+
})
|
|
46
|
+
.join('');
|
|
47
|
+
};
|
|
48
|
+
return {
|
|
49
|
+
level,
|
|
50
|
+
bold: wrap('1'),
|
|
51
|
+
dim: wrap('2'),
|
|
52
|
+
italic: wrap('3'),
|
|
53
|
+
underline: wrap('4'),
|
|
54
|
+
inverse: wrap('7'),
|
|
55
|
+
cyan: wrap('36'),
|
|
56
|
+
green: wrap('32'),
|
|
57
|
+
red: wrap('31'),
|
|
58
|
+
yellow: wrap('33'),
|
|
59
|
+
gray: wrap('90'),
|
|
60
|
+
// pickem accent — lavender/violet (selector UI, see docs/standards/selector-ui.md).
|
|
61
|
+
// truecolor → 256 fallback is handled by rgb().
|
|
62
|
+
accent: rgb(180, 160, 250),
|
|
63
|
+
rgb,
|
|
64
|
+
gradient,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=colors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"colors.js","sourceRoot":"","sources":["../../src/core/colors.ts"],"names":[],"mappings":"AAOA,MAAM,UAAU,WAAW,CAAC,GAAsB,EAAE,KAAc;IAChE,IAAI,UAAU,IAAI,GAAG,IAAI,GAAG,CAAC,QAAQ,KAAK,EAAE;QAAE,OAAO,CAAC,CAAA;IACtD,IAAI,GAAG,CAAC,WAAW,IAAI,IAAI,EAAE,CAAC;QAC5B,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QACjC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAkB,CAAA;IAC7E,CAAC;IACD,IAAI,CAAC,KAAK;QAAE,OAAO,CAAC,CAAA;IACpB,MAAM,EAAE,GAAG,GAAG,CAAC,SAAS,IAAI,EAAE,CAAA;IAC9B,IAAI,EAAE,KAAK,WAAW,IAAI,EAAE,KAAK,OAAO;QAAE,OAAO,CAAC,CAAA;IAClD,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,IAAI,EAAE,CAAA;IAC3B,IAAI,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,CAAC,CAAA;IACxC,IAAI,IAAI,IAAI,IAAI,KAAK,MAAM;QAAE,OAAO,CAAC,CAAA;IACrC,OAAO,CAAC,CAAA;AACV,CAAC;AAED,+DAA+D;AAC/D,SAAS,QAAQ,CAAC,CAAS,EAAE,CAAS,EAAE,CAAS;IAC/C,MAAM,CAAC,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA;IAC/E,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;AACzC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,OAAqB,EAAE;IAChD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,WAAW,CAAC,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IACtG,MAAM,IAAI,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,IAAI,IAAI,CAAC,SAAS,CAAC,CAAA;IAC5F,MAAM,GAAG,GAAG,CAAC,CAAS,EAAE,CAAS,EAAE,CAAS,EAAE,EAAE,CAAC,CAAC,CAAS,EAAE,EAAE;QAC7D,IAAI,KAAK,KAAK,CAAC;YAAE,OAAO,CAAC,CAAA;QACzB,IAAI,KAAK,IAAI,CAAC;YAAE,OAAO,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAA;QAC7D,OAAO,aAAa,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,SAAS,CAAA;IACrD,CAAC,CAAA;IACD,sEAAsE;IACtE,MAAM,QAAQ,GAAG,CAAC,IAA8B,EAAE,EAA4B,EAAE,EAAE,CAAC,CAAC,CAAS,EAAE,EAAE;QAC/F,IAAI,KAAK,KAAK,CAAC;YAAE,OAAO,CAAC,CAAA;QACzB,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC,CAAA;QACpB,OAAO,KAAK;aACT,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE;YACb,MAAM,CAAC,GAAG,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;YACxD,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAA6B,CAAA;YACvG,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;QAClC,CAAC,CAAC;aACD,IAAI,CAAC,EAAE,CAAC,CAAA;IACb,CAAC,CAAA;IACD,OAAO;QACL,KAAK;QACL,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC;QACf,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC;QACd,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC;QACjB,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC;QACpB,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC;QAClB,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC;QAChB,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC;QACjB,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC;QACf,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC;QAClB,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC;QAChB,oFAAoF;QACpF,gDAAgD;QAChD,MAAM,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;QAC1B,GAAG;QACH,QAAQ;KACT,CAAA;AACH,CAAC"}
|
package/core/hooks.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { KeyEvent } from './keys.js';
|
|
2
|
+
import type { PickerInput } from './runtime.js';
|
|
3
|
+
interface Slot {
|
|
4
|
+
value?: unknown;
|
|
5
|
+
deps?: unknown[];
|
|
6
|
+
cleanup?: () => void;
|
|
7
|
+
}
|
|
8
|
+
export interface HookStore {
|
|
9
|
+
slots: Slot[];
|
|
10
|
+
cursor: number;
|
|
11
|
+
scheduleRender: () => void;
|
|
12
|
+
keypressHandlers: ((key: KeyEvent, input: PickerInput) => void)[];
|
|
13
|
+
effects: (() => void)[];
|
|
14
|
+
reset(): void;
|
|
15
|
+
}
|
|
16
|
+
export declare function createHookStore(scheduleRender: () => void): HookStore;
|
|
17
|
+
export declare function withHookStore<T>(store: HookStore, fn: () => T): T;
|
|
18
|
+
export declare function useState<T>(initial: T): [T, (next: T) => void];
|
|
19
|
+
export declare function useRef<T>(initial: T): {
|
|
20
|
+
current: T;
|
|
21
|
+
};
|
|
22
|
+
export declare function useMemo<T>(factory: () => T, deps: unknown[]): T;
|
|
23
|
+
export declare function useEffect(effect: () => void | (() => void), deps: unknown[]): void;
|
|
24
|
+
export declare function useKeypress(handler: (key: KeyEvent, input: PickerInput) => void): void;
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/core/hooks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAE/C,UAAU,IAAI;IACZ,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,IAAI,CAAC,EAAE,OAAO,EAAE,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CACrB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,IAAI,EAAE,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,cAAc,EAAE,MAAM,IAAI,CAAA;IAC1B,gBAAgB,EAAE,CAAC,CAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC,EAAE,CAAA;IACjE,OAAO,EAAE,CAAC,MAAM,IAAI,CAAC,EAAE,CAAA;IACvB,KAAK,IAAI,IAAI,CAAA;CACd;AAID,wBAAgB,eAAe,CAAC,cAAc,EAAE,MAAM,IAAI,GAAG,SAAS,CAcrE;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAEjE;AAeD,wBAAgB,QAAQ,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC,CAU9D;AAED,wBAAgB,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG;IAAE,OAAO,EAAE,CAAC,CAAA;CAAE,CAIpD;AAOD,wBAAgB,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,CAO/D;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAWlF;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,KAAK,IAAI,GAAG,IAAI,CAEtF"}
|