diff --git a/packages/core/src/style/Color.ts b/packages/core/src/style/Color.ts index 39dc85e00..4adefbcbd 100644 --- a/packages/core/src/style/Color.ts +++ b/packages/core/src/style/Color.ts @@ -205,7 +205,9 @@ function rgbToAnsi256(r: number, g: number, b: number): number { if (grayIdx > 23) grayIdx = 23; const grayColor = 232 + grayIdx; r_c = ANSI256_RGB[grayColor * 3]; - const distGray = (r - r_c)**2 + (g - r_c)**2 + (b - r_c)**2; + g_c = ANSI256_RGB[grayColor * 3 + 1]; + b_c = ANSI256_RGB[grayColor * 3 + 2]; + const distGray = (r - r_c)**2 + (g - g_c)**2 + (b - b_c)**2; if (distGray < bestDist) { bestDist = distGray; bestColor = grayColor; diff --git a/packages/core/src/utils/throttle.ts b/packages/core/src/utils/throttle.ts index 88b2aff7c..f2198768f 100644 --- a/packages/core/src/utils/throttle.ts +++ b/packages/core/src/utils/throttle.ts @@ -27,14 +27,17 @@ export function throttle void>( const leading = options?.leading ?? true; let timer: ReturnType | undefined; let lastArgs: Parameters | undefined; + let hasNewCalls = false; const throttled = function (...args: Parameters) { lastArgs = args; + if (timer) hasNewCalls = true; if (!timer) { if (leading) func(...args); timer = setTimeout(() => { timer = undefined; - if (lastArgs !== args || !leading) func(...lastArgs!); + if (hasNewCalls || !leading) func(...lastArgs!); + hasNewCalls = false; lastArgs = undefined; }, wait); } diff --git a/packages/store/src/store.ts b/packages/store/src/store.ts index 7b2250fb4..f4dc34b3a 100644 --- a/packages/store/src/store.ts +++ b/packages/store/src/store.ts @@ -73,9 +73,7 @@ export function batch(fn: () => T): T { } catch (err) { threw = true; _batchDepth--; - if (_batchDepth === 0) { - flushBatch(threw); - } + flushBatch(threw); throw err; } diff --git a/packages/ui/src/CheckboxGroup.ts b/packages/ui/src/CheckboxGroup.ts index c63b464a3..1b2d200e8 100644 --- a/packages/ui/src/CheckboxGroup.ts +++ b/packages/ui/src/CheckboxGroup.ts @@ -42,6 +42,7 @@ export class CheckboxGroup extends Widget { (options.defaultValues ?? []).filter(v => knownValues.has(v)), ); this.onChange = options.onChange; + this.events.on('key', this.handleKey.bind(this)); } get selectedValues(): string[] { diff --git a/packages/ui/src/Tree.ts b/packages/ui/src/Tree.ts index a4dd39e55..7a354043e 100644 --- a/packages/ui/src/Tree.ts +++ b/packages/ui/src/Tree.ts @@ -17,6 +17,22 @@ export class Tree extends Widget { this._roots = roots; this._activeColor = options.activeColor ?? { type: 'named', name: 'cyan' }; this._onSelect = options.onSelect; + this.events.on('key', this.handleKey.bind(this)); + } + + private handleKey(event: { key: string }): void { + switch (event.key) { + case 'up': + this.selectPrev(); + break; + case 'down': + this.selectNext(); + break; + case 'enter': + case ' ': + this.confirm(); + break; + } } private _flatten(): { node: TreeNode; depth: number; path: number[]; hasChildren: boolean }[] { @@ -36,6 +52,7 @@ export class Tree extends Widget { selectNext(): void { const f = this._flatten(); if (this._cursorIndex < f.length - 1) { this._cursorIndex++; this.markDirty(); } } selectPrev(): void { if (this._cursorIndex > 0) { this._cursorIndex--; this.markDirty(); } } toggleExpand(): void { const f = this._flatten(); const it = f[this._cursorIndex]; if (it?.hasChildren) { it.node.expanded = !it.node.expanded; this.markDirty(); } } + toggleExpandKey(): void { this.toggleExpand(); } confirm(): void { const f = this._flatten(); const it = f[this._cursorIndex]; if (it) { it.hasChildren ? this.toggleExpand() : this._onSelect?.(it.node, it.path); }