@workerdeck/ui 2.0.0 → 2.1.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.
@@ -1,73 +0,0 @@
1
- import { useCallback, useEffect, useRef, useState } from 'react'
2
- import { Clock } from 'lucide-react'
3
-
4
- export type HeldSend = { text: string; attachmentIds: string[] }
5
-
6
- export type HeldSends = {
7
- held: HeldSend[]
8
- submit: (text: string, attachmentIds: string[]) => void
9
- flush: () => void
10
- }
11
-
12
- // Catch-up mode is the engine's behaviour, not ours: a message sent mid-turn is folded into the
13
- // running turn. Holding it here is the only way to turn that off, and it is a client preference,
14
- // so nothing about it travels on the wire.
15
- export function useHeldSends(options: { hold: boolean; busy: boolean; send: (text: string, attachmentIds: string[]) => void }): HeldSends {
16
- const [held, setHeld] = useState<HeldSend[]>([])
17
- // The queue is a ref and the state is its shadow: flushing sends, and a state updater that
18
- // sends would fire twice under StrictMode.
19
- const queue = useRef<HeldSend[]>([])
20
- const sendRef = useRef(options.send)
21
- sendRef.current = options.send
22
-
23
- const flush = useCallback(() => {
24
- const queued = queue.current
25
- if (queued.length === 0) {
26
- return
27
- }
28
- queue.current = []
29
- setHeld([])
30
- for (const item of queued) {
31
- sendRef.current(item.text, item.attachmentIds)
32
- }
33
- }, [])
34
-
35
- useEffect(() => {
36
- if (!options.busy) {
37
- flush()
38
- }
39
- }, [options.busy, flush])
40
-
41
- const submit = useCallback(
42
- (text: string, attachmentIds: string[]) => {
43
- if (!options.hold || !options.busy) {
44
- sendRef.current(text, attachmentIds)
45
- return
46
- }
47
- queue.current = [...queue.current, { text, attachmentIds }]
48
- setHeld(queue.current)
49
- },
50
- [options.hold, options.busy],
51
- )
52
-
53
- return { held, submit, flush }
54
- }
55
-
56
- export function HeldSendsBar({ held, onSendNow }: { held: HeldSend[]; onSendNow: () => void }) {
57
- if (held.length === 0) {
58
- return null
59
- }
60
- return (
61
- <div className="px-3 pt-2">
62
- <div className="mx-auto flex w-full max-w-[var(--wd-transcript-max-width)] items-center gap-2 rounded-md border border-border bg-surface px-3 py-1.5 text-label text-fg-3">
63
- <Clock className="size-3.5 shrink-0" />
64
- <span className="min-w-0 flex-1 truncate">
65
- {held.length === 1 ? '1 message' : `${held.length} messages`} waiting for this turn to end — {held[held.length - 1]!.text}
66
- </span>
67
- <button type="button" onClick={onSendNow} className="shrink-0 underline-offset-2 hover:underline">
68
- Send now
69
- </button>
70
- </div>
71
- </div>
72
- )
73
- }