feat(client): localize composer hints and rework input command interaction
Unify the /plan claimed hint with the plan placeholder through a locale namespace, localize slash menu group titles, replace the PermissionSelect native select with the Menu primitive, add a goal pause verb chain, clamp anchored popups to the viewport with scroll-into-view and outside-dismiss, and fix onPasteUpgrade insertedRange to account for the chip trailing gap.
This commit is contained in:
@@ -57,6 +57,7 @@ function bench(options: { projection?: GoalProjection | null | undefined; failWi
|
||||
const ref = { id: 'g-1', revision: 3 }
|
||||
ctx.provide('connection', { api: { goals: {
|
||||
edit: answer('goal.edit', { ref }),
|
||||
pause: answer('goal.pause', { ref }),
|
||||
resume: answer('goal.resume', { ref }),
|
||||
clear: answer('goal.clear', { cleared: true as const }),
|
||||
} } })
|
||||
@@ -100,13 +101,15 @@ describe('ui-goal browser plugin', () => {
|
||||
await b.fiber.await()
|
||||
const verbs = b.entry()!.inject!(sid('s1'))
|
||||
expect(await verbs.onEdit('New objective')).toEqual({ ok: true })
|
||||
expect(await verbs.onPause()).toEqual({ ok: true })
|
||||
expect(await verbs.onResume()).toEqual({ ok: true })
|
||||
expect(await verbs.onClear()).toEqual({ ok: true })
|
||||
expect(b.calls.map(c => c.method)).toEqual(['goal.edit', 'goal.resume', 'goal.clear'])
|
||||
expect(b.calls.map(c => c.method)).toEqual(['goal.edit', 'goal.pause', 'goal.resume', 'goal.clear'])
|
||||
const ref = { id: 'g-1', revision: 5 }
|
||||
expect(b.calls[0]?.payload).toEqual({ sessionId: 's1', ref, objective: 'New objective' })
|
||||
expect(b.calls[1]?.payload).toEqual({ sessionId: 's1', ref })
|
||||
expect(b.calls[2]?.payload).toEqual({ sessionId: 's1', ref })
|
||||
expect(b.calls[3]?.payload).toEqual({ sessionId: 's1', ref })
|
||||
})
|
||||
|
||||
it('a null or absent projection short-circuits every verb without touching the wire', async () => {
|
||||
@@ -114,7 +117,7 @@ describe('ui-goal browser plugin', () => {
|
||||
const b = bench({ projection })
|
||||
await b.fiber.await()
|
||||
const verbs = b.entry()!.inject!(sid('s1'))
|
||||
for (const result of [await verbs.onEdit('x'), await verbs.onResume(), await verbs.onClear()]) {
|
||||
for (const result of [await verbs.onEdit('x'), await verbs.onPause(), await verbs.onResume(), await verbs.onClear()]) {
|
||||
expect(result).toEqual({ ok: false, error: { code: 'no-current-goal', message: 'no current goal to mutate' } })
|
||||
}
|
||||
expect(b.calls).toHaveLength(0)
|
||||
@@ -143,6 +146,7 @@ describe('GoalDock adapter', () => {
|
||||
const useProjection = vi.fn(() => projection)
|
||||
const actions: GoalBarActions = {
|
||||
onEdit: () => Promise.resolve({ ok: true }),
|
||||
onPause: () => Promise.resolve({ ok: true }),
|
||||
onResume: () => Promise.resolve({ ok: true }),
|
||||
onClear: () => Promise.resolve({ ok: true }),
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ function makeGoal(over: Partial<GoalSnapshot> = {}): GoalSnapshot {
|
||||
function makeActions() {
|
||||
return {
|
||||
onEdit: vi.fn<GoalBarActions['onEdit']>(() => Promise.resolve({ ok: true })),
|
||||
onPause: vi.fn<GoalBarActions['onPause']>(() => Promise.resolve({ ok: true })),
|
||||
onResume: vi.fn<GoalBarActions['onResume']>(() => Promise.resolve({ ok: true })),
|
||||
onClear: vi.fn<GoalBarActions['onClear']>(() => Promise.resolve({ ok: true })),
|
||||
} satisfies GoalBarActions
|
||||
|
||||
Reference in New Issue
Block a user