termcast 1.3.46 → 1.3.48
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/apis/cache.d.ts.map +1 -1
- package/dist/apis/cache.js +1 -2
- package/dist/apis/cache.js.map +1 -1
- package/dist/apis/localstorage.d.ts.map +1 -1
- package/dist/apis/localstorage.js +1 -2
- package/dist/apis/localstorage.js.map +1 -1
- package/dist/apis/sqlite.d.ts +7 -0
- package/dist/apis/sqlite.d.ts.map +1 -0
- package/dist/apis/sqlite.js +13 -0
- package/dist/apis/sqlite.js.map +1 -0
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +7 -1
- package/dist/build.js.map +1 -1
- package/dist/compile.js +1 -1
- package/dist/compile.js.map +1 -1
- package/dist/components/actions.d.ts +18 -0
- package/dist/components/actions.d.ts.map +1 -1
- package/dist/components/actions.js +70 -5
- package/dist/components/actions.js.map +1 -1
- package/dist/components/detail.d.ts.map +1 -1
- package/dist/components/detail.js +3 -1
- package/dist/components/detail.js.map +1 -1
- package/dist/components/dropdown.d.ts.map +1 -1
- package/dist/components/dropdown.js +40 -11
- package/dist/components/dropdown.js.map +1 -1
- package/dist/components/form/dropdown.d.ts.map +1 -1
- package/dist/components/form/dropdown.js +26 -10
- package/dist/components/form/dropdown.js.map +1 -1
- package/dist/components/list.d.ts +7 -0
- package/dist/components/list.d.ts.map +1 -1
- package/dist/components/list.js +82 -15
- package/dist/components/list.js.map +1 -1
- package/dist/components/metadata.d.ts.map +1 -1
- package/dist/components/metadata.js +2 -1
- package/dist/components/metadata.js.map +1 -1
- package/dist/components/spinner.d.ts +6 -0
- package/dist/components/spinner.d.ts.map +1 -0
- package/dist/components/spinner.js +12 -0
- package/dist/components/spinner.js.map +1 -0
- package/dist/examples/action-shortcut.d.ts +2 -0
- package/dist/examples/action-shortcut.d.ts.map +1 -0
- package/dist/examples/action-shortcut.js +20 -0
- package/dist/examples/action-shortcut.js.map +1 -0
- package/dist/examples/internal/scrollbox-with-descendants.js +19 -8
- package/dist/examples/internal/scrollbox-with-descendants.js.map +1 -1
- package/dist/examples/list-spacing-default.d.ts +5 -0
- package/dist/examples/list-spacing-default.d.ts.map +1 -0
- package/dist/examples/list-spacing-default.js +10 -0
- package/dist/examples/list-spacing-default.js.map +1 -0
- package/dist/examples/list-spacing-mode.d.ts +10 -0
- package/dist/examples/list-spacing-mode.d.ts.map +1 -0
- package/dist/examples/list-spacing-mode.js +26 -0
- package/dist/examples/list-spacing-mode.js.map +1 -0
- package/dist/examples/list-spacing-relaxed.d.ts +5 -0
- package/dist/examples/list-spacing-relaxed.d.ts.map +1 -0
- package/dist/examples/list-spacing-relaxed.js +10 -0
- package/dist/examples/list-spacing-relaxed.js.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +2 -1
- package/dist/logger.js.map +1 -1
- package/dist/state.d.ts +9 -0
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js +2 -0
- package/dist/state.js.map +1 -1
- package/dist/swift-runtime.d.ts.map +1 -1
- package/dist/swift-runtime.js +20 -5
- package/dist/swift-runtime.js.map +1 -1
- package/dist/utils.js +1 -1
- package/dist/utils.js.map +1 -1
- package/package.json +5 -5
- package/src/apis/cache.test.ts +1 -1
- package/src/apis/cache.tsx +1 -2
- package/src/apis/localstorage.tsx +1 -2
- package/src/apis/sqlite.ts +14 -0
- package/src/build.tsx +7 -1
- package/src/compile.tsx +1 -1
- package/src/components/actions.tsx +77 -5
- package/src/components/detail.tsx +3 -1
- package/src/components/dropdown.tsx +49 -11
- package/src/components/form/dropdown.tsx +32 -10
- package/src/components/list.tsx +157 -18
- package/src/components/metadata.tsx +3 -2
- package/src/components/spinner.tsx +25 -0
- package/src/examples/action-shortcut.tsx +53 -0
- package/src/examples/action-shortcut.vitest.tsx +178 -0
- package/src/examples/actions-context.vitest.tsx +4 -4
- package/src/examples/detail-metadata-showcase.vitest.tsx +32 -18
- package/src/examples/form-dropdown.vitest.tsx +8 -8
- package/src/examples/form-tagpicker.vitest.tsx +4 -4
- package/src/examples/github.vitest.tsx +16 -9
- package/src/examples/internal/scrollbox-with-descendants.tsx +27 -8
- package/src/examples/list-detail-metadata.vitest.tsx +3 -1
- package/src/examples/list-loading-empty-view.vitest.tsx +5 -5
- package/src/examples/list-scrollbox.vitest.tsx +5 -5
- package/src/examples/list-spacing-default.tsx +38 -0
- package/src/examples/list-spacing-mode.tsx +137 -0
- package/src/examples/list-spacing-mode.vitest.tsx +158 -0
- package/src/examples/list-spacing-relaxed.tsx +38 -0
- package/src/examples/list-with-detail.vitest.tsx +63 -28
- package/src/examples/list-with-sections.vitest.tsx +14 -14
- package/src/examples/simple-detail-markdown.vitest.tsx +3 -4
- package/src/examples/simple-file-picker.vitest.tsx +1 -1
- package/src/examples/simple-grid.vitest.tsx +42 -35
- package/src/examples/simple-navigation.vitest.tsx +14 -14
- package/src/extensions/dev.vitest.tsx +9 -3
- package/src/index.tsx +2 -0
- package/src/logger.tsx +2 -1
- package/src/state.tsx +13 -0
- package/src/swift-runtime.tsx +19 -5
- package/src/utils.test.tsx +1 -1
- package/src/utils.tsx +1 -1
|
@@ -137,7 +137,6 @@ test('grid navigation and display', async () => {
|
|
|
137
137
|
Simple Grid Example ────────────────────────────────────────────
|
|
138
138
|
|
|
139
139
|
> Search items...
|
|
140
|
-
|
|
141
140
|
╭────────────────────────────────────────────────────────────────╮
|
|
142
141
|
│ │
|
|
143
142
|
│ Actions esc │
|
|
@@ -152,11 +151,12 @@ test('grid navigation and display', async () => {
|
|
|
152
151
|
│ See Console Logs │
|
|
153
152
|
│ │
|
|
154
153
|
│ │
|
|
154
|
+
│ │
|
|
155
|
+
│ │
|
|
156
|
+
│ │
|
|
155
157
|
│ ↵ select ↑↓ navigate │
|
|
156
158
|
│ │
|
|
157
|
-
╰────────────────────────────────────────────────────────────────╯
|
|
158
|
-
|
|
159
|
-
"
|
|
159
|
+
╰────────────────────────────────────────────────────────────────╯"
|
|
160
160
|
`)
|
|
161
161
|
|
|
162
162
|
// Close actions with escape
|
|
@@ -522,7 +522,6 @@ test('grid mouse interaction', async () => {
|
|
|
522
522
|
Simple Grid Example ────────────────────────────────────────────
|
|
523
523
|
|
|
524
524
|
> Search items...
|
|
525
|
-
|
|
526
525
|
╭────────────────────────────────────────────────────────────────╮
|
|
527
526
|
│ │
|
|
528
527
|
│ Actions esc │
|
|
@@ -537,23 +536,31 @@ test('grid mouse interaction', async () => {
|
|
|
537
536
|
│ See Console Logs │
|
|
538
537
|
│ │
|
|
539
538
|
│ │
|
|
539
|
+
│ │
|
|
540
|
+
│ │
|
|
541
|
+
│ │
|
|
540
542
|
│ ↵ select ↑↓ navigate │
|
|
541
543
|
│ │
|
|
542
|
-
╰────────────────────────────────────────────────────────────────╯
|
|
543
|
-
|
|
544
|
-
"
|
|
544
|
+
╰────────────────────────────────────────────────────────────────╯"
|
|
545
545
|
`)
|
|
546
546
|
|
|
547
547
|
// Close the actions panel first
|
|
548
548
|
await session.press('esc')
|
|
549
549
|
|
|
550
|
-
// Navigate back up to make Apple visible
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
550
|
+
// Navigate back up to make Apple visible.
|
|
551
|
+
// Grid is implemented via List, which uses edge-triggered pagination.
|
|
552
|
+
// Pressing up a fixed small number of times can leave the viewport unchanged.
|
|
553
|
+
// Overshooting is safe since List doesn't wrap at the top boundary.
|
|
554
|
+
for (let i = 0; i < 30; i++) {
|
|
555
|
+
await session.press('up')
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
await session.text({
|
|
559
|
+
waitFor: (text) => {
|
|
560
|
+
return text.includes('Apple')
|
|
561
|
+
},
|
|
562
|
+
timeout: 5000,
|
|
563
|
+
})
|
|
557
564
|
|
|
558
565
|
// Click on "Apple" to go back to first section
|
|
559
566
|
await session.click('Apple', { first: true })
|
|
@@ -566,25 +573,25 @@ test('grid mouse interaction', async () => {
|
|
|
566
573
|
Simple Grid Example ────────────────────────────────────────────
|
|
567
574
|
|
|
568
575
|
> Search items...
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
576
|
+
╭────────────────────────────────────────────────────────────────╮
|
|
577
|
+
│ │
|
|
578
|
+
│ Actions esc │
|
|
579
|
+
│ │
|
|
580
|
+
│ > Search actions... │
|
|
581
|
+
│ │
|
|
582
|
+
│ ›Show Details │
|
|
583
|
+
│ Copy Emoji ⌃C │
|
|
584
|
+
│ │
|
|
585
|
+
│ Settings │
|
|
586
|
+
│ Change Theme... │
|
|
587
|
+
│ See Console Logs │
|
|
588
|
+
│ │
|
|
589
|
+
│ │
|
|
590
|
+
│ │
|
|
591
|
+
│ │
|
|
592
|
+
│ │
|
|
593
|
+
│ ↵ select ↑↓ navigate │
|
|
594
|
+
│ │
|
|
595
|
+
╰────────────────────────────────────────────────────────────────╯"
|
|
589
596
|
`)
|
|
590
597
|
}, 10000)
|
|
@@ -295,7 +295,6 @@ test('navigation with actions panel', async () => {
|
|
|
295
295
|
expect(actionsOpenSnapshot).toMatchInlineSnapshot(`
|
|
296
296
|
"
|
|
297
297
|
|
|
298
|
-
|
|
299
298
|
╭────────────────────────────────────────────────────────────────╮
|
|
300
299
|
│ │
|
|
301
300
|
│ Actions esc │
|
|
@@ -310,14 +309,15 @@ test('navigation with actions panel', async () => {
|
|
|
310
309
|
│ See Console Logs │
|
|
311
310
|
│ │
|
|
312
311
|
│ │
|
|
312
|
+
│ │
|
|
313
|
+
│ │
|
|
314
|
+
│ │
|
|
313
315
|
│ ↵ select ↑↓ navigate │
|
|
314
316
|
│ │
|
|
315
317
|
╰────────────────────────────────────────────────────────────────╯
|
|
316
318
|
|
|
317
319
|
|
|
318
320
|
|
|
319
|
-
|
|
320
|
-
|
|
321
321
|
"
|
|
322
322
|
`)
|
|
323
323
|
|
|
@@ -328,7 +328,6 @@ test('navigation with actions panel', async () => {
|
|
|
328
328
|
expect(secondActionSnapshot).toMatchInlineSnapshot(`
|
|
329
329
|
"
|
|
330
330
|
|
|
331
|
-
|
|
332
331
|
╭────────────────────────────────────────────────────────────────╮
|
|
333
332
|
│ │
|
|
334
333
|
│ Actions esc │
|
|
@@ -343,14 +342,15 @@ test('navigation with actions panel', async () => {
|
|
|
343
342
|
│ See Console Logs │
|
|
344
343
|
│ │
|
|
345
344
|
│ │
|
|
345
|
+
│ │
|
|
346
|
+
│ │
|
|
347
|
+
│ │
|
|
346
348
|
│ ↵ select ↑↓ navigate │
|
|
347
349
|
│ │
|
|
348
350
|
╰────────────────────────────────────────────────────────────────╯
|
|
349
351
|
|
|
350
352
|
|
|
351
353
|
|
|
352
|
-
|
|
353
|
-
|
|
354
354
|
"
|
|
355
355
|
`)
|
|
356
356
|
|
|
@@ -439,7 +439,6 @@ test('navigation with actions panel', async () => {
|
|
|
439
439
|
expect(detailActionsSnapshot).toMatchInlineSnapshot(`
|
|
440
440
|
"
|
|
441
441
|
|
|
442
|
-
|
|
443
442
|
╭────────────────────────────────────────────────────────────────╮
|
|
444
443
|
│ │
|
|
445
444
|
│ Actions esc │
|
|
@@ -454,14 +453,15 @@ test('navigation with actions panel', async () => {
|
|
|
454
453
|
│ See Console Logs │
|
|
455
454
|
│ │
|
|
456
455
|
│ │
|
|
456
|
+
│ │
|
|
457
|
+
│ │
|
|
458
|
+
│ │
|
|
457
459
|
│ ↵ select ↑↓ navigate │
|
|
458
460
|
│ │
|
|
459
461
|
╰────────────────────────────────────────────────────────────────╯
|
|
460
462
|
|
|
461
463
|
|
|
462
464
|
|
|
463
|
-
|
|
464
|
-
|
|
465
465
|
"
|
|
466
466
|
`)
|
|
467
467
|
|
|
@@ -525,12 +525,12 @@ test('search functionality in main and detail views', async () => {
|
|
|
525
525
|
|
|
526
526
|
Navigation Example ─────────────────────────────────────────────
|
|
527
527
|
|
|
528
|
-
>
|
|
528
|
+
> second
|
|
529
|
+
|
|
530
|
+
›Second Item Navigate to second detail
|
|
531
|
+
|
|
532
|
+
|
|
529
533
|
|
|
530
|
-
Items
|
|
531
|
-
›First Item Navigate to first detail
|
|
532
|
-
Second Item Navigate to second detail
|
|
533
|
-
Third Item Navigate to third detail
|
|
534
534
|
|
|
535
535
|
|
|
536
536
|
|
|
@@ -93,7 +93,6 @@ test('selecting command with arguments shows arguments form', async () => {
|
|
|
93
93
|
|
|
94
94
|
> Search commands...
|
|
95
95
|
|
|
96
|
-
Google Oauth view
|
|
97
96
|
usePromise Demo Shows how to use the usePromise h view
|
|
98
97
|
Show State Shows the current application state in view
|
|
99
98
|
›With Arguments Demonstrates command arguments (te view
|
|
@@ -101,6 +100,7 @@ test('selecting command with arguments shows arguments form', async () => {
|
|
|
101
100
|
Throw Error Command that throws an error at root view
|
|
102
101
|
|
|
103
102
|
|
|
103
|
+
|
|
104
104
|
↵ run command ↑↓ navigate ^k actions
|
|
105
105
|
"
|
|
106
106
|
`)
|
|
@@ -161,6 +161,7 @@ test('can fill arguments and run command', async () => {
|
|
|
161
161
|
|
|
162
162
|
// Type in the search query field
|
|
163
163
|
await session.type('my search term')
|
|
164
|
+
await session.waitIdle()
|
|
164
165
|
|
|
165
166
|
const afterTypingSnapshot = await session.text()
|
|
166
167
|
expect(afterTypingSnapshot).toMatchInlineSnapshot(`
|
|
@@ -183,9 +184,14 @@ test('can fill arguments and run command', async () => {
|
|
|
183
184
|
"
|
|
184
185
|
`)
|
|
185
186
|
|
|
186
|
-
// Submit via
|
|
187
|
+
// Submit via actions dialog.
|
|
188
|
+
// Terminals don't reliably encode Ctrl+Enter, but Ctrl+K is stable.
|
|
187
189
|
await session.press(['ctrl', 'k'])
|
|
188
|
-
await
|
|
190
|
+
await waitForTextWithDebug({
|
|
191
|
+
session,
|
|
192
|
+
waitFor: (text) => text.includes('Search actions...') && text.includes('Run Command'),
|
|
193
|
+
timeout: 10000,
|
|
194
|
+
})
|
|
189
195
|
await session.press('enter')
|
|
190
196
|
|
|
191
197
|
await waitForTextWithDebug({
|
package/src/index.tsx
CHANGED
|
@@ -9,6 +9,7 @@ export { List, Grid } from 'termcast/src/components/list'
|
|
|
9
9
|
export { List as default } from 'termcast/src/components/list'
|
|
10
10
|
export type {
|
|
11
11
|
ListProps,
|
|
12
|
+
ListSpacingMode,
|
|
12
13
|
ItemProps as ListItemProps,
|
|
13
14
|
SectionProps as ListSectionProps,
|
|
14
15
|
DetailProps as ListDetailProps,
|
|
@@ -143,6 +144,7 @@ export type {
|
|
|
143
144
|
|
|
144
145
|
// Icons and Images
|
|
145
146
|
export { Icon, getIconEmoji, getIconShape, IconComponent } from 'termcast/src/components/icon'
|
|
147
|
+
export { Spinner } from 'termcast/src/components/spinner'
|
|
146
148
|
import {
|
|
147
149
|
Image as ImageComponent,
|
|
148
150
|
ImageMask,
|
package/src/logger.tsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as fs from 'fs'
|
|
2
2
|
import * as path from 'path'
|
|
3
|
+
import util from 'node:util'
|
|
3
4
|
import { useEffect } from 'react'
|
|
4
5
|
|
|
5
6
|
const LOG_FILE = path.join(process.cwd(), 'app.log')
|
|
@@ -16,7 +17,7 @@ function serialize(msg: any): string {
|
|
|
16
17
|
if (typeof msg === 'string') {
|
|
17
18
|
return msg
|
|
18
19
|
}
|
|
19
|
-
return
|
|
20
|
+
return util.inspect(msg, { depth: 3 })
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
export const logger = {
|
package/src/state.tsx
CHANGED
|
@@ -2,6 +2,14 @@ import { create } from 'zustand'
|
|
|
2
2
|
import { type ReactNode } from 'react'
|
|
3
3
|
import type { TextareaRenderable } from '@opentui/core'
|
|
4
4
|
import type { RaycastPackageJson } from './package-json'
|
|
5
|
+
import type { KeyboardKeyEquivalent, KeyboardKeyModifier } from 'termcast/src/keyboard'
|
|
6
|
+
|
|
7
|
+
// Registered action shortcuts for global keyboard handling
|
|
8
|
+
// Stored by ActionPanel, consumed by List/Detail/Form keyboard handlers
|
|
9
|
+
export interface RegisteredActionShortcut {
|
|
10
|
+
shortcut: { modifiers?: KeyboardKeyModifier[]; key: KeyboardKeyEquivalent }
|
|
11
|
+
execute: () => void
|
|
12
|
+
}
|
|
5
13
|
|
|
6
14
|
// Toast action keyboard shortcuts (ctrl+t for primary, ctrl+g for secondary)
|
|
7
15
|
export const toastPrimaryActionKey = { ctrl: true, name: 't' } as const
|
|
@@ -73,6 +81,9 @@ interface AppState {
|
|
|
73
81
|
currentThemeName: string
|
|
74
82
|
// Active search input ref - used to clear search before exiting on ESC
|
|
75
83
|
activeSearchInputRef: TextareaRenderable | null
|
|
84
|
+
// Registered action shortcuts for global keyboard handling
|
|
85
|
+
// ActionPanel populates this, List/Detail/Form consume it
|
|
86
|
+
registeredActionShortcuts: RegisteredActionShortcut[]
|
|
76
87
|
}
|
|
77
88
|
|
|
78
89
|
export const useStore = create<AppState>(() => ({
|
|
@@ -101,4 +112,6 @@ export const useStore = create<AppState>(() => ({
|
|
|
101
112
|
currentThemeName: 'termcast',
|
|
102
113
|
// Active search input ref
|
|
103
114
|
activeSearchInputRef: null,
|
|
115
|
+
// Registered action shortcuts
|
|
116
|
+
registeredActionShortcuts: [],
|
|
104
117
|
}))
|
package/src/swift-runtime.tsx
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import childProcess from 'node:child_process'
|
|
1
2
|
import { logger } from './logger'
|
|
2
3
|
|
|
3
4
|
export async function runSwiftFunction(
|
|
@@ -9,14 +10,27 @@ export async function runSwiftFunction(
|
|
|
9
10
|
|
|
10
11
|
logger.log(`Swift: calling ${functionName} with args:`, jsonArgs)
|
|
11
12
|
|
|
12
|
-
const proc =
|
|
13
|
-
|
|
14
|
-
stderr: 'inherit',
|
|
13
|
+
const proc = childProcess.spawn(binaryPath, [functionName, ...jsonArgs], {
|
|
14
|
+
stdio: ['ignore', 'pipe', 'inherit'],
|
|
15
15
|
})
|
|
16
16
|
|
|
17
17
|
const [stdout, exitCode] = await Promise.all([
|
|
18
|
-
new
|
|
19
|
-
|
|
18
|
+
new Promise<string>((resolve, reject) => {
|
|
19
|
+
const chunks: Buffer[] = []
|
|
20
|
+
proc.stdout!.on('data', (chunk) => { chunks.push(chunk) })
|
|
21
|
+
proc.stdout!.on('error', reject)
|
|
22
|
+
proc.stdout!.on('end', () => { resolve(Buffer.concat(chunks).toString()) })
|
|
23
|
+
}),
|
|
24
|
+
new Promise<number | null>((resolve, reject) => {
|
|
25
|
+
proc.on('error', reject)
|
|
26
|
+
proc.on('close', (code, signal) => {
|
|
27
|
+
if (signal) {
|
|
28
|
+
reject(new Error(`Swift function "${functionName}" was killed by signal ${signal}`))
|
|
29
|
+
} else {
|
|
30
|
+
resolve(code)
|
|
31
|
+
}
|
|
32
|
+
})
|
|
33
|
+
}),
|
|
20
34
|
])
|
|
21
35
|
|
|
22
36
|
if (exitCode !== 0) {
|
package/src/utils.test.tsx
CHANGED
package/src/utils.tsx
CHANGED
|
@@ -812,7 +812,7 @@ export async function executeSQL<T = unknown>(
|
|
|
812
812
|
databasePath: string,
|
|
813
813
|
query: string,
|
|
814
814
|
): Promise<T[]> {
|
|
815
|
-
const { Database } = await import('
|
|
815
|
+
const { Database } = await import('./apis/sqlite')
|
|
816
816
|
|
|
817
817
|
if (!fs.existsSync(databasePath)) {
|
|
818
818
|
throw new Error(`Database file not found: ${databasePath}`)
|