feat(plugin): add ui.tabs API for session tab control (#39591)
This commit is contained in:
parent
c161978852
commit
78c139b8b5
2 changed files with 48 additions and 0 deletions
|
|
@ -351,6 +351,25 @@ export interface UI {
|
|||
navigate(destination: Destination): void
|
||||
current(): Route
|
||||
}
|
||||
readonly tabs: {
|
||||
/** Returns whether session tabs are enabled for this TUI. */
|
||||
enabled(): boolean
|
||||
/** Returns the currently open root-session tabs. Reactive when read in a Solid computation. */
|
||||
list(): readonly {
|
||||
readonly sessionID: string
|
||||
readonly title?: string
|
||||
readonly active: boolean
|
||||
readonly busy: boolean
|
||||
readonly attention: boolean
|
||||
readonly unread?: "activity" | "error"
|
||||
}[]
|
||||
/** Opens (or focuses) a tab for a session, adding it when not already open. Returns false when tabs are disabled. */
|
||||
open(sessionID: string): boolean
|
||||
/** Focuses an already-open tab and returns false when it is not open. */
|
||||
focus(sessionID: string): boolean
|
||||
/** Closes an open tab, or the active tab when omitted, and returns false when no tab matched. */
|
||||
close(sessionID?: string): boolean
|
||||
}
|
||||
readonly slot: <Name extends SlotName>(name: Name, render: Slot<Name>) => () => void
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import { useDialog } from "../ui/dialog"
|
|||
import { useToast } from "../ui/toast"
|
||||
import { useAttention } from "../context/attention"
|
||||
import { useStorage } from "../context/storage"
|
||||
import { useSessionTabs } from "../context/session-tabs"
|
||||
import { abbreviateHome } from "../util/path-format"
|
||||
import { builtins } from "./builtins"
|
||||
import { discoverTuiPlugins } from "./discovery"
|
||||
|
|
@ -94,6 +95,7 @@ export function PluginProvider(props: ParentProps<{ packages: PackageResolver }>
|
|||
const toast = useToast()
|
||||
const attention = useAttention()
|
||||
const storage = useStorage()
|
||||
const sessionTabs = useSessionTabs()
|
||||
const directory = config.path ? path.dirname(config.path) : process.cwd()
|
||||
const [store, setStore] = createStore({
|
||||
ready: false,
|
||||
|
|
@ -278,6 +280,33 @@ export function PluginProvider(props: ParentProps<{ packages: PackageResolver }>
|
|||
return route.data
|
||||
},
|
||||
},
|
||||
tabs: {
|
||||
enabled: sessionTabs.enabled,
|
||||
list: () =>
|
||||
sessionTabs.tabs().map((tab) => ({
|
||||
...tab,
|
||||
active: sessionTabs.current() === tab.sessionID,
|
||||
...sessionTabs.status(tab.sessionID),
|
||||
})),
|
||||
open(sessionID) {
|
||||
if (!sessionTabs.enabled()) return false
|
||||
sessionTabs.select(sessionID)
|
||||
return true
|
||||
},
|
||||
focus(sessionID) {
|
||||
if (!sessionTabs.enabled()) return false
|
||||
if (!sessionTabs.tabs().some((tab) => tab.sessionID === sessionID)) return false
|
||||
sessionTabs.select(sessionID)
|
||||
return true
|
||||
},
|
||||
close(sessionID) {
|
||||
if (!sessionTabs.enabled()) return false
|
||||
const target = sessionID ?? sessionTabs.current()
|
||||
if (!target || !sessionTabs.tabs().some((tab) => tab.sessionID === target)) return false
|
||||
sessionTabs.close(target)
|
||||
return true
|
||||
},
|
||||
},
|
||||
slot(name, render) {
|
||||
if (store.registrations[item.plugin.id]?.slots[name]) throw new Error(`Slot already registered: ${name}`)
|
||||
setStore("registrations", item.plugin.id, "slots", name, () => (input: SlotMap[typeof name]) => (
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue