@cueplusplus/ui 0.20.1 → 0.22.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.
Files changed (236) hide show
  1. package/CHANGELOG.md +133 -0
  2. package/dist/chat/agent-pile.js +2 -2
  3. package/dist/chrome/_status-bar.js +1 -1
  4. package/dist/chrome/app-shell.js +1 -1
  5. package/dist/chrome/navigation-menu.js +3 -3
  6. package/dist/chrome/row.js +1 -1
  7. package/dist/chrome/scroll-area.js +1 -1
  8. package/dist/chrome/section-header.js +1 -1
  9. package/dist/chrome/segmented-control.js +1 -1
  10. package/dist/chrome/tabs.js +1 -1
  11. package/dist/chrome/toolbar.js +1 -1
  12. package/dist/chrome/tree.js +3 -3
  13. package/dist/date/calendar.js +3 -3
  14. package/dist/dmx/channel-matrix.js +1 -1
  15. package/dist/dmx/universe-grid.js +1 -1
  16. package/dist/elements/agent-handoff.js +3 -3
  17. package/dist/elements/agent-plan.js +1 -1
  18. package/dist/elements/agent-status.js +1 -1
  19. package/dist/elements/agent-surface.d.ts +9 -6
  20. package/dist/elements/agent-surface.js +3 -2
  21. package/dist/elements/approval-card.d.ts +29 -3
  22. package/dist/elements/approval-card.js +18 -8
  23. package/dist/elements/artifact-card.js +2 -2
  24. package/dist/elements/canvas-split.js +3 -3
  25. package/dist/elements/chart.js +1 -1
  26. package/dist/elements/chat-panel.js +2 -2
  27. package/dist/elements/checkpoint-history.js +1 -1
  28. package/dist/elements/code-diff.js +1 -1
  29. package/dist/elements/code-runner.js +1 -1
  30. package/dist/elements/composer.d.ts +8 -2
  31. package/dist/elements/composer.js +20 -12
  32. package/dist/elements/computer-use.js +2 -2
  33. package/dist/elements/confidence-marker.js +1 -1
  34. package/dist/elements/connection-state.js +2 -2
  35. package/dist/elements/context-breakdown.js +1 -1
  36. package/dist/elements/context-usage.js +1 -1
  37. package/dist/elements/conversation-search.js +2 -2
  38. package/dist/elements/cost-meter.js +1 -1
  39. package/dist/elements/data-table.js +1 -1
  40. package/dist/elements/diagram.js +1 -1
  41. package/dist/elements/draft-restore.js +2 -2
  42. package/dist/elements/edit-message.js +1 -1
  43. package/dist/elements/elements.css +134 -0
  44. package/dist/elements/elicitation-form.d.ts +8 -1
  45. package/dist/elements/elicitation-form.js +24 -16
  46. package/dist/elements/empty-state.js +3 -3
  47. package/dist/elements/error-state.js +2 -2
  48. package/dist/elements/event-feed.d.ts +88 -0
  49. package/dist/elements/event-feed.js +190 -0
  50. package/dist/elements/feedback-dialog.js +2 -2
  51. package/dist/elements/file-tree.js +1 -1
  52. package/dist/elements/flow-graph.js +2 -2
  53. package/dist/elements/generative.css +13 -0
  54. package/dist/elements/generative.d.ts +8 -6
  55. package/dist/elements/generative.js +4 -3
  56. package/dist/elements/image-generation.js +2 -2
  57. package/dist/elements/index.d.ts +7 -3
  58. package/dist/elements/index.js +5 -2
  59. package/dist/elements/inline-citation.js +1 -1
  60. package/dist/elements/job-progress.js +1 -1
  61. package/dist/elements/launcher-bubble.js +3 -3
  62. package/dist/elements/loading-state.js +1 -1
  63. package/dist/elements/map-answer.js +1 -1
  64. package/dist/elements/math-block.js +1 -1
  65. package/dist/elements/mcp-server-panel.js +3 -3
  66. package/dist/elements/memory-chips.js +1 -1
  67. package/dist/elements/message-attachment.js +3 -3
  68. package/dist/elements/message-branches.js +1 -1
  69. package/dist/elements/message-pair.js +2 -2
  70. package/dist/elements/message-queue.js +1 -1
  71. package/dist/elements/message-timing.js +1 -1
  72. package/dist/elements/mobile-composer.js +1 -1
  73. package/dist/elements/model-picker.js +1 -1
  74. package/dist/elements/number-ticker.js +1 -1
  75. package/dist/elements/onboarding.js +3 -3
  76. package/dist/elements/permission-grant.js +3 -3
  77. package/dist/elements/prompt-library.js +1 -1
  78. package/dist/elements/question-card.d.ts +50 -0
  79. package/dist/elements/question-card.js +117 -0
  80. package/dist/elements/queue-dock.js +1 -1
  81. package/dist/elements/quota-banner.js +1 -1
  82. package/dist/elements/quote-reply.js +3 -3
  83. package/dist/elements/read-aloud.js +2 -2
  84. package/dist/elements/reasoning-effort.js +2 -2
  85. package/dist/elements/reasoning-panel.js +3 -3
  86. package/dist/elements/recommendation-card.js +2 -2
  87. package/dist/elements/regenerate-menu.js +1 -1
  88. package/dist/elements/request-delivery.js +31 -0
  89. package/dist/elements/research-report.js +1 -1
  90. package/dist/elements/retrieval-chunks.js +3 -3
  91. package/dist/elements/revert-dock.js +1 -1
  92. package/dist/elements/reviewable-diff.js +4 -4
  93. package/dist/elements/schedule-card.js +2 -2
  94. package/dist/elements/score-breakdown.js +2 -2
  95. package/dist/elements/scroll-anchor.js +2 -2
  96. package/dist/elements/settings-panel.js +3 -3
  97. package/dist/elements/sources.js +1 -1
  98. package/dist/elements/spec-sheet.js +1 -1
  99. package/dist/elements/stopped-run.js +2 -2
  100. package/dist/elements/streaming-text.js +2 -2
  101. package/dist/elements/subagent-list.js +4 -4
  102. package/dist/elements/suggestions.js +1 -1
  103. package/dist/elements/surfaces.d.ts +6 -6
  104. package/dist/elements/surfaces.js +7 -7
  105. package/dist/elements/tail-status.js +1 -1
  106. package/dist/elements/terminal-block.js +1 -1
  107. package/dist/elements/thinking-indicator.js +1 -1
  108. package/dist/elements/timeline.js +1 -1
  109. package/dist/elements/todo-list.js +1 -1
  110. package/dist/elements/tool-call.d.ts +18 -2
  111. package/dist/elements/tool-call.js +20 -11
  112. package/dist/elements/tool-error.js +2 -2
  113. package/dist/elements/tool-group.d.ts +11 -3
  114. package/dist/elements/tool-group.js +62 -38
  115. package/dist/elements/tool-state.d.ts +13 -0
  116. package/dist/elements/tool-state.js +44 -0
  117. package/dist/elements/tool-timeline.js +2 -2
  118. package/dist/elements/trace-waterfall.js +2 -2
  119. package/dist/elements/unsupported-request-card.d.ts +31 -0
  120. package/dist/elements/unsupported-request-card.js +80 -0
  121. package/dist/elements/vocabulary.d.ts +50 -1
  122. package/dist/elements/vocabulary.js +50 -1
  123. package/dist/elements/voice-conversation.js +5 -5
  124. package/dist/elements/web-preview.js +1 -1
  125. package/dist/elements/web-search.js +2 -2
  126. package/dist/elements/work-collapse.js +1 -1
  127. package/dist/forms/_chassis.d.ts +6 -1
  128. package/dist/forms/_chassis.js +8 -3
  129. package/dist/forms/file-upload.js +1 -1
  130. package/dist/forms/rating.js +1 -1
  131. package/dist/forms/select.js +1 -1
  132. package/dist/forms/switch.js +2 -2
  133. package/dist/forms/toggle.js +1 -1
  134. package/dist/index.d.ts +3 -1
  135. package/dist/index.js +3 -1
  136. package/dist/instruments/_ledger-disclosure.js +1 -1
  137. package/dist/instruments/data-tree.js +1 -1
  138. package/dist/instruments/meter.js +1 -1
  139. package/dist/instruments/seam-grid.js +1 -1
  140. package/dist/layout/_collapse.js +3 -3
  141. package/dist/layout/bento.js +1 -1
  142. package/dist/layout/breadcrumb.js +1 -1
  143. package/dist/layout/carousel.js +1 -1
  144. package/dist/layout/collapsible.js +1 -1
  145. package/dist/layout/index.d.ts +3 -1
  146. package/dist/layout/index.js +3 -1
  147. package/dist/layout/item.js +1 -1
  148. package/dist/layout/link.js +1 -1
  149. package/dist/layout/pagination.js +1 -1
  150. package/dist/layout/pane-seam.d.ts +75 -0
  151. package/dist/layout/pane-seam.js +127 -0
  152. package/dist/layout/resizable.d.ts +2 -1
  153. package/dist/layout/resizable.js +3 -2
  154. package/dist/layout/sidebar.js +3 -3
  155. package/dist/layout/split-pane.d.ts +74 -0
  156. package/dist/layout/split-pane.js +135 -0
  157. package/dist/layout/stepper.js +1 -1
  158. package/dist/lib/auto-grow.js +42 -0
  159. package/dist/overlays/_surface.d.ts +5 -5
  160. package/dist/overlays/_surface.js +4 -4
  161. package/dist/overlays/drawer.js +1 -1
  162. package/dist/overlays/menubar.js +1 -1
  163. package/dist/overlays/sheet.js +1 -1
  164. package/dist/overlays/toast.js +1 -1
  165. package/dist/primitives/button.js +1 -1
  166. package/dist/primitives/chip.d.ts +1 -1
  167. package/dist/styles.css +52 -0
  168. package/dist/system/_paint-stroke-sunken.js +22 -2
  169. package/dist/system/_paint-stroke-surface-1.js +5 -1
  170. package/dist/system/_paint-stroke-surface-2.js +5 -1
  171. package/dist/system/_style-disabled.js +1 -7
  172. package/dist/system/agent-skin.d.ts +11 -5
  173. package/manifest/components/agent-surface.json +5 -4
  174. package/manifest/components/alert-dialog.json +1 -0
  175. package/manifest/components/approval-card.json +45 -7
  176. package/manifest/components/autocomplete.json +2 -0
  177. package/manifest/components/button.json +0 -3
  178. package/manifest/components/card.json +1 -0
  179. package/manifest/components/channel-matrix.json +1 -0
  180. package/manifest/components/chart-tooltip-content.json +1 -0
  181. package/manifest/components/checkbox-group.json +0 -3
  182. package/manifest/components/checkbox.json +0 -3
  183. package/manifest/components/color-field.json +1 -0
  184. package/manifest/components/color-picker.json +1 -0
  185. package/manifest/components/combobox.json +2 -0
  186. package/manifest/components/command-palette.json +1 -0
  187. package/manifest/components/composer-input.json +16 -2
  188. package/manifest/components/composer.json +1 -0
  189. package/manifest/components/context-menu.json +1 -0
  190. package/manifest/components/date-field.json +1 -0
  191. package/manifest/components/date-picker.json +1 -0
  192. package/manifest/components/date-range-picker.json +1 -0
  193. package/manifest/components/dialog.json +1 -0
  194. package/manifest/components/dmx-bar.json +1 -0
  195. package/manifest/components/dmx-strip.json +1 -0
  196. package/manifest/components/drawer.json +1 -0
  197. package/manifest/components/dropdown-menu.json +1 -0
  198. package/manifest/components/elicitation-form.json +16 -1
  199. package/manifest/components/env-var-input.json +1 -0
  200. package/manifest/components/event-feed.json +171 -0
  201. package/manifest/components/event-row.json +116 -0
  202. package/manifest/components/generative-ui.json +4 -3
  203. package/manifest/components/hover-card.json +1 -0
  204. package/manifest/components/input-group.json +1 -0
  205. package/manifest/components/input.json +1 -0
  206. package/manifest/components/menubar.json +1 -0
  207. package/manifest/components/multi-select.json +2 -0
  208. package/manifest/components/musical-time-input.json +1 -0
  209. package/manifest/components/navigation-menu.json +1 -0
  210. package/manifest/components/number-field.json +1 -0
  211. package/manifest/components/otp-field.json +1 -0
  212. package/manifest/components/pane-seam.json +171 -0
  213. package/manifest/components/password-input.json +1 -0
  214. package/manifest/components/popover.json +1 -0
  215. package/manifest/components/question-card.json +157 -0
  216. package/manifest/components/resizable.json +1 -1
  217. package/manifest/components/scrub-input.json +1 -0
  218. package/manifest/components/search-input.json +1 -0
  219. package/manifest/components/select.json +2 -0
  220. package/manifest/components/sheet.json +1 -0
  221. package/manifest/components/split-pane.json +224 -0
  222. package/manifest/components/switch.json +0 -3
  223. package/manifest/components/tags-input.json +2 -0
  224. package/manifest/components/textarea.json +1 -0
  225. package/manifest/components/theme-configurator.json +1 -0
  226. package/manifest/components/time-field.json +1 -0
  227. package/manifest/components/toast.json +1 -0
  228. package/manifest/components/toggle.json +0 -3
  229. package/manifest/components/tool-call.json +46 -2
  230. package/manifest/components/tool-group.json +15 -3
  231. package/manifest/components/tooltip.json +1 -0
  232. package/manifest/components/unsupported-request-card.json +117 -0
  233. package/manifest/fixtures.json +16 -0
  234. package/manifest/manifest.json +134 -56
  235. package/manifest/tokens.json +12 -2
  236. package/package.json +3 -3
@@ -46,7 +46,7 @@ function ChatPanelMessages({ className, ...props }) {
46
46
  function ChatPanelUserMessage({ className, ...props }) {
47
47
  return /* @__PURE__ */ jsx("div", {
48
48
  "data-slot": "chat-panel-user-message",
49
- className: cn(field, "cue-elements-fade-in cue-elements-slide-in-from-bottom-1 cue-elements-animate-in self-end rounded-overlay px-3 py-1.5 text-(length:--cue-text-ui) duration-300", className),
49
+ className: cn(field, "cue-elements-fade-in cue-elements-slide-in-from-bottom-1 cue-elements-animate-in self-end rounded-overlay px-3 py-1.5 text-(length:--cue-text-ui) duration-base", className),
50
50
  ...props
51
51
  });
52
52
  }
@@ -62,7 +62,7 @@ function ChatPanelAssistantMessage({ className, ...props }) {
62
62
  function ChatPanelTyping({ className, ...props }) {
63
63
  return /* @__PURE__ */ jsx("div", {
64
64
  "data-slot": "chat-panel-typing",
65
- className: cn("cue-elements-fade-in cue-elements-animate-in flex gap-1 self-start px-1 duration-300", className),
65
+ className: cn("cue-elements-fade-in cue-elements-animate-in flex gap-1 self-start px-1 duration-base", className),
66
66
  ...props,
67
67
  children: [
68
68
  "-0.32s",
@@ -53,7 +53,7 @@ function CheckpointHistory({ checkpoints, currentId, onRestore, className, ...pr
53
53
  type: "button",
54
54
  "aria-label": `Restore to ${checkpoint.label}`,
55
55
  onClick: () => onRestore?.(checkpoint.id),
56
- className: "text-fg-muted hover:bg-surface-2 hover:text-fg flex h-6 shrink-0 items-center gap-1 rounded-full px-2 text-(length:--cue-text-label) font-medium opacity-0 transition-[background-color,color,opacity,scale] duration-150 group-hover:opacity-100 focus-visible:opacity-100 active:scale-[0.96]",
56
+ className: "text-fg-muted hover:bg-surface-2 hover:text-fg flex h-6 shrink-0 items-center gap-1 rounded-full px-2 text-(length:--cue-text-label) font-medium opacity-0 transition-[background-color,color,opacity,scale] duration-fast group-hover:opacity-100 focus-visible:opacity-100 active:scale-[0.96]",
57
57
  children: [/* @__PURE__ */ jsx(RotateCcwIcon, { className: "size-2.5" }), "Restore"]
58
58
  })
59
59
  ]
@@ -54,7 +54,7 @@ function CodeDiff({ filename, additions, deletions, lines, cycle, className, ...
54
54
  children: /* @__PURE__ */ jsx("div", {
55
55
  className: codeSurface,
56
56
  children: lines.map((line, i) => /* @__PURE__ */ jsxs("div", {
57
- className: cn("cue-elements-fade-in cue-elements-animate-in cue-elements-fill-mode-both flex px-4 py-0.5 leading-(--cue-leading-ui) whitespace-pre duration-300", line.kind === "context" && "text-fg-muted", line.kind === "added" && "bg-ok/10 text-ok", line.kind === "removed" && "bg-danger/10 text-danger"),
57
+ className: cn("cue-elements-fade-in cue-elements-animate-in cue-elements-fill-mode-both flex px-4 py-0.5 leading-(--cue-leading-ui) whitespace-pre duration-base", line.kind === "context" && "text-fg-muted", line.kind === "added" && "bg-ok/10 text-ok", line.kind === "removed" && "bg-danger/10 text-danger"),
58
58
  style: { animationDelay: `${i * 60}ms` },
59
59
  children: [/* @__PURE__ */ jsx("span", {
60
60
  className: "w-4 shrink-0 select-none",
@@ -54,7 +54,7 @@ function CodeRunner({ language, code, state, output, durationMs, onRun, classNam
54
54
  })
55
55
  }),
56
56
  state !== "idle" && /* @__PURE__ */ jsxs("div", {
57
- className: "border-border cue-elements-fade-in cue-elements-animate-in flex flex-col border-t px-3.5 py-2.5 duration-300",
57
+ className: "border-border cue-elements-fade-in cue-elements-animate-in flex flex-col border-t px-3.5 py-2.5 duration-base",
58
58
  children: [
59
59
  /* @__PURE__ */ jsx("span", {
60
60
  className: cn("font-mono text-(length:--cue-text-label) tracking-tight", "text-fg-subtle pb-1"),
@@ -197,15 +197,21 @@ declare function ComposerAttachmentChip({ attachment, onRemove, className, ...pr
197
197
  onRemove?: (name: string) => void;
198
198
  }): import("react").JSX.Element;
199
199
  /**
200
- * The text field. Enter submits, guarded against IME composition so accepting a
200
+ * The text field: a textarea that grows with what it holds, to a cap. Enter sends and
201
+ * Shift+Enter breaks the line, both guarded against IME composition so accepting a
201
202
  * candidate does not send the message.
202
203
  */
203
- declare function ComposerInput({ onSubmit, onKeyDown, className, ...props }: Omit<ComponentProps<"input">, "onSubmit"> & {
204
+ declare function ComposerInput({ onSubmit, onKeyDown, size, className, ...props }: Omit<ComponentProps<"textarea">, "onSubmit"> & {
204
205
  /**
205
206
  * Called on Enter, guarded against IME composition so accepting a candidate does not
206
207
  * send.
207
208
  */
208
209
  onSubmit?: () => void;
210
+ /**
211
+ * `md` (the default) or `sm`: the smaller rung, a 36px floor with body type, for a
212
+ * compact console.
213
+ */
214
+ size?: "sm" | "md";
209
215
  }): import("react").JSX.Element;
210
216
  /**
211
217
  * What replaces the input while the microphone is open: a level meter, a running clock
@@ -3,6 +3,7 @@ import { cn } from "../lib/cn.js";
3
3
  import { FOCUS_RING } from "../system/_focus-ring.js";
4
4
  import { ShimmerLabel, field, floating, ghostButton, iconSwap, iconSwapIn, iconSwapOut, inkButton, mono, paper } from "./surfaces.js";
5
5
  import { clamp, pct } from "./range.js";
6
+ import { useAutoGrow } from "../lib/auto-grow.js";
6
7
  import { useMemo } from "react";
7
8
  import { jsx, jsxs } from "react/jsx-runtime";
8
9
  import { ArrowUpIcon, CheckIcon, ChevronDownIcon, FileArchiveIcon, FileImageIcon, FileTextIcon, Loader2Icon, MicIcon, PlusIcon, SquareIcon, XIcon } from "lucide-react";
@@ -127,7 +128,7 @@ function ComposerMenu({ open, align = "start", className, ...props }) {
127
128
  return /* @__PURE__ */ jsx("div", {
128
129
  "data-slot": "composer-menu",
129
130
  "data-open": open || void 0,
130
- className: cn(floating, "absolute bottom-full z-10 mb-2 flex w-72 flex-col gap-0.5 rounded-overlay p-1.5", align === "start" ? "start-0 origin-bottom-left" : "end-0 origin-bottom-right", "transition-[opacity,scale] duration-200 ease-[cubic-bezier(0.23,1,0.32,1)] motion-reduce:transition-none", open ? "scale-100 opacity-100" : "pointer-events-none scale-[0.97] opacity-0", className),
131
+ className: cn(floating, "absolute bottom-full z-10 mb-2 flex w-72 flex-col gap-0.5 rounded-overlay p-1.5", align === "start" ? "start-0 origin-bottom-left" : "end-0 origin-bottom-right", "transition-[opacity,scale] duration-brisk ease-[cubic-bezier(0.23,1,0.32,1)] motion-reduce:transition-none", open ? "scale-100 opacity-100" : "pointer-events-none scale-[0.97] opacity-0", className),
131
132
  ...props
132
133
  });
133
134
  }
@@ -240,26 +241,33 @@ function ComposerAttachmentChip({ attachment, onRemove, className, ...props }) {
240
241
  }),
241
242
  attachment.state === "uploading" && /* @__PURE__ */ jsx("span", {
242
243
  "aria-hidden": true,
243
- className: "absolute inset-x-0 bottom-0 h-0.5 bg-stream/70 transition-[width] duration-300",
244
+ className: "absolute inset-x-0 bottom-0 h-0.5 bg-stream/70 transition-[width] duration-base",
244
245
  style: { width: `${pct(attachment.progress ?? 0, 100)}%` }
245
246
  })
246
247
  ]
247
248
  });
248
249
  }
249
250
  /**
250
- * The text field. Enter submits, guarded against IME composition so accepting a
251
+ * The text field: a textarea that grows with what it holds, to a cap. Enter sends and
252
+ * Shift+Enter breaks the line, both guarded against IME composition so accepting a
251
253
  * candidate does not send the message.
252
254
  */
253
- function ComposerInput({ onSubmit, onKeyDown, className, ...props }) {
254
- return /* @__PURE__ */ jsx("input", {
255
+ function ComposerInput({ onSubmit, onKeyDown, size = "md", className, ...props }) {
256
+ const grow = useAutoGrow(props.value);
257
+ return /* @__PURE__ */ jsx("textarea", {
258
+ ...grow,
255
259
  "data-slot": "composer-input",
260
+ rows: 1,
261
+ "data-size": size,
262
+ "data-small": size === "sm" || void 0,
256
263
  onKeyDown: (event) => {
257
264
  onKeyDown?.(event);
258
265
  if (event.defaultPrevented) return;
259
- if (event.key !== "Enter" || event.nativeEvent.isComposing) return;
266
+ if (event.key !== "Enter" || event.shiftKey || event.nativeEvent.isComposing) return;
267
+ event.preventDefault();
260
268
  onSubmit?.();
261
269
  },
262
- className: cn(`placeholder:text-fg-subtle min-h-11 w-full bg-transparent px-3 text-(length:--cue-text-emphasis) caret-stream outline-none ${FOCUS_RING}`, className),
270
+ className: cn(`placeholder:text-fg-subtle min-h-11 max-h-48 w-full resize-none overflow-y-auto bg-transparent px-3 py-2.5 field-sizing-content data-small:min-h-9 data-small:py-1.5 data-small:text-(length:--cue-text-body) text-(length:--cue-text-emphasis) caret-stream outline-none ${FOCUS_RING}`, className),
263
271
  ...props
264
272
  });
265
273
  }
@@ -282,7 +290,7 @@ function ComposerVoice({ recording, seconds, className, ...props }) {
282
290
  className: "flex h-6 items-center gap-[3px]",
283
291
  "aria-hidden": true,
284
292
  children: BARS.map((bar) => /* @__PURE__ */ jsx("span", {
285
- className: cn("w-0.5 rounded-full transition-[height,background-color] duration-150 motion-reduce:transition-none", recording ? "bg-accent" : "bg-surface-3"),
293
+ className: cn("w-0.5 rounded-full transition-[height,background-color] duration-fast motion-reduce:transition-none", recording ? "bg-accent" : "bg-surface-3"),
286
294
  style: { height: recording ? barHeight(bar, seconds * 10) : 3 }
287
295
  }, bar))
288
296
  }),
@@ -357,7 +365,7 @@ function ComposerModelItem({ entry, selected, ...props }) {
357
365
  }),
358
366
  /* @__PURE__ */ jsx("span", {
359
367
  className: "flex w-4 justify-end",
360
- children: selected && /* @__PURE__ */ jsx(CheckIcon, { className: "cue-elements-fade-in cue-elements-zoom-in-90 cue-elements-animate-in size-3.5 duration-200" })
368
+ children: selected && /* @__PURE__ */ jsx(CheckIcon, { className: "cue-elements-fade-in cue-elements-zoom-in-90 cue-elements-animate-in size-3.5 duration-brisk" })
361
369
  })
362
370
  ]
363
371
  });
@@ -394,7 +402,7 @@ function ComposerContext({ usage, className, ...props }) {
394
402
  className: cn("group/ctx relative", className),
395
403
  ...props,
396
404
  children: [/* @__PURE__ */ jsxs("div", {
397
- className: cn(floating, "absolute end-0 bottom-full z-10 mb-2 flex w-60 origin-bottom-right flex-col gap-3.5 rounded-overlay p-4", "transition-[opacity,scale] duration-200 ease-[cubic-bezier(0.23,1,0.32,1)] motion-reduce:transition-none", "pointer-events-none scale-[0.97] opacity-0", "group-hover/ctx:pointer-events-auto group-hover/ctx:scale-100 group-hover/ctx:opacity-100", "group-focus-within/ctx:pointer-events-auto group-focus-within/ctx:scale-100 group-focus-within/ctx:opacity-100"),
405
+ className: cn(floating, "absolute end-0 bottom-full z-10 mb-2 flex w-60 origin-bottom-right flex-col gap-3.5 rounded-overlay p-4", "transition-[opacity,scale] duration-brisk ease-[cubic-bezier(0.23,1,0.32,1)] motion-reduce:transition-none", "pointer-events-none scale-[0.97] opacity-0", "group-hover/ctx:pointer-events-auto group-hover/ctx:scale-100 group-hover/ctx:opacity-100", "group-focus-within/ctx:pointer-events-auto group-focus-within/ctx:scale-100 group-focus-within/ctx:opacity-100"),
398
406
  children: [
399
407
  /* @__PURE__ */ jsxs("div", {
400
408
  className: "flex items-baseline justify-between",
@@ -409,7 +417,7 @@ function ComposerContext({ usage, className, ...props }) {
409
417
  /* @__PURE__ */ jsx("div", {
410
418
  className: "bg-surface-2 flex h-[5px] w-full gap-px overflow-hidden rounded-full",
411
419
  children: segments.map((segment) => /* @__PURE__ */ jsx("span", {
412
- className: cn("h-full transition-[width] duration-700 motion-reduce:transition-none", segment.className),
420
+ className: cn("h-full transition-[width] duration-slower motion-reduce:transition-none", segment.className),
413
421
  style: { width: `${pct(segment.value, usage.total)}%` }
414
422
  }, segment.label))
415
423
  }),
@@ -469,7 +477,7 @@ function ComposerContext({ usage, className, ...props }) {
469
477
  fill: "none",
470
478
  strokeWidth: "2.5",
471
479
  strokeLinecap: "round",
472
- className: "stroke-current transition-[stroke-dashoffset] duration-700 motion-reduce:transition-none",
480
+ className: "stroke-current transition-[stroke-dashoffset] duration-slower motion-reduce:transition-none",
473
481
  strokeDasharray: circumference,
474
482
  strokeDashoffset: circumference * (1 - clamp(fraction, 0, 1))
475
483
  })]
@@ -47,7 +47,7 @@ function ComputerUse({ url, steps, activeIndex, children, className, ...props })
47
47
  children,
48
48
  trail.map((step, i) => /* @__PURE__ */ jsx("span", {
49
49
  "aria-hidden": true,
50
- className: "pointer-events-none absolute size-2 rounded-full bg-stream transition-opacity duration-300",
50
+ className: "pointer-events-none absolute size-2 rounded-full bg-stream transition-opacity duration-base",
51
51
  style: {
52
52
  left: `${step.x}%`,
53
53
  top: `${step.y}%`,
@@ -56,7 +56,7 @@ function ComputerUse({ url, steps, activeIndex, children, className, ...props })
56
56
  }, step.id)),
57
57
  active && /* @__PURE__ */ jsx(MousePointer2Icon, {
58
58
  "aria-hidden": true,
59
- className: "pointer-events-none absolute size-4 fill-stream text-stream transition-[left,top] duration-500 ease-out motion-reduce:transition-none",
59
+ className: "pointer-events-none absolute size-4 fill-stream text-stream transition-[left,top] duration-slow ease-out motion-reduce:transition-none",
60
60
  style: {
61
61
  left: `${active.x}%`,
62
62
  top: `${active.y}%`
@@ -47,7 +47,7 @@ function ConfidenceMarker({ claims, hoveredId, onHover, className, ...props }) {
47
47
  children: hovered && /* @__PURE__ */ jsxs("span", {
48
48
  id: basisId,
49
49
  role: "status",
50
- className: cn("bg-surface-2 border border-border-overlay", "font-mono text-(length:--cue-text-label) tracking-tight", "cue-elements-fade-in cue-elements-zoom-in-95 cue-elements-animate-in text-fg-muted flex items-center gap-1.5 rounded-full px-2.5 py-1.5 duration-150"),
50
+ className: cn("bg-surface-2 border border-border-overlay", "font-mono text-(length:--cue-text-label) tracking-tight", "cue-elements-fade-in cue-elements-zoom-in-95 cue-elements-animate-in text-fg-muted flex items-center gap-1.5 rounded-full px-2.5 py-1.5 duration-fast"),
51
51
  children: [
52
52
  /* @__PURE__ */ jsx("span", {
53
53
  "aria-hidden": true,
@@ -17,7 +17,7 @@ function ConnectionState({ phase, attempt, resumedTokens, onRetry, className, ..
17
17
  if (phase === "online") return null;
18
18
  return /* @__PURE__ */ jsxs("div", {
19
19
  "data-slot": "connection-state",
20
- className: cn(paper, "cue-elements-fade-in cue-elements-slide-in-from-top-1 cue-elements-animate-in flex w-full max-w-sm items-center gap-2.5 rounded-overlay px-3.5 py-2.5 duration-300", className),
20
+ className: cn(paper, "cue-elements-fade-in cue-elements-slide-in-from-top-1 cue-elements-animate-in flex w-full max-w-sm items-center gap-2.5 rounded-overlay px-3.5 py-2.5 duration-base", className),
21
21
  ...props,
22
22
  children: [
23
23
  phase === "dropped" && /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -29,7 +29,7 @@ function ConnectionState({ phase, attempt, resumedTokens, onRetry, className, ..
29
29
  /* @__PURE__ */ jsx("button", {
30
30
  type: "button",
31
31
  onClick: onRetry,
32
- className: "text-fg-muted hover:bg-surface-2 hover:text-fg shrink-0 rounded-full px-2.5 py-1 text-(length:--cue-text-ui) font-medium transition-[background-color,color,scale] duration-150 active:scale-[0.96]",
32
+ className: "text-fg-muted hover:bg-surface-2 hover:text-fg shrink-0 rounded-full px-2.5 py-1 text-(length:--cue-text-ui) font-medium transition-[background-color,color,scale] duration-fast active:scale-[0.96]",
33
33
  children: "Reconnect"
34
34
  })
35
35
  ] }),
@@ -39,7 +39,7 @@ function ContextBreakdown({ segments, limit, className, ...props }) {
39
39
  /* @__PURE__ */ jsx("div", {
40
40
  className: "bg-surface-2 flex h-2 w-full overflow-hidden rounded-full",
41
41
  children: segments.map((segment) => /* @__PURE__ */ jsx("span", {
42
- className: cn("h-full transition-[width] duration-500 ease-out motion-reduce:transition-none", segment.tint),
42
+ className: cn("h-full transition-[width] duration-slow ease-out motion-reduce:transition-none", segment.tint),
43
43
  style: { width: `${share(segment.tokens)}%` }
44
44
  }, segment.label))
45
45
  }),
@@ -124,7 +124,7 @@ const ContextUsage = React.forwardRef(function ContextUsage({ categories, limit,
124
124
  children: rows.map(({ category, tone }) => /* @__PURE__ */ jsx("span", {
125
125
  "data-slot": "context-usage-segment",
126
126
  "data-color": tone,
127
- className: cn("h-full transition-[width] duration-500 ease-out motion-reduce:transition-none", TONE_FILL[tone]),
127
+ className: cn("h-full transition-[width] duration-slow ease-out motion-reduce:transition-none", TONE_FILL[tone]),
128
128
  style: { width: `${pct(category.tokens, limit)}%` }
129
129
  }, category.label))
130
130
  }),
@@ -59,7 +59,7 @@ function ConversationSearch({ query, hits, activeIndex, onQueryChange, onStep, c
59
59
  })
60
60
  ]
61
61
  }), active && /* @__PURE__ */ jsxs("div", {
62
- className: cn("bg-fg/[0.06]", "cue-elements-fade-in cue-elements-animate-in rounded-surface px-3 py-2 text-(length:--cue-text-ui) leading-(--cue-leading-ui) duration-200"),
62
+ className: cn("bg-fg/[0.06]", "cue-elements-fade-in cue-elements-animate-in rounded-surface px-3 py-2 text-(length:--cue-text-ui) leading-(--cue-leading-ui) duration-brisk"),
63
63
  children: [
64
64
  /* @__PURE__ */ jsx("span", {
65
65
  className: "text-fg-muted",
@@ -79,7 +79,7 @@ function ConversationSearch({ query, hits, activeIndex, onQueryChange, onStep, c
79
79
  className: "bg-surface-1 relative w-1.5 shrink-0 rounded-full",
80
80
  children: hits.map((hit, i) => /* @__PURE__ */ jsx("span", {
81
81
  "aria-hidden": true,
82
- className: cn("absolute inset-x-0 h-1 rounded-full transition-colors duration-200", i === index ? "bg-warn" : "bg-warn/35"),
82
+ className: cn("absolute inset-x-0 h-1 rounded-full transition-colors duration-brisk", i === index ? "bg-warn" : "bg-warn/35"),
83
83
  style: { top: `${hit.position}%` }
84
84
  }, hit.id))
85
85
  })]
@@ -38,7 +38,7 @@ function CostMeter({ runCost, sessionCost, lines, className, ...props }) {
38
38
  /* @__PURE__ */ jsx("div", {
39
39
  className: "bg-surface-2 flex h-1.5 w-full overflow-hidden rounded-full",
40
40
  children: lines.map((line, i) => /* @__PURE__ */ jsx("span", {
41
- className: cn("h-full transition-[width] duration-500 motion-reduce:transition-none", i === 0 ? "bg-stream" : i === 1 ? "bg-stream/55" : "bg-surface-3"),
41
+ className: cn("h-full transition-[width] duration-slow motion-reduce:transition-none", i === 0 ? "bg-stream" : i === 1 ? "bg-stream/55" : "bg-surface-3"),
42
42
  style: { width: `${pct(line.share, 1)}%` }
43
43
  }, line.model))
44
44
  }),
@@ -39,7 +39,7 @@ function ElementsDataTable({ rows, cycle, className, ...props }) {
39
39
  }),
40
40
  /* @__PURE__ */ jsx("div", { className: "bg-surface-2 mx-4 h-px" }),
41
41
  /* @__PURE__ */ jsx("div", { children: rows.map((row, index) => /* @__PURE__ */ jsxs("div", {
42
- className: "cue-elements-fade-in cue-elements-slide-in-from-bottom-1 cue-elements-animate-in cue-elements-fill-mode-both hover:bg-surface-1 flex items-center gap-2.5 px-4 py-2.5 transition-colors duration-300",
42
+ className: "cue-elements-fade-in cue-elements-slide-in-from-bottom-1 cue-elements-animate-in cue-elements-fill-mode-both hover:bg-surface-1 flex items-center gap-2.5 px-4 py-2.5 transition-colors duration-base",
43
43
  style: { animationDelay: `${index * 80}ms` },
44
44
  children: [
45
45
  /* @__PURE__ */ jsx("span", {
@@ -64,7 +64,7 @@ function Diagram({ title, zoom, children, onZoomIn, onZoomOut, onReset, onExpand
64
64
  }), /* @__PURE__ */ jsx("div", {
65
65
  className: "border-border flex min-h-[10rem] items-center justify-center overflow-hidden border-t p-4",
66
66
  children: /* @__PURE__ */ jsx("div", {
67
- className: "origin-center transition-transform duration-200 ease-out motion-reduce:transition-none",
67
+ className: "origin-center transition-transform duration-brisk ease-out motion-reduce:transition-none",
68
68
  style: { transform: `scale(${zoom})` },
69
69
  children
70
70
  })
@@ -20,7 +20,7 @@ import { PencilLineIcon, XIcon } from "lucide-react";
20
20
  function DraftRestore({ draft, savedAt, onRestore, onDiscard, className, ...props }) {
21
21
  return /* @__PURE__ */ jsxs("div", {
22
22
  "data-slot": "draft-restore",
23
- className: cn(paper, "cue-elements-fade-in cue-elements-slide-in-from-bottom-1 cue-elements-animate-in flex w-full max-w-sm items-center gap-2.5 rounded-overlay py-2 pr-2 pl-3.5 duration-300", className),
23
+ className: cn(paper, "cue-elements-fade-in cue-elements-slide-in-from-bottom-1 cue-elements-animate-in flex w-full max-w-sm items-center gap-2.5 rounded-overlay py-2 pr-2 pl-3.5 duration-base", className),
24
24
  ...props,
25
25
  children: [
26
26
  /* @__PURE__ */ jsx(PencilLineIcon, { className: "text-fg-subtle size-3.5 shrink-0" }),
@@ -37,7 +37,7 @@ function DraftRestore({ draft, savedAt, onRestore, onDiscard, className, ...prop
37
37
  /* @__PURE__ */ jsx("button", {
38
38
  type: "button",
39
39
  onClick: onRestore,
40
- className: "text-fg-muted hover:bg-surface-2 hover:text-fg shrink-0 rounded-full px-2.5 py-1 text-(length:--cue-text-ui) font-medium transition-[background-color,color,scale] duration-150 active:scale-[0.96]",
40
+ className: "text-fg-muted hover:bg-surface-2 hover:text-fg shrink-0 rounded-full px-2.5 py-1 text-(length:--cue-text-ui) font-medium transition-[background-color,color,scale] duration-fast active:scale-[0.96]",
41
41
  children: "Restore"
42
42
  }),
43
43
  /* @__PURE__ */ jsx("button", {
@@ -62,7 +62,7 @@ function EditMessage({ value, discardedReplies, editing, onValueChange, onSave,
62
62
  children: [/* @__PURE__ */ jsx("button", {
63
63
  type: "button",
64
64
  onClick: onCancel,
65
- className: "text-fg-muted hover:bg-surface-2 hover:text-fg h-8 rounded-full px-3.5 text-(length:--cue-text-ui) font-medium transition-[background-color,color,scale] duration-150 active:scale-[0.96]",
65
+ className: "text-fg-muted hover:bg-surface-2 hover:text-fg h-8 rounded-full px-3.5 text-(length:--cue-text-ui) font-medium transition-[background-color,color,scale] duration-fast active:scale-[0.96]",
66
66
  children: "Cancel"
67
67
  }), /* @__PURE__ */ jsx("button", {
68
68
  type: "button",
@@ -429,6 +429,112 @@
429
429
  }
430
430
  }
431
431
 
432
+ /* ── Supersede mode: Cursor's values ───────────────────────────────────
433
+ *
434
+ * Cursor's agent pane, as a skin a consumer can wear with
435
+ * `<AgentSurface skin="cursor">` (cue-ui-56). The values are the gallery
436
+ * study's, `CURSOR` in `packages/specimens/src/pages/clones/palette.ts`, where
437
+ * their provenance is written out: the dark half is quoted from Cursor's own
438
+ * theme seed, and the light half is synthesised from that seed. The study and
439
+ * this block are held to each other value for value by
440
+ * `packages/specimens/test/cursor-skin.test.ts`, so a correction to either
441
+ * fails until the other agrees.
442
+ *
443
+ * The same shape and the same accounting as assistant-ui's island above. Three
444
+ * blocks, so the light half is reached the three ways a light theme is. Derived
445
+ * tokens are absent by construction, and `--cue-busy`, `--cue-info`,
446
+ * `--cue-selection` and `--cue-scrim` are absent by choice. Unlike upstream,
447
+ * Cursor documents its own status hues, so this island takes them. The ring is
448
+ * the island's own blue rather than the console's.
449
+ */
450
+ [data-cue-skin="cursor"] {
451
+ color-scheme: dark;
452
+ --cue-bg: #181818;
453
+ --cue-sunken: #141414;
454
+ --cue-surface-1: #1f1f1f;
455
+ --cue-surface-2: color-mix(in srgb, #f0f0f0 6%, transparent);
456
+ --cue-surface-3: #262626;
457
+ --cue-fg: #f0f0f0;
458
+ --cue-fg-muted: color-mix(in srgb, #f0f0f0 74%, transparent);
459
+ --cue-fg-subtle: color-mix(in srgb, #f0f0f0 60%, transparent);
460
+ --cue-border: #2c2c2c;
461
+ --cue-border-strong: #3a3a3a;
462
+ --cue-border-overlay: #2c2c2c;
463
+ --cue-accent: #599ce7;
464
+ --cue-accent-hover: #7db2ee;
465
+ --cue-accent-fg: #101010;
466
+ --cue-stream: #599ce7;
467
+ --cue-ok: #3fa266;
468
+ --cue-warn: #f1b467;
469
+ --cue-danger: #e34671;
470
+ --cue-focus: var(--cue-accent);
471
+ /* The inks on the red and the amber. The study records neither, because
472
+ * its chrome never fills a button with either. The dark half's accent ink
473
+ * reads on both: 4.88:1 on the red and 10.39:1 on the amber. */
474
+ --cue-danger-fg: var(--cue-accent-fg);
475
+ --cue-warn-fg: var(--cue-accent-fg);
476
+ }
477
+
478
+ [data-mode="light"] [data-cue-skin="cursor"],
479
+ [data-cue-skin="cursor"][data-mode="light"] {
480
+ color-scheme: light;
481
+ --cue-bg: #ffffff;
482
+ --cue-sunken: #f2f2f2;
483
+ --cue-surface-1: #f7f7f7;
484
+ --cue-surface-2: color-mix(in srgb, #1a1a1a 6%, transparent);
485
+ --cue-surface-3: #e8e8e8;
486
+ --cue-fg: #1a1a1a;
487
+ --cue-fg-muted: color-mix(in srgb, #1a1a1a 74%, transparent);
488
+ --cue-fg-subtle: color-mix(in srgb, #1a1a1a 60%, transparent);
489
+ --cue-border: #e0e0e0;
490
+ --cue-border-strong: #c8c8c8;
491
+ --cue-border-overlay: #e0e0e0;
492
+ --cue-accent: #2f6fbf;
493
+ --cue-accent-hover: #255a9d;
494
+ --cue-accent-fg: #ffffff;
495
+ --cue-stream: #2f6fbf;
496
+ --cue-ok: #2f7d52;
497
+ --cue-warn: #a86a13;
498
+ --cue-danger: #c22e50;
499
+ --cue-focus: var(--cue-accent);
500
+ /* White on the red, 5.53:1. The amber is the one place this half needs an
501
+ * ink from outside the palette. Its white reaches 4.43:1 and its type
502
+ * 3.93:1, both under AA. Black is the only ink that clears it, at 4.74:1. */
503
+ --cue-danger-fg: var(--cue-accent-fg);
504
+ --cue-warn-fg: #000000;
505
+ }
506
+
507
+ @media (prefers-color-scheme: light) {
508
+ [data-mode="system"] [data-cue-skin="cursor"],
509
+ [data-cue-skin="cursor"][data-mode="system"] {
510
+ color-scheme: light;
511
+ --cue-bg: #ffffff;
512
+ --cue-sunken: #f2f2f2;
513
+ --cue-surface-1: #f7f7f7;
514
+ --cue-surface-2: color-mix(in srgb, #1a1a1a 6%, transparent);
515
+ --cue-surface-3: #e8e8e8;
516
+ --cue-fg: #1a1a1a;
517
+ --cue-fg-muted: color-mix(in srgb, #1a1a1a 74%, transparent);
518
+ --cue-fg-subtle: color-mix(in srgb, #1a1a1a 60%, transparent);
519
+ --cue-border: #e0e0e0;
520
+ --cue-border-strong: #c8c8c8;
521
+ --cue-border-overlay: #e0e0e0;
522
+ --cue-accent: #2f6fbf;
523
+ --cue-accent-hover: #255a9d;
524
+ --cue-accent-fg: #ffffff;
525
+ --cue-stream: #2f6fbf;
526
+ --cue-ok: #2f7d52;
527
+ --cue-warn: #a86a13;
528
+ --cue-danger: #c22e50;
529
+ --cue-focus: var(--cue-accent);
530
+ /* White on the red, 5.53:1. The amber is the one place this half needs an
531
+ * ink from outside the palette. Its white reaches 4.43:1 and its type
532
+ * 3.93:1, both under AA. Black is the only ink that clears it, at 4.74:1. */
533
+ --cue-danger-fg: var(--cue-accent-fg);
534
+ --cue-warn-fg: #000000;
535
+ }
536
+ }
537
+
432
538
  /* ── Metrics ───────────────────────────────────────────────────────────
433
539
  *
434
540
  * `fidelity="upstream"` pins geometry to assistant-ui's, which means the
@@ -468,6 +574,34 @@
468
574
  --cue-text-title: 24px;
469
575
  }
470
576
 
577
+ /* Cursor's geometry, at `fidelity="upstream"`. What the record has is its
578
+ * corners and its two faces, so those are what this pins. Its type sizes and
579
+ * spacing were never recorded. The plain upstream block above still matches a
580
+ * Cursor island and would pin assistant-ui's literal pixels on it, so this
581
+ * block hands both back to cue. The type rungs inherit the console's, and
582
+ * spacing rides the density ladder, as it does at `cue-metrics`. Two attribute
583
+ * selectors outrank the one above, whatever the order. */
584
+ [data-cue-skin="cursor"][data-cue-fidelity="upstream"] {
585
+ --spacing: calc(0.25rem * var(--cue-density, 1));
586
+ --cue-radius-scale: 1;
587
+ --cue-radius-control: 0.375rem;
588
+ --cue-radius-surface: 0.5rem;
589
+ --cue-radius-overlay: 0.75rem;
590
+ --radius-control: 0.375rem;
591
+ --radius-surface: 0.5rem;
592
+ --radius-overlay: 0.75rem;
593
+ --cue-font-sans: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", ui-sans-serif, system-ui, sans-serif;
594
+ --font-sans: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", ui-sans-serif, system-ui, sans-serif;
595
+ --cue-font-mono: "Geist Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
596
+ --font-mono: "Geist Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
597
+ --cue-text-micro: inherit;
598
+ --cue-text-label: inherit;
599
+ --cue-text-ui: inherit;
600
+ --cue-text-body: inherit;
601
+ --cue-text-emphasis: inherit;
602
+ --cue-text-title: inherit;
603
+ }
604
+
471
605
  /* `fidelity="cue-metrics"` is the default and changes only one thing — but it
472
606
  * is the thing the density ladder could not otherwise reach. Every box size and
473
607
  * gap in the family is a Tailwind spacing utility, which multiplies
@@ -1,3 +1,4 @@
1
+ import { RequestDelivery } from "./vocabulary.js";
1
2
  import { ComponentProps } from "react";
2
3
  //#region src/elements/elicitation-form.d.ts
3
4
  type ElicitationState = "request" | "accepted" | "declined";
@@ -30,7 +31,7 @@ interface ElicitationField {
30
31
  * onDecline={decline}
31
32
  * />
32
33
  */
33
- declare function ElicitationForm({ server, message, fields, state, onAccept, onDecline, className, ...props }: Omit<ComponentProps<"div">, "children" | "server" | "message" | "fields" | "state" | "onAccept" | "onDecline"> & {
34
+ declare function ElicitationForm({ server, message, fields, state, onAccept, onDecline, delivery, className, ...props }: Omit<ComponentProps<"div">, "children" | "server" | "message" | "fields" | "state" | "onAccept" | "onDecline" | "delivery"> & {
34
35
  /** Which server paused to ask. */
35
36
  server: string;
36
37
  /** Why the input is needed, in the server's words. */
@@ -43,6 +44,12 @@ declare function ElicitationForm({ server, message, fields, state, onAccept, onD
43
44
  onAccept?: () => void;
44
45
  /** Called when the request is refused. */
45
46
  onDecline?: () => void;
47
+ /**
48
+ * Where the answer has got to: `sending`, `sent` or `failed`. While it is on its way
49
+ * and once it has arrived, the form offers nothing to press. `failed` offers Decline
50
+ * and Send again. An outcome `state` wins over it.
51
+ */
52
+ delivery?: RequestDelivery;
46
53
  }): import("react").JSX.Element;
47
54
  //#endregion
48
55
  export { ElicitationField, ElicitationForm, ElicitationState };
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
  import { cn } from "../lib/cn.js";
3
3
  import { field, inkButton, mono, paper } from "./surfaces.js";
4
+ import { DeliveryNote } from "./request-delivery.js";
4
5
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
6
  import { CheckIcon, PlugIcon, XIcon } from "lucide-react";
6
7
  //#region src/elements/elicitation-form.tsx
@@ -19,7 +20,7 @@ import { CheckIcon, PlugIcon, XIcon } from "lucide-react";
19
20
  * onDecline={decline}
20
21
  * />
21
22
  */
22
- function ElicitationForm({ server, message, fields, state, onAccept, onDecline, className, ...props }) {
23
+ function ElicitationForm({ server, message, fields, state, onAccept, onDecline, delivery, className, ...props }) {
23
24
  return /* @__PURE__ */ jsxs("div", {
24
25
  "data-slot": "elicitation-form",
25
26
  className: cn(paper, "flex w-full max-w-sm flex-col gap-3.5 rounded-overlay p-4", className),
@@ -66,8 +67,8 @@ function ElicitationForm({ server, message, fields, state, onAccept, onDecline,
66
67
  className: "flex items-center gap-2",
67
68
  children: [/* @__PURE__ */ jsx("span", {
68
69
  "aria-hidden": true,
69
- className: cn("flex h-4 w-7 items-center rounded-full p-0.5 transition-colors duration-200", item.value === "true" ? "bg-accent" : "bg-surface-3"),
70
- children: /* @__PURE__ */ jsx("span", { className: cn("bg-bg size-3 rounded-full transition-transform duration-200 motion-reduce:transition-none", item.value === "true" && "translate-x-3") })
70
+ className: cn("flex h-4 w-7 items-center rounded-full p-0.5 transition-colors duration-brisk", item.value === "true" ? "bg-accent" : "bg-surface-3"),
71
+ children: /* @__PURE__ */ jsx("span", { className: cn("bg-bg size-3 rounded-full transition-transform duration-brisk motion-reduce:transition-none", item.value === "true" && "translate-x-3") })
71
72
  }), /* @__PURE__ */ jsx("span", {
72
73
  className: "text-fg-muted text-(length:--cue-text-ui)",
73
74
  children: item.value === "true" ? "On" : "Off"
@@ -79,19 +80,26 @@ function ElicitationForm({ server, message, fields, state, onAccept, onDecline,
79
80
  }, item.name))
80
81
  }),
81
82
  /* @__PURE__ */ jsx("div", {
82
- className: "flex h-8 items-center justify-end gap-2",
83
- children: state === "request" ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("button", {
84
- type: "button",
85
- onClick: onDecline,
86
- className: "text-fg-muted hover:bg-surface-2 hover:text-fg h-8 rounded-full px-3.5 text-(length:--cue-text-ui) font-medium transition-[background-color,color,scale] duration-150 active:scale-[0.96]",
87
- children: "Decline"
88
- }), /* @__PURE__ */ jsx("button", {
89
- type: "button",
90
- onClick: onAccept,
91
- className: cn(inkButton, "flex h-8 items-center rounded-full px-3.5 text-(length:--cue-text-ui) font-medium"),
92
- children: "Send"
93
- })] }) : /* @__PURE__ */ jsx("span", {
94
- className: "cue-elements-fade-in cue-elements-animate-in text-fg-muted flex items-center gap-2 text-(length:--cue-text-ui) duration-300",
83
+ className: "flex min-h-8 flex-wrap items-center justify-end gap-2",
84
+ children: state === "request" && (delivery === "sending" || delivery === "sent") ? /* @__PURE__ */ jsx(DeliveryNote, { delivery }) : state === "request" ? /* @__PURE__ */ jsxs(Fragment, { children: [
85
+ delivery === "failed" ? /* @__PURE__ */ jsx(DeliveryNote, {
86
+ delivery: "failed",
87
+ className: "me-auto"
88
+ }) : null,
89
+ /* @__PURE__ */ jsx("button", {
90
+ type: "button",
91
+ onClick: onDecline,
92
+ className: "text-fg-muted hover:bg-surface-2 hover:text-fg h-8 rounded-full px-3.5 text-(length:--cue-text-ui) font-medium transition-[background-color,color,scale] duration-fast active:scale-[0.96]",
93
+ children: "Decline"
94
+ }),
95
+ /* @__PURE__ */ jsx("button", {
96
+ type: "button",
97
+ onClick: onAccept,
98
+ className: cn(inkButton, "flex h-8 items-center rounded-full px-3.5 text-(length:--cue-text-ui) font-medium"),
99
+ children: "Send"
100
+ })
101
+ ] }) : /* @__PURE__ */ jsx("span", {
102
+ className: "cue-elements-fade-in cue-elements-animate-in text-fg-muted flex items-center gap-2 text-(length:--cue-text-ui) duration-base",
95
103
  children: state === "accepted" ? /* @__PURE__ */ jsxs(Fragment, { children: [
96
104
  /* @__PURE__ */ jsx(CheckIcon, { className: "size-3.5 text-ok" }),
97
105
  "Sent to ",
@@ -40,7 +40,7 @@ function ChatEmptyState({ className, ...props }) {
40
40
  function EmptyStateGreeting({ className, ...props }) {
41
41
  return /* @__PURE__ */ jsx("h2", {
42
42
  "data-slot": "empty-state-greeting",
43
- className: cn("cue-elements-fade-in cue-elements-slide-in-from-bottom-1 cue-elements-animate-in cue-elements-fill-mode-both text-center text-(length:--cue-text-title) font-medium tracking-tight duration-500 motion-reduce:animate-none", className),
43
+ className: cn("cue-elements-fade-in cue-elements-slide-in-from-bottom-1 cue-elements-animate-in cue-elements-fill-mode-both text-center text-(length:--cue-text-title) font-medium tracking-tight duration-slow motion-reduce:animate-none", className),
44
44
  ...props
45
45
  });
46
46
  }
@@ -64,7 +64,7 @@ function EmptyStateSuggestion({ index = 0, className, style, ...props }) {
64
64
  animationDelay: `${120 + index * 70}ms`,
65
65
  ...style
66
66
  },
67
- className: cn(paper, `cue-elements-fade-in cue-elements-slide-in-from-bottom-2 cue-elements-animate-in cue-elements-fill-mode-both ${FOCUS_RING} rounded-full px-4 py-2 text-(length:--cue-text-body) transition-transform duration-500 outline-none hover:-translate-y-px active:scale-[0.96] motion-reduce:animate-none`, className),
67
+ className: cn(paper, `cue-elements-fade-in cue-elements-slide-in-from-bottom-2 cue-elements-animate-in cue-elements-fill-mode-both ${FOCUS_RING} rounded-full px-4 py-2 text-(length:--cue-text-body) transition-transform duration-slow outline-none hover:-translate-y-px active:scale-[0.96] motion-reduce:animate-none`, className),
68
68
  ...props
69
69
  });
70
70
  }
@@ -80,7 +80,7 @@ function EmptyStateComposer({ placeholder, onSend, className, style, ...props })
80
80
  animationDelay: "360ms",
81
81
  ...style
82
82
  },
83
- className: cn(paper, "cue-elements-fade-in cue-elements-slide-in-from-bottom-2 cue-elements-animate-in cue-elements-fill-mode-both flex h-13 w-full items-center justify-between rounded-full py-2 ps-5 pe-2.5 duration-500 motion-reduce:animate-none", className),
83
+ className: cn(paper, "cue-elements-fade-in cue-elements-slide-in-from-bottom-2 cue-elements-animate-in cue-elements-fill-mode-both flex h-13 w-full items-center justify-between rounded-full py-2 ps-5 pe-2.5 duration-slow motion-reduce:animate-none", className),
84
84
  ...props,
85
85
  children: [/* @__PURE__ */ jsx("span", {
86
86
  className: "text-fg-subtle text-(length:--cue-text-emphasis)",
@@ -21,7 +21,7 @@ function ErrorState({ title, detail, retrying, onRetry, className, ...props }) {
21
21
  if (retrying) return /* @__PURE__ */ jsxs("div", {
22
22
  "data-slot": "error-state",
23
23
  role: "status",
24
- className: cn("cue-elements-fade-in cue-elements-animate-in flex w-full max-w-sm items-center gap-2.5 text-(length:--cue-text-body) duration-300 motion-reduce:animate-none", className),
24
+ className: cn("cue-elements-fade-in cue-elements-animate-in flex w-full max-w-sm items-center gap-2.5 text-(length:--cue-text-body) duration-base motion-reduce:animate-none", className),
25
25
  ...props,
26
26
  children: [/* @__PURE__ */ jsx(RefreshCwIcon, { className: "text-fg-muted size-3.5 shrink-0 animate-spin motion-reduce:animate-none" }), /* @__PURE__ */ jsx(ShimmerLabel, {
27
27
  className: "text-fg-muted relative inline-block",
@@ -31,7 +31,7 @@ function ErrorState({ title, detail, retrying, onRetry, className, ...props }) {
31
31
  return /* @__PURE__ */ jsxs("div", {
32
32
  "data-slot": "error-state",
33
33
  role: "alert",
34
- className: cn("cue-elements-fade-in cue-elements-animate-in flex w-full max-w-sm items-start gap-2.5 rounded-overlay bg-danger/10 px-4 py-3 text-(length:--cue-text-body) duration-300 motion-reduce:animate-none", className),
34
+ className: cn("cue-elements-fade-in cue-elements-animate-in flex w-full max-w-sm items-start gap-2.5 rounded-overlay bg-danger/10 px-4 py-3 text-(length:--cue-text-body) duration-base motion-reduce:animate-none", className),
35
35
  ...props,
36
36
  children: [
37
37
  /* @__PURE__ */ jsx(CircleAlertIcon, { className: "mt-0.5 size-4 shrink-0 text-danger/80" }),